diff --git a/CMakeLists.txt b/CMakeLists.txt index 909fba74..d84a8eb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,6 +204,8 @@ add_library (secure rai/versioning.cpp) add_library (rai_lib SHARED + rai/blocks.cpp + rai/blocks.hpp rai/interface.cpp rai/interface.h rai/numbers.cpp @@ -236,18 +238,19 @@ if (RAIBLOCKS_TEST) add_executable (core_test rai/core_test/block.cpp rai/core_test/block_store.cpp - rai/core_test/node.cpp + rai/core_test/interface.cpp rai/core_test/conflicts.cpp rai/core_test/daemon.cpp rai/core_test/entry.cpp rai/core_test/gap_cache.cpp rai/core_test/ledger.cpp + rai/core_test/network.cpp + rai/core_test/node.cpp rai/core_test/message.cpp rai/core_test/message_parser.cpp rai/core_test/processor_service.cpp rai/core_test/peer_container.cpp rai/core_test/rpc.cpp - rai/core_test/network.cpp rai/core_test/uint256_union.cpp rai/core_test/versioning.cpp rai/core_test/wallet.cpp diff --git a/rai/blocks.cpp b/rai/blocks.cpp new file mode 100644 index 00000000..5e96fe36 --- /dev/null +++ b/rai/blocks.cpp @@ -0,0 +1,1114 @@ +#include + +std::string rai::to_string_hex (uint64_t value_a) +{ + std::stringstream stream; + stream << std::hex << std::noshowbase << std::setw (16) << std::setfill ('0'); + stream << value_a; + return stream.str (); +} + +bool rai::from_string_hex (std::string const & value_a, uint64_t & target_a) +{ + auto result (value_a.empty ()); + if (!result) + { + result = value_a.size () > 16; + if (!result) + { + std::stringstream stream (value_a); + stream << std::hex << std::noshowbase; + uint64_t number_l; + try + { + stream >> number_l; + target_a = number_l; + if (!stream.eof()) + { + result = true; + } + } + catch (std::runtime_error &) + { + result = true; + } + } + } + return result; +} + +std::string rai::block::to_json () +{ + std::string result; + serialize_json (result); + return result; +} + +rai::block_hash rai::block::hash () const +{ + rai::uint256_union result; + blake2b_state hash_l; + auto status (blake2b_init (&hash_l, sizeof (result.bytes))); + assert (status == 0); + hash (hash_l); + status = blake2b_final (&hash_l, result.bytes.data (), sizeof (result.bytes)); + assert (status == 0); + return result; +} + +void rai::send_block::visit (rai::block_visitor & visitor_a) const +{ + visitor_a.send_block (*this); +} + +void rai::send_block::hash (blake2b_state & hash_a) const +{ + hashables.hash (hash_a); +} + +uint64_t rai::send_block::block_work () const +{ + return work; +} + +void rai::send_block::block_work_set (uint64_t work_a) +{ + work = work_a; +} + +rai::send_hashables::send_hashables (rai::block_hash const & previous_a, rai::account const & destination_a, rai::amount const & balance_a) : +previous (previous_a), +destination (destination_a), +balance (balance_a) +{ +} + +rai::send_hashables::send_hashables (bool & error_a, rai::stream & stream_a) +{ + error_a = rai::read (stream_a, previous.bytes); + if (!error_a) + { + error_a = rai::read (stream_a, destination.bytes); + if (!error_a) + { + error_a = rai::read (stream_a, balance.bytes); + } + } +} + +rai::send_hashables::send_hashables (bool & error_a, boost::property_tree::ptree const & tree_a) +{ + try + { + auto previous_l (tree_a.get ("previous")); + auto destination_l (tree_a.get ("destination")); + auto balance_l (tree_a.get ("balance")); + error_a = previous.decode_hex (previous_l); + if (!error_a) + { + error_a = destination.decode_account (destination_l); + if (!error_a) + { + error_a = balance.decode_hex (balance_l); + } + } + } + catch (std::runtime_error const &) + { + error_a = true; + } +} + +void rai::send_hashables::hash (blake2b_state & hash_a) const +{ + auto status (blake2b_update (&hash_a, previous.bytes.data (), sizeof (previous.bytes))); + assert (status == 0); + status = blake2b_update (&hash_a, destination.bytes.data (), sizeof (destination.bytes)); + assert (status == 0); + status = blake2b_update (&hash_a, balance.bytes.data (), sizeof (balance.bytes)); + assert (status == 0); +} + +void rai::send_block::serialize (rai::stream & stream_a) const +{ + write (stream_a, hashables.previous.bytes); + write (stream_a, hashables.destination.bytes); + write (stream_a, hashables.balance.bytes); + write (stream_a, signature.bytes); + write (stream_a, work); +} + +void rai::send_block::serialize_json (std::string & string_a) const +{ + boost::property_tree::ptree tree; + tree.put ("type", "send"); + std::string previous; + hashables.previous.encode_hex (previous); + tree.put ("previous", previous); + tree.put ("destination", hashables.destination.to_account ()); + std::string balance; + hashables.balance.encode_hex (balance); + tree.put ("balance", balance); + std::string signature_l; + signature.encode_hex (signature_l); + tree.put ("work", rai::to_string_hex (work)); + tree.put ("signature", signature_l); + std::stringstream ostream; + boost::property_tree::write_json (ostream, tree); + string_a = ostream.str (); +} + +bool rai::send_block::deserialize (rai::stream & stream_a) +{ + auto result (false); + result = read (stream_a, hashables.previous.bytes); + if (!result) + { + result = read (stream_a, hashables.destination.bytes); + if (!result) + { + result = read (stream_a, hashables.balance.bytes); + if (!result) + { + result = read (stream_a, signature.bytes); + if (!result) + { + result = read (stream_a, work); + } + } + } + } + return result; +} + +bool rai::send_block::deserialize_json (boost::property_tree::ptree const & tree_a) +{ + auto result (false); + try + { + assert (tree_a.get ("type") == "send"); + auto previous_l (tree_a.get ("previous")); + auto destination_l (tree_a.get ("destination")); + auto balance_l (tree_a.get ("balance")); + auto work_l (tree_a.get ("work")); + auto signature_l (tree_a.get ("signature")); + result = hashables.previous.decode_hex (previous_l); + if (!result) + { + result = hashables.destination.decode_account (destination_l); + if (!result) + { + result = hashables.balance.decode_hex (balance_l); + if (!result) + { + result = rai::from_string_hex (work_l, work); + if (!result) + { + result = signature.decode_hex (signature_l); + } + } + } + } + } + catch (std::runtime_error const &) + { + result = true; + } + return result; +} + +rai::send_block::send_block (rai::block_hash const & previous_a, rai::account const & destination_a, rai::amount const & balance_a, rai::raw_key const & prv_a, rai::public_key const & pub_a, uint64_t work_a) : +hashables (previous_a, destination_a, balance_a), +signature (rai::sign_message (prv_a, pub_a, hash ())), +work (work_a) +{ +} + +rai::send_block::send_block (bool & error_a, rai::stream & stream_a) : +hashables (error_a, stream_a) +{ + if (!error_a) + { + error_a = rai::read (stream_a, signature.bytes); + if (!error_a) + { + error_a = rai::read (stream_a, work); + } + } +} + +rai::send_block::send_block (bool & error_a, boost::property_tree::ptree const & tree_a) : +hashables (error_a, tree_a) +{ + if (!error_a) + { + try + { + auto signature_l (tree_a.get ("signature")); + auto work_l (tree_a.get ("work")); + error_a = signature.decode_hex (signature_l); + if (!error_a) + { + error_a = rai::from_string_hex (work_l, work); + } + } + catch (std::runtime_error const &) + { + error_a = true; + } + } +} + +bool rai::send_block::operator == (rai::block const & other_a) const +{ + auto other_l (dynamic_cast (&other_a)); + auto result (other_l != nullptr); + if (result) + { + result = *this == *other_l; + } + return result; +} + +rai::block_type rai::send_block::type () const +{ + return rai::block_type::send; +} + +bool rai::send_block::operator == (rai::send_block const & other_a) const +{ + auto result (hashables.destination == other_a.hashables.destination && hashables.previous == other_a.hashables.previous && hashables.balance == other_a.hashables.balance && work == other_a.work && signature == other_a.signature); + return result; +} + +rai::block_hash rai::send_block::previous () const +{ + return hashables.previous; +} + +rai::block_hash rai::send_block::source () const +{ + return 0; +} + +rai::block_hash rai::send_block::root () const +{ + return hashables.previous; +} + +rai::account rai::send_block::representative () const +{ + return 0; +} + +void rai::send_block::signature_set (rai::uint512_union const & signature_a) +{ + signature = signature_a; +} + +rai::open_hashables::open_hashables (rai::block_hash const & source_a, rai::account const & representative_a, rai::account const & account_a) : +source (source_a), +representative (representative_a), +account (account_a) +{ +} + +rai::open_hashables::open_hashables (bool & error_a, rai::stream & stream_a) +{ + error_a = rai::read (stream_a, source.bytes); + if (!error_a) + { + error_a = rai::read (stream_a, representative.bytes); + if (!error_a) + { + error_a = rai::read (stream_a, account.bytes); + } + } +} + +rai::open_hashables::open_hashables (bool & error_a, boost::property_tree::ptree const & tree_a) +{ + try + { + auto source_l (tree_a.get ("source")); + auto representative_l (tree_a.get ("representative")); + auto account_l (tree_a.get ("account")); + error_a = source.decode_hex (source_l); + if (!error_a) + { + error_a = representative.decode_account (representative_l); + if (!error_a) + { + error_a = account.decode_account (account_l); + } + } + } + catch (std::runtime_error const &) + { + error_a = true; + } +} + +void rai::open_hashables::hash (blake2b_state & hash_a) const +{ + blake2b_update (&hash_a, source.bytes.data (), sizeof (source.bytes)); + blake2b_update (&hash_a, representative.bytes.data (), sizeof (representative.bytes)); + blake2b_update (&hash_a, account.bytes.data (), sizeof (account.bytes)); +} + +rai::open_block::open_block (rai::block_hash const & source_a, rai::account const & representative_a, rai::account const & account_a, rai::raw_key const & prv_a, rai::public_key const & pub_a, uint64_t work_a) : +hashables (source_a, representative_a, account_a), +signature (rai::sign_message (prv_a, pub_a, hash ())), +work (work_a) +{ + assert (!representative_a.is_zero ()); +} + +rai::open_block::open_block (rai::block_hash const & source_a, rai::account const & representative_a, rai::account const & account_a, std::nullptr_t) : +hashables (source_a, representative_a, account_a), +work (0) +{ + signature.clear (); +} + +rai::open_block::open_block (bool & error_a, rai::stream & stream_a) : +hashables (error_a, stream_a) +{ + if (!error_a) + { + error_a = rai::read (stream_a, signature); + if (!error_a) + { + error_a = rai::read (stream_a, work); + } + } +} + +rai::open_block::open_block (bool & error_a, boost::property_tree::ptree const & tree_a) : +hashables (error_a, tree_a) +{ + if (!error_a) + { + try + { + auto work_l (tree_a.get ("work")); + auto signature_l (tree_a.get ("signature")); + error_a = rai::from_string_hex (work_l, work); + if (!error_a) + { + error_a = signature.decode_hex (signature_l); + } + } + catch (std::runtime_error const &) + { + error_a = true; + } + } +} + +void rai::open_block::hash (blake2b_state & hash_a) const +{ + hashables.hash (hash_a); +} + +uint64_t rai::open_block::block_work () const +{ + return work; +} + +void rai::open_block::block_work_set (uint64_t work_a) +{ + work = work_a; +} + +rai::block_hash rai::open_block::previous () const +{ + rai::block_hash result (0); +return result; +} + +void rai::open_block::serialize (rai::stream & stream_a) const +{ + write (stream_a, hashables.source); + write (stream_a, hashables.representative); + write (stream_a, hashables.account); + write (stream_a, signature); + write (stream_a, work); +} + +void rai::open_block::serialize_json (std::string & string_a) const +{ + boost::property_tree::ptree tree; + tree.put ("type", "open"); + tree.put ("source", hashables.source.to_string ()); + tree.put ("representative", representative ().to_account ()); + tree.put ("account", hashables.account.to_account ()); + std::string signature_l; + signature.encode_hex (signature_l); + tree.put ("work", rai::to_string_hex (work)); + tree.put ("signature", signature_l); + std::stringstream ostream; + boost::property_tree::write_json (ostream, tree); + string_a = ostream.str (); +} + +bool rai::open_block::deserialize (rai::stream & stream_a) +{ + auto result (read (stream_a, hashables.source)); + if (!result) + { + result = read (stream_a, hashables.representative); + if (!result) + { + result = read (stream_a, hashables.account); + if (!result) + { + result = read (stream_a, signature); + if (!result) + { + result = read (stream_a, work); + } + } + } + } + return result; +} + +bool rai::open_block::deserialize_json (boost::property_tree::ptree const & tree_a) +{ + auto result (false); + try + { + assert (tree_a.get ("type") == "open"); + auto source_l (tree_a.get ("source")); + auto representative_l (tree_a.get ("representative")); + auto account_l (tree_a.get ("account")); + auto work_l (tree_a.get ("work")); + auto signature_l (tree_a.get ("signature")); + result = hashables.source.decode_hex (source_l); + if (!result) + { + result = hashables.representative.decode_hex (representative_l); + if (!result) + { + result = hashables.account.decode_hex (account_l); + if (!result) + { + result = rai::from_string_hex (work_l, work); + if (!result) + { + result = signature.decode_hex (signature_l); + } + } + } + } + } + catch (std::runtime_error const &) + { + result = true; + } + return result; +} + +void rai::open_block::visit (rai::block_visitor & visitor_a) const +{ + visitor_a.open_block (*this); +} + +rai::block_type rai::open_block::type () const +{ + return rai::block_type::open; +} + +bool rai::open_block::operator == (rai::block const & other_a) const +{ + auto other_l (dynamic_cast (&other_a)); + auto result (other_l != nullptr); + if (result) + { + result = *this == *other_l; + } + return result; +} + +bool rai::open_block::operator == (rai::open_block const & other_a) const +{ + return hashables.source == other_a.hashables.source && hashables.representative == other_a.hashables.representative && hashables.account == other_a.hashables.account && work == other_a.work && signature == other_a.signature; +} + +rai::block_hash rai::open_block::source () const +{ + return hashables.source; +} + +rai::block_hash rai::open_block::root () const +{ + return hashables.account; +} + +rai::account rai::open_block::representative () const +{ + return hashables.representative; +} + +void rai::open_block::signature_set (rai::uint512_union const & signature_a) +{ + signature = signature_a; +} + +rai::change_hashables::change_hashables (rai::block_hash const & previous_a, rai::account const & representative_a) : +previous (previous_a), +representative (representative_a) +{ +} + +rai::change_hashables::change_hashables (bool & error_a, rai::stream & stream_a) +{ + error_a = rai::read (stream_a, previous); + if (!error_a) + { + error_a = rai::read (stream_a, representative); + } +} + +rai::change_hashables::change_hashables (bool & error_a, boost::property_tree::ptree const & tree_a) +{ + try + { + auto previous_l (tree_a.get ("previous")); + auto representative_l (tree_a.get ("representative")); + error_a = previous.decode_hex (previous_l); + if (!error_a) + { + error_a = representative.decode_account (representative_l); + } + } + catch (std::runtime_error const &) + { + error_a = true; + } +} + +void rai::change_hashables::hash (blake2b_state & hash_a) const +{ + blake2b_update (&hash_a, previous.bytes.data (), sizeof (previous.bytes)); + blake2b_update (&hash_a, representative.bytes.data (), sizeof (representative.bytes)); +} + +rai::change_block::change_block (rai::block_hash const & previous_a, rai::account const & representative_a, rai::raw_key const & prv_a, rai::public_key const & pub_a, uint64_t work_a) : +hashables (previous_a, representative_a), +signature (rai::sign_message (prv_a, pub_a, hash ())), +work (work_a) +{ +} + +rai::change_block::change_block (bool & error_a, rai::stream & stream_a) : +hashables (error_a, stream_a) +{ + if (!error_a) + { + error_a = rai::read (stream_a, signature); + if (!error_a) + { + error_a = rai::read (stream_a, work); + } + } +} + +rai::change_block::change_block (bool & error_a, boost::property_tree::ptree const & tree_a) : +hashables (error_a, tree_a) +{ + if (!error_a) + { + try + { + auto work_l (tree_a.get ("work")); + auto signature_l (tree_a.get ("signature")); + error_a = rai::from_string_hex (work_l, work); + if (!error_a) + { + error_a = signature.decode_hex (signature_l); + } + } + catch (std::runtime_error const &) + { + error_a = true; + } + } +} + +void rai::change_block::hash (blake2b_state & hash_a) const +{ + hashables.hash (hash_a); +} + +uint64_t rai::change_block::block_work () const +{ + return work; +} + +void rai::change_block::block_work_set (uint64_t work_a) +{ + work = work_a; +} + +rai::block_hash rai::change_block::previous () const +{ + return hashables.previous; +} + +void rai::change_block::serialize (rai::stream & stream_a) const +{ + write (stream_a, hashables.previous); + write (stream_a, hashables.representative); + write (stream_a, signature); + write (stream_a, work); +} + +void rai::change_block::serialize_json (std::string & string_a) const +{ + boost::property_tree::ptree tree; + tree.put ("type", "change"); + tree.put ("previous", hashables.previous.to_string ()); + tree.put ("representative", representative ().to_account ()); + tree.put ("work", rai::to_string_hex (work)); + std::string signature_l; + signature.encode_hex (signature_l); + tree.put ("signature", signature_l); + std::stringstream ostream; + boost::property_tree::write_json (ostream, tree); + string_a = ostream.str (); +} + +bool rai::change_block::deserialize (rai::stream & stream_a) +{ + auto result (read (stream_a, hashables.previous)); + if (!result) + { + result = read (stream_a, hashables.representative); + if (!result) + { + result = read (stream_a, signature); + if (!result) + { + result = read (stream_a, work); + } + } + } + return result; +} + +bool rai::change_block::deserialize_json (boost::property_tree::ptree const & tree_a) +{ + auto result (false); + try + { + assert (tree_a.get ("type") == "change"); + auto previous_l (tree_a.get ("previous")); + auto representative_l (tree_a.get ("representative")); + auto work_l (tree_a.get ("work")); + auto signature_l (tree_a.get ("signature")); + result = hashables.previous.decode_hex (previous_l); + if (!result) + { + result = hashables.representative.decode_hex (representative_l); + if (!result) + { + result = rai::from_string_hex (work_l, work); + if (!result) + { + result = signature.decode_hex (signature_l); + } + } + } + } + catch (std::runtime_error const &) + { + result = true; + } + return result; +} + +void rai::change_block::visit (rai::block_visitor & visitor_a) const +{ + visitor_a.change_block (*this); +} + +rai::block_type rai::change_block::type () const +{ + return rai::block_type::change; +} + +bool rai::change_block::operator == (rai::block const & other_a) const +{ + auto other_l (dynamic_cast (&other_a)); + auto result (other_l != nullptr); + if (result) + { + result = *this == *other_l; + } + return result; +} + +bool rai::change_block::operator == (rai::change_block const & other_a) const +{ + return hashables.previous == other_a.hashables.previous && hashables.representative == other_a.hashables.representative && work == other_a.work && signature == other_a.signature; +} + +rai::block_hash rai::change_block::source () const +{ + return 0; +} + +rai::block_hash rai::change_block::root () const +{ + return hashables.previous; +} + +rai::account rai::change_block::representative () const +{ + return hashables.representative; +} + +void rai::change_block::signature_set (rai::uint512_union const & signature_a) +{ + signature = signature_a; +} + +std::unique_ptr rai::deserialize_block_json (boost::property_tree::ptree const & tree_a) +{ + std::unique_ptr result; + try + { + auto type (tree_a.get ("type")); + if (type == "receive") + { + bool error; + std::unique_ptr obj (new rai::receive_block (error, tree_a)); + if (!error) + { + result = std::move (obj); + } + } + else if (type == "send") + { + bool error; + std::unique_ptr obj (new rai::send_block (error, tree_a)); + if (!error) + { + result = std::move (obj); + } + } + else if (type == "open") + { + bool error; + std::unique_ptr obj (new rai::open_block (error, tree_a)); + if (!error) + { + result = std::move (obj); + } + } + else if (type == "change") + { + bool error; + std::unique_ptr obj (new rai::change_block (error, tree_a)); + if (!error) + { + result = std::move (obj); + } + } + } + catch (std::runtime_error const &) + { + } + return result; +} + +std::unique_ptr rai::deserialize_block (rai::stream & stream_a) +{ + rai::block_type type; + auto error (read (stream_a, type)); + std::unique_ptr result; + if (!error) + { + result = rai::deserialize_block (stream_a, type); + } + return result; +} + +std::unique_ptr rai::deserialize_block (rai::stream & stream_a, rai::block_type type_a) +{ + std::unique_ptr result; + switch (type_a) + { + case rai::block_type::receive: + { + bool error; + std::unique_ptr obj (new rai::receive_block (error, stream_a)); + if (!error) + { + result = std::move (obj); + } + break; + } + case rai::block_type::send: + { + bool error; + std::unique_ptr obj (new rai::send_block (error, stream_a)); + if (!error) + { + result = std::move (obj); + } + break; + } + case rai::block_type::open: + { + bool error; + std::unique_ptr obj (new rai::open_block (error, stream_a)); + if (!error) + { + result = std::move (obj); + } + break; + } + case rai::block_type::change: + { + bool error; + std::unique_ptr obj (new rai::change_block (error, stream_a)); + if (!error) + { + result = std::move (obj); + } + break; + } + default: + assert (false); + break; + } + return result; +} + +void rai::receive_block::visit (rai::block_visitor & visitor_a) const +{ + visitor_a.receive_block (*this); +} + +bool rai::receive_block::operator == (rai::receive_block const & other_a) const +{ + auto result (hashables.previous == other_a.hashables.previous && hashables.source == other_a.hashables.source && work == other_a.work && signature == other_a.signature); + return result; +} + +bool rai::receive_block::deserialize (rai::stream & stream_a) +{ + auto result (false); + result = read (stream_a, hashables.previous.bytes); + if (!result) + { + result = read (stream_a, hashables.source.bytes); + if (!result) + { + result = read (stream_a, signature.bytes); + if (!result) + { + result = read (stream_a, work); + } + } + } + return result; +} + +bool rai::receive_block::deserialize_json (boost::property_tree::ptree const & tree_a) +{ + auto result (false); + try + { + assert (tree_a.get ("type") == "receive"); + auto previous_l (tree_a.get ("previous")); + auto source_l (tree_a.get ("source")); + auto work_l (tree_a.get ("work")); + auto signature_l (tree_a.get ("signature")); + result = hashables.previous.decode_hex (previous_l); + if (!result) + { + result = hashables.source.decode_hex (source_l); + if (!result) + { + result = rai::from_string_hex (work_l, work); + if (!result) + { + result = signature.decode_hex (signature_l); + } + } + } + } + catch (std::runtime_error const &) + { + result = true; + } + return result; +} + +void rai::receive_block::serialize (rai::stream & stream_a) const +{ + write (stream_a, hashables.previous.bytes); + write (stream_a, hashables.source.bytes); + write (stream_a, signature.bytes); + write (stream_a, work); +} + +void rai::receive_block::serialize_json (std::string & string_a) const +{ + boost::property_tree::ptree tree; + tree.put ("type", "receive"); + std::string previous; + hashables.previous.encode_hex (previous); + tree.put ("previous", previous); + std::string source; + hashables.source.encode_hex (source); + tree.put ("source", source); + std::string signature_l; + signature.encode_hex (signature_l); + tree.put ("work", rai::to_string_hex (work)); + tree.put ("signature", signature_l); + std::stringstream ostream; + boost::property_tree::write_json (ostream, tree); + string_a = ostream.str (); +} + +rai::receive_block::receive_block (rai::block_hash const & previous_a, rai::block_hash const & source_a, rai::raw_key const & prv_a, rai::public_key const & pub_a, uint64_t work_a) : +hashables (previous_a, source_a), +signature (rai::sign_message (prv_a, pub_a, hash())), +work (work_a) +{ +} + +rai::receive_block::receive_block (bool & error_a, rai::stream & stream_a) : +hashables (error_a, stream_a) +{ + if (!error_a) + { + error_a = rai::read (stream_a, signature); + if (!error_a) + { + error_a = rai::read (stream_a, work); + } + } +} + +rai::receive_block::receive_block (bool & error_a, boost::property_tree::ptree const & tree_a) : +hashables (error_a, tree_a) +{ + if (!error_a) + { + try + { + auto signature_l (tree_a.get ("signature")); + auto work_l (tree_a.get ("work")); + error_a = signature.decode_hex (signature_l); + if (!error_a) + { + error_a = rai::from_string_hex (work_l, work); + } + } + catch (std::runtime_error const &) + { + error_a = true; + } + } +} + +void rai::receive_block::hash (blake2b_state & hash_a) const +{ + hashables.hash (hash_a); +} + +uint64_t rai::receive_block::block_work () const +{ + return work; +} + +void rai::receive_block::block_work_set (uint64_t work_a) +{ + work = work_a; +} + +bool rai::receive_block::operator == (rai::block const & other_a) const +{ + auto other_l (dynamic_cast (&other_a)); + auto result (other_l != nullptr); + if (result) + { + result = *this == *other_l; + } + return result; +} + +rai::block_hash rai::receive_block::previous () const +{ + return hashables.previous; +} + +rai::block_hash rai::receive_block::source () const +{ + return hashables.source; +} + +rai::block_hash rai::receive_block::root () const +{ + return hashables.previous; +} + +rai::account rai::receive_block::representative () const +{ + return 0; +} + +void rai::receive_block::signature_set (rai::uint512_union const & signature_a) +{ + signature = signature_a; +} + +rai::block_type rai::receive_block::type () const +{ + return rai::block_type::receive; +} + +rai::receive_hashables::receive_hashables (rai::block_hash const & previous_a, rai::block_hash const & source_a) : +previous (previous_a), +source (source_a) +{ +} + +rai::receive_hashables::receive_hashables (bool & error_a, rai::stream & stream_a) +{ + error_a = rai::read (stream_a, previous.bytes); + if (!error_a) + { + error_a = rai::read (stream_a, source.bytes); + } +} + +rai::receive_hashables::receive_hashables (bool & error_a, boost::property_tree::ptree const & tree_a) +{ + try + { + auto previous_l (tree_a.get ("previous")); + auto source_l (tree_a.get ("source")); + error_a = previous.decode_hex (previous_l); + if (!error_a) + { + error_a = source.decode_hex (source_l); + } + } + catch (std::runtime_error const &) + { + error_a = true; + } +} + +void rai::receive_hashables::hash (blake2b_state & hash_a) const +{ + blake2b_update (&hash_a, previous.bytes.data (), sizeof (previous.bytes)); + blake2b_update (&hash_a, source.bytes.data (), sizeof (source.bytes)); +} diff --git a/rai/blocks.hpp b/rai/blocks.hpp new file mode 100644 index 00000000..f1c34bb9 --- /dev/null +++ b/rai/blocks.hpp @@ -0,0 +1,231 @@ +#pragma once + +#include + +#include +#include +#include +#include + +namespace rai +{ +std::string to_string_hex (uint64_t); +bool from_string_hex (std::string const &, uint64_t &); +// We operate on streams of uint8_t by convention +using stream = std::basic_streambuf ; +// Read a raw byte stream the size of `T' and fill value. +template +bool read (rai::stream & stream_a, T & value) +{ + static_assert (std::is_pod ::value, "Can't stream read non-standard layout types"); + auto amount_read (stream_a.sgetn (reinterpret_cast (&value), sizeof (value))); + return amount_read != sizeof (value); +} +template +void write (rai::stream & stream_a, T const & value) +{ + static_assert (std::is_pod ::value, "Can't stream write non-standard layout types"); + auto amount_written (stream_a.sputn (reinterpret_cast (&value), sizeof (value))); + assert (amount_written == sizeof (value)); +} +class block_visitor; +enum class block_type : uint8_t +{ + invalid, + not_a_block, + send, + receive, + open, + change +}; +class block +{ +public: + // Return a digest of the hashables in this block. + rai::block_hash hash () const; + std::string to_json (); + virtual void hash (blake2b_state &) const = 0; + virtual uint64_t block_work () const = 0; + virtual void block_work_set (uint64_t) = 0; + // Previous block in account's chain, zero for open block + virtual rai::block_hash previous () const = 0; + // Source block for open/receive blocks, zero otherwise. + virtual rai::block_hash source () const = 0; + // Previous block or account number for open blocks + virtual rai::block_hash root () const = 0; + virtual rai::account representative () const = 0; + virtual void serialize (rai::stream &) const = 0; + virtual void serialize_json (std::string &) const = 0; + virtual void visit (rai::block_visitor &) const = 0; + virtual bool operator == (rai::block const &) const = 0; + virtual rai::block_type type () const = 0; + virtual void signature_set (rai::uint512_union const &) = 0; +}; +class send_hashables +{ +public: + send_hashables (rai::account const &, rai::block_hash const &, rai::amount const &); + send_hashables (bool &, rai::stream &); + send_hashables (bool &, boost::property_tree::ptree const &); + void hash (blake2b_state &) const; + rai::block_hash previous; + rai::account destination; + rai::amount balance; +}; +class send_block : public rai::block +{ +public: + send_block (rai::block_hash const &, rai::account const &, rai::amount const &, rai::raw_key const &, rai::public_key const &, uint64_t); + send_block (bool &, rai::stream &); + send_block (bool &, boost::property_tree::ptree const &); + using rai::block::hash; + void hash (blake2b_state &) const override; + uint64_t block_work () const override; + void block_work_set (uint64_t) override; + rai::block_hash previous () const override; + rai::block_hash source () const override; + rai::block_hash root () const override; + rai::account representative () const override; + void serialize (rai::stream &) const override; + void serialize_json (std::string &) const override; + bool deserialize (rai::stream &); + bool deserialize_json (boost::property_tree::ptree const &); + void visit (rai::block_visitor &) const override; + rai::block_type type () const override; + void signature_set (rai::uint512_union const &) override; + bool operator == (rai::block const &) const override; + bool operator == (rai::send_block const &) const; + static size_t constexpr size = sizeof (rai::account) + sizeof (rai::block_hash) + sizeof (rai::amount) + sizeof (rai::signature) + sizeof (uint64_t); + send_hashables hashables; + rai::signature signature; + uint64_t work; +}; +class receive_hashables +{ +public: + receive_hashables (rai::block_hash const &, rai::block_hash const &); + receive_hashables (bool &, rai::stream &); + receive_hashables (bool &, boost::property_tree::ptree const &); + void hash (blake2b_state &) const; + rai::block_hash previous; + rai::block_hash source; +}; +class receive_block : public rai::block +{ +public: + receive_block (rai::block_hash const &, rai::block_hash const &, rai::raw_key const &, rai::public_key const &, uint64_t); + receive_block (bool &, rai::stream &); + receive_block (bool &, boost::property_tree::ptree const &); + using rai::block::hash; + void hash (blake2b_state &) const override; + uint64_t block_work () const override; + void block_work_set (uint64_t) override; + rai::block_hash previous () const override; + rai::block_hash source () const override; + rai::block_hash root () const override; + rai::account representative () const override; + void serialize (rai::stream &) const override; + void serialize_json (std::string &) const override; + bool deserialize (rai::stream &); + bool deserialize_json (boost::property_tree::ptree const &); + void visit (rai::block_visitor &) const override; + rai::block_type type () const override; + void signature_set (rai::uint512_union const &) override; + bool operator == (rai::block const &) const override; + bool operator == (rai::receive_block const &) const; + static size_t constexpr size = sizeof (rai::block_hash) + sizeof (rai::block_hash) + sizeof (rai::signature) + sizeof (uint64_t); + receive_hashables hashables; + rai::signature signature; + uint64_t work; +}; +class open_hashables +{ +public: + open_hashables (rai::block_hash const &, rai::account const &, rai::account const &); + open_hashables (bool &, rai::stream &); + open_hashables (bool &, boost::property_tree::ptree const &); + void hash (blake2b_state &) const; + rai::block_hash source; + rai::account representative; + rai::account account; +}; +class open_block : public rai::block +{ +public: + open_block (rai::block_hash const &, rai::account const &, rai::account const &, rai::raw_key const &, rai::public_key const &, uint64_t); + open_block (rai::block_hash const &, rai::account const &, rai::account const &, std::nullptr_t); + open_block (bool &, rai::stream &); + open_block (bool &, boost::property_tree::ptree const &); + using rai::block::hash; + void hash (blake2b_state &) const override; + uint64_t block_work () const override; + void block_work_set (uint64_t) override; + rai::block_hash previous () const override; + rai::block_hash source () const override; + rai::block_hash root () const override; + rai::account representative () const override; + void serialize (rai::stream &) const override; + void serialize_json (std::string &) const override; + bool deserialize (rai::stream &); + bool deserialize_json (boost::property_tree::ptree const &); + void visit (rai::block_visitor &) const override; + rai::block_type type () const override; + void signature_set (rai::uint512_union const &) override; + bool operator == (rai::block const &) const override; + bool operator == (rai::open_block const &) const; + static size_t constexpr size = sizeof (rai::block_hash) + sizeof (rai::account) + sizeof (rai::account) + sizeof (rai::signature) + sizeof (uint64_t); + rai::open_hashables hashables; + rai::signature signature; + uint64_t work; +}; +class change_hashables +{ +public: + change_hashables (rai::block_hash const &, rai::account const &); + change_hashables (bool &, rai::stream &); + change_hashables (bool &, boost::property_tree::ptree const &); + void hash (blake2b_state &) const; + rai::block_hash previous; + rai::account representative; +}; +class change_block : public rai::block +{ +public: + change_block (rai::block_hash const &, rai::account const &, rai::raw_key const &, rai::public_key const &, uint64_t); + change_block (bool &, rai::stream &); + change_block (bool &, boost::property_tree::ptree const &); + using rai::block::hash; + void hash (blake2b_state &) const override; + uint64_t block_work () const override; + void block_work_set (uint64_t) override; + rai::block_hash previous () const override; + rai::block_hash source () const override; + rai::block_hash root () const override; + rai::account representative () const override; + void serialize (rai::stream &) const override; + void serialize_json (std::string &) const override; + bool deserialize (rai::stream &); + bool deserialize_json (boost::property_tree::ptree const &); + void visit (rai::block_visitor &) const override; + rai::block_type type () const override; + void signature_set (rai::uint512_union const &) override; + bool operator == (rai::block const &) const override; + bool operator == (rai::change_block const &) const; + static size_t constexpr size = sizeof (rai::block_hash) + sizeof (rai::account) + sizeof (rai::signature) + sizeof (uint64_t); + rai::change_hashables hashables; + rai::signature signature; + uint64_t work; +}; +class block_visitor +{ +public: + virtual void send_block (rai::send_block const &) = 0; + virtual void receive_block (rai::receive_block const &) = 0; + virtual void open_block (rai::open_block const &) = 0; + virtual void change_block (rai::change_block const &) = 0; +}; +std::unique_ptr deserialize_block (rai::stream &); +std::unique_ptr deserialize_block (rai::stream &, rai::block_type); +std::unique_ptr deserialize_block_json (boost::property_tree::ptree const &); +void serialize_block (rai::stream &, rai::block const &); +} diff --git a/rai/core_test/interface.cpp b/rai/core_test/interface.cpp new file mode 100644 index 00000000..499da399 --- /dev/null +++ b/rai/core_test/interface.cpp @@ -0,0 +1,100 @@ +#include + +#include + +#include +#include +#include + +TEST (interface, xrb_uint256_to_string) +{ + rai::uint256_union zero (0); + char text [65] = { 0 }; + xrb_uint256_to_string (zero.bytes.data (), text); + ASSERT_STREQ ("0000000000000000000000000000000000000000000000000000000000000000", text); +} + +TEST (interface, xrb_uint256_to_address) +{ + rai::uint256_union zero (0); + char text [65] = { 0 }; + xrb_uint256_to_address (zero.bytes.data (), text); + ASSERT_STREQ ("xrb_1111111111111111111111111111111111111111111111111111hifc8npp", text); +} + +TEST (interface, xrb_uint512_to_string) +{ + rai::uint512_union zero (0); + char text [129] = { 0 }; + xrb_uint512_to_string (zero.bytes.data (), text); + ASSERT_STREQ ("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", text); +} + +TEST (interface, xrb_uint256_from_string) +{ + rai::uint256_union zero (0); + ASSERT_EQ (0, xrb_uint256_from_string ("0000000000000000000000000000000000000000000000000000000000000000", zero.bytes.data ())); + ASSERT_EQ (1, xrb_uint256_from_string ("00000000000000000000000000000000000000000000000000000000000000000", zero.bytes.data ())); + ASSERT_EQ (1, xrb_uint256_from_string ("000000000000000000000000000%000000000000000000000000000000000000", zero.bytes.data ())); +} + +TEST (interface, xrb_uint512_from_string) +{ + rai::uint512_union zero (0); + ASSERT_EQ (0, xrb_uint512_from_string ("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", zero.bytes.data ())); + ASSERT_EQ (1, xrb_uint512_from_string ("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", zero.bytes.data ())); + ASSERT_EQ (1, xrb_uint512_from_string ("0000000000000000000000000000000000000000000000000000000000%000000000000000000000000000000000000000000000000000000000000000000000", zero.bytes.data ())); +} + +TEST (interface, xrb_valid_address) +{ + ASSERT_EQ (0, xrb_valid_address ("xrb_1111111111111111111111111111111111111111111111111111hifc8npp")); + ASSERT_EQ (1, xrb_valid_address ("xrb_1111111111111111111111111111111111111111111111111111hifc8nppp")); + ASSERT_EQ (1, xrb_valid_address ("xrb_1111111211111111111111111111111111111111111111111111hifc8npp")); +} + +TEST (interface, xrb_seed_create) +{ + rai::uint256_union seed; + xrb_generate_random (seed.bytes.data ()); + ASSERT_FALSE (seed.is_zero ()); +} + +TEST (interface, xrb_seed_key) +{ + rai::uint256_union seed (0); + rai::uint256_union prv; + xrb_seed_key (seed.bytes.data (), 0, prv.bytes.data ()); + ASSERT_FALSE (prv.is_zero ()); +} + +TEST (interface, xrb_key_account) +{ + rai::uint256_union prv (0); + rai::uint256_union pub; + xrb_key_account (prv.bytes.data (), pub.bytes.data ()); + ASSERT_FALSE (pub.is_zero ()); +} + +TEST (interface, sign_transaction) +{ + rai::raw_key key; + xrb_generate_random (key.data.bytes.data ()); + rai::uint256_union pub; + xrb_key_account (key.data.bytes.data (), pub.bytes.data ()); + rai::send_block send (0, 0, 0, key, pub, 0); + ASSERT_FALSE (rai::validate_message (pub, send.hash (), send.signature)); + send.signature.bytes [0] ^= 1; + ASSERT_TRUE (rai::validate_message (pub, send.hash (), send.signature)); + auto transaction (xrb_sign_transaction (send.to_json ().c_str (), key.data.bytes.data ())); + boost::property_tree::ptree block_l; + std::string transaction_l (transaction); + std::stringstream block_stream (transaction_l); + boost::property_tree::read_json (block_stream, block_l); + auto block (rai::deserialize_block_json (block_l)); + ASSERT_NE (nullptr, block); + auto send1 (dynamic_cast (block.get ())); + ASSERT_NE (nullptr, send1); + ASSERT_FALSE (rai::validate_message (pub, send.hash (), send1->signature)); + free (transaction); +} diff --git a/rai/interface.cpp b/rai/interface.cpp index 42e07e3e..6979c966 100644 --- a/rai/interface.cpp +++ b/rai/interface.cpp @@ -6,6 +6,9 @@ #include +#include + +#include #include #include @@ -53,7 +56,7 @@ int xrb_valid_address (const char * account_a) return result; } -void xrb_seed_create (xrb_uint256 seed) +void xrb_generate_random (xrb_uint256 seed) { auto & number (*reinterpret_cast (seed)); rai::random_pool.GenerateBlock (number.bytes.data (), number.bytes.size ()); @@ -71,9 +74,26 @@ void xrb_key_account (const xrb_uint256 key, xrb_uint256 pub) ed25519_publickey (key, pub); } -char * sign_transaction (const char * transaction, const xrb_uint256 private_key, xrb_uint512 signature) +char * xrb_sign_transaction (const char * transaction, const xrb_uint256 private_key) { - return nullptr; + char * result (nullptr); + boost::property_tree::ptree block_l; + std::string transaction_l (transaction); + std::stringstream block_stream (transaction_l); + boost::property_tree::read_json (block_stream, block_l); + auto block (rai::deserialize_block_json (block_l)); + if (block != nullptr) + { + rai::uint256_union pub; + ed25519_publickey (private_key, pub.bytes.data ()); + rai::raw_key prv; + prv.data = *reinterpret_cast (private_key); + block->signature_set (rai::sign_message (prv, pub, block->hash ())); + auto json (block->to_json ()); + result = reinterpret_cast (malloc (json.size () + 1)); + strncpy (result, json.c_str (), json.size () + 1); + } + return result; } #include diff --git a/rai/interface.h b/rai/interface.h index 3c04cc8f..e7aa03ef 100644 --- a/rai/interface.h +++ b/rai/interface.h @@ -27,15 +27,15 @@ int xrb_uint512_from_string (const char * source, xrb_uint512 destination); // Return 0 on correct, nonzero on invalid int xrb_valid_address (const char * account); -// Create a new random seed in 'seed' -void xrb_seed_create (xrb_uint256 seed); +// Create a new random number in to 'destination' +void xrb_generate_random (xrb_uint256 destination); // Retrieve the detereministic private key for 'seed' at 'index' void xrb_seed_key (const xrb_uint256 seed, int index, xrb_uint256); // Derive the public key 'pub' from 'key' void xrb_key_account (xrb_uint256 key, xrb_uint256 pub); // Sign 'transaction' using 'private_key' and write to 'signature' -char * sign_transaction (const char * transaction, const xrb_uint256 private_key, xrb_uint512 signature); +char * xrb_sign_transaction (const char * transaction, const xrb_uint256 private_key); #if __cplusplus } // extern "C" diff --git a/rai/numbers.cpp b/rai/numbers.cpp index b1984e67..ea611323 100644 --- a/rai/numbers.cpp +++ b/rai/numbers.cpp @@ -462,3 +462,144 @@ bool rai::validate_message (rai::public_key const & public_key, rai::uint256_uni return result; } +rai::uint128_union::uint128_union (std::string const & string_a) +{ + decode_hex (string_a); +} + +rai::uint128_union::uint128_union (uint64_t value_a) +{ + *this = rai::uint128_t (value_a); +} + +rai::uint128_union::uint128_union (rai::uint128_t const & value_a) +{ + rai::uint128_t number_l (value_a); + for (auto i (bytes.rbegin ()), n (bytes.rend ()); i != n; ++i) + { + *i = ((number_l) & 0xff).convert_to (); + number_l >>= 8; + } +} + +bool rai::uint128_union::operator == (rai::uint128_union const & other_a) const +{ + return qwords [0] == other_a.qwords [0] && qwords [1] == other_a.qwords [1]; +} + +bool rai::uint128_union::operator != (rai::uint128_union const & other_a) const +{ + return !(*this == other_a); +} + +bool rai::uint128_union::operator < (rai::uint128_union const & other_a) const +{ + return number () < other_a.number (); +} + +bool rai::uint128_union::operator > (rai::uint128_union const & other_a) const +{ + return number () > other_a.number (); +} + +rai::uint128_t rai::uint128_union::number () const +{ + rai::uint128_t result; + auto shift (0); + for (auto i (bytes.begin ()), n (bytes.end ()); i != n; ++i) + { + result <<= shift; + result |= *i; + shift = 8; + } + return result; +} + +void rai::uint128_union::encode_hex (std::string & text) const +{ + assert (text.empty ()); + std::stringstream stream; + stream << std::hex << std::noshowbase << std::setw (32) << std::setfill ('0'); + stream << number (); + text = stream.str (); +} + +bool rai::uint128_union::decode_hex (std::string const & text) +{ + auto result (text.size () > 32); + if (!result) + { + std::stringstream stream (text); + stream << std::hex << std::noshowbase; + rai::uint128_t number_l; + try + { + stream >> number_l; + *this = number_l; + if (!stream.eof ()) + { + result = true; + } + } + catch (std::runtime_error &) + { + result = true; + } + } + return result; +} + +void rai::uint128_union::encode_dec (std::string & text) const +{ + assert (text.empty ()); + std::stringstream stream; + stream << std::dec << std::noshowbase; + stream << number (); + text = stream.str (); +} + +bool rai::uint128_union::decode_dec (std::string const & text) +{ + auto result (text.size () > 39); + if (!result) + { + std::stringstream stream (text); + stream << std::dec << std::noshowbase; + rai::uint128_t number_l; + try + { + stream >> number_l; + *this = number_l; + } + catch (std::runtime_error &) + { + result = true; + } + } + return result; +} + +void rai::uint128_union::clear () +{ + qwords.fill (0); +} + +bool rai::uint128_union::is_zero () const +{ + return qwords [0] == 0 && qwords [1] == 0; +} + +std::string rai::uint128_union::to_string () const +{ + std::string result; + encode_hex (result); + return result; +} + +std::string rai::uint128_union::to_string_dec () const +{ + std::string result; + encode_dec (result); + return result; +} + diff --git a/rai/secure.cpp b/rai/secure.cpp index 0159383c..9dd44a8b 100755 --- a/rai/secure.cpp +++ b/rai/secure.cpp @@ -224,406 +224,6 @@ inactive_supply (inactive_supply_a) { } -void rai::send_block::visit (rai::block_visitor & visitor_a) const -{ - visitor_a.send_block (*this); -} - -void rai::send_block::hash (blake2b_state & hash_a) const -{ - hashables.hash (hash_a); -} - -uint64_t rai::send_block::block_work () const -{ - return work; -} - -void rai::send_block::block_work_set (uint64_t work_a) -{ - work = work_a; -} - -rai::send_hashables::send_hashables (rai::block_hash const & previous_a, rai::account const & destination_a, rai::amount const & balance_a) : -previous (previous_a), -destination (destination_a), -balance (balance_a) -{ -} - -rai::send_hashables::send_hashables (bool & error_a, rai::stream & stream_a) -{ - error_a = rai::read (stream_a, previous.bytes); - if (!error_a) - { - error_a = rai::read (stream_a, destination.bytes); - if (!error_a) - { - error_a = rai::read (stream_a, balance.bytes); - } - } -} - -rai::send_hashables::send_hashables (bool & error_a, boost::property_tree::ptree const & tree_a) -{ - try - { - auto previous_l (tree_a.get ("previous")); - auto destination_l (tree_a.get ("destination")); - auto balance_l (tree_a.get ("balance")); - error_a = previous.decode_hex (previous_l); - if (!error_a) - { - error_a = destination.decode_account (destination_l); - if (!error_a) - { - error_a = balance.decode_hex (balance_l); - } - } - } - catch (std::runtime_error const &) - { - error_a = true; - } -} - -void rai::send_hashables::hash (blake2b_state & hash_a) const -{ - auto status (blake2b_update (&hash_a, previous.bytes.data (), sizeof (previous.bytes))); - assert (status == 0); - status = blake2b_update (&hash_a, destination.bytes.data (), sizeof (destination.bytes)); - assert (status == 0); - status = blake2b_update (&hash_a, balance.bytes.data (), sizeof (balance.bytes)); - assert (status == 0); -} - -void rai::send_block::serialize (rai::stream & stream_a) const -{ - write (stream_a, hashables.previous.bytes); - write (stream_a, hashables.destination.bytes); - write (stream_a, hashables.balance.bytes); - write (stream_a, signature.bytes); - write (stream_a, work); -} - -void rai::send_block::serialize_json (std::string & string_a) const -{ - boost::property_tree::ptree tree; - tree.put ("type", "send"); - std::string previous; - hashables.previous.encode_hex (previous); - tree.put ("previous", previous); - tree.put ("destination", hashables.destination.to_account ()); - std::string balance; - hashables.balance.encode_hex (balance); - tree.put ("balance", balance); - std::string signature_l; - signature.encode_hex (signature_l); - tree.put ("work", rai::to_string_hex (work)); - tree.put ("signature", signature_l); - std::stringstream ostream; - boost::property_tree::write_json (ostream, tree); - string_a = ostream.str (); -} - -bool rai::send_block::deserialize (rai::stream & stream_a) -{ - auto result (false); - result = read (stream_a, hashables.previous.bytes); - if (!result) - { - result = read (stream_a, hashables.destination.bytes); - if (!result) - { - result = read (stream_a, hashables.balance.bytes); - if (!result) - { - result = read (stream_a, signature.bytes); - if (!result) - { - result = read (stream_a, work); - } - } - } - } - return result; -} - -bool rai::send_block::deserialize_json (boost::property_tree::ptree const & tree_a) -{ - auto result (false); - try - { - assert (tree_a.get ("type") == "send"); - auto previous_l (tree_a.get ("previous")); - auto destination_l (tree_a.get ("destination")); - auto balance_l (tree_a.get ("balance")); - auto work_l (tree_a.get ("work")); - auto signature_l (tree_a.get ("signature")); - result = hashables.previous.decode_hex (previous_l); - if (!result) - { - result = hashables.destination.decode_account (destination_l); - if (!result) - { - result = hashables.balance.decode_hex (balance_l); - if (!result) - { - result = rai::from_string_hex (work_l, work); - if (!result) - { - result = signature.decode_hex (signature_l); - } - } - } - } - } - catch (std::runtime_error const &) - { - result = true; - } - return result; -} - -void rai::receive_block::visit (rai::block_visitor & visitor_a) const -{ - visitor_a.receive_block (*this); -} - -bool rai::receive_block::operator == (rai::receive_block const & other_a) const -{ - auto result (hashables.previous == other_a.hashables.previous && hashables.source == other_a.hashables.source && work == other_a.work && signature == other_a.signature); - return result; -} - -bool rai::receive_block::deserialize (rai::stream & stream_a) -{ - auto result (false); - result = read (stream_a, hashables.previous.bytes); - if (!result) - { - result = read (stream_a, hashables.source.bytes); - if (!result) - { - result = read (stream_a, signature.bytes); - if (!result) - { - result = read (stream_a, work); - } - } - } - return result; -} - -bool rai::receive_block::deserialize_json (boost::property_tree::ptree const & tree_a) -{ - auto result (false); - try - { - assert (tree_a.get ("type") == "receive"); - auto previous_l (tree_a.get ("previous")); - auto source_l (tree_a.get ("source")); - auto work_l (tree_a.get ("work")); - auto signature_l (tree_a.get ("signature")); - result = hashables.previous.decode_hex (previous_l); - if (!result) - { - result = hashables.source.decode_hex (source_l); - if (!result) - { - result = rai::from_string_hex (work_l, work); - if (!result) - { - result = signature.decode_hex (signature_l); - } - } - } - } - catch (std::runtime_error const &) - { - result = true; - } - return result; -} - -void rai::receive_block::serialize (rai::stream & stream_a) const -{ - write (stream_a, hashables.previous.bytes); - write (stream_a, hashables.source.bytes); - write (stream_a, signature.bytes); - write (stream_a, work); -} - -void rai::receive_block::serialize_json (std::string & string_a) const -{ - boost::property_tree::ptree tree; - tree.put ("type", "receive"); - std::string previous; - hashables.previous.encode_hex (previous); - tree.put ("previous", previous); - std::string source; - hashables.source.encode_hex (source); - tree.put ("source", source); - std::string signature_l; - signature.encode_hex (signature_l); - tree.put ("work", rai::to_string_hex (work)); - tree.put ("signature", signature_l); - std::stringstream ostream; - boost::property_tree::write_json (ostream, tree); - string_a = ostream.str (); -} - -rai::receive_block::receive_block (rai::block_hash const & previous_a, rai::block_hash const & source_a, rai::raw_key const & prv_a, rai::public_key const & pub_a, uint64_t work_a) : -hashables (previous_a, source_a), -signature (rai::sign_message (prv_a, pub_a, hash())), -work (work_a) -{ -} - -rai::receive_block::receive_block (bool & error_a, rai::stream & stream_a) : -hashables (error_a, stream_a) -{ - if (!error_a) - { - error_a = rai::read (stream_a, signature); - if (!error_a) - { - error_a = rai::read (stream_a, work); - } - } -} - -rai::receive_block::receive_block (bool & error_a, boost::property_tree::ptree const & tree_a) : -hashables (error_a, tree_a) -{ - if (!error_a) - { - try - { - auto signature_l (tree_a.get ("signature")); - auto work_l (tree_a.get ("work")); - error_a = signature.decode_hex (signature_l); - if (!error_a) - { - error_a = rai::from_string_hex (work_l, work); - } - } - catch (std::runtime_error const &) - { - error_a = true; - } - } -} - -void rai::receive_block::hash (blake2b_state & hash_a) const -{ - hashables.hash (hash_a); -} - -uint64_t rai::receive_block::block_work () const -{ - return work; -} - -void rai::receive_block::block_work_set (uint64_t work_a) -{ - work = work_a; -} - -bool rai::receive_block::operator == (rai::block const & other_a) const -{ - auto other_l (dynamic_cast (&other_a)); - auto result (other_l != nullptr); - if (result) - { - result = *this == *other_l; - } - return result; -} - -rai::block_hash rai::receive_block::previous () const -{ - return hashables.previous; -} - -rai::block_hash rai::receive_block::source () const -{ - return hashables.source; -} - -rai::block_hash rai::receive_block::root () const -{ - return hashables.previous; -} - -rai::account rai::receive_block::representative () const -{ - return 0; -} - -rai::block_type rai::receive_block::type () const -{ - return rai::block_type::receive; -} - -rai::receive_hashables::receive_hashables (rai::block_hash const & previous_a, rai::block_hash const & source_a) : -previous (previous_a), -source (source_a) -{ -} - -rai::receive_hashables::receive_hashables (bool & error_a, rai::stream & stream_a) -{ - error_a = rai::read (stream_a, previous.bytes); - if (!error_a) - { - error_a = rai::read (stream_a, source.bytes); - } -} - -rai::receive_hashables::receive_hashables (bool & error_a, boost::property_tree::ptree const & tree_a) -{ - try - { - auto previous_l (tree_a.get ("previous")); - auto source_l (tree_a.get ("source")); - error_a = previous.decode_hex (previous_l); - if (!error_a) - { - error_a = source.decode_hex (source_l); - } - } - catch (std::runtime_error const &) - { - error_a = true; - } -} - -void rai::receive_hashables::hash (blake2b_state & hash_a) const -{ - blake2b_update (&hash_a, previous.bytes.data (), sizeof (previous.bytes)); - blake2b_update (&hash_a, source.bytes.data (), sizeof (source.bytes)); -} - -rai::block_hash rai::block::hash () const -{ - rai::uint256_union result; - blake2b_state hash_l; - auto status (blake2b_init (&hash_l, sizeof (result.bytes))); - assert (status == 0); - hash (hash_l); - status = blake2b_final (&hash_l, result.bytes.data (), sizeof (result.bytes)); - assert (status == 0); - return result; -} - -std::string rai::block::to_json () -{ - std::string result; - serialize_json (result); - return result; -} - // Serialize a block prefixed with an 8-bit typecode void rai::serialize_block (rai::stream & stream_a, rai::block const & block_a) { @@ -631,668 +231,12 @@ void rai::serialize_block (rai::stream & stream_a, rai::block const & block_a) block_a.serialize (stream_a); } -std::unique_ptr rai::deserialize_block (rai::stream & stream_a, rai::block_type type_a) -{ - std::unique_ptr result; - switch (type_a) - { - case rai::block_type::receive: - { - bool error; - std::unique_ptr obj (new rai::receive_block (error, stream_a)); - if (!error) - { - result = std::move (obj); - } - break; - } - case rai::block_type::send: - { - bool error; - std::unique_ptr obj (new rai::send_block (error, stream_a)); - if (!error) - { - result = std::move (obj); - } - break; - } - case rai::block_type::open: - { - bool error; - std::unique_ptr obj (new rai::open_block (error, stream_a)); - if (!error) - { - result = std::move (obj); - } - break; - } - case rai::block_type::change: - { - bool error; - std::unique_ptr obj (new rai::change_block (error, stream_a)); - if (!error) - { - result = std::move (obj); - } - break; - } - default: - assert (false); - break; - } - return result; -} - -std::unique_ptr rai::deserialize_block_json (boost::property_tree::ptree const & tree_a) -{ - std::unique_ptr result; - try - { - auto type (tree_a.get ("type")); - if (type == "receive") - { - bool error; - std::unique_ptr obj (new rai::receive_block (error, tree_a)); - if (!error) - { - result = std::move (obj); - } - } - else if (type == "send") - { - bool error; - std::unique_ptr obj (new rai::send_block (error, tree_a)); - if (!error) - { - result = std::move (obj); - } - } - else if (type == "open") - { - bool error; - std::unique_ptr obj (new rai::open_block (error, tree_a)); - if (!error) - { - result = std::move (obj); - } - } - else if (type == "change") - { - bool error; - std::unique_ptr obj (new rai::change_block (error, tree_a)); - if (!error) - { - result = std::move (obj); - } - } - } - catch (std::runtime_error const &) - { - } - return result; -} - std::unique_ptr rai::deserialize_block (MDB_val const & val_a) { rai::bufferstream stream (reinterpret_cast (val_a.mv_data), val_a.mv_size); return deserialize_block (stream); } -std::unique_ptr rai::deserialize_block (rai::stream & stream_a) -{ - rai::block_type type; - auto error (read (stream_a, type)); - std::unique_ptr result; - if (!error) - { - result = rai::deserialize_block (stream_a, type); - } - return result; -} - -rai::send_block::send_block (rai::block_hash const & previous_a, rai::account const & destination_a, rai::amount const & balance_a, rai::raw_key const & prv_a, rai::public_key const & pub_a, uint64_t work_a) : -hashables (previous_a, destination_a, balance_a), -signature (rai::sign_message (prv_a, pub_a, hash ())), -work (work_a) -{ -} - -rai::send_block::send_block (bool & error_a, rai::stream & stream_a) : -hashables (error_a, stream_a) -{ - if (!error_a) - { - error_a = rai::read (stream_a, signature.bytes); - if (!error_a) - { - error_a = rai::read (stream_a, work); - } - } -} - -rai::send_block::send_block (bool & error_a, boost::property_tree::ptree const & tree_a) : -hashables (error_a, tree_a) -{ - if (!error_a) - { - try - { - auto signature_l (tree_a.get ("signature")); - auto work_l (tree_a.get ("work")); - error_a = signature.decode_hex (signature_l); - if (!error_a) - { - error_a = rai::from_string_hex (work_l, work); - } - } - catch (std::runtime_error const &) - { - error_a = true; - } - } -} - -bool rai::send_block::operator == (rai::block const & other_a) const -{ - auto other_l (dynamic_cast (&other_a)); - auto result (other_l != nullptr); - if (result) - { - result = *this == *other_l; - } - return result; -} - -rai::block_type rai::send_block::type () const -{ - return rai::block_type::send; -} - -bool rai::send_block::operator == (rai::send_block const & other_a) const -{ - auto result (hashables.destination == other_a.hashables.destination && hashables.previous == other_a.hashables.previous && hashables.balance == other_a.hashables.balance && work == other_a.work && signature == other_a.signature); - return result; -} - -rai::block_hash rai::send_block::previous () const -{ - return hashables.previous; -} - -rai::block_hash rai::send_block::source () const -{ - return 0; -} - -rai::block_hash rai::send_block::root () const -{ - return hashables.previous; -} - -rai::account rai::send_block::representative () const -{ - return 0; -} - -rai::open_hashables::open_hashables (rai::block_hash const & source_a, rai::account const & representative_a, rai::account const & account_a) : -source (source_a), -representative (representative_a), -account (account_a) -{ -} - -rai::open_hashables::open_hashables (bool & error_a, rai::stream & stream_a) -{ - error_a = rai::read (stream_a, source.bytes); - if (!error_a) - { - error_a = rai::read (stream_a, representative.bytes); - if (!error_a) - { - error_a = rai::read (stream_a, account.bytes); - } - } -} - -rai::open_hashables::open_hashables (bool & error_a, boost::property_tree::ptree const & tree_a) -{ - try - { - auto source_l (tree_a.get ("source")); - auto representative_l (tree_a.get ("representative")); - auto account_l (tree_a.get ("account")); - error_a = source.decode_hex (source_l); - if (!error_a) - { - error_a = representative.decode_account (representative_l); - if (!error_a) - { - error_a = account.decode_account (account_l); - } - } - } - catch (std::runtime_error const &) - { - error_a = true; - } -} - -void rai::open_hashables::hash (blake2b_state & hash_a) const -{ - blake2b_update (&hash_a, source.bytes.data (), sizeof (source.bytes)); - blake2b_update (&hash_a, representative.bytes.data (), sizeof (representative.bytes)); - blake2b_update (&hash_a, account.bytes.data (), sizeof (account.bytes)); -} - -rai::open_block::open_block (rai::block_hash const & source_a, rai::account const & representative_a, rai::account const & account_a, rai::raw_key const & prv_a, rai::public_key const & pub_a, uint64_t work_a) : -hashables (source_a, representative_a, account_a), -signature (rai::sign_message (prv_a, pub_a, hash ())), -work (work_a) -{ - assert (!representative_a.is_zero ()); -} - -rai::open_block::open_block (rai::block_hash const & source_a, rai::account const & representative_a, rai::account const & account_a, std::nullptr_t) : -hashables (source_a, representative_a, account_a), -work (0) -{ - signature.clear (); -} - -rai::open_block::open_block (bool & error_a, rai::stream & stream_a) : -hashables (error_a, stream_a) -{ - if (!error_a) - { - error_a = rai::read (stream_a, signature); - if (!error_a) - { - error_a = rai::read (stream_a, work); - } - } -} - -rai::open_block::open_block (bool & error_a, boost::property_tree::ptree const & tree_a) : -hashables (error_a, tree_a) -{ - if (!error_a) - { - try - { - auto work_l (tree_a.get ("work")); - auto signature_l (tree_a.get ("signature")); - error_a = rai::from_string_hex (work_l, work); - if (!error_a) - { - error_a = signature.decode_hex (signature_l); - } - } - catch (std::runtime_error const &) - { - error_a = true; - } - } -} - -void rai::open_block::hash (blake2b_state & hash_a) const -{ - hashables.hash (hash_a); -} - -uint64_t rai::open_block::block_work () const -{ - return work; -} - -void rai::open_block::block_work_set (uint64_t work_a) -{ - work = work_a; -} - -rai::block_hash rai::open_block::previous () const -{ - rai::block_hash result (0); - return result; -} - -void rai::open_block::serialize (rai::stream & stream_a) const -{ - write (stream_a, hashables.source); - write (stream_a, hashables.representative); - write (stream_a, hashables.account); - write (stream_a, signature); - write (stream_a, work); -} - -void rai::open_block::serialize_json (std::string & string_a) const -{ - boost::property_tree::ptree tree; - tree.put ("type", "open"); - tree.put ("source", hashables.source.to_string ()); - tree.put ("representative", representative ().to_account ()); - tree.put ("account", hashables.account.to_account ()); - std::string signature_l; - signature.encode_hex (signature_l); - tree.put ("work", rai::to_string_hex (work)); - tree.put ("signature", signature_l); - std::stringstream ostream; - boost::property_tree::write_json (ostream, tree); - string_a = ostream.str (); -} - -bool rai::open_block::deserialize (rai::stream & stream_a) -{ - auto result (read (stream_a, hashables.source)); - if (!result) - { - result = read (stream_a, hashables.representative); - if (!result) - { - result = read (stream_a, hashables.account); - if (!result) - { - result = read (stream_a, signature); - if (!result) - { - result = read (stream_a, work); - } - } - } - } - return result; -} - -bool rai::open_block::deserialize_json (boost::property_tree::ptree const & tree_a) -{ - auto result (false); - try - { - assert (tree_a.get ("type") == "open"); - auto source_l (tree_a.get ("source")); - auto representative_l (tree_a.get ("representative")); - auto account_l (tree_a.get ("account")); - auto work_l (tree_a.get ("work")); - auto signature_l (tree_a.get ("signature")); - result = hashables.source.decode_hex (source_l); - if (!result) - { - result = hashables.representative.decode_hex (representative_l); - if (!result) - { - result = hashables.account.decode_hex (account_l); - if (!result) - { - result = rai::from_string_hex (work_l, work); - if (!result) - { - result = signature.decode_hex (signature_l); - } - } - } - } - } - catch (std::runtime_error const &) - { - result = true; - } - return result; -} - -void rai::open_block::visit (rai::block_visitor & visitor_a) const -{ - visitor_a.open_block (*this); -} - -rai::block_type rai::open_block::type () const -{ - return rai::block_type::open; -} - -bool rai::open_block::operator == (rai::block const & other_a) const -{ - auto other_l (dynamic_cast (&other_a)); - auto result (other_l != nullptr); - if (result) - { - result = *this == *other_l; - } - return result; -} - -bool rai::open_block::operator == (rai::open_block const & other_a) const -{ - return hashables.source == other_a.hashables.source && hashables.representative == other_a.hashables.representative && hashables.account == other_a.hashables.account && work == other_a.work && signature == other_a.signature; -} - -rai::block_hash rai::open_block::source () const -{ - return hashables.source; -} - -rai::block_hash rai::open_block::root () const -{ - return hashables.account; -} - -rai::account rai::open_block::representative () const -{ - return hashables.representative; -} - -rai::change_hashables::change_hashables (rai::block_hash const & previous_a, rai::account const & representative_a) : -previous (previous_a), -representative (representative_a) -{ -} - -rai::change_hashables::change_hashables (bool & error_a, rai::stream & stream_a) -{ - error_a = rai::read (stream_a, previous); - if (!error_a) - { - error_a = rai::read (stream_a, representative); - } -} - -rai::change_hashables::change_hashables (bool & error_a, boost::property_tree::ptree const & tree_a) -{ - try - { - auto previous_l (tree_a.get ("previous")); - auto representative_l (tree_a.get ("representative")); - error_a = previous.decode_hex (previous_l); - if (!error_a) - { - error_a = representative.decode_account (representative_l); - } - } - catch (std::runtime_error const &) - { - error_a = true; - } -} - -void rai::change_hashables::hash (blake2b_state & hash_a) const -{ - blake2b_update (&hash_a, previous.bytes.data (), sizeof (previous.bytes)); - blake2b_update (&hash_a, representative.bytes.data (), sizeof (representative.bytes)); -} - -rai::change_block::change_block (rai::block_hash const & previous_a, rai::account const & representative_a, rai::raw_key const & prv_a, rai::public_key const & pub_a, uint64_t work_a) : -hashables (previous_a, representative_a), -signature (rai::sign_message (prv_a, pub_a, hash ())), -work (work_a) -{ -} - -rai::change_block::change_block (bool & error_a, rai::stream & stream_a) : -hashables (error_a, stream_a) -{ - if (!error_a) - { - error_a = rai::read (stream_a, signature); - if (!error_a) - { - error_a = rai::read (stream_a, work); - } - } -} - -rai::change_block::change_block (bool & error_a, boost::property_tree::ptree const & tree_a) : -hashables (error_a, tree_a) -{ - if (!error_a) - { - try - { - auto work_l (tree_a.get ("work")); - auto signature_l (tree_a.get ("signature")); - error_a = rai::from_string_hex (work_l, work); - if (!error_a) - { - error_a = signature.decode_hex (signature_l); - } - } - catch (std::runtime_error const &) - { - error_a = true; - } - } -} - -void rai::change_block::hash (blake2b_state & hash_a) const -{ - hashables.hash (hash_a); -} - -uint64_t rai::change_block::block_work () const -{ - return work; -} - -void rai::change_block::block_work_set (uint64_t work_a) -{ - work = work_a; -} - -rai::block_hash rai::change_block::previous () const -{ - return hashables.previous; -} - -void rai::change_block::serialize (rai::stream & stream_a) const -{ - write (stream_a, hashables.previous); - write (stream_a, hashables.representative); - write (stream_a, signature); - write (stream_a, work); -} - -void rai::change_block::serialize_json (std::string & string_a) const -{ - boost::property_tree::ptree tree; - tree.put ("type", "change"); - tree.put ("previous", hashables.previous.to_string ()); - tree.put ("representative", representative ().to_account ()); - tree.put ("work", rai::to_string_hex (work)); - std::string signature_l; - signature.encode_hex (signature_l); - tree.put ("signature", signature_l); - std::stringstream ostream; - boost::property_tree::write_json (ostream, tree); - string_a = ostream.str (); -} - -bool rai::change_block::deserialize (rai::stream & stream_a) -{ - auto result (read (stream_a, hashables.previous)); - if (!result) - { - result = read (stream_a, hashables.representative); - if (!result) - { - result = read (stream_a, signature); - if (!result) - { - result = read (stream_a, work); - } - } - } - return result; -} - -bool rai::change_block::deserialize_json (boost::property_tree::ptree const & tree_a) -{ - auto result (false); - try - { - assert (tree_a.get ("type") == "change"); - auto previous_l (tree_a.get ("previous")); - auto representative_l (tree_a.get ("representative")); - auto work_l (tree_a.get ("work")); - auto signature_l (tree_a.get ("signature")); - result = hashables.previous.decode_hex (previous_l); - if (!result) - { - result = hashables.representative.decode_hex (representative_l); - if (!result) - { - result = rai::from_string_hex (work_l, work); - if (!result) - { - result = signature.decode_hex (signature_l); - } - } - } - } - catch (std::runtime_error const &) - { - result = true; - } - return result; -} - -void rai::change_block::visit (rai::block_visitor & visitor_a) const -{ - visitor_a.change_block (*this); -} - -rai::block_type rai::change_block::type () const -{ - return rai::block_type::change; -} - -bool rai::change_block::operator == (rai::block const & other_a) const -{ - auto other_l (dynamic_cast (&other_a)); - auto result (other_l != nullptr); - if (result) - { - result = *this == *other_l; - } - return result; -} - -bool rai::change_block::operator == (rai::change_block const & other_a) const -{ - return hashables.previous == other_a.hashables.previous && hashables.representative == other_a.hashables.representative && work == other_a.work && signature == other_a.signature; -} - -rai::block_hash rai::change_block::source () const -{ - return 0; -} - -rai::block_hash rai::change_block::root () const -{ - return hashables.previous; -} - -rai::account rai::change_block::representative () const -{ - return hashables.representative; -} - rai::account_info::account_info () : head (0), rep_block (0), diff --git a/rai/secure.hpp b/rai/secure.hpp index b3e91ff4..724fe1e0 100644 --- a/rai/secure.hpp +++ b/rai/secure.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -30,38 +31,6 @@ public: rai::public_key pub; rai::raw_key prv; }; -class block_visitor; -enum class block_type : uint8_t -{ - invalid, - not_a_block, - send, - receive, - open, - change -}; -class block -{ -public: - // Return a digest of the hashables in this block. - rai::block_hash hash () const; - std::string to_json (); - virtual void hash (blake2b_state &) const = 0; - virtual uint64_t block_work () const = 0; - virtual void block_work_set (uint64_t) = 0; - // Previous block in account's chain, zero for open block - virtual rai::block_hash previous () const = 0; - // Source block for open/receive blocks, zero otherwise. - virtual rai::block_hash source () const = 0; - // Previous block or account number for open blocks - virtual rai::block_hash root () const = 0; - virtual rai::account representative () const = 0; - virtual void serialize (rai::stream &) const = 0; - virtual void serialize_json (std::string &) const = 0; - virtual void visit (rai::block_visitor &) const = 0; - virtual bool operator == (rai::block const &) const = 0; - virtual rai::block_type type () const = 0; -}; class shared_ptr_block_hash { public: @@ -69,169 +38,6 @@ public: bool operator () (std::shared_ptr const &, std::shared_ptr const &) const; }; std::unique_ptr deserialize_block (MDB_val const &); -std::unique_ptr deserialize_block (rai::stream &); -std::unique_ptr deserialize_block (rai::stream &, rai::block_type); -std::unique_ptr deserialize_block_json (boost::property_tree::ptree const &); -void serialize_block (rai::stream &, rai::block const &); -class send_hashables -{ -public: - send_hashables (rai::account const &, rai::block_hash const &, rai::amount const &); - send_hashables (bool &, rai::stream &); - send_hashables (bool &, boost::property_tree::ptree const &); - void hash (blake2b_state &) const; - rai::block_hash previous; - rai::account destination; - rai::amount balance; -}; -class send_block : public rai::block -{ -public: - send_block (rai::block_hash const &, rai::account const &, rai::amount const &, rai::raw_key const &, rai::public_key const &, uint64_t); - send_block (bool &, rai::stream &); - send_block (bool &, boost::property_tree::ptree const &); - using rai::block::hash; - void hash (blake2b_state &) const override; - uint64_t block_work () const override; - void block_work_set (uint64_t) override; - rai::block_hash previous () const override; - rai::block_hash source () const override; - rai::block_hash root () const override; - rai::account representative () const override; - void serialize (rai::stream &) const override; - void serialize_json (std::string &) const override; - bool deserialize (rai::stream &); - bool deserialize_json (boost::property_tree::ptree const &); - void visit (rai::block_visitor &) const override; - rai::block_type type () const override; - bool operator == (rai::block const &) const override; - bool operator == (rai::send_block const &) const; - static size_t constexpr size = sizeof (rai::account) + sizeof (rai::block_hash) + sizeof (rai::amount) + sizeof (rai::signature) + sizeof (uint64_t); - send_hashables hashables; - rai::signature signature; - uint64_t work; -}; -class receive_hashables -{ -public: - receive_hashables (rai::block_hash const &, rai::block_hash const &); - receive_hashables (bool &, rai::stream &); - receive_hashables (bool &, boost::property_tree::ptree const &); - void hash (blake2b_state &) const; - rai::block_hash previous; - rai::block_hash source; -}; -class receive_block : public rai::block -{ -public: - receive_block (rai::block_hash const &, rai::block_hash const &, rai::raw_key const &, rai::public_key const &, uint64_t); - receive_block (bool &, rai::stream &); - receive_block (bool &, boost::property_tree::ptree const &); - using rai::block::hash; - void hash (blake2b_state &) const override; - uint64_t block_work () const override; - void block_work_set (uint64_t) override; - rai::block_hash previous () const override; - rai::block_hash source () const override; - rai::block_hash root () const override; - rai::account representative () const override; - void serialize (rai::stream &) const override; - void serialize_json (std::string &) const override; - bool deserialize (rai::stream &); - bool deserialize_json (boost::property_tree::ptree const &); - void visit (rai::block_visitor &) const override; - rai::block_type type () const override; - bool operator == (rai::block const &) const override; - bool operator == (rai::receive_block const &) const; - static size_t constexpr size = sizeof (rai::block_hash) + sizeof (rai::block_hash) + sizeof (rai::signature) + sizeof (uint64_t); - receive_hashables hashables; - rai::signature signature; - uint64_t work; -}; -class open_hashables -{ -public: - open_hashables (rai::block_hash const &, rai::account const &, rai::account const &); - open_hashables (bool &, rai::stream &); - open_hashables (bool &, boost::property_tree::ptree const &); - void hash (blake2b_state &) const; - rai::block_hash source; - rai::account representative; - rai::account account; -}; -class open_block : public rai::block -{ -public: - open_block (rai::block_hash const &, rai::account const &, rai::account const &, rai::raw_key const &, rai::public_key const &, uint64_t); - open_block (rai::block_hash const &, rai::account const &, rai::account const &, std::nullptr_t); - open_block (bool &, rai::stream &); - open_block (bool &, boost::property_tree::ptree const &); - using rai::block::hash; - void hash (blake2b_state &) const override; - uint64_t block_work () const override; - void block_work_set (uint64_t) override; - rai::block_hash previous () const override; - rai::block_hash source () const override; - rai::block_hash root () const override; - rai::account representative () const override; - void serialize (rai::stream &) const override; - void serialize_json (std::string &) const override; - bool deserialize (rai::stream &); - bool deserialize_json (boost::property_tree::ptree const &); - void visit (rai::block_visitor &) const override; - rai::block_type type () const override; - bool operator == (rai::block const &) const override; - bool operator == (rai::open_block const &) const; - static size_t constexpr size = sizeof (rai::block_hash) + sizeof (rai::account) + sizeof (rai::account) + sizeof (rai::signature) + sizeof (uint64_t); - rai::open_hashables hashables; - rai::signature signature; - uint64_t work; -}; -class change_hashables -{ -public: - change_hashables (rai::block_hash const &, rai::account const &); - change_hashables (bool &, rai::stream &); - change_hashables (bool &, boost::property_tree::ptree const &); - void hash (blake2b_state &) const; - rai::block_hash previous; - rai::account representative; -}; -class change_block : public rai::block -{ -public: - change_block (rai::block_hash const &, rai::account const &, rai::raw_key const &, rai::public_key const &, uint64_t); - change_block (bool &, rai::stream &); - change_block (bool &, boost::property_tree::ptree const &); - using rai::block::hash; - void hash (blake2b_state &) const override; - uint64_t block_work () const override; - void block_work_set (uint64_t) override; - rai::block_hash previous () const override; - rai::block_hash source () const override; - rai::block_hash root () const override; - rai::account representative () const override; - void serialize (rai::stream &) const override; - void serialize_json (std::string &) const override; - bool deserialize (rai::stream &); - bool deserialize_json (boost::property_tree::ptree const &); - void visit (rai::block_visitor &) const override; - rai::block_type type () const override; - bool operator == (rai::block const &) const override; - bool operator == (rai::change_block const &) const; - static size_t constexpr size = sizeof (rai::block_hash) + sizeof (rai::account) + sizeof (rai::signature) + sizeof (uint64_t); - rai::change_hashables hashables; - rai::signature signature; - uint64_t work; -}; -class block_visitor -{ -public: - virtual void send_block (rai::send_block const &) = 0; - virtual void receive_block (rai::receive_block const &) = 0; - virtual void open_block (rai::open_block const &) = 0; - virtual void change_block (rai::change_block const &) = 0; -}; // Latest information about an account class account_info { diff --git a/rai/utility.cpp b/rai/utility.cpp index cd8eb55f..371b2482 100644 --- a/rai/utility.cpp +++ b/rai/utility.cpp @@ -12,43 +12,6 @@ boost::filesystem::path rai::unique_path () return result; } -std::string rai::to_string_hex (uint64_t value_a) -{ - std::stringstream stream; - stream << std::hex << std::noshowbase << std::setw (16) << std::setfill ('0'); - stream << value_a; - return stream.str (); -} - -bool rai::from_string_hex (std::string const & value_a, uint64_t & target_a) -{ - auto result (value_a.empty ()); - if (!result) - { - result = value_a.size () > 16; - if (!result) - { - std::stringstream stream (value_a); - stream << std::hex << std::noshowbase; - uint64_t number_l; - try - { - stream >> number_l; - target_a = number_l; - if (!stream.eof()) - { - result = true; - } - } - catch (std::runtime_error &) - { - result = true; - } - } - } - return result; -} - rai::mdb_env::mdb_env (bool & error_a, boost::filesystem::path const & path_a) { boost::system::error_code error; @@ -164,147 +127,6 @@ rai::transaction::operator MDB_txn * () const return handle; } -rai::uint128_union::uint128_union (std::string const & string_a) -{ - decode_hex (string_a); -} - -rai::uint128_union::uint128_union (uint64_t value_a) -{ - *this = rai::uint128_t (value_a); -} - -rai::uint128_union::uint128_union (rai::uint128_t const & value_a) -{ - rai::uint128_t number_l (value_a); - for (auto i (bytes.rbegin ()), n (bytes.rend ()); i != n; ++i) - { - *i = ((number_l) & 0xff).convert_to (); - number_l >>= 8; - } -} - -bool rai::uint128_union::operator == (rai::uint128_union const & other_a) const -{ - return qwords [0] == other_a.qwords [0] && qwords [1] == other_a.qwords [1]; -} - -bool rai::uint128_union::operator != (rai::uint128_union const & other_a) const -{ - return !(*this == other_a); -} - -bool rai::uint128_union::operator < (rai::uint128_union const & other_a) const -{ - return number () < other_a.number (); -} - -bool rai::uint128_union::operator > (rai::uint128_union const & other_a) const -{ - return number () > other_a.number (); -} - -rai::uint128_t rai::uint128_union::number () const -{ - rai::uint128_t result; - auto shift (0); - for (auto i (bytes.begin ()), n (bytes.end ()); i != n; ++i) - { - result <<= shift; - result |= *i; - shift = 8; - } - return result; -} - -void rai::uint128_union::encode_hex (std::string & text) const -{ - assert (text.empty ()); - std::stringstream stream; - stream << std::hex << std::noshowbase << std::setw (32) << std::setfill ('0'); - stream << number (); - text = stream.str (); -} - -bool rai::uint128_union::decode_hex (std::string const & text) -{ - auto result (text.size () > 32); - if (!result) - { - std::stringstream stream (text); - stream << std::hex << std::noshowbase; - rai::uint128_t number_l; - try - { - stream >> number_l; - *this = number_l; - if (!stream.eof ()) - { - result = true; - } - } - catch (std::runtime_error &) - { - result = true; - } - } - return result; -} - -void rai::uint128_union::encode_dec (std::string & text) const -{ - assert (text.empty ()); - std::stringstream stream; - stream << std::dec << std::noshowbase; - stream << number (); - text = stream.str (); -} - -bool rai::uint128_union::decode_dec (std::string const & text) -{ - auto result (text.size () > 39); - if (!result) - { - std::stringstream stream (text); - stream << std::dec << std::noshowbase; - rai::uint128_t number_l; - try - { - stream >> number_l; - *this = number_l; - } - catch (std::runtime_error &) - { - result = true; - } - } - return result; -} - -void rai::uint128_union::clear () -{ - qwords.fill (0); -} - -bool rai::uint128_union::is_zero () const -{ - return qwords [0] == 0 && qwords [1] == 0; -} - -std::string rai::uint128_union::to_string () const -{ - std::string result; - encode_hex (result); - return result; -} - -std::string rai::uint128_union::to_string_dec () const -{ - std::string result; - encode_dec (result); - return result; -} - void rai::open_or_create (std::fstream & stream_a, std::string const & path_a) { stream_a.open (path_a, std::ios_base::in); diff --git a/rai/utility.hpp b/rai/utility.hpp index 8952ac9a..4d9e746a 100755 --- a/rai/utility.hpp +++ b/rai/utility.hpp @@ -20,8 +20,6 @@ namespace rai { -// We operate on streams of uint8_t by convention -using stream = std::basic_streambuf ; using bufferstream = boost::iostreams::stream_buffer >; using vectorstream = boost::iostreams::stream_buffer >>; // OS-specific way of finding a path to a home directory. @@ -30,21 +28,6 @@ boost::filesystem::path working_path (); boost::filesystem::path unique_path (); // Lower priority of calling work generating thread void work_thread_reprioritize (); -// Read a raw byte stream the size of `T' and fill value. -template -bool read (rai::stream & stream_a, T & value) -{ - static_assert (std::is_pod ::value, "Can't stream read non-standard layout types"); - auto amount_read (stream_a.sgetn (reinterpret_cast (&value), sizeof (value))); - return amount_read != sizeof (value); -} -template -void write (rai::stream & stream_a, T const & value) -{ - static_assert (std::is_pod ::value, "Can't stream write non-standard layout types"); - auto amount_written (stream_a.sputn (reinterpret_cast (&value), sizeof (value))); - assert (amount_written == sizeof (value)); -} // C++ stream are absolutely horrible so I need this helper function to do the most basic operation of creating a file if it doesn't exist or truntacing it. void open_or_create (std::fstream &, std::string const &); // Reads a json object from the stream and if was changed, write the object back to the stream @@ -116,8 +99,6 @@ bool fetch_object (T & object, boost::filesystem::path const & path_a, std::fstr } return error; } -std::string to_string_hex (uint64_t); -bool from_string_hex (std::string const &, uint64_t &); class mdb_env { diff --git a/rai/versioning.hpp b/rai/versioning.hpp index 45a4a74d..33bc5ef0 100644 --- a/rai/versioning.hpp +++ b/rai/versioning.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include namespace rai