forked from cheng/wallet
Removed the old "is_serializable" in favor of C++20 concepts syntax.
Changed the name to "has_machine_independent_representation" for a more intellible error explanation
This commit is contained in:
parent
5f4fe3104b
commit
bc3f2c9daf
@ -107,7 +107,7 @@ namespace ro {
|
|||||||
template < typename T,
|
template < typename T,
|
||||||
typename std::enable_if<!is_sqlite3_field_type<T>::value, int >::type dummy_arg = 0 >
|
typename std::enable_if<!is_sqlite3_field_type<T>::value, int >::type dummy_arg = 0 >
|
||||||
void bind(int i, const T& j) {
|
void bind(int i, const T& j) {
|
||||||
static_assert(ro::serializable<T>, "Don't know how to store this type in a database");
|
static_assert(ro::has_machine_independent_representation<T>, "Don't know how to store this type in a database");
|
||||||
(*this)->Isqlite3_bind(i, ro::serialize(j));
|
(*this)->Isqlite3_bind(i, ro::serialize(j));
|
||||||
}
|
}
|
||||||
typedef Icompiled_sql::sql_result result;
|
typedef Icompiled_sql::sql_result result;
|
||||||
|
@ -61,7 +61,7 @@ namespace ristretto255 {
|
|||||||
ro::to_base64_string, ro::is_serializable,
|
ro::to_base64_string, ro::is_serializable,
|
||||||
ro::serialize, ro::bin2hex, ro::hex2bin,
|
ro::serialize, ro::bin2hex, ro::hex2bin,
|
||||||
ro::bin2hex, ro::CompileSizedString,
|
ro::bin2hex, ro::CompileSizedString,
|
||||||
ro::serializable;
|
ro::has_machine_independent_representation;
|
||||||
;
|
;
|
||||||
// a class representing ristretto255 elliptic points
|
// a class representing ristretto255 elliptic points
|
||||||
class point;
|
class point;
|
||||||
@ -119,7 +119,7 @@ namespace ristretto255 {
|
|||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<serializable T, typename... Args>
|
template<has_machine_independent_representation T, typename... Args>
|
||||||
hsh<hashsize>& hashinto(const T& j, Args... args) {
|
hsh<hashsize>& hashinto(const T& j, Args... args) {
|
||||||
auto sj = ro::serialize(j);
|
auto sj = ro::serialize(j);
|
||||||
int i = crypto_generichash_blake2b_update(
|
int i = crypto_generichash_blake2b_update(
|
||||||
@ -134,7 +134,7 @@ namespace ristretto255 {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<serializable T> hsh<hashsize>& operator << (const T& j) {
|
template<has_machine_independent_representation T> hsh<hashsize>& operator << (const T& j) {
|
||||||
auto sj = ro::serialize(j);
|
auto sj = ro::serialize(j);
|
||||||
auto i = crypto_generichash_blake2b_update(
|
auto i = crypto_generichash_blake2b_update(
|
||||||
&(this->st),
|
&(this->st),
|
||||||
@ -147,7 +147,7 @@ namespace ristretto255 {
|
|||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
static_assert(!serializable<hsh<256> >, "Don't want to partially hash partial hashes");
|
static_assert(!has_machine_independent_representation<hsh<256> >, "Don't want to partially hash partial hashes");
|
||||||
|
|
||||||
// This constructs a finalized hash.
|
// This constructs a finalized hash.
|
||||||
// If it has one argument, and that argument is hsh (unfinalized hash) object,
|
// If it has one argument, and that argument is hsh (unfinalized hash) object,
|
||||||
@ -194,11 +194,12 @@ namespace ristretto255 {
|
|||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
if (i) throw HashReuseException();
|
if (i) throw HashReuseException();
|
||||||
}
|
}
|
||||||
template< serializable T, typename... Args>explicit hash(const T& first, Args... args) {
|
template< has_machine_independent_representation T, typename... Args>explicit hash(const T& first, Args... args) {
|
||||||
|
|
||||||
hsh<hashsize> in;
|
hsh<hashsize> in;
|
||||||
in << first;
|
in << first;
|
||||||
if constexpr (sizeof...(args) > 0) {
|
if constexpr (sizeof...(args) > 0) {
|
||||||
in.hashinto(args...);
|
in.hashinto( args...);
|
||||||
}
|
}
|
||||||
int i = crypto_generichash_blake2b_final(
|
int i = crypto_generichash_blake2b_final(
|
||||||
&in.st,
|
&in.st,
|
||||||
@ -280,6 +281,7 @@ namespace ristretto255 {
|
|||||||
"we need 512 bit randoms to ensure our points and scalars are uniformly distributed"
|
"we need 512 bit randoms to ensure our points and scalars are uniformly distributed"
|
||||||
);
|
);
|
||||||
// There should be scalar from hash, not point from hash
|
// There should be scalar from hash, not point from hash
|
||||||
|
// libsodium already supplies a random point
|
||||||
int i{
|
int i{
|
||||||
crypto_core_ristretto255_from_hash(&blob[0], &(x.blob)[0]) };
|
crypto_core_ristretto255_from_hash(&blob[0], &(x.blob)[0]) };
|
||||||
assert(i == 0);
|
assert(i == 0);
|
||||||
@ -434,21 +436,21 @@ namespace ristretto255 {
|
|||||||
static_assert(ro::is_blob_field_type<point>::value);
|
static_assert(ro::is_blob_field_type<point>::value);
|
||||||
static_assert(ro::is_blob_field_type<hash<256> >::value);
|
static_assert(ro::is_blob_field_type<hash<256> >::value);
|
||||||
static_assert(false == ro::is_blob_field_type<char*>::value);
|
static_assert(false == ro::is_blob_field_type<char*>::value);
|
||||||
static_assert(ro::is_serializable<scalar&>::value);
|
static_assert(ro::has_machine_independent_representation<scalar&>);
|
||||||
static_assert(ro::is_serializable<hash<512>&>::value);
|
static_assert(ro::has_machine_independent_representation<hash<512>&>);
|
||||||
static_assert(ro::is_blob_field_type<int>::value == false);
|
static_assert(ro::is_blob_field_type<int>::value == false);
|
||||||
static_assert(ro::is_serializable<unsigned int>::value);
|
static_assert(ro::has_machine_independent_representation<unsigned int>);
|
||||||
static_assert(ro::is_serializable<char*>::value);
|
static_assert(ro::has_machine_independent_representation<char*>);
|
||||||
static_assert(ro::is_serializable<uint8_t*>::value == false); //false because uint8_t * has no inband terminator
|
static_assert(ro::has_machine_independent_representation<uint8_t*> == false); //false because uint8_t * has no inband terminator
|
||||||
static_assert(false == ro::is_serializable<wxString>::value && !ro::is_constructible_from_v<hash<256>, wxString>, "wxStrings are apt to convert anything to anything, with surprising and unexpected results");
|
static_assert(false == ro::has_machine_independent_representation<wxString> && !ro::is_constructible_from_v<hash<256>, wxString>, "wxStrings are apt to convert anything to anything, with surprising and unexpected results");
|
||||||
static_assert(ro::is_serializable<decltype(std::declval<wxString>().ToUTF8())>::value == true);
|
static_assert(ro::has_machine_independent_representation<decltype(std::declval<wxString>().ToUTF8())> == true);
|
||||||
static_assert(ro::is_constructible_from_all_of<scalar, int, hash<512>, std::array<uint8_t, crypto_core_ristretto255_BYTES>>);
|
static_assert(ro::is_constructible_from_all_of<scalar, int, hash<512>, std::array<uint8_t, crypto_core_ristretto255_BYTES>>);
|
||||||
static_assert(ro::is_constructible_from_all_of<hash<256>, char*, short, unsigned short, hash<512>, point, scalar>, "want to be able to hash anything serializable");
|
static_assert(ro::is_constructible_from_all_of<hash<256>, char*, short, unsigned short, hash<512>, point, scalar>, "want to be able to hash anything has_machine_independent_representation");
|
||||||
static_assert(false == ro::is_constructible_from_any_of<int, scalar, point, hsh<512>, hash<256>>);
|
static_assert(false == ro::is_constructible_from_any_of<int, scalar, point, hsh<512>, hash<256>>);
|
||||||
static_assert(false == ro::is_constructible_from_any_of <scalar, wxString, hash<256>, byte*>, "do not want indiscriminate casts");
|
static_assert(false == ro::is_constructible_from_any_of <scalar, wxString, hash<256>, byte*>, "do not want indiscriminate casts");
|
||||||
static_assert(false == ro::is_constructible_from_any_of <point, wxString, hash<256>, byte*>, "do not want indiscriminate casts ");
|
static_assert(false == ro::is_constructible_from_any_of <point, wxString, hash<256>, byte*>, "do not want indiscriminate casts ");
|
||||||
static_assert(false == ro::is_constructible_from_v<hash<256>, float>);
|
static_assert(false == ro::is_constructible_from_v<hash<256>, float>);
|
||||||
static_assert(ro::is_serializable<float>::value == false);//Need to convert floats to
|
static_assert(ro::has_machine_independent_representation<float> == false);//Need to convert floats to
|
||||||
// their machine independent representation, possibly through idexp, frexp
|
// their machine independent representation, possibly through idexp, frexp
|
||||||
// and DBL_MANT_DIG
|
// and DBL_MANT_DIG
|
||||||
static_assert(sizeof(decltype(ro::serialize(std::declval<scalar>())[0])) == 1);
|
static_assert(sizeof(decltype(ro::serialize(std::declval<scalar>())[0])) == 1);
|
||||||
|
@ -59,12 +59,14 @@
|
|||||||
|
|
||||||
// This template generates a span over an indexable byte type,
|
// This template generates a span over an indexable byte type,
|
||||||
// such as a C array or an std::array, but not pointers
|
// such as a C array or an std::array, but not pointers
|
||||||
template < typename T>
|
template<class T>
|
||||||
std::enable_if_t<
|
concept byte_spannable = requires (T a) {
|
||||||
!std::is_pointer<T>::value &&
|
std::size(a);
|
||||||
sizeof(std::declval<T>()[0]) == 1,
|
a[0];
|
||||||
std::span<const byte>
|
} && sizeof(std::declval<T>()[0]) == 1;
|
||||||
> serialize(const T& a) {
|
|
||||||
|
template<byte_spannable T>
|
||||||
|
auto serialize(const T& a) {
|
||||||
int l;
|
int l;
|
||||||
const void* pt;
|
const void* pt;
|
||||||
if constexpr (std::is_same_v<std::remove_cvref_t<T>, std::string>) {
|
if constexpr (std::is_same_v<std::remove_cvref_t<T>, std::string>) {
|
||||||
@ -301,27 +303,21 @@
|
|||||||
format being 44 digits in a base 58 representation.*/
|
format being 44 digits in a base 58 representation.*/
|
||||||
|
|
||||||
// a compile time test to check if an object class has a machine independent representation
|
// a compile time test to check if an object class has a machine independent representation
|
||||||
template <typename T, typename... Args> struct is_serializable{
|
template<typename T> concept has_machine_independent_representation = requires (T a) {
|
||||||
template <typename U, typename... Args2>
|
serialize(a);
|
||||||
static constexpr decltype(ro::serialize(std::declval<U>()), bool()) test() {
|
};
|
||||||
if constexpr (sizeof...(Args2) > 0) {
|
|
||||||
return is_serializable::template test<Args2...>();
|
template <typename T, typename... Args> static constexpr bool is_serializable() {
|
||||||
}
|
if constexpr (!has_machine_independent_representation<T>) return false;
|
||||||
else {
|
else if constexpr (sizeof...(Args) > 0) return is_serializable<Args...>();
|
||||||
return true;
|
else return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
template <typename U, typename... Args2> static constexpr bool test(int = 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
static constexpr bool value = is_serializable::template test<T,Args...>();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
concept serializable = is_serializable<Args...>::value;
|
concept allserializable = is_serializable<Args...>();
|
||||||
|
|
||||||
static_assert( !serializable<double>
|
static_assert( !has_machine_independent_representation<double>
|
||||||
&& serializable<std::span<const byte>, char*, std::span<const char>>,
|
&& allserializable<std::span<const byte>, char*, std::span<const char>>,
|
||||||
"concepts needed");
|
"concepts needed");
|
||||||
|
|
||||||
template<class T> ro::CompileSizedString< (2 * sizeof(T))>bin2hex(const T& pt) {
|
template<class T> ro::CompileSizedString< (2 * sizeof(T))>bin2hex(const T& pt) {
|
||||||
|
@ -28,7 +28,7 @@ namespace testbed {
|
|||||||
using /*ristretto255::hash, ristretto255::hsh, */ristretto255::scalar,
|
using /*ristretto255::hash, ristretto255::hsh, */ristretto255::scalar,
|
||||||
ristretto255::point, ro::serialize, ro::bin2hex, ro::hex2bin,
|
ristretto255::point, ro::serialize, ro::bin2hex, ro::hex2bin,
|
||||||
ro::bin2hex, ro::fasthash, ro::CompileSizedString,
|
ro::bin2hex, ro::fasthash, ro::CompileSizedString,
|
||||||
ro::base58, ro::serializable;
|
ro::base58, ro::has_machine_independent_representation;
|
||||||
static constexpr char SrcFilename[]{ "src/testbed.cpp" };
|
static constexpr char SrcFilename[]{ "src/testbed.cpp" };
|
||||||
|
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ static bool checkDataConversionsProduceExpected(void){
|
|||||||
point pt_a{ scl_a.timesBase() };
|
point pt_a{ scl_a.timesBase() };
|
||||||
std::string str_pt_a = &(base58(pt_a))[0];
|
std::string str_pt_a = &(base58(pt_a))[0];
|
||||||
assert(base58<point>::bin(str_pt_a.c_str()) == pt_a);
|
assert(base58<point>::bin(str_pt_a.c_str()) == pt_a);
|
||||||
hash<256> hash_b{ hash_a,str_hash_a,scl_a,str_sclr_a,pt_a,str_pt_a,33, 66ull };
|
hash<256> hash_b{ hash_a, str_hash_a, scl_a, str_sclr_a, pt_a, str_pt_a, 33, 66ull };
|
||||||
auto str_b = base58(hash_b).operator std::string();
|
auto str_b = base58(hash_b).operator std::string();
|
||||||
if (str_b != "7cTScjKyUtmbvc28BV3ok51szgrQmaBa2YE5HPBcukC9e"
|
if (str_b != "7cTScjKyUtmbvc28BV3ok51szgrQmaBa2YE5HPBcukC9e"
|
||||||
) {
|
) {
|
||||||
|
Loading…
Reference in New Issue
Block a user