From 4d9f373d62aa973b310a777b6ab85893f5d8321e Mon Sep 17 00:00:00 2001 From: gulliver Date: Fri, 18 Nov 2022 15:47:52 +0100 Subject: [PATCH] implemented jsn encoding for req and responses --- CMakeLists.txt | 11 ++- src/main.cpp | 114 +++++++++++++++---------- src/model.cpp | 223 +++++++++++++++++++++++++++++++++++++++++++++---- src/model.hpp | 144 +++++++++++++++++++++++++++++-- 4 files changed, 419 insertions(+), 73 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 126cf29..4738a99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,16 @@ FetchContent_Declare(expected if(NOT expected_POPULATED) FetchContent_Populate(expected) endif(NOT expected_POPULATED) - + +find_package(Doxygen + REQUIRED dot + OPTIONAL_COMPONENTS mscgen dia) +set(DOXYGEN_HAVE_DOT YES) +doxygen_add_docs( + doc + src + COMMENT "Generate dcoumentation" +) set(API_SOURCES src/main.cpp src/model.cpp src/model.hpp) add_executable(oc-mint ${API_SOURCES}) target_link_libraries(oc-mint PRIVATE Crow::Crow INTERFACE tl::expected::expected) diff --git a/src/main.cpp b/src/main.cpp index 3bdd5ad..c6ac98c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,72 +1,96 @@ -#include "crow/http_response.h" -#include "crow/json.h" -#include - #include "crow.h" - #include "model.hpp" - int main() { crow::SimpleApp app; std::shared_ptr model = Model::getModel("simple"); - CROW_ROUTE(app, "/cddc")//.methods(crow::HTTPMethod::GET) + CROW_ROUTE(app, "/cddc") ([&model](const crow::request& req){ - auto json = crow::json::load(req.body); - if (!json) { - return crow::response(crow::status::BAD_REQUEST, - "json parse error"); + auto req_cddc = RequestCDDC::from_string(req.body); + if (!req_cddc) { + return crow::response(crow::status::BAD_REQUEST); } else { - auto req_cddc = RequestCDDC::from_json(json); - if (!req_cddc) - return crow::response(crow::status::BAD_REQUEST, - "json decode error "); - else { - ResponseCDDC res; - // TBD use serial from req - res.cddc = model->getCDDC(); - res.message_reference = req_cddc->message_reference; - res.status_code = 200; - return crow::response(res.to_json()); - } + ResponseCDDC res; + // TBD use serial from req + res.cddc = model->getCDDC(); + res.message_reference = req_cddc->message_reference; + res.status_code = crow::status::OK; + return crow::response(res.to_json()); } }); - CROW_ROUTE(app, "/cddc/serial").methods(crow::HTTPMethod::GET) - ([](){ - return crow::response(crow::status::NOT_IMPLEMENTED); + CROW_ROUTE(app, "/cddc/serial") + ([&model](const crow::request& request){ + auto req = RequestCDDSerial::from_string(request.body); + if (!req) { + return crow::response(crow::status::BAD_REQUEST); + } else { + // \todo check serial input + ResponseCDDSerial res; + res.cdd_serial = model->getCurrentCDDC().cdd.cdd_serial; + res.message_reference = req->message_reference; + res.status_code = crow::status::OK; + return crow::response(res.to_json()); + } }); - CROW_ROUTE(app, "/mkcs").methods(crow::HTTPMethod::GET) - ([](){ - return crow::response(crow::status::NOT_IMPLEMENTED); - }); + CROW_ROUTE(app, "/mkcs") + ([&model](const crow::request& request){ + auto req = RequestMKCs::from_string(request.body); + if (!req) { + return crow::response(crow::status::BAD_REQUEST); + } else { + // \todo implement request + return crow::response(crow::status::NOT_IMPLEMENTED); + } + }); CROW_ROUTE(app, "/mint").methods(crow::HTTPMethod::GET) - ([](){ - return crow::response(crow::status::NOT_IMPLEMENTED); - }); + ([&model](const crow::request& request){ + auto req = RequestMint::from_string(request.body); + if (!req) { + return crow::response(crow::status::BAD_REQUEST); + } else { + // \todo implement request + return crow::response(crow::status::NOT_IMPLEMENTED); + } + }); CROW_ROUTE(app, "/renew").methods(crow::HTTPMethod::GET) - ([](){ - return crow::response(crow::status::NOT_IMPLEMENTED); - }); + ([&model](const crow::request& request){ + auto req = RequestMint::from_string(request.body); + if (!req) { + return crow::response(crow::status::BAD_REQUEST); + } else { + // \todo implement request + return crow::response(crow::status::NOT_IMPLEMENTED); + } + }); CROW_ROUTE(app, "/resume").methods(crow::HTTPMethod::GET) - ([](){ - return crow::response(crow::status::NOT_IMPLEMENTED); - }); + ([&model](const crow::request& request){ + auto req = RequestResume::from_string(request.body); + if (!req) { + return crow::response(crow::status::BAD_REQUEST); + } else { + // \todo implement request + return crow::response(crow::status::NOT_IMPLEMENTED); + } + }); CROW_ROUTE(app, "/redeem").methods(crow::HTTPMethod::GET) - ([](){ - return crow::response(crow::status::NOT_IMPLEMENTED); - }); - - - + ([&model](const crow::request& request){ + auto req = RequestRedeem::from_string(request.body); + if (!req) { + return crow::response(crow::status::BAD_REQUEST); + } else { + // \todo implement request + return crow::response(crow::status::NOT_IMPLEMENTED); + } + }); app.port(18080).run(); } diff --git a/src/model.cpp b/src/model.cpp index 975968c..0ccbcd1 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -3,7 +3,7 @@ #define TO_JSON(name) r[#name]=name #define TO_JSON_JSON(name) r[#name]=name.to_json() -#define SEQ_TO_JSON(name) r[#name]=list_to_json(name) +#define TO_JSON_ARRAY(name) r[#name]=list_to_json(name) template crow::json::wvalue list_to_json(const std::vector& array) { @@ -49,15 +49,15 @@ crow::json::wvalue CDD::to_json() const { TO_JSON(cdd_signing_date); TO_JSON(currency_divisor); TO_JSON( currency_name); - SEQ_TO_JSON(denominations); + TO_JSON_ARRAY(denominations); TO_JSON(id); - SEQ_TO_JSON(info_service); + TO_JSON_ARRAY(info_service); TO_JSON(issuer_cipher_suite); TO_JSON_JSON(issuer_public_master_key); - SEQ_TO_JSON(mint_service); + TO_JSON_ARRAY(mint_service); TO_JSON(protocol_version); - SEQ_TO_JSON(redeem_service); - SEQ_TO_JSON(renew_service); + TO_JSON_ARRAY(redeem_service); + TO_JSON_ARRAY(renew_service); r["type"]= "cdd"; return r; @@ -97,36 +97,223 @@ crow::json::wvalue MintKeyCert::to_json() const { return r; } -crow::json::wvalue ResponseCDDC::to_json() const +crow::json::wvalue Response::to_json() const { crow::json::wvalue r; - TO_JSON_JSON(cddc); TO_JSON(message_reference); TO_JSON(status_code); TO_JSON(status_description); - - r["type"]= "response cddc"; return r; } -std::optional RequestCDDC::from_json(const crow::json::rvalue & json) { - if (json.has("cdd_serial")&&json.has("message_reference")) { - auto r = std::make_optional(); - r->cdd_serial=json["cdd_serial"].u(); - r->message_reference= json["message_reference"].u(); + +crow::json::wvalue ResponseCDDSerial::to_json() const +{ + crow::json::wvalue r = Response::to_json(); + TO_JSON(cdd_serial); + + r["type"]= "response cdd serial"; + return r; +} + +tl::expected +RequestCDDSerial::from_string(const std::string& str) +{ + auto json = crow::json::load(str); + if (!json) { + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } else if (!json.has("message_reference")) { + return tl::make_unexpected(eError::JSON_ERROR); + } else { + RequestCDDSerial r; + r.message_reference= json["message_reference"].u(); return r; } - else { - return std::nullopt; +} + +crow::json::wvalue ResponseCDDC::to_json() const +{ + crow::json::wvalue r = Response::to_json(); + TO_JSON_JSON(cddc); + r["type"]= "response cdd serial"; + return r; +} + +tl::expected +RequestCDDC::from_string(const std::string& str) +{ + auto json = crow::json::load(str); + if (!json) { + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } else if (!(json.has("cdd_serial")&&json.has("message_reference"))) { + return tl::make_unexpected(eError::JSON_ERROR); + } else { + RequestCDDC r; + r.cdd_serial=json["cdd_serial"].u(); + r.message_reference= json["message_reference"].u(); + return r; } +} + +tl::expected +RequestMKCs::from_string(const std::string& str) { + std::vector denominations; + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + std::vector mint_key_ids; + // "type": "request mint key certificates" + + auto json = crow::json::load(str); + if (!json) { + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } else { + return tl::make_unexpected(eError::NOT_IMPLEMENTED); + } +} + + +crow::json::wvalue ResponseMKCs::to_json() const{ + crow::json::wvalue r = Response::to_json(); + TO_JSON_ARRAY(keys); + r["type"]= "response mint key certificates"; + return r; +} + +crow::json::wvalue Blind::to_json() const { + crow::json::wvalue r; + TO_JSON(blinded_payload_hash); + TO_JSON(mint_key_id); + TO_JSON(reference); + r["type"]= "blinded payload hash"; + return r; } -/** blafasel */ +crow::json::wvalue BlindSignature::to_json() const { + crow::json::wvalue r; + TO_JSON(blind_signature); + TO_JSON(reference); + r["type"]= "blind signature"; + return r; + +} + +tl::expected +RequestMint::from_string(const std::string& str){ + std::vector blinds; + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + // "type": "request mint" + auto json = crow::json::load(str); + if (!json) { + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } else { + return tl::make_unexpected(eError::NOT_IMPLEMENTED); + } +} + +crow::json::wvalue ResponseMint::to_json() const { + crow::json::wvalue r = Response::to_json(); + TO_JSON_ARRAY(blind_signatures); + r["type"]= "response mint"; + return r; +} + +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); + TO_JSON(protocol_version); + TO_JSON(serial); + + r["type"]= "payload"; + return r; +} + +crow::json::wvalue Coin::to_json() const +{ + crow::json::wvalue r; + TO_JSON_JSON(payload); + TO_JSON(signature); + r["type"]= "coin"; + return r; +} + +crow::json::wvalue CoinStack::to_json() const { + crow::json::wvalue r; + TO_JSON_ARRAY(coins); + TO_JSON(subject); + r["type"]= "coinstack"; + return r; +} + + +tl::expected +RequestRenew::from_string(const std::string& str) { + std::vector blinds; + std::vector coins; + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + unsigned int transaction_reference; + // "type": "request renew" + auto json = crow::json::load(str); + if (!json) { + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } else { + return tl::make_unexpected(eError::NOT_IMPLEMENTED); + } +} + +crow::json::wvalue ResponseDelay::to_json() const { + crow::json::wvalue r = Response::to_json(); + r["type"]= "response delay"; + return r; +} + +tl::expected +RequestResume::from_string(const std::string& str) { + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + unsigned int transaction_reference; + // "type": "request resume" + auto json = crow::json::load(str); + if (!json) { + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } else { + return tl::make_unexpected(eError::NOT_IMPLEMENTED); + } +} + +tl::expected +RequestRedeem::from_string(const std::string& str) { + std::vector coins; + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + unsigned int transaction_reference; + // "type": "request redeem" + auto json = crow::json::load(str); + if (!json) { + return tl::make_unexpected(eError::JSON_PARSE_ERROR); + } else { + return tl::make_unexpected(eError::NOT_IMPLEMENTED); + } +} + +crow::json::wvalue ResponseReedem::to_json() const { + crow::json::wvalue r = Response::to_json(); + r["type"]= "response redeem"; + return r; +} + + +/** this is for now our sample model */ class DefaultModel : public Model { public: DefaultModel() {} const CDDC& getCDDC() override {return m_cddc; }; + const CDDC& getCurrentCDDC() override {return m_cddc; }; void mint() override {}; private: diff --git a/src/model.hpp b/src/model.hpp index a2d1c86..4067575 100644 --- a/src/model.hpp +++ b/src/model.hpp @@ -10,6 +10,7 @@ #include "tl/expected.hpp" + struct PublicKey { std::string modulus; //: "daaa63ddda38c189b8c49020c8276adbe0a695685a...", std::string public_exponent;//: 65537, @@ -24,7 +25,6 @@ struct WeightedUrl { crow::json::wvalue to_json() const; }; - /** currency description document */ struct CDD { @@ -80,28 +80,154 @@ struct MintKeyCert { crow::json::wvalue to_json() const; }; -struct RequestCDDC { - unsigned int cdd_serial;/// The version of the CDD. (Int) - unsigned int message_reference; /// Client internal message reference. - /// (Integer) - static std::optional from_json(const crow::json::rvalue & json); +enum class eError { + JSON_PARSE_ERROR, + JSON_ERROR, + NOT_IMPLEMENTED }; -struct ResponseCDDC { - CDDC cddc; +struct Response { unsigned int message_reference; unsigned int status_code; std::string status_description; + virtual crow::json::wvalue to_json() const; +}; + +struct RequestCDDSerial { + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + static tl::expected from_string(const std::string& str); +}; + +struct ResponseCDDSerial: Response { + unsigned int cdd_serial; + + crow::json::wvalue to_json() const override; +}; + +struct RequestCDDC { + unsigned int cdd_serial;/// The version of the CDD. (Int) + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + static tl::expected from_string(const std::string& str); +}; + +struct ResponseCDDC : Response { + CDDC cddc; + + crow::json::wvalue to_json() const override; +}; + +struct RequestMKCs { + std::vector denominations; + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + std::vector mint_key_ids; + // "type": "request mint key certificates" + static tl::expected from_string(const std::string& str); +}; + +struct ResponseMKCs: Response { + std::vector keys; + + crow::json::wvalue to_json() const override; +}; + +struct Blind { + std::string blinded_payload_hash; + std::string mint_key_id; + std::string reference; crow::json::wvalue to_json() const; }; - +struct BlindSignature { + std::string blind_signature; + std::string reference; + crow::json::wvalue to_json() const; +}; + +struct RequestMint { + std::vector blinds; + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + // "type": "request mint" + static tl::expected from_string(const std::string& str); +}; + +struct ResponseMint : Response { + std::vector blind_signatures; + + crow::json::wvalue to_json() const override; +}; + + +struct Coin { + struct Payload { + std::string cdd_location; + unsigned int denomination; + std::string issuer_id; + std::string mint_key_id; + std::string protocol_version; + std::string serial; + + crow::json::wvalue to_json() const; +}; + + Payload payload; + std::string signature; + + crow::json::wvalue to_json() const; +}; + +struct CoinStack { + std::vector coins; + std::string subject; + // "type": "coinstack" + crow::json::wvalue to_json() const; +}; + +struct RequestRenew { + std::vector blinds; + std::vector coins; + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + unsigned int transaction_reference; + // "type": "request renew" + static tl::expected from_string(const std::string& str); +}; + +struct ResponseDelay : Response { + crow::json::wvalue to_json() const override; +}; + +struct RequestResume { + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + unsigned int transaction_reference; + // "type": "request resume" + static tl::expected from_string(const std::string& str); +}; + +struct RequestRedeem { + std::vector coins; + unsigned int message_reference; /// Client internal message reference. + /// (Integer) + unsigned int transaction_reference; + // "type": "request redeem" + static tl::expected from_string(const std::string& str); +}; + +struct ResponseReedem : Response { + crow::json::wvalue to_json() const override; +}; + class Model { public: virtual ~Model(){}; virtual const CDDC& getCDDC() = 0; + virtual const CDDC& getCurrentCDDC() = 0; virtual void mint() = 0; static std::unique_ptr getModel(const std::string& backend_name);