diff --git a/README.md b/README.md index 54075d42..ebf6f84d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ A C++ version of hotpocket designed for production envrionments, original protot ## Steps to setup Hot Pocket -### Install Libsodium +#### Install Libsodium Instructions are based on [this](https://libsodium.gitbook.io/doc/installation). 1. Download and extract Libsodium 1.0.18 from [here](https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz). @@ -46,4 +46,31 @@ This will update your library cache and avoid potential issues when running your 3. Run `./build/hpcore new ~/mycontract`. This will initialize a new contract directory `mycontract` in your home directory. 4. Take a look at `~/mycontract/cfg/hp.cfg`. This is your new contract config file. You can modify it according to your contract hosting requirements. 5. Optional: Run `./build/hpcore rekey ~/mycontract` to generate new public/private key pair. -6. Run `./build/hpcore run ~/mycontract` to run your smart contract (to do). \ No newline at end of file +6. Run `./build/hpcore run ~/mycontract` to run your smart contract (to do). + +## Code structure +Code is divided into subsystems via namespaces. Some subsystems mentioned here are yet to be introduced. + +#### conf +Handles contract configuration. Loads and holds the central configuration object. Used by most of the subsystems. + +#### crypto +Handles cryptographic activities. Wraps libsodium and offers convinience functions. + +#### proc +Handles contract process execution. + +#### usr +Handles user connections and processing of user I/O with the smart contract. Makes use of **crypto** and **sock**. + +#### ntn +Handles node-to-node connections and message exchange between nodes. Also handles smart contract node-party-line (npl) I/O. Makes use of **crypto** and **sock**. + +#### cons +Handles consensus and proposal rounds. Makes use of **usr**, **ntn** and **proc** + +#### sock +Handles generic web sockets functionality. Mainly acts as a wrapper for boost/beast. + +#### shared +Contains shared data structures/helper functions used by multiple subsystems. Used by most of the subsystems. \ No newline at end of file diff --git a/makefile b/makefile index 77a96895..844d6224 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ all: mkdir -p build - g++ src/*.cpp -lsodium -lboost_system -lboost_filesystem -std=c++17 -o build/hpcore + g++ src/*.cpp src/usr/*.cpp -lsodium -lboost_system -lboost_filesystem -std=c++17 -o build/hpcore echo 'build successful, binary in '`pwd`'/build/hpcore' diff --git a/src/crypto.cpp b/src/crypto.cpp index aa3456a0..7c03f720 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -3,6 +3,7 @@ #include #include "conf.h" #include "crypto.h" +#include "shared.h" using namespace std; using namespace rapidjson; @@ -11,8 +12,6 @@ namespace crypto { void generate_crypto_keys(); -string base64_encode(unsigned char *bin, size_t bin_len); -int base64_decode(string base64_str, unsigned char *decoded, size_t decoded_len); void binpair_to_b64(); int b64pair_to_bin(); @@ -25,7 +24,7 @@ string sign_b64(string msg) { unsigned char sig[crypto_sign_BYTES]; crypto_sign_detached(sig, NULL, (unsigned char *)msg.data(), msg.size() + 1, conf::cfg.seckey); - return base64_encode(sig, crypto_sign_BYTES); + return shared::base64_encode(sig, crypto_sign_BYTES); } bool verify(const unsigned char *msg, unsigned long long msg_len, const unsigned char *sig, const unsigned char *pubkey) @@ -37,10 +36,10 @@ bool verify(const unsigned char *msg, unsigned long long msg_len, const unsigned bool verify_b64(string msg, string sigb64, string pubkeyb64) { unsigned char decoded_pubkey[crypto_sign_PUBLICKEYBYTES]; - base64_decode(pubkeyb64, decoded_pubkey, crypto_sign_PUBLICKEYBYTES); + shared::base64_decode(pubkeyb64, decoded_pubkey, crypto_sign_PUBLICKEYBYTES); unsigned char decoded_sig[crypto_sign_BYTES]; - base64_decode(sigb64, decoded_sig, crypto_sign_BYTES); + shared::base64_decode(sigb64, decoded_sig, crypto_sign_BYTES); int result = crypto_sign_verify_detached(decoded_sig, (unsigned char *)msg.data(), msg.size() + 1, decoded_pubkey); return result == 0; @@ -102,43 +101,10 @@ void generate_crypto_keys() crypto_sign_keypair(conf::cfg.pubkey, conf::cfg.seckey); } -string base64_encode(unsigned char *bin, size_t bin_len) -{ - const size_t base64_max_len = sodium_base64_encoded_len(bin_len, sodium_base64_VARIANT_ORIGINAL); - char base64_str[base64_max_len]; - - char *encoded_str_char = sodium_bin2base64( - base64_str, base64_max_len, - bin, bin_len, - sodium_base64_VARIANT_ORIGINAL); - - if (encoded_str_char == NULL) - throw "Base64 Error: Failed to encode string"; - - string s(base64_str); - return s; -} - -int base64_decode(string base64_str, unsigned char *decoded, size_t decoded_len) -{ - const char *b64_end; - size_t bin_len; - if (sodium_base642bin( - decoded, decoded_len, - base64_str.data(), base64_str.size() + 1, - "", &bin_len, &b64_end, - sodium_base64_VARIANT_ORIGINAL)) - { - return 0; - } - - return 1; -} - void binpair_to_b64() { - conf::cfg.pubkeyb64 = base64_encode(conf::cfg.pubkey, crypto_sign_PUBLICKEYBYTES); - conf::cfg.seckeyb64 = base64_encode(conf::cfg.seckey, crypto_sign_SECRETKEYBYTES); + conf::cfg.pubkeyb64 = shared::base64_encode(conf::cfg.pubkey, crypto_sign_PUBLICKEYBYTES); + conf::cfg.seckeyb64 = shared::base64_encode(conf::cfg.seckey, crypto_sign_SECRETKEYBYTES); } int b64pair_to_bin() @@ -146,13 +112,13 @@ int b64pair_to_bin() unsigned char *decoded_pubkey = (unsigned char *)malloc(crypto_sign_PUBLICKEYBYTES); unsigned char *decoded_seckey = (unsigned char *)malloc(crypto_sign_SECRETKEYBYTES); - if (!base64_decode(conf::cfg.pubkeyb64, decoded_pubkey, crypto_sign_PUBLICKEYBYTES)) + if (!shared::base64_decode(conf::cfg.pubkeyb64, decoded_pubkey, crypto_sign_PUBLICKEYBYTES)) { cerr << "Error decoding public key.\n"; return 0; } - if (!base64_decode(conf::cfg.seckeyb64, decoded_seckey, crypto_sign_SECRETKEYBYTES)) + if (!shared::base64_decode(conf::cfg.seckeyb64, decoded_seckey, crypto_sign_SECRETKEYBYTES)) { cerr << "Error decoding secret key.\n"; return 0; diff --git a/src/main.cpp b/src/main.cpp index 057f7728..cf32922e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,7 +7,7 @@ #include #include "conf.h" #include "crypto.h" -#include "usr.h" +#include "usr/usr.h" #include "proc.h" using namespace std; diff --git a/src/shared.cpp b/src/shared.cpp new file mode 100644 index 00000000..84e9fbda --- /dev/null +++ b/src/shared.cpp @@ -0,0 +1,42 @@ +#include +#include + +using namespace std; + +namespace shared +{ + +string base64_encode(unsigned char *bin, size_t bin_len) +{ + const size_t base64_max_len = sodium_base64_encoded_len(bin_len, sodium_base64_VARIANT_ORIGINAL); + char base64_str[base64_max_len]; + + char *encoded_str_char = sodium_bin2base64( + base64_str, base64_max_len, + bin, bin_len, + sodium_base64_VARIANT_ORIGINAL); + + if (encoded_str_char == NULL) + throw "Base64 Error: Failed to encode string"; + + string s(base64_str); + return s; +} + +int base64_decode(string base64_str, unsigned char *decoded, size_t decoded_len) +{ + const char *b64_end; + size_t bin_len; + if (sodium_base642bin( + decoded, decoded_len, + base64_str.data(), base64_str.size() + 1, + "", &bin_len, &b64_end, + sodium_base64_VARIANT_ORIGINAL)) + { + return 0; + } + + return 1; +} + +} \ No newline at end of file diff --git a/src/shared.h b/src/shared.h index c4bc750b..fe28da3e 100644 --- a/src/shared.h +++ b/src/shared.h @@ -26,6 +26,9 @@ struct ContractUser } }; +string base64_encode(unsigned char *bin, size_t bin_len); +int base64_decode(string base64_str, unsigned char *decoded, size_t decoded_len); + } // namespace usr #endif \ No newline at end of file diff --git a/src/usr.cpp b/src/usr/usr.cpp similarity index 91% rename from src/usr.cpp rename to src/usr/usr.cpp index ff384328..1b3ef0e4 100644 --- a/src/usr.cpp +++ b/src/usr/usr.cpp @@ -3,10 +3,11 @@ #include #include #include -#include "proc.h" +#include "../shared.h" #include "usr.h" using namespace std; +using namespace shared; namespace usr { @@ -52,12 +53,6 @@ void remove_user(string pubkeyb64) //Read per-user outputs produced by the contract process. int read_contract_user_outputs() { - if (proc::is_contract_running()) - { - cerr << "Contract process still running.\n"; - return 0; - } - for (auto& [pk, user] : users) { int fdout = user.outpipe[0]; diff --git a/src/usr.h b/src/usr/usr.h similarity index 90% rename from src/usr.h rename to src/usr/usr.h index 15383a7a..bb10ea6a 100644 --- a/src/usr.h +++ b/src/usr/usr.h @@ -4,7 +4,7 @@ #include #include #include -#include "shared.h" +#include "../shared.h" using namespace std; using namespace shared;