diff --git a/CMakeLists.txt b/CMakeLists.txt index 0866fb0..5c288e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,7 @@ doxygen_add_docs( ) # build common library -set(LIB_SOURCES src/model.cpp src/model.hpp) +set(LIB_SOURCES src/model.cpp src/model.hpp src/big_int.hpp src/big_int.cpp) add_library(oc-mint-lib ${LIB_SOURCES}) target_link_libraries(oc-mint-lib PUBLIC Crow::Crow) target_include_directories(oc-mint-lib PUBLIC ${expected_SOURCE_DIR}/include src) @@ -80,7 +80,7 @@ add_executable(oc-mint src/main.cpp) target_link_libraries(oc-mint PRIVATE oc-mint-lib INTERFACE tl::expected::expected) ## these are unittests that can be run on any platform -add_executable(tests test/test.cpp) +add_executable(tests test/test_big_int.cpp test/test.cpp) target_link_libraries(tests oc-mint-lib Catch2::Catch2WithMain) diff --git a/src/big_int.cpp b/src/big_int.cpp new file mode 100644 index 0000000..b43a2f5 --- /dev/null +++ b/src/big_int.cpp @@ -0,0 +1,108 @@ +#include "big_int.hpp" +#include "tl/expected.hpp" +#include +#include +#include + +inline uint8_t hex(char c) { + switch(c) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': return 10; + case 'b': return 11; + case 'c': return 12; + case 'd': return 13; + case 'e': return 14; + case 'f': return 15; + case 'A': return 10; + case 'B': return 11; + case 'C': return 12; + case 'D': return 13; + case 'E': return 14; + case 'F': return 15; + default: + return 0xff; + } +} + +tl::expected +BigInt::from_string(const std::string& str) { + BigInt b; + // std::cout << str << std::endl; + + uint8_t hval=0; + uint8_t nibble; + size_t i = str.size()+1; + + for(auto c : str) { + nibble = hex(c); + if (nibble ==0xFF) { + return tl::make_unexpected(eError::PARSE_ERROR); + } + if (i%2) { + hval = nibble << 4; + } else { + hval |= nibble; + b.data[256 - (i/2)]= hval; + hval = 0; + } + i--; + } + + // std::cout << std::hex; + // for (auto b: b.data) + // { + // std::cout << (int)b; + // } + // std::cout << std::dec << std::endl; + return b; +} + +BigInt BigInt::from_int(uint64_t value) +{ + BigInt b; + b.data[248]=(value >> 56 & 0xff); + b.data[249]=(value >> 48 & 0xff); + b.data[250]=(value >> 40 & 0xff); + b.data[251]=(value >> 32 & 0xff); + b.data[252]=(value >> 24 & 0xff); + b.data[253]=(value >> 16 & 0xff); + b.data[254]=(value >> 8 & 0xff); + b.data[255]=(value & 0xff); + return b; +} + +constexpr char hex_char [] = "0123456789abcdef"; +std::string BigInt::to_string() const +{ + std::string s; + uint8_t b; + uint8_t first_digit = 0; + for (size_t i = 0; i<256;i++) { + b = data[i]; + if (first_digit==0) { + if (b==0) { + continue; + } else if (b>0xf) { + s.push_back(hex_char[b >> 4]); + } + s.push_back(hex_char[b & 0xf]); + first_digit = b; + } else { + s.push_back(hex_char[b >> 4]); + s.push_back(hex_char[b & 0xf]); + } + } + return s; +} + +bool operator == (const BigInt& rhs, const BigInt& lhs) +{ return rhs.data == lhs.data; } diff --git a/src/big_int.hpp b/src/big_int.hpp new file mode 100644 index 0000000..93a2a60 --- /dev/null +++ b/src/big_int.hpp @@ -0,0 +1,27 @@ +#ifndef BIG_INT_HPP +#define BIG_INT_HPP + +#include +#include + +#include "tl/expected.hpp" + +struct BigInt { + + BigInt() : data() {} + virtual ~BigInt() {} + + enum class eError : uint8_t { PARSE_ERROR }; + static tl::expected from_string(const std::string &str); + + static BigInt from_int(uint64_t value); + std::string to_string() const; + + friend bool operator == (const BigInt& rhs, const BigInt& lhs); +private: + std::array data; +}; + +bool operator==(const BigInt &rhs, const BigInt &lhs); + +#endif // #ifndef #ifndef BIG_INT_HPP diff --git a/src/main.cpp b/src/main.cpp index 8d4c217..a45fa57 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,7 +70,8 @@ int main() { ResponseMint res; res.message_reference = req->message_reference; - auto minted = model->mint(req->transaction_reference, req->blinds); + /// \todo change argument transaction_reference to bigint + auto minted = model->mint(req->transaction_reference.to_string(), req->blinds); res.blind_signatures = minted; res.status_code = crow::status::OK; diff --git a/src/model.cpp b/src/model.cpp index a66de4d..b3abcfa 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -1,9 +1,11 @@ #include "model.hpp" #include "crow/json.h" +#include "tl/expected.hpp" -#define TO_JSON(name) r[#name] = name -#define TO_JSON_JSON(name) r[#name] = name.to_json() -#define TO_JSON_ARRAY(name) r[#name] = list_to_json(name) +#define TO_JSON(name) r[#name]=name +#define BIGINT_TO_JSON(name) r[#name]=name.to_string() +#define TO_JSON_JSON(name) r[#name]=name.to_json() +#define TO_JSON_ARRAY(name) r[#name]=list_to_json(name) template crow::json::wvalue list_to_json(const std::vector &array) { @@ -22,9 +24,9 @@ crow::json::wvalue list_to_json(const std::vector &array) { crow::json::wvalue PublicKey::to_json() const { crow::json::wvalue r; - TO_JSON(modulus); - TO_JSON(public_exponent); - r["type"] = "rsa public key"; + BIGINT_TO_JSON(modulus); + BIGINT_TO_JSON(public_exponent); + r["type"]="rsa public key"; return r; } @@ -48,7 +50,7 @@ crow::json::wvalue CDD::to_json() const { TO_JSON(currency_divisor); TO_JSON(currency_name); TO_JSON_ARRAY(denominations); - TO_JSON(id); + BIGINT_TO_JSON(id); TO_JSON_ARRAY(info_service); TO_JSON(issuer_cipher_suite); TO_JSON_JSON(issuer_public_master_key); @@ -75,8 +77,8 @@ crow::json::wvalue MintKey::to_json() const { TO_JSON(cdd_serial); TO_JSON(coins_expiry_date); TO_JSON(denomination); - TO_JSON(id); - TO_JSON(issuer_id); + BIGINT_TO_JSON(id); + BIGINT_TO_JSON(issuer_id); TO_JSON_JSON(public_mint_key); TO_JSON(sign_coins_not_after); @@ -177,8 +179,13 @@ RequestMKCs::from_string(const std::string &str) { if (mint_key_ids.t() != crow::json::type::List) { return tl::make_unexpected(eError::JSON_WRONG_REQUEST_TYPE); } else { - for (auto k : mint_key_ids.lo()) { - r.mint_key_ids.push_back(k.u()); + for (auto k: mint_key_ids.lo()) { + auto kv = BigInt::from_string(k.s()); + if (!kv.has_value()) { + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } else { + r.mint_key_ids.push_back(*kv); + } } } return r; @@ -194,23 +201,38 @@ crow::json::wvalue ResponseMKCs::to_json() const { crow::json::wvalue Blind::to_json() const { crow::json::wvalue r; - TO_JSON(blinded_payload_hash); - TO_JSON(mint_key_id); + BIGINT_TO_JSON(blinded_payload_hash); + BIGINT_TO_JSON(mint_key_id); TO_JSON(reference); r["type"] = "blinded payload hash"; return r; } tl::expected Blind::from_json(const crow::json::rvalue &json) { - if (!(json.has("type") && json.has("blinded_payload_hash") && - json.has("mint_key_id") && json.has("reference"))) { + if (!(json.has("type") + && json.has("blinded_payload_hash") + && json.has("mint_key_id") + && json.has("reference"))) { return tl::make_unexpected(eError::JSON_ERROR); } else if (json["type"] != "blinded payload hash") { return tl::make_unexpected(eError::JSON_ERROR); } else { Blind r; - r.blinded_payload_hash = json["blinded_payload_hash"].s(); - r.mint_key_id = json["mint_key_id"].s(); + + auto hash = BigInt::from_string(json["blinded_payload_hash"].s()); + if (!hash) { + std::cout << "invalid hash : " << json["blinded_payload_hash"].s() + << std::endl; + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } + r.blinded_payload_hash = hash.value(); + + auto key_id = BigInt::from_string(json["mint_key_id"].s()); + if (!key_id) { + printf("invalid key_id"); + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } + r.mint_key_id = key_id.value(); r.reference = json["reference"].s(); return r; } @@ -218,7 +240,7 @@ tl::expected Blind::from_json(const crow::json::rvalue &json) { crow::json::wvalue BlindSignature::to_json() const { crow::json::wvalue r; - TO_JSON(blind_signature); + BIGINT_TO_JSON(blind_signature); TO_JSON(reference); r["type"] = "blind signature"; return r; @@ -238,9 +260,13 @@ RequestMint::from_string(const std::string &str) { return tl::make_unexpected(eError::JSON_ERROR); } else { RequestMint r; - r.message_reference = json["message_reference"].u(); - r.transaction_reference = json["transaction_reference"].s(); - if (json["blinds"].t() != crow::json::type::List) { + r.message_reference= json["message_reference"].u(); + auto tr = BigInt::from_string(json["transaction_reference"].s()); + if (!tr) + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + + r.transaction_reference = *tr; + if (json["blinds"].t()!=crow::json::type::List) { return tl::make_unexpected(eError::JSON_WRONG_VALUE_TYPE); } @@ -267,10 +293,10 @@ crow::json::wvalue Coin::Payload::to_json() const { crow::json::wvalue r; TO_JSON(cdd_location); TO_JSON(denomination); - TO_JSON(issuer_id); - TO_JSON(mint_key_id); + BIGINT_TO_JSON(issuer_id); + BIGINT_TO_JSON(mint_key_id); TO_JSON(protocol_version); - TO_JSON(serial); + BIGINT_TO_JSON(serial); r["type"] = "payload"; return r; @@ -297,10 +323,20 @@ Coin::Payload::from_json(const crow::json::rvalue &json) { Coin::Payload payload; payload.cdd_location = json["cdd_location"].s(); payload.denomination = json["denomination"].u(); - payload.issuer_id = json["issuer_id"].s(); - payload.mint_key_id = json["mint_key_id"].s(); + auto id = BigInt::from_string(json["issuer_id"].s()); + if (!id) + tl::make_unexpected(eError::JSON_PARSE_ERROR); + payload.issuer_id = *id; + + id = BigInt::from_string(json["mint_key_id"].s()); + if (!id) + tl::make_unexpected(eError::JSON_PARSE_ERROR); + payload.mint_key_id = *id; payload.protocol_version = json["protocol_version"].s(); - payload.serial = json["serial"].s(); + id = BigInt::from_string(json["serial"].s()); + if (!id) + tl::make_unexpected(eError::JSON_PARSE_ERROR); + payload.serial = *id; return payload; } } @@ -392,7 +428,10 @@ RequestResume::from_string(const std::string &str) { } else { RequestResume r; r.message_reference = json["message_reference"].u(); - r.transaction_reference = json["transaction_reference"].s(); + auto tr = BigInt::from_string(json["transaction_reference"].s()); + if (!tr) + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + r.transaction_reference = *tr; return r; } } @@ -451,7 +490,7 @@ public: return &m_cddc; } - std::vector mint(const std::string &transaction_reference, + std::vector mint(const std::string& transaction_reference, const std::vector &blinds) override { std::vector res; cout << __FUNCTION__ << "(" @@ -462,7 +501,7 @@ public: const std::vector getMKCs(const std::vector &denominations, - const std::vector &mint_key_ids) override { + const std::vector &mint_key_ids) override { std::vector res; cout << __FUNCTION__ << endl; return res; diff --git a/src/model.hpp b/src/model.hpp index e4bb52c..584581c 100644 --- a/src/model.hpp +++ b/src/model.hpp @@ -9,10 +9,11 @@ #include "crow/json.h" #include "tl/expected.hpp" +#include "big_int.hpp" struct PublicKey { - std::string modulus; //: "daaa63ddda38c189b8c49020c8276adbe0a695685a...", - std::string public_exponent; //: 65537, + BigInt modulus; //: "daaa63ddda38c189b8c49020c8276adbe0a695685a...", + BigInt public_exponent;//: 65537, crow::json::wvalue to_json() const; }; @@ -28,15 +29,16 @@ struct WeightedUrl { struct CDD { std::string additional_info; - time_t cdd_expiry_date; //: 2023-07-22T15:45:53.164685 - std::string cdd_location; //: https://opencent.org, - size_t cdd_serial; //: 1, - time_t cdd_signing_date; //: 2022-07-22T15:45:53.164685, - size_t currency_divisor; //: 100, - std::string currency_name; //: OpenCent, - std::vector denominations; //: [1, 2, 5], - std::string id; //: 23ed956e629ba35f0002eaf833ea436aea7db5c2, - std::vector info_service; + time_t cdd_expiry_date;//: 2023-07-22T15:45:53.164685 + std::string cdd_location;//: https://opencent.org, + size_t cdd_serial;//: 1, + time_t cdd_signing_date;//: 2022-07-22T15:45:53.164685, + size_t currency_divisor;//: 100, + std::string currency_name;//: OpenCent, + std::vector denominations;//: [1, 2, 5], + BigInt id;//: 23ed956e629ba35f0002eaf833ea436aea7db5c2, + +std::vector info_service; /* eCipherSuite*/ std::string issuer_cipher_suite; //: RSA-SHA256-PSS-CHAUM82, PublicKey issuer_public_master_key; //: { @@ -63,9 +65,9 @@ struct CDDC { struct MintKey { unsigned int cdd_serial; std::string coins_expiry_date; //": "2023-10-30T15:45:53.164685", - unsigned int denomination; //": 1, - std::string id; // "1ceb977bb531c65f133ab8b0d60862b17369d96", - std::string issuer_id; //": "23ed956e629ba35f0002eaf833ea436aea7db5c2", + unsigned int denomination; //": 1, + BigInt id; // "1ceb977bb531c65f133ab8b0d60862b17369d96", + BigInt issuer_id; //": "23ed956e629ba35f0002eaf833ea436aea7db5c2", PublicKey public_mint_key; std::string sign_coins_not_after; @@ -128,7 +130,7 @@ struct RequestMKCs { std::vector denominations; unsigned int message_reference; /// Client internal message reference. /// (Integer) - std::vector mint_key_ids; + std::vector mint_key_ids; // "type": "request mint key certificates" static tl::expected from_string(const std::string &str); }; @@ -140,15 +142,15 @@ struct ResponseMKCs : Response { }; struct Blind { - std::string blinded_payload_hash; // bigint - std::string mint_key_id; // bigint + BigInt blinded_payload_hash; //bigint + BigInt mint_key_id; //bigint std::string reference; crow::json::wvalue to_json() const; static tl::expected from_json(const crow::json::rvalue &json); }; struct BlindSignature { - std::string blind_signature; + BigInt blind_signature; std::string reference; crow::json::wvalue to_json() const; }; @@ -156,7 +158,7 @@ struct BlindSignature { struct RequestMint { unsigned int message_reference; /// Client internal message reference. /// (Integer) - std::string transaction_reference; + BigInt transaction_reference; std::vector blinds; // "type": "request mint" static tl::expected from_string(const std::string &str); @@ -172,14 +174,13 @@ struct Coin { struct Payload { std::string cdd_location; unsigned int denomination; - std::string issuer_id; - std::string mint_key_id; + BigInt issuer_id; + BigInt mint_key_id; std::string protocol_version; - std::string serial; - - crow::json::wvalue to_json() const; - static tl::expected - from_json(const crow::json::rvalue &json); + BigInt serial; + + crow::json::wvalue to_json() const; + static tl::expected from_json(const crow::json::rvalue& json); }; Payload payload; @@ -213,7 +214,7 @@ struct ResponseDelay : Response { struct RequestResume { unsigned int message_reference; /// Client internal message reference. /// (Integer) - std::string transaction_reference; + BigInt transaction_reference; // "type": "request resume" static tl::expected from_string(const std::string &str); @@ -241,10 +242,10 @@ public: virtual const std::vector getMKCs(const std::vector &denominations, - const std::vector &mint_key_ids) = 0; + const std::vector &mint_key_ids) = 0; virtual std::vector - mint(const std::string &transaction_reference, + mint(std::string const& transaction_reference, const std::vector &blinds) = 0; virtual bool redeem(const std::vector &coins) = 0; diff --git a/test/test.cpp b/test/test.cpp index d4b88b9..0df0361 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -2,15 +2,17 @@ #include "model.hpp" #include -TEST_CASE("PublicKey::to_json", "[to_json]") { - PublicKey k{"daaa63ddda38c189b8c49020c8276adbe0a695685a...", "65537"}; - +TEST_CASE( "PublicKey::to_json", "[to_json]" ) { + + PublicKey k //{ BigInt::from_string("daaa63ddda38c189b8c49020c8276adbe0a695685a...").value(), + // BigInt::from_int(65537UL) }; + ; auto json = k.to_json(); - REQUIRE(json["modulus"].dump() == "\"" + k.modulus + "\""); - REQUIRE(json["public_exponent"].dump() == "\"" + k.public_exponent + "\""); - REQUIRE(json["type"].dump() == "\"rsa public key\""); - REQUIRE(json.keys().size() == 3); + REQUIRE( json["modulus"].dump() == "\"" + k.modulus.to_string() + "\"" ); + REQUIRE( json["public_exponent"].dump() == "\"" + k.public_exponent.to_string()+"\"" ); + REQUIRE( json["type"].dump() == "\"rsa public key\"" ); + REQUIRE( json.keys().size() == 3 ); } TEST_CASE("RequestCDDSerial::from_string", "[from_string]") { @@ -76,15 +78,14 @@ TEST_CASE("RequestCDDC::from_string", "[from_string]") { TEST_CASE("RequestMKCs::from_string", "[from_string]") { // good case - auto res = - RequestMKCs::from_string("{" - "\"denominations\": [1, 2, 5]," - "\"message_reference\": 100002," - "\"mint_key_ids\": []," - "\"type\": \"request mint key certificates\"" - "}"); - const std::vector EXPECTED_DENOMINATIONS = {1, 2, 5}; - const std::vector EXPECTED_MINT_KEY_IDS = {}; + auto res = RequestMKCs::from_string( "{" + "\"denominations\": [1, 2, 5]," + "\"message_reference\": 100002," + "\"mint_key_ids\": []," + "\"type\": \"request mint key certificates\"" + "}"); + const std::vector EXPECTED_DENOMINATIONS = {1,2,5}; + const std::vector EXPECTED_MINT_KEY_IDS = {}; REQUIRE(res.has_value() == true); REQUIRE(res->denominations == EXPECTED_DENOMINATIONS); @@ -129,62 +130,59 @@ TEST_CASE("Blind::from_json", "[from_string]") { auto good = crow::json::load( "{" "\"blinded_payload_hash\": " - "\"924edb672c3345492f38341ff86b57181da4c673ef...\"," + "\"924edb672c3345492f38341ff86b57181da4c673efd5fd76c0f64e369974c678f89ffcb1c5f77bf04911a9a63831b52675b70c06548a4d945ec5dd1d825ab08\"," "\"mint_key_id\": \"1ceb977bb531c65f133ab8b0d60862b17369d96\"," "\"reference\": \"a0\"," "\"type\": \"blinded payload hash\"" "}"); auto res = Blind::from_json(good); - REQUIRE(res.has_value() == true); - REQUIRE(res->blinded_payload_hash == - "924edb672c3345492f38341ff86b57181da4c673ef..."); - REQUIRE(res->mint_key_id == "1ceb977bb531c65f133ab8b0d60862b17369d96"); - REQUIRE(res->reference == "a0"); - // bad cases - // wrong_type["blinded_payload_hash"]= - // "924edb672c3345492f38341ff86b57181da4c673ef..."; wrong_type["mint_key_id"]= - // "1ceb977bb531c65f133ab8b0d60862b17369d96"; wrong_type["reference"] = "a0"; + REQUIRE(res.has_value()==true); + REQUIRE(res->blinded_payload_hash.to_string()== + "924edb672c3345492f38341ff86b57181da4c673efd5fd76c0f64e369974c678f89ffcb1c5f77bf04911a9a63831b52675b70c06548a4d945ec5dd1d825ab08"); + REQUIRE(res->mint_key_id.to_string()=="1ceb977bb531c65f133ab8b0d60862b17369d96"); + REQUIRE(res->reference=="a0"); + // bad cases + // wrong_type["blinded_payload_hash"]= "924edb672c3345492f38341ff86b57181da4c673ef..."; + // wrong_type["mint_key_id"]= "1ceb977bb531c65f133ab8b0d60862b17369d96"; + // wrong_type["reference"] = "a0"; // wrong_type["type"]= "wrong type"; // res = Blind::from_json(wrong_type); } TEST_CASE("RequestMint::from_string", "[from_string]") { - // good case - auto res = RequestMint::from_string( - "{" - "\"blinds\": [" - "{" - "\"blinded_payload_hash\": " - "\"924edb672c3345492f38341ff86b57181da4c673ef...\"," - "\"mint_key_id\": \"1ceb977bb531c65f133ab8b0d60862b17369d96\"," - "\"reference\": \"a0\"," - "\"type\": \"blinded payload hash\"" - "}," - "{" - "\"blinded_payload_hash\": " - "\"95db92e1c46ebea5edec5e508a831263de6fb78b4c...\"," - "\"mint_key_id\": \"f2864e5cd937dbaa4825e73a81062de162143682\"," - "\"reference\": \"a1\"," - "\"type\": \"blinded payload hash\"" - "}," - "{" - "\"blinded_payload_hash\": " - "\"10afac98ac43eb40e996c621d5db4d2238348e3f74...\"," - "\"mint_key_id\": \"897a16bf12bd9ba474ef7be0e3a53553a7b4ece8\"," - "\"reference\": \"a2\"," - "\"type\": \"blinded payload hash\"" - "}" - "]," - "\"message_reference\": 100003," - "\"transaction_reference\": \"b2221a58008a05a6c4647159c324c985\"," - "\"type\": \"request mint\"" - "}"); - REQUIRE(res.has_value() == true); - REQUIRE(res->message_reference == 100003); - REQUIRE(res->transaction_reference == "b2221a58008a05a6c4647159c324c985"); + // good case + auto res = RequestMint::from_string( "{" + "\"blinds\": [" + "{" + "\"blinded_payload_hash\": \"924edb672c3345492f38341ff86b57181da4c673efd5fd76c0f64e369974c678f89ffcb1c5f77bf04911a9a63831b52675b70c06548a4d945ec5dd1d825ab08\"," + "\"mint_key_id\": \"1ceb977bb531c65f133ab8b0d60862b17369d96\"," + "\"reference\": \"a0\"," + "\"type\": \"blinded payload hash\"" + "}," + "{" + "\"blinded_payload_hash\": \"95db92e1c46ebea5edec5e508a831263de6fb78b4cf9187593f6af815b51db9db35ad5eaf2c0c83bd7e13c999df4f0f1af65b367eb7c2b6addb9735dce156b5\"," + "\"mint_key_id\": \"f2864e5cd937dbaa4825e73a81062de162143682\"," + "\"reference\": \"a1\"," + "\"type\": \"blinded payload hash\"" + "}," + "{" + "\"blinded_payload_hash\": \"10afac98ac43eb40e996c621d5db4d2238348e3f74850856d940955da0fd24fa4d3aee79da1e9da24e85cf9cefd96feaca5b26a9353a3d9fcb4bd34145046ce8\"," + "\"mint_key_id\": \"897a16bf12bd9ba474ef7be0e3a53553a7b4ece8\"," + "\"reference\": \"a2\"," + "\"type\": \"blinded payload hash\"" + "}" + "]," + "\"message_reference\": 100003," + "\"transaction_reference\": \"b2221a58008a05a6c4647159c324c985\"," + "\"type\": \"request mint\"" + "}"); + + REQUIRE(res.has_value()==true); + REQUIRE(res->message_reference==100003); + REQUIRE(res->transaction_reference.to_string() == "b2221a58008a05a6c4647159c324c985"); /// \todo check blinds // bad cases @@ -280,17 +278,16 @@ TEST_CASE("RequestRenew::from_string", "[from_string]") { TEST_CASE("RequestResume::from_string", "[from_string]") { // good case - auto res = RequestResume::from_string( - "{" - "\"message_reference\": 100005," - "\"transaction_reference\": \"ad45f23d3b1a11df587fd2803bab6c39\"," - "\"type\": \"request resume\"" - "}"); - - REQUIRE(res.has_value() == true); - REQUIRE(res->message_reference == 100005); - REQUIRE(res->transaction_reference == "ad45f23d3b1a11df587fd2803bab6c39"); + auto res = RequestResume::from_string( "{" + "\"message_reference\": 100005," + "\"transaction_reference\": \"ad45f23d3b1a11df587fd2803bab6c39\"," + "\"type\": \"request resume\"" + "}"); + REQUIRE(res.has_value()==true); + REQUIRE(res->message_reference==100005); + REQUIRE(res->transaction_reference.to_string()=="ad45f23d3b1a11df587fd2803bab6c39"); + // bad cases res = RequestResume::from_string(""); REQUIRE(res.has_value() == false); diff --git a/test/test_big_int.cpp b/test/test_big_int.cpp new file mode 100644 index 0000000..0a168dd --- /dev/null +++ b/test/test_big_int.cpp @@ -0,0 +1,37 @@ +#include "big_int.hpp" +#include + +TEST_CASE("BigInt::from_string", "[big_int]") { + std::string VALID [] = { + "1", + "12", + "123", + "1234", + "12345", + "123456", + "120456", + "123056", + "120345", + "1234560abc", + "aabbcc", + "abcdef1" + }; + + for (size_t i= 0; ito_string() == VALID[i]); + REQUIRE(b.has_value()); + } + + auto invalid_hex = "aabbcc.."; + { + auto b = BigInt::from_string(invalid_hex); + REQUIRE(!b); + } + +} + +TEST_CASE("BigInt::from_int", "[big_int]") { + auto b = BigInt::from_int(0xaabbccdd); + REQUIRE(b.to_string()=="aabbccdd"); +}