1
0
Fork 0
forked from lthn/blockchain

implemented proper versioning for binary serialization

This commit is contained in:
cryptozoidberg 2022-09-23 23:19:44 +02:00
parent 2ba139ebaf
commit 213cb4f85c
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
3 changed files with 207 additions and 1 deletions

View file

@ -687,6 +687,27 @@ namespace currency
struct asset_descriptor_base
{
uint64_t total_max_supply = 0;
uint64_t current_supply = 0;
uint8_t decimal_point = 12;
std::string ticker;
std::string full_name;
crypto::public_key owner = currency::null_pkey;
BEGIN_VERSIONED_SERIALIZE()
FIELD(total_max_supply)
FIELD(current_supply)
FIELD(decimal_point)
FIELD(ticker)
FIELD(full_name)
FIELD(owner)
END_SERIALIZE()
};
struct extra_padding
{
std::vector<uint8_t> buff; //stub

View file

@ -61,7 +61,7 @@ inline bool do_serialize(Archive &ar, T &v)
#define VARIANT_TAG(A, T, Tg) \
template <bool W> struct variant_serialization_traits<A<W>, T> { static inline typename A<W>::variant_tag_type get_tag() { return Tg; } }
#define BEGIN_SERIALIZE() \
template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &_ser_ar) {
template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &_ser_ar) {uint8_t s_current_version = 0; uint8_t s_version = 0;
#define BEGIN_SERIALIZE_OBJECT() \
template <bool W, template <bool> class Archive> bool do_serialize(Archive<W> &_ser_ar) { _ser_ar.begin_object(); bool _ser_res = do_serialize_object(_ser_ar); _ser_ar.end_object(); return _ser_res; } \
template <bool W, template <bool> class Archive> bool do_serialize_object(Archive<W> &_ser_ar){
@ -98,6 +98,28 @@ do { \
if (!_ser_ar.stream().good()) return false; \
} while (0);
#define VERSION() \
do { \
_ser_ar.tag("VERSION"); \
if (!_ser_ar.stream().good()){break;} \
_ser_ar.serialize_varint(s_version); \
if (!_ser_ar.stream().good()) return false; \
if(s_version > s_current_version) return false; \
} while (0);
#define CURRENT_VERSION(v) \
do { \
s_current_version = v; \
if (_ser_ar.is_saving_arch()) { s_version = v; } \
} while (0);
#define BEGIN_VERSIONED_SERIALIZE() \
BEGIN_SERIALIZE() \
VERSION()
#define DEFINE_SERIALIZATION_VERSION(v) inline static uint32_t get_serialization_version() { return v; }

View file

@ -740,3 +740,166 @@ TEST(Serialization, serializes_transacion_versions)
validate_tx_serialisation(tx);
}
struct A
{
std::string one;
std::string two;
std::vector<std::string> vector_one;
BEGIN_SERIALIZE()
FIELD(one)
FIELD(two)
FIELD(vector_one)
END_SERIALIZE()
};
struct A_v1 : public A
{
std::vector<std::string> vector_two;
BEGIN_SERIALIZE()
CURRENT_VERSION(1)
FIELD(one)
FIELD(two)
FIELD(vector_one)
VERSION()
if (s_version < 1) return true;
FIELD(vector_two)
END_SERIALIZE()
};
struct A_v2 : public A_v1
{
std::vector<std::string> vector_3;
std::vector<std::string> vector_4;
BEGIN_SERIALIZE()
CURRENT_VERSION(2)
FIELD(one)
FIELD(two)
FIELD(vector_one)
VERSION()
if (s_version < 1) return true;
FIELD(vector_two)
if (s_version < 2) return true;
FIELD(vector_3)
FIELD(vector_4)
END_SERIALIZE()
};
struct A_v3 : public A_v2
{
std::vector<std::string> vector_5;
BEGIN_SERIALIZE()
CURRENT_VERSION(3)
FIELD(one)
FIELD(two)
FIELD(vector_one)
VERSION()
if (s_version < 1) return true;
FIELD(vector_two)
if (s_version < 2) return true;
FIELD(vector_3)
FIELD(vector_4)
if (s_version < 3) return true;
FIELD(vector_4)
END_SERIALIZE()
};
inline bool operator==(const A& lhs, const A& rhs)
{
if ((lhs.one != rhs.one || lhs.two != rhs.two || lhs.vector_one != rhs.vector_one))
{
return false;
}
return true;
}
inline bool operator==(const A_v1& lhs, const A_v1& rhs)
{
if (!(static_cast<const A&>(lhs) == static_cast<const A&>(rhs)))
return false;
if ((lhs.vector_two != rhs.vector_two))
{
return false;
}
return true;
}
inline bool operator==(const A_v2& lhs, const A_v2& rhs)
{
if (!(static_cast<const A_v1&>(lhs) == static_cast<const A_v1&>(rhs)))
return false;
if ((lhs.vector_3 != rhs.vector_3))
{
return false;
}
return true;
}
inline bool operator==(const A_v3& lhs, const A_v3& rhs)
{
if (!(static_cast<const A_v2&>(lhs) == static_cast<const A_v2&>(rhs)))
return false;
if ((lhs.vector_5 != rhs.vector_5))
{
return false;
}
return true;
}
template<typename first, typename second>
bool perform_test_ser_vers(second& f)
{
string blob;
first s_s = AUTO_VAL_INIT(s_s);
if (!serialization::dump_binary(f, blob))
return false;
if (!serialization::parse_binary(blob, s_s))
return false;
if (!(f == static_cast<second&>(s_s)))
{
return false;
}
return true;
}
TEST(Serialization, versioning2)
{
A_v3 a_3;
a_3.one = "one";
a_3.two = "two";
a_3.vector_one.push_back(a_3.one);
a_3.vector_one.push_back(a_3.two);
a_3.vector_two = a_3.vector_one;
a_3.vector_5 = a_3.vector_4 = a_3.vector_3 = a_3.vector_two;
A_v2 a_2(a_3);
A_v1 a_1(a_3);
A a(a_3);
bool r = perform_test_ser_vers<A_v1>(a);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v2>(a);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v3>(a);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v2>(a_1);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v3>(a_1);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v3>(a_2);
ASSERT_TRUE(r);
r = perform_test_ser_vers<A_v3>(a_3);
ASSERT_TRUE(r);
}