// Copyright (c) 2011-2016 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "gtest/gtest.h" #include "Common/StdInputStream.h" #include "Common/StdOutputStream.h" #include "Serialization/BinaryInputStreamSerializer.h" #include "Serialization/BinaryOutputStreamSerializer.h" #include "Serialization/BinarySerializationTools.h" using namespace Common; using namespace CryptoNote; TEST(BinarySerializer, uint16) { std::stringstream ss; uint16_t u16 = 0xfeff; uint32_t u32 = 0x3fddfd48; { StdOutputStream os(ss); BinaryOutputStreamSerializer s(os); s(u32, "u32"); s(u16, "u16"); } { StdInputStream is(ss); BinaryInputStreamSerializer s(is); uint32_t t32 = 0; uint16_t t16 = 0; s(t32, "u32"); s(t16, "u16"); ASSERT_EQ(u32, t32); ASSERT_EQ(u16, t16); } } //#include //#include //#include //#include //#include //#include //#include "CryptoNoteCore/CryptoNoteBasic.h" //#include "CryptoNoteCore/CryptoNoteBasicImpl.h" //#include "Serialization/serialization.h" //#include "Serialization/binary_archive.h" //#include "Serialization/json_archive.h" //#include "Serialization/variant.h" //#include "Serialization/vector.h" //#include "Serialization/binary_utils.h" //#include "gtest/gtest.h" //using namespace std; // //struct Struct //{ // int32_t a; // int32_t b; // char blob[8]; //}; // //template //struct serializer //{ // static bool serialize(Archive &ar, Struct &s) { // ar.begin_object(); // ar.tag("a"); // ar.serialize_int(s.a); // ar.tag("b"); // ar.serialize_int(s.b); // ar.tag("blob"); // ar.serialize_blob(s.blob, sizeof(s.blob)); // ar.end_object(); // return true; // } //}; // //struct Struct1 //{ // vector> si; // vector vi; // // BEGIN_SERIALIZE_OBJECT() // FIELD(si) // FIELD(vi) // END_SERIALIZE() // /*template class Archive> // bool do_serialize(Archive &ar) // { // ar.begin_object(); // ar.tag("si"); // ::do_serialize(ar, si); // ar.tag("vi"); // ::do_serialize(ar, vi); // ar.end_object(); // }*/ //}; // //struct Blob //{ // uint64_t a; // uint32_t b; // // bool operator==(const Blob& rhs) const // { // return a == rhs.a; // } //}; // //VARIANT_TAG(binary_archive, Struct, 0xe0); //VARIANT_TAG(binary_archive, int, 0xe1); //VARIANT_TAG(json_archive, Struct, "struct"); //VARIANT_TAG(json_archive, int, "int"); // //BLOB_SERIALIZER(Blob); // //bool try_parse(const string &blob) //{ // Struct1 s1; // return serialization::parse_binary(blob, s1); //} // //TEST(Serialization, BinaryArchiveInts) { // uint64_t x = 0xff00000000, x1; // // ostringstream oss; // binary_archive oar(oss); // oar.serialize_int(x); // ASSERT_TRUE(oss.good()); // ASSERT_EQ(8, oss.str().size()); // ASSERT_EQ(string("\0\0\0\0\xff\0\0\0", 8), oss.str()); // // istringstream iss(oss.str()); // binary_archive iar(iss); // iar.serialize_int(x1); // ASSERT_EQ(8, iss.tellg()); // ASSERT_TRUE(iss.good()); // // ASSERT_EQ(x, x1); //} // //TEST(Serialization, BinaryArchiveVarInts) { // uint64_t x = 0xff00000000, x1; // // ostringstream oss; // binary_archive oar(oss); // oar.serialize_varint(x); // ASSERT_TRUE(oss.good()); // ASSERT_EQ(6, oss.str().size()); // ASSERT_EQ(string("\x80\x80\x80\x80\xF0\x1F", 6), oss.str()); // // istringstream iss(oss.str()); // binary_archive iar(iss); // iar.serialize_varint(x1); // ASSERT_TRUE(iss.good()); // ASSERT_EQ(x, x1); //} // //TEST(Serialization, Test1) { // ostringstream str; // binary_archive ar(str); // // Struct1 s1; // s1.si.push_back(0); // { // Struct s; // s.a = 5; // s.b = 65539; // std::memcpy(s.blob, "12345678", 8); // s1.si.push_back(s); // } // s1.si.push_back(1); // s1.vi.push_back(10); // s1.vi.push_back(22); // // string blob; // ASSERT_TRUE(serialization::dump_binary(s1, blob)); // ASSERT_TRUE(try_parse(blob)); // // ASSERT_EQ('\xE0', blob[6]); // blob[6] = '\xE1'; // ASSERT_FALSE(try_parse(blob)); // blob[6] = '\xE2'; // ASSERT_FALSE(try_parse(blob)); //} // //TEST(Serialization, Overflow) { // Blob x = { 0xff00000000 }; // Blob x1; // // string blob; // ASSERT_TRUE(serialization::dump_binary(x, blob)); // ASSERT_EQ(sizeof(Blob), blob.size()); // // ASSERT_TRUE(serialization::parse_binary(blob, x1)); // ASSERT_EQ(x, x1); // // vector bigvector; // ASSERT_FALSE(serialization::parse_binary(blob, bigvector)); // ASSERT_EQ(0, bigvector.size()); //} // //TEST(Serialization, serializes_vector_uint64_as_varint) //{ // std::vector v; // string blob; // // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(1, blob.size()); // // // +1 byte // v.push_back(0); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(2, blob.size()); // // // +1 byte // v.push_back(1); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(3, blob.size()); // // // +2 bytes // v.push_back(0x80); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(5, blob.size()); // // // +2 bytes // v.push_back(0xFF); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(7, blob.size()); // // // +2 bytes // v.push_back(0x3FFF); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(9, blob.size()); // // // +3 bytes // v.push_back(0x40FF); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(12, blob.size()); // // // +10 bytes // v.push_back(0xFFFFFFFFFFFFFFFF); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(22, blob.size()); //} // //TEST(Serialization, serializes_vector_int64_as_fixed_int) //{ // std::vector v; // string blob; // // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(1, blob.size()); // // // +8 bytes // v.push_back(0); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(9, blob.size()); // // // +8 bytes // v.push_back(1); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(17, blob.size()); // // // +8 bytes // v.push_back(0x80); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(25, blob.size()); // // // +8 bytes // v.push_back(0xFF); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(33, blob.size()); // // // +8 bytes // v.push_back(0x3FFF); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(41, blob.size()); // // // +8 bytes // v.push_back(0x40FF); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(49, blob.size()); // // // +8 bytes // v.push_back(0xFFFFFFFFFFFFFFFF); // ASSERT_TRUE(serialization::dump_binary(v, blob)); // ASSERT_EQ(57, blob.size()); //} // //namespace //{ // template // std::vector linearize_vector2(const std::vector< std::vector >& vec_vec) // { // std::vector res; // BOOST_FOREACH(const auto& vec, vec_vec) // { // res.insert(res.end(), vec.begin(), vec.end()); // } // return res; // } //} // //TEST(Serialization, serializes_transacion_signatures_correctly) //{ // using namespace CryptoNote; // // Transaction tx; // Transaction tx1; // string blob; // // // Empty tx // tx.clear(); // ASSERT_TRUE(serialization::dump_binary(tx, blob)); // ASSERT_EQ(5, blob.size()); // 5 bytes + 0 bytes extra + 0 bytes signatures // ASSERT_TRUE(serialization::parse_binary(blob, tx1)); // ASSERT_EQ(tx, tx1); // ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); // // // Miner tx without signatures // TransactionInputGenerate txin_gen1; // txin_gen1.height = 0; // tx.clear(); // tx.vin.push_back(txin_gen1); // ASSERT_TRUE(serialization::dump_binary(tx, blob)); // ASSERT_EQ(7, blob.size()); // 5 bytes + 2 bytes vin[0] + 0 bytes extra + 0 bytes signatures // ASSERT_TRUE(serialization::parse_binary(blob, tx1)); // ASSERT_EQ(tx, tx1); // ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); // // // Miner tx with empty signatures 2nd vector // tx.signatures.resize(1); // ASSERT_TRUE(serialization::dump_binary(tx, blob)); // ASSERT_EQ(7, blob.size()); // 5 bytes + 2 bytes vin[0] + 0 bytes extra + 0 bytes signatures // ASSERT_TRUE(serialization::parse_binary(blob, tx1)); // ASSERT_EQ(tx, tx1); // ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); // // // Miner tx with one signature // tx.signatures[0].resize(1); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // Miner tx with 2 empty vectors // tx.signatures.resize(2); // tx.signatures[0].resize(0); // tx.signatures[1].resize(0); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // Miner tx with 2 signatures // tx.signatures[0].resize(1); // tx.signatures[1].resize(1); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // Two TransactionInputGenerate, no signatures // tx.vin.push_back(txin_gen1); // tx.signatures.resize(0); // ASSERT_TRUE(serialization::dump_binary(tx, blob)); // ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures // ASSERT_TRUE(serialization::parse_binary(blob, tx1)); // ASSERT_EQ(tx, tx1); // ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); // // // Two TransactionInputGenerate, signatures vector contains only one empty element // tx.signatures.resize(1); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // Two TransactionInputGenerate, signatures vector contains two empty elements // tx.signatures.resize(2); // ASSERT_TRUE(serialization::dump_binary(tx, blob)); // ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures // ASSERT_TRUE(serialization::parse_binary(blob, tx1)); // ASSERT_EQ(tx, tx1); // ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); // // // Two TransactionInputGenerate, signatures vector contains three empty elements // tx.signatures.resize(3); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // Two TransactionInputGenerate, signatures vector contains two non empty elements // tx.signatures.resize(2); // tx.signatures[0].resize(1); // tx.signatures[1].resize(1); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // A few bytes instead of signature // tx.vin.clear(); // tx.vin.push_back(txin_gen1); // tx.signatures.clear(); // ASSERT_TRUE(serialization::dump_binary(tx, blob)); // blob.append(std::string(sizeof(Crypto::Signature) / 2, 'x')); // ASSERT_FALSE(serialization::parse_binary(blob, tx1)); // // // blob contains one signature // blob.append(std::string(sizeof(Crypto::Signature) / 2, 'y')); // ASSERT_FALSE(serialization::parse_binary(blob, tx1)); // // // Not enough signature vectors for all inputs // TransactionInputToKey txin_to_key1; // txin_to_key1.keyOffsets.resize(2); // tx.vin.clear(); // tx.vin.push_back(txin_to_key1); // tx.vin.push_back(txin_to_key1); // tx.signatures.resize(1); // tx.signatures[0].resize(2); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // Too much signatures for two inputs // tx.signatures.resize(3); // tx.signatures[0].resize(2); // tx.signatures[1].resize(2); // tx.signatures[2].resize(2); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // First signatures vector contains too little elements // tx.signatures.resize(2); // tx.signatures[0].resize(1); // tx.signatures[1].resize(2); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // First signatures vector contains too much elements // tx.signatures.resize(2); // tx.signatures[0].resize(3); // tx.signatures[1].resize(2); // ASSERT_FALSE(serialization::dump_binary(tx, blob)); // // // There are signatures for each input // tx.signatures.resize(2); // tx.signatures[0].resize(2); // tx.signatures[1].resize(2); // ASSERT_TRUE(serialization::dump_binary(tx, blob)); // ASSERT_TRUE(serialization::parse_binary(blob, tx1)); // ASSERT_EQ(tx, tx1); // ASSERT_EQ(linearize_vector2(tx.signatures), linearize_vector2(tx1.signatures)); // // // Blob doesn't contain enough data // blob.resize(blob.size() - sizeof(Crypto::Signature) / 2); // ASSERT_FALSE(serialization::parse_binary(blob, tx1)); // // // Blob contains too much data // blob.resize(blob.size() + sizeof(Crypto::Signature)); // ASSERT_FALSE(serialization::parse_binary(blob, tx1)); // // // Blob contains one excess signature // blob.resize(blob.size() + sizeof(Crypto::Signature) / 2); // ASSERT_FALSE(serialization::parse_binary(blob, tx1)); //}