diff --git a/irohad/ametsuchi/block_serializer.hpp b/irohad/ametsuchi/block_serializer.hpp new file mode 100644 index 0000000000..63727fbdb7 --- /dev/null +++ b/irohad/ametsuchi/block_serializer.hpp @@ -0,0 +1,90 @@ +/** + * Copyright Soramitsu Co., Ltd. 2017 All Rights Reserved. + * http://soramitsu.co.jp + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IROHA_BLOCK_SERIALIZER_HPP +#define IROHA_BLOCK_SERIALIZER_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace iroha{ +namespace ametsuchi{ + +using namespace rapidjson; + +class BlockSerializer{ + public: + std::vector serialize(model::Block block); + nonstd::optional deserialize(const std::vector& bytes); + private: + void serialize(PrettyWriter& writer, const model::Block& block); + void serialize(PrettyWriter& writer, const model::Signature& signature); + void serialize(PrettyWriter& writer, const model::Transaction& transaction); + void serialize(PrettyWriter& writer, const model::Command& command); + + void serialize(PrettyWriter& writer, const model::AddPeer& add_peer); + void serialize(PrettyWriter& writer, const model::AddAssetQuantity& add_asset_quantity); + void serialize(PrettyWriter& writer, const model::AddSignatory& add_signatory); + void serialize(PrettyWriter& writer, const model::AssignMasterKey& assign_master_key); + void serialize(PrettyWriter& writer, const model::CreateAccount& create_account); + void serialize(PrettyWriter& writer, const model::CreateAsset& create_asset); + void serialize(PrettyWriter& writer, const model::CreateDomain& create_domain); + void serialize(PrettyWriter& writer, const model::RemoveSignatory& remove_signatory); + void serialize(PrettyWriter& writer, const model::SetAccountPermissions& set_account_permissions); + void serialize(PrettyWriter& writer, const model::SetQuorum& set_quorum); + void serialize(PrettyWriter& writer, const model::TransferAsset& transfer_asset); + + void deserialize(Document& doc, std::vector& transactions); + void deserialize(GenericValue>::Object& json_tx, + std::vector>& commands); + nonstd::optional deserialize_add_peer(GenericValue>::Object& json_command); + nonstd::optional deserialize_add_asset_quantity(GenericValue>::Object& json_command); + nonstd::optional deserialize_add_signatory(GenericValue>::Object& json_command); + nonstd::optional deserialize_assign_master_key(GenericValue>::Object& json_command); + nonstd::optional deserialize_create_account(GenericValue>::Object& json_command); + nonstd::optional deserialize_create_asset(GenericValue>::Object& json_command); + nonstd::optional deserialize_create_domain(GenericValue>::Object& json_command); + nonstd::optional deserialize_remove_signatory(GenericValue>::Object& json_command); + nonstd::optional deserialize_set_account_permissions(GenericValue>::Object& json_command); + nonstd::optional deserialize_set_quorum(GenericValue>::Object& json_command); + nonstd::optional deserialize_transfer_asset(GenericValue>::Object& json_command); + + template + inline bool instanceof(const T *ptr) { + return typeid(Base) == typeid(*ptr); + } +}; + +} +} + +#endif //IROHA_BLOCK_SERIALIZER_HPP diff --git a/irohad/ametsuchi/impl/block_serializer.cpp b/irohad/ametsuchi/impl/block_serializer.cpp new file mode 100644 index 0000000000..bca60daa61 --- /dev/null +++ b/irohad/ametsuchi/impl/block_serializer.cpp @@ -0,0 +1,800 @@ +/** + * Copyright Soramitsu Co., Ltd. 2017 All Rights Reserved. + * http://soramitsu.co.jp + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +namespace iroha { + namespace ametsuchi { + + using namespace rapidjson; + + /* Serialize */ + + std::vector BlockSerializer::serialize(const model::Block block) { + rapidjson::StringBuffer sb; + rapidjson::PrettyWriter writer(sb); + serialize(writer, std::move(block)); + auto str = sb.GetString(); + std::vector bytes{str, str + sb.GetLength()}; + return bytes; + } + + void BlockSerializer::serialize(PrettyWriter& writer, + const model::Block& block) { + writer.StartObject(); + writer.String("hash"); + writer.String(block.hash.to_hexstring().c_str()); + + writer.String("signatures"); + writer.StartArray(); + for (auto sig : block.sigs) { + serialize(writer, sig); + } + writer.EndArray(); + + writer.String("created_ts"); + writer.Uint64(block.created_ts); + + writer.String("height"); + writer.Uint64(block.height); + + writer.String("prev_hash"); + writer.String(block.prev_hash.to_hexstring().c_str()); + + writer.String("txs_number"); + writer.Uint(block.txs_number); + + writer.String("merkle_root"); + writer.String(block.merkle_root.to_hexstring().c_str()); + + writer.String("transactions"); + writer.StartArray(); + for (auto tx : block.transactions) { + serialize(writer, tx); + } + writer.EndArray(); + + writer.EndObject(); + } + + void BlockSerializer::serialize(PrettyWriter& writer, + const model::Signature& signature) { + writer.StartObject(); + + writer.String("pubkey"); + writer.String(signature.pubkey.to_hexstring().c_str()); + + writer.String("signature"); + writer.String(signature.signature.to_hexstring().c_str()); + + writer.EndObject(); + } + + void BlockSerializer::serialize(PrettyWriter& writer, + const model::Transaction& transaction) { + writer.StartObject(); + + writer.String("signatures"); + writer.StartArray(); + for (auto sig : transaction.signatures) { + serialize(writer, sig); + } + writer.EndArray(); + + writer.String("created_ts"); + writer.Uint64(transaction.created_ts); + + writer.String("creator_account_id"); + writer.String(transaction.creator_account_id.c_str()); + + writer.String("tx_counter"); + writer.Uint64(transaction.tx_counter); + + writer.String("commands"); + writer.StartArray(); + for (auto command : transaction.commands) { + serialize(writer, *command); + } + writer.EndArray(); + + writer.EndObject(); + } + + void BlockSerializer::serialize(PrettyWriter& writer, + const model::Command& command) { + if (instanceof (&command)) { + auto add_peer = static_cast(command); + serialize(writer, add_peer); + } + if (instanceof (&command)) { + auto add_asset_quantity = + static_cast(command); + serialize(writer, add_asset_quantity); + } + if (instanceof (&command)) { + auto add_signatory = static_cast(command); + serialize(writer, add_signatory); + } + if (instanceof (&command)) { + auto assign_master_key = + static_cast(command); + serialize(writer, assign_master_key); + } + if (instanceof (&command)) { + auto create_account = static_cast(command); + serialize(writer, create_account); + } + if (instanceof (&command)) { + auto create_asset = static_cast(command); + serialize(writer, create_asset); + } + if (instanceof (&command)) { + auto create_domain = static_cast(command); + serialize(writer, create_domain); + } + if (instanceof (&command)) { + auto remove_signatory = + static_cast(command); + serialize(writer, remove_signatory); + } + if (instanceof (&command)) { + auto set_account_permissions = + static_cast(command); + serialize(writer, set_account_permissions); + } + if (instanceof (&command)) { + auto set_quorum = static_cast(command); + serialize(writer, set_quorum); + } + if (instanceof (&command)) { + auto transfer_asset = static_cast(command); + serialize(writer, transfer_asset); + } + } + + void BlockSerializer::serialize(PrettyWriter& writer, + const model::AddPeer& add_peer) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("AddPeer"); + + writer.String("address"); + writer.String(add_peer.address.c_str()); + + writer.String("peer_key"); + writer.String(add_peer.peer_key.to_hexstring().c_str()); + + writer.EndObject(); + } + + void BlockSerializer::serialize( + PrettyWriter& writer, + const model::AddAssetQuantity& add_asset_quantity) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("AddAssetQuantity"); + + writer.String("account_id"); + writer.String(add_asset_quantity.account_id.c_str()); + + writer.String("asset_id"); + writer.String(add_asset_quantity.asset_id.c_str()); + + writer.String("amount"); + + writer.Double( + std::decimal::decimal64_to_double(add_asset_quantity.amount)); + + writer.EndObject(); + } + + void BlockSerializer::serialize(PrettyWriter& writer, + const model::AddSignatory& add_signatory) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("AddSignatory"); + + writer.String("account_id"); + writer.String(add_signatory.account_id.c_str()); + + writer.String("pubkey"); + writer.String(add_signatory.pubkey.to_hexstring().c_str()); + + writer.EndObject(); + } + + void BlockSerializer::serialize( + PrettyWriter& writer, + const model::AssignMasterKey& assign_master_key) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("AssignMasterKey"); + + writer.String("account_id"); + writer.String(assign_master_key.account_id.c_str()); + + writer.String("pubkey"); + writer.String(assign_master_key.pubkey.to_hexstring().c_str()); + + writer.EndObject(); + } + + void BlockSerializer::serialize( + PrettyWriter& writer, + const model::CreateAccount& create_account) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("CreateAccount"); + + writer.String("domain_id"); + writer.String(create_account.domain_id.c_str()); + + writer.String("account_name"); + writer.String(create_account.account_name.c_str()); + + writer.String("pubkey"); + writer.String(create_account.pubkey.to_hexstring().c_str()); + + writer.EndObject(); + } + + void BlockSerializer::serialize(PrettyWriter& writer, + const model::CreateAsset& create_asset) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("CreateAsset"); + + writer.String("asset_name"); + writer.String(create_asset.asset_name.c_str()); + + writer.String("domain_id"); + writer.String(create_asset.domain_id.c_str()); + + writer.String("precision"); + writer.Uint(create_asset.precision); + + writer.EndObject(); + } + + void BlockSerializer::serialize(PrettyWriter& writer, + const model::CreateDomain& create_domain) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("CreateDomain"); + + writer.String("domain_name"); + writer.String(create_domain.domain_name.c_str()); + + writer.EndObject(); + } + + void BlockSerializer::serialize( + PrettyWriter& writer, + const model::RemoveSignatory& remove_signatory) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("RemoveSignatory"); + + writer.String("account_id"); + writer.String(remove_signatory.account_id.c_str()); + + writer.String("pubkey"); + writer.String(remove_signatory.pubkey.to_hexstring().c_str()); + + writer.EndObject(); + } + + void BlockSerializer::serialize( + PrettyWriter& writer, + const model::SetAccountPermissions& set_account_permissions) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("SetAccountPermissions"); + + writer.String("account_id"); + writer.String(set_account_permissions.account_id.c_str()); + + writer.String("new_permissions"); + writer.StartObject(); + + writer.String("add_signatory"); + writer.Bool(set_account_permissions.new_permissions.add_signatory); + + writer.String("can_transfer"); + writer.Bool(set_account_permissions.new_permissions.can_transfer); + + writer.String("create_accounts"); + writer.Bool(set_account_permissions.new_permissions.create_accounts); + + writer.String("create_assets"); + writer.Bool(set_account_permissions.new_permissions.create_assets); + + writer.String("create_domains"); + writer.Bool(set_account_permissions.new_permissions.create_domains); + + writer.String("issue_assets"); + writer.Bool(set_account_permissions.new_permissions.issue_assets); + + writer.String("read_all_accounts"); + writer.Bool(set_account_permissions.new_permissions.read_all_accounts); + + writer.String("remove_signatory"); + writer.Bool(set_account_permissions.new_permissions.remove_signatory); + + writer.String("set_permissions"); + writer.Bool(set_account_permissions.new_permissions.set_permissions); + + writer.String("set_quorum"); + writer.Bool(set_account_permissions.new_permissions.set_quorum); + + writer.EndObject(); + + writer.EndObject(); + } + + void BlockSerializer::serialize(PrettyWriter& writer, + const model::SetQuorum& set_quorum) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("SetQuorum"); + + writer.String("account_id"); + writer.String(set_quorum.account_id.c_str()); + + writer.String("new_quorum"); + writer.Uint(set_quorum.new_quorum); + + writer.EndObject(); + } + + void BlockSerializer::serialize( + PrettyWriter& writer, + const model::TransferAsset& transfer_asset) { + writer.StartObject(); + + writer.String("command_type"); + writer.String("TransferAsset"); + + writer.String("dest_account_id"); + writer.String(transfer_asset.dest_account_id.c_str()); + + writer.String("src_account_id"); + writer.String(transfer_asset.src_account_id.c_str()); + + writer.String("asset_id"); + writer.String(transfer_asset.asset_id.c_str()); + + writer.String("amount"); + writer.Double(std::decimal::decimal64_to_double(transfer_asset.amount)); + + writer.EndObject(); + } + + /* Deserialize */ + + nonstd::optional BlockSerializer::deserialize( + const std::vector& bytes) { + // TODO: return nullopt when some necessary field is missed + std::string block_json(bytes.begin(), bytes.end()); + rapidjson::Document doc; + if (doc.Parse(block_json.c_str()).HasParseError()) { + return nonstd::nullopt; + } + + model::Block block{}; + + // hash + std::string hash_str(doc["hash"].GetString(), + doc["hash"].GetStringLength()); + auto hash_bytes = hex2bytes(hash_str); + std::copy(hash_bytes.begin(), hash_bytes.end(), block.hash.begin()); + + // signatures + auto json_sigs = doc["signatures"].GetArray(); + + for (auto iter = json_sigs.begin(); iter < json_sigs.end(); ++iter) { + auto json_sig = iter->GetObject(); + model::Signature signature{}; + + std::string sig_pubkey(json_sig["pubkey"].GetString(), + json_sig["pubkey"].GetStringLength()); + auto sig_pubkey_bytes = hex2bytes(sig_pubkey); + std::copy(sig_pubkey_bytes.begin(), sig_pubkey_bytes.end(), + signature.pubkey.begin()); + + std::string sig_sign(json_sig["signature"].GetString(), + json_sig["signature"].GetStringLength()); + auto sig_sign_bytes = hex2bytes(sig_sign); + std::copy(sig_sign_bytes.begin(), sig_sign_bytes.end(), + signature.signature.begin()); + + block.sigs.push_back(signature); + } + + // created_ts + block.created_ts = doc["created_ts"].GetUint64(); + + // height + block.height = doc["height"].GetUint64(); + + // prev_hash + std::string prev_hash_str(doc["prev_hash"].GetString(), + doc["prev_hash"].GetStringLength()); + auto prev_hash_bytes = hex2bytes(prev_hash_str); + std::copy(prev_hash_bytes.begin(), prev_hash_bytes.end(), + block.prev_hash.begin()); + + // txs number + block.txs_number = static_cast(doc["txs_number"].GetUint()); + + // merkle_root + std::string merkle_root_str(doc["merkle_root"].GetString(), + doc["merkle_root"].GetStringLength()); + auto merkle_root_bytes = hex2bytes(merkle_root_str); + std::copy(merkle_root_bytes.begin(), merkle_root_bytes.end(), + block.merkle_root.begin()); + + // transactions + deserialize(doc, block.transactions); + + return block; + } + + void BlockSerializer::deserialize( + Document& doc, std::vector& transactions) { + auto json_txs = doc["transactions"].GetArray(); + + for (auto iter = json_txs.begin(); iter < json_txs.end(); iter++) { + model::Transaction tx{}; + + auto json_tx = iter->GetObject(); + + // signatures + auto json_sigs = json_tx["signatures"].GetArray(); + for (auto sig_iter = json_sigs.begin(); sig_iter < json_sigs.end(); + ++sig_iter) { + auto json_sig = sig_iter->GetObject(); + model::Signature signature{}; + + std::string sig_pubkey(json_sig["pubkey"].GetString(), + json_sig["pubkey"].GetStringLength()); + auto sig_pubkey_bytes = hex2bytes(sig_pubkey); + std::copy(sig_pubkey_bytes.begin(), sig_pubkey_bytes.end(), + signature.pubkey.begin()); + + std::string sig_sign(json_sig["signature"].GetString(), + json_sig["signature"].GetStringLength()); + auto sig_sign_bytes = hex2bytes(sig_sign); + std::copy(sig_sign_bytes.begin(), sig_sign_bytes.end(), + signature.signature.begin()); + + tx.signatures.push_back(signature); + } + + // created_ts + tx.created_ts = json_tx["created_ts"].GetUint64(); + + // creator_account_id + tx.creator_account_id = json_tx["creator_account_id"].GetString(); + + // tx_counter + tx.tx_counter = json_tx["tx_counter"].GetUint64(); + + // commands + deserialize(json_tx, tx.commands); + transactions.push_back(tx); + } + } + + void BlockSerializer::deserialize( + GenericValue>::Object& json_tx, + std::vector>& commands) { + auto json_commands = json_tx["commands"].GetArray(); + for (auto iter = json_commands.begin(); iter < json_commands.end(); + ++iter) { + auto json_command = iter->GetObject(); + + std::string command_type = json_command["command_type"].GetString(); + + if (command_type == "AddPeer") { + if (auto add_peer = deserialize_add_peer(json_command)) { + commands.push_back( + std::make_shared(add_peer.value())); + } + } else if (command_type == "AddAssetQuantity") { + if (auto add_asset_quantity = + deserialize_add_asset_quantity(json_command)) { + commands.push_back(std::make_shared( + add_asset_quantity.value())); + } + } else if (command_type == "AddSignatory") { + if (auto add_signatory = deserialize_add_signatory(json_command)) { + commands.push_back( + std::make_shared(add_signatory.value())); + } + } else if (command_type == "AssignMasterKey") { + if (auto assign_master_key = + deserialize_assign_master_key(json_command)) { + commands.push_back(std::make_shared( + assign_master_key.value())); + } + } else if (command_type == "CreateAccount") { + if (auto create_account = deserialize_create_account(json_command)) { + commands.push_back( + std::make_shared(create_account.value())); + } + } else if (command_type == "CreateAsset") { + if (auto create_asset = deserialize_create_asset(json_command)) { + commands.push_back( + std::make_shared(create_asset.value())); + } + } else if (command_type == "CreateDomain") { + if (auto create_domain = deserialize_create_domain(json_command)) { + commands.push_back( + std::make_shared(create_domain.value())); + } + } else if (command_type == "RemoveSignatory") { + if (auto remove_signatory = deserialize_remove_signatory(json_command)) { + commands.push_back( + std::make_shared(remove_signatory.value())); + } + } else if (command_type == "SetAccountPermissions") { + if (auto set_account_permissions = deserialize_set_account_permissions(json_command)) { + commands.push_back( + std::make_shared(set_account_permissions.value())); + } + } else if (command_type == "SetQuorum") { + if (auto set_quorum = deserialize_set_quorum(json_command)) { + commands.push_back( + std::make_shared(set_quorum.value())); + } + } else if (command_type == "TransferAsset") { + if (auto transfer_asset = deserialize_transfer_asset(json_command)) { + commands.push_back( + std::make_shared(transfer_asset.value())); + } + } + } + } + + nonstd::optional BlockSerializer::deserialize_add_peer( + GenericValue>::Object& json_command) { + // TODO: make this function return nullopt when some field is missed + model::AddPeer add_peer{}; + + // peer_key + std::string peer_key_str(json_command["peer_key"].GetString(), + json_command["peer_key"].GetStringLength()); + auto peer_key_bytes = hex2bytes(peer_key_str); + std::copy(peer_key_bytes.begin(), peer_key_bytes.end(), + add_peer.peer_key.begin()); + + // address + add_peer.address = json_command["address"].GetString(); + return add_peer; + } + + nonstd::optional + BlockSerializer::deserialize_add_asset_quantity( + GenericValue>::Object& json_command) { + // TODO: make this function return nullopt when some field is missed + model::AddAssetQuantity add_asset_quantity{}; + + // account_id + add_asset_quantity.account_id = json_command["account_id"].GetString(); + + // asset_id + add_asset_quantity.asset_id = json_command["asset_id"].GetString(); + + // amount + auto amount = std::decimal::decimal64(json_command["amount"].GetDouble()); + add_asset_quantity.amount = amount; + + return add_asset_quantity; + } + + nonstd::optional + BlockSerializer::deserialize_add_signatory( + GenericValue>::Object& json_command) { + // TODO: make this function return nullopt when some field is missed + model::AddSignatory add_signatory{}; + + // account_id + add_signatory.account_id = json_command["account_id"].GetString(); + + // pubkey + std::string pubkey_str(json_command["pubkey"].GetString(), + json_command["pubkey"].GetStringLength()); + auto pubkey_bytes = hex2bytes(pubkey_str); + std::copy(pubkey_bytes.begin(), pubkey_bytes.end(), + add_signatory.pubkey.begin()); + + return add_signatory; + } + + nonstd::optional + BlockSerializer::deserialize_assign_master_key( + GenericValue>::Object& json_command) { + // TODO: make this function return nullopt when some field is missed + model::AssignMasterKey assign_master_key{}; + + // account_id + assign_master_key.account_id = json_command["account_id"].GetString(); + + // pubkey + std::string pubkey_str(json_command["pubkey"].GetString(), + json_command["pubkey"].GetStringLength()); + auto pubkey_bytes = hex2bytes(pubkey_str); + std::copy(pubkey_bytes.begin(), pubkey_bytes.end(), + assign_master_key.pubkey.begin()); + return assign_master_key; + } + + nonstd::optional + BlockSerializer::deserialize_create_account( + GenericValue>::Object& json_command) { + // TODO: make this function return nullopt when some field is missed + model::CreateAccount create_account{}; + + // domain_id + create_account.domain_id = json_command["domain_id"].GetString(); + + // account_name + create_account.account_name = json_command["account_name"].GetString(); + + // pubkey + std::string pubkey_str(json_command["pubkey"].GetString(), + json_command["pubkey"].GetStringLength()); + auto pubkey_bytes = hex2bytes(pubkey_str); + std::copy(pubkey_bytes.begin(), pubkey_bytes.end(), + create_account.pubkey.begin()); + return create_account; + } + + nonstd::optional + BlockSerializer::deserialize_create_asset( + GenericValue>::Object& json_command) { + // TODO: make this function return nullopt when some field is missed + model::CreateAsset createAsset; + + // asset_name + createAsset.asset_name = json_command["asset_name"].GetString(); + + // domain_id + createAsset.domain_id = json_command["domain_id"].GetString(); + + // precision + createAsset.precision = json_command["precision"].GetUint(); + + return createAsset; + } + + nonstd::optional + BlockSerializer::deserialize_create_domain( + GenericValue>::Object& json_command) { + // TODO: make this function return nullopt when some field is missed + model::CreateDomain createDomain; + + // domain_name + createDomain.domain_name = json_command["domain_name"].GetString(); + + return createDomain; + } + + nonstd::optional + BlockSerializer::deserialize_remove_signatory( + GenericValue>::Object& json_command) { + // TODO: make this function return nullopt when some field is missed + model::RemoveSignatory removeSignatory; + + // account_id + removeSignatory.account_id = json_command["account_id"].GetString(); + + // pubkey + std::string pubkey_str(json_command["pubkey"].GetString(), + json_command["pubkey"].GetStringLength()); + auto pubkey_bytes = hex2bytes(pubkey_str); + std::copy(pubkey_bytes.begin(), pubkey_bytes.end(), + removeSignatory.pubkey.begin()); + return removeSignatory; + } + + nonstd::optional + BlockSerializer::deserialize_set_account_permissions( + GenericValue>::Object& json_command) { + model::SetAccountPermissions setAccountPermissions; + + // account_id + setAccountPermissions.account_id = json_command["account_id"].GetString(); + + // permissions + auto new_permissions = json_command["new_permissions"].GetObject(); + setAccountPermissions.new_permissions.add_signatory = + new_permissions["add_signatory"].GetBool(); + setAccountPermissions.new_permissions.can_transfer = + new_permissions["can_transfer"].GetBool(); + setAccountPermissions.new_permissions.create_accounts = + new_permissions["create_accounts"].GetBool(); + setAccountPermissions.new_permissions.create_assets = + new_permissions["create_assets"].GetBool(); + setAccountPermissions.new_permissions.create_domains = + new_permissions["create_domains"].GetBool(); + setAccountPermissions.new_permissions.issue_assets = + new_permissions["issue_assets"].GetBool(); + setAccountPermissions.new_permissions.read_all_accounts = + new_permissions["read_all_accounts"].GetBool(); + setAccountPermissions.new_permissions.remove_signatory = + new_permissions["remove_signatory"].GetBool(); + setAccountPermissions.new_permissions.set_permissions = + new_permissions["set_permissions"].GetBool(); + setAccountPermissions.new_permissions.set_quorum = + new_permissions["set_quorum"].GetBool(); + + return setAccountPermissions; + } + + nonstd::optional BlockSerializer::deserialize_set_quorum( + GenericValue>::Object& json_command) { + model::SetQuorum setQuorum; + + // account_id + setQuorum.account_id = json_command["account_id"].GetString(); + + // new_quorum + setQuorum.new_quorum = json_command["new_quorum"].GetUint(); + + return setQuorum; + } + + nonstd::optional + BlockSerializer::deserialize_transfer_asset( + GenericValue>::Object& json_command) { + model::TransferAsset transferAsset; + + // src_account_id + transferAsset.src_account_id = json_command["src_account_id"].GetString(); + + // dest_account_id + transferAsset.dest_account_id = + json_command["dest_account_id"].GetString(); + + // asset_id + transferAsset.asset_id = json_command["asset_id"].GetString(); + + // amount + transferAsset.amount = + std::decimal::decimal64(json_command["amount"].GetDouble()); + + return transferAsset; + } + } +} diff --git a/irohad/ametsuchi/wsv_query.hpp b/irohad/ametsuchi/wsv_query.hpp index c0cfda08d8..6d0ae0d272 100644 --- a/irohad/ametsuchi/wsv_query.hpp +++ b/irohad/ametsuchi/wsv_query.hpp @@ -73,7 +73,7 @@ namespace iroha { * @param address * @return */ - virtual nonstd::optional getPeers() = 0; + virtual nonstd::optional getPeer(const std::string &address) = 0; }; } // namespace ametsuchi diff --git a/libs/common/types.hpp b/libs/common/types.hpp index 911cf0dbf3..1c52b2b661 100644 --- a/libs/common/types.hpp +++ b/libs/common/types.hpp @@ -83,7 +83,16 @@ namespace iroha { } }; + static std::vector hex2bytes(const std::string& hex) { + std::vector bytes; + for (size_t i = 0; i < hex.length(); i += 2) { + std::string byteString = hex.substr(i, 2); + uint8_t byte = (uint8_t)strtol(byteString.c_str(), NULL, 16); + bytes.push_back(byte); + } + return bytes; + } template using hash_t = blob_t; diff --git a/test/module/irohad/ametsuchi/block_serializer_test.cpp b/test/module/irohad/ametsuchi/block_serializer_test.cpp new file mode 100644 index 0000000000..c428b5f8e6 --- /dev/null +++ b/test/module/irohad/ametsuchi/block_serializer_test.cpp @@ -0,0 +1,274 @@ +/** + * Copyright Soramitsu Co., Ltd. 2017 All Rights Reserved. + * http://soramitsu.co.jp + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +iroha::model::Signature create_signature(); +iroha::model::Transaction create_transaction(); +iroha::model::Proposal create_proposal(); +iroha::model::Block create_block(); + +iroha::model::Signature create_signature() { + iroha::model::Signature signature{}; + memset(signature.signature.data(), 0x123, iroha::ed25519::sig_t::size()); + memset(signature.pubkey.data(), 0x123, iroha::ed25519::pubkey_t::size()); + return signature; +} + +iroha::model::Transaction create_transaction() { + iroha::model::Transaction tx{}; + tx.creator_account_id = "123"; + + tx.tx_counter = 0; + tx.created_ts = 0; + + tx.signatures.push_back(create_signature()); + tx.signatures.push_back(create_signature()); + + // tx.commands + + // Add peer + iroha::model::AddPeer add_peer; + add_peer.address = "localhost"; + std::fill(add_peer.peer_key.begin(), add_peer.peer_key.end(), 0x123); + tx.commands.push_back(std::make_shared(add_peer)); + + // AddAssetQuantity + iroha::model::AddAssetQuantity add_asset_qty; + add_asset_qty.account_id = "123"; + add_asset_qty.asset_id = "123"; + add_asset_qty.amount = std::decimal::make_decimal64(1010LL, -2); + tx.commands.push_back(std::make_shared(add_asset_qty)); + + // AddSignatory + iroha::model::AddSignatory add_signatory; + add_signatory.account_id = "123"; + std::fill(add_signatory.pubkey.begin(), add_signatory.pubkey.end(), 0x123); + tx.commands.push_back(std::make_shared(add_signatory)); + + //AssignMasterKey + iroha::model::AssignMasterKey assign_master_key; + std::fill(assign_master_key.pubkey.begin(), assign_master_key.pubkey.end(), 0x123); + assign_master_key.account_id = "123"; + tx.commands.push_back(std::make_shared(assign_master_key)); + + //CreateAccount + iroha::model::CreateAccount create_account; + std::fill(create_account.pubkey.begin(), create_account.pubkey.end(), 0x123); + create_account.account_name = "123"; + create_account.domain_id = "123"; + tx.commands.push_back(std::make_shared(create_account)); + + //CreateAsset + iroha::model::CreateAsset create_asset; + create_asset.domain_id = "123"; + create_asset.asset_name = "123"; + create_asset.precision = 2; + tx.commands.push_back(std::make_shared(create_asset)); + + //CreateDomain + iroha::model::CreateDomain create_domain; + create_domain.domain_name = "123"; + tx.commands.push_back(std::make_shared(create_domain)); + + //RemoveSignatory + iroha::model::RemoveSignatory remove_signatory; + remove_signatory.account_id = "123"; + std::fill(remove_signatory.pubkey.begin(), remove_signatory.pubkey.end(), 0x123); + tx.commands.push_back(std::make_shared(remove_signatory)); + + //SetPermissions + iroha::model::SetAccountPermissions set_account_permissions; + set_account_permissions.account_id = "123"; + set_account_permissions.new_permissions.can_transfer = true; + tx.commands.push_back(std::make_shared(set_account_permissions)); + + //SetQuorum + iroha::model::SetQuorum set_quorum; + set_quorum.account_id = "123"; + set_quorum.new_quorum = 123; + tx.commands.push_back(std::make_shared(set_quorum)); + + //TransferAsset + iroha::model::TransferAsset transfer_asset; + transfer_asset.src_account_id = "123"; + transfer_asset.dest_account_id = "321"; + transfer_asset.amount = std::decimal::make_decimal64(1010ll, -2); + transfer_asset.asset_id = "123"; + tx.commands.push_back(std::make_shared(transfer_asset)); + return tx; +} + +iroha::model::Proposal create_proposal() { + std::vector txs; + txs.push_back(create_transaction()); + txs.push_back(create_transaction()); + + iroha::model::Proposal proposal(txs); + return proposal; +} + +iroha::model::Block create_block() { + iroha::model::Block block{}; + memset(block.hash.data(), 0x1, iroha::ed25519::pubkey_t::size()); + block.sigs.push_back(create_signature()); + block.created_ts = 0; + block.height = 0; + memset(block.prev_hash.data(), 0x5, iroha::ed25519::pubkey_t::size()); + block.txs_number = 0; + memset(block.merkle_root.data(), 0x123, iroha::ed25519::pubkey_t::size()); + block.transactions.push_back(create_transaction()); + return block; +} + + +template +inline bool instanceof(const T *ptr) { + return typeid(Base) == typeid(*ptr); +} + +TEST(block_serialize, block_serialize_test){ + + auto block = create_block(); + + iroha::ametsuchi::BlockSerializer blockSerializer; + + std::cout << unsigned(block.hash[0]) << std::endl; + + auto bytes = blockSerializer.serialize(block); + std::string str(bytes.begin(), bytes.end()); + std::cout << str << std::endl; + // deserialize + + auto res = blockSerializer.deserialize(bytes); + if (res){ + auto deserialized = res.value(); + ASSERT_EQ(block.hash, deserialized.hash); + ASSERT_EQ(block.created_ts, deserialized.created_ts); + + ASSERT_TRUE(block.sigs.size() > 0); + for (int i = 0; i < block.sigs.size(); i++){ + ASSERT_EQ(block.sigs[i].signature, deserialized.sigs[i].signature); + ASSERT_EQ(block.sigs[i].pubkey, deserialized.sigs[i].pubkey); + } + + ASSERT_EQ(block.prev_hash, deserialized.prev_hash); + ASSERT_EQ(block.created_ts, deserialized.created_ts); + ASSERT_EQ(block.merkle_root, deserialized.merkle_root); + + ASSERT_TRUE(block.transactions.size() > 0); + for (int i = 0; i < block.transactions.size(); i++){ + auto tx = block.transactions[i]; + auto des_tx = deserialized.transactions[i]; // deserialized tx + + ASSERT_TRUE(tx.signatures.size() > 0); + for (int j = 0; j < tx.signatures.size(); j++){ + ASSERT_EQ(tx.signatures[j].pubkey, des_tx.signatures[j].pubkey); + ASSERT_EQ(tx.signatures[j].signature, des_tx.signatures[j].signature); + } + + ASSERT_EQ(tx.created_ts, des_tx.created_ts); + ASSERT_EQ(tx.creator_account_id, des_tx.creator_account_id); + ASSERT_EQ(tx.tx_counter, des_tx.tx_counter); + + for (int j = 0; j < tx.commands.size(); j++){ + if (instanceof(tx.commands[j].get())){ + auto add_peer = static_cast(*tx.commands[j].get()); + auto des_add_peer = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(add_peer.address, des_add_peer.address); + ASSERT_EQ(add_peer.peer_key, des_add_peer.peer_key); + } + else if (instanceof(tx.commands[j].get())){ + auto add_asset_quantity = static_cast(*tx.commands[j].get()); + auto des_add_asset_quantity = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(add_asset_quantity.amount, des_add_asset_quantity.amount); + ASSERT_EQ(add_asset_quantity.asset_id, des_add_asset_quantity.asset_id); + ASSERT_EQ(add_asset_quantity.account_id, des_add_asset_quantity.account_id); + } + else if (instanceof(tx.commands[j].get())){ + auto add_signatory = static_cast(*tx.commands[j].get()); + auto des_add_signatory = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(add_signatory.account_id, des_add_signatory.account_id); + ASSERT_EQ(add_signatory.pubkey, des_add_signatory.pubkey); + } + else if (instanceof(tx.commands[j].get())){ + auto assign_master_key = static_cast(*tx.commands[j].get()); + auto des_assign_master_key = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(assign_master_key.account_id, des_assign_master_key.account_id); + ASSERT_EQ(assign_master_key.pubkey, des_assign_master_key.pubkey); + } + else if (instanceof(tx.commands[j].get())){ + auto create_account = static_cast(*tx.commands[j].get()); + auto des_create_account = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(create_account.account_name, des_create_account.account_name); + ASSERT_EQ(create_account.domain_id, des_create_account.domain_id); + ASSERT_EQ(create_account.pubkey, des_create_account.pubkey); + } + else if (instanceof(tx.commands[j].get())) { + auto create_asset = static_cast(*tx.commands[j].get()); + auto des_create_asset = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(create_asset.asset_name, des_create_asset.asset_name); + ASSERT_EQ(create_asset.domain_id, des_create_asset.domain_id); + ASSERT_EQ(create_asset.precision, des_create_asset.precision); + } + else if (instanceof(tx.commands[j].get())) { + auto create_domain = static_cast(*tx.commands[j].get()); + auto des_create_domain = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(create_domain.domain_name, des_create_domain.domain_name); + } + else if (instanceof(tx.commands[j].get())) { + auto remove_signatory = static_cast(*tx.commands[j].get()); + auto des_remove_signatory = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(remove_signatory.account_id, des_remove_signatory.account_id); + ASSERT_EQ(remove_signatory.pubkey, des_remove_signatory.pubkey); + } + else if (instanceof(tx.commands[j].get())) { + auto set_account_permissions = static_cast(*tx.commands[j].get()); + auto des_set_account_permissions = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(set_account_permissions.account_id, des_set_account_permissions.account_id); + ASSERT_EQ(set_account_permissions.new_permissions.add_signatory, des_set_account_permissions.new_permissions.add_signatory); + ASSERT_EQ(set_account_permissions.new_permissions.can_transfer, des_set_account_permissions.new_permissions.can_transfer); + ASSERT_EQ(set_account_permissions.new_permissions.create_accounts, des_set_account_permissions.new_permissions.create_accounts); + ASSERT_EQ(set_account_permissions.new_permissions.create_assets, des_set_account_permissions.new_permissions.create_assets); + ASSERT_EQ(set_account_permissions.new_permissions.create_domains, des_set_account_permissions.new_permissions.create_domains); + ASSERT_EQ(set_account_permissions.new_permissions.issue_assets, des_set_account_permissions.new_permissions.issue_assets); + ASSERT_EQ(set_account_permissions.new_permissions.read_all_accounts, des_set_account_permissions.new_permissions.read_all_accounts); + ASSERT_EQ(set_account_permissions.new_permissions.remove_signatory, des_set_account_permissions.new_permissions.remove_signatory); + ASSERT_EQ(set_account_permissions.new_permissions.set_permissions, des_set_account_permissions.new_permissions.set_permissions); + ASSERT_EQ(set_account_permissions.new_permissions.set_quorum, des_set_account_permissions.new_permissions.set_quorum); + } + else if (instanceof(tx.commands[j].get())) { + auto set_quorum = static_cast(*tx.commands[j].get()); + auto des_set_quorum = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(set_quorum.account_id, des_set_quorum.account_id); + ASSERT_EQ(set_quorum.new_quorum, des_set_quorum.new_quorum); + } + else if (instanceof(tx.commands[j].get())){ + auto transfer_asset = static_cast(*tx.commands[j].get()); + auto des_transfer_asset = static_cast(*des_tx.commands[j].get()); + ASSERT_EQ(transfer_asset.src_account_id, des_transfer_asset.src_account_id); + ASSERT_EQ(transfer_asset.dest_account_id, des_transfer_asset.dest_account_id); + ASSERT_EQ(transfer_asset.asset_id, des_transfer_asset.asset_id); + ASSERT_EQ(transfer_asset.amount, des_transfer_asset.amount); + } + } + + } + + } +}