From 7449f73e89ccb6d1cae09716eac5bc9d6ee7e8f0 Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 14 Sep 2020 21:09:18 +0200 Subject: [PATCH] Update code for sending transaction over hedera --- src/cpp/Crypto/KeyPairHedera.cpp | 18 + src/cpp/Crypto/KeyPairHedera.h | 7 +- .../HTTPInterface/AdminHederaAccountPage.cpp | 364 ++++++++++++------ .../SingletonManager/HederaTaskManager.cpp | 17 + src/cpp/SingletonManager/HederaTaskManager.h | 23 ++ src/cpp/SingletonManager/SessionManager.cpp | 1 + src/cpp/SingletonManager/SessionManager.h | 1 + src/cpp/controller/HederaAccount.cpp | 75 +++- src/cpp/controller/HederaAccount.h | 9 + src/cpp/controller/HederaId.cpp | 47 +++ src/cpp/controller/HederaId.h | 6 + src/cpp/controller/HederaRequest.cpp | 28 ++ src/cpp/controller/HederaRequest.h | 7 + src/cpp/controller/HederaTopic.cpp | 2 + src/cpp/controller/HederaTopic.h | 4 +- src/cpp/lib/DataTypeConverter.cpp | 28 ++ src/cpp/lib/DataTypeConverter.h | 1 + .../model/hedera/ConsensusSubmitMessage.cpp | 42 ++ src/cpp/model/hedera/ConsensusSubmitMessage.h | 32 ++ .../model/hedera/CryptoCreateTransaction.cpp | 22 +- .../model/hedera/CryptoCreateTransaction.h | 10 +- .../hedera/CryptoTransferTransaction.cpp | 5 - .../model/hedera/CryptoTransferTransaction.h | 2 +- src/cpp/model/hedera/Transaction.cpp | 29 ++ src/cpp/model/hedera/Transaction.h | 3 + src/cpp/model/hedera/TransactionBody.cpp | 46 ++- src/cpp/model/hedera/TransactionBody.h | 16 + src/cpp/model/hedera/TransactionResponse.cpp | 18 + src/cpp/model/hedera/TransactionResponse.h | 30 ++ src/cpp/model/table/HederaId.cpp | 7 + src/cpp/model/table/HederaId.h | 4 +- src/cpp/tasks/HederaTask.cpp | 0 src/cpp/tasks/HederaTask.h | 15 + src/cpp/tasks/SigningTransaction.cpp | 41 ++ src/cpsp/adminHederaAccount.cpsp | 291 +++++++++----- 35 files changed, 1009 insertions(+), 242 deletions(-) create mode 100644 src/cpp/SingletonManager/HederaTaskManager.cpp create mode 100644 src/cpp/SingletonManager/HederaTaskManager.h create mode 100644 src/cpp/model/hedera/TransactionResponse.cpp create mode 100644 src/cpp/model/hedera/TransactionResponse.h create mode 100644 src/cpp/tasks/HederaTask.cpp create mode 100644 src/cpp/tasks/HederaTask.h diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index e3a377864..c2738e886 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -96,6 +96,24 @@ KeyPairHedera::~KeyPairHedera() } } +KeyPairHedera* KeyPairHedera::create() +{ + /* + The crypto_sign_keypair() function randomly generates a secret key and a corresponding public key. + The public key is put into pk (crypto_sign_PUBLICKEYBYTES bytes) + and the secret key into sk (crypto_sign_SECRETKEYBYTES bytes). + */ + + assert(getPublicKeySize() == crypto_sign_PUBLICKEYBYTES); + + auto mm = MemoryManager::getInstance(); + auto private_key = mm->getFreeMemory(crypto_sign_SECRETKEYBYTES); + auto public_key = mm->getFreeMemory(getPublicKeySize()); + + crypto_sign_keypair(*public_key, *private_key); + return new KeyPairHedera(private_key, public_key); +} + void KeyPairHedera::createKeyFromSeed(const unsigned char* seed, size_t seedSize) { diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h index 4613618c5..769f29af6 100644 --- a/src/cpp/Crypto/KeyPairHedera.h +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -26,6 +26,9 @@ public: KeyPairHedera(const unsigned char* privateKey, size_t privateKeySize, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0); KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey = nullptr); KeyPairHedera(const std::vector& privateKey, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0); + + + static KeyPairHedera* create(); ~KeyPairHedera(); @@ -43,12 +46,12 @@ public: const static size_t getPublicKeySize() {return ed25519_pubkey_SIZE;} inline bool isTheSame(const KeyPairHedera& b) const { - return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, ed25519_pubkey_SIZE); + return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, getPublicKeySize()); } inline bool isTheSame(const unsigned char* pubkey) const { if (!pubkey) return false; - return 0 == sodium_memcmp(mPublicKey, pubkey, ed25519_pubkey_SIZE); + return 0 == sodium_memcmp(mPublicKey, pubkey, getPublicKeySize()); } //! \return 0 if the same //! \return -1 if not the same diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index 3247e1130..5ff4f7218 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -45,6 +45,9 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request auto sm = SessionManager::getInstance(); auto mm = MemoryManager::getInstance(); auto user = mSession->getNewUser(); + int auto_renew_period = 604800; // 7 Tage + int auto_renew_account = 0; + double initial_balance = 0.0; Profiler hedera_time; std::string hedera_time_string; @@ -80,8 +83,11 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if(action == "updateBalance") { hedera_time.reset(); - query_hedera_account->hederaAccountGetBalance(user); - addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + if(query_hedera_account->hederaAccountGetBalance(user)) { + addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + } else { + addError(new ParamError("Hedera", "crypto get balance failed in ", hedera_time.string())); + } } else if(action == "changeEncryption") { @@ -90,113 +96,150 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request } } } - else if(!form.empty()) // add + else if(!form.empty()) // add or create { - // collect - auto shardNumString = form.get("account-shard-num", "0"); - auto realmNumString = form.get("account-realm-num", "0"); - auto numString = form.get("account-num", "0"); - auto privateKeyString = form.get("account-private-key", ""); - auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); - auto publicKeyString = form.get("account-public-key", ""); - auto networkTypeString = form.get("account-network-type", "0"); + auto creationButton = form.get("create",""); + if(creationButton != "") { - //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); - - int shardNum = 0; - int realmNum = 0; - int num = 0; - int networkType = 0; - - MemoryBin* private_key = nullptr; - MemoryBin* public_key = nullptr; - - // validate - if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "shard num not integer")); - } else { - if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting shardNumString to int")); - } - } - if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "realm num not integer")); - } else { - if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting realmNumString to int")); - } - } - if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "num not integer")); - } else { - if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting num to int")); - } - } - if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { - addError(new Error("Account Keys", "private key not hex")); - } - if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { - addError(new Error("Account Keys", "public key not hex")); - } - if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Network Type", "not integer")); - } else { - if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting network type to int")); - } - if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { - addError(new Error("Network Type", "invalid value")); - } - } - - if(0 == errorCount()) { - - auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + // collect + auto auto_renew_account_string = form.get("account-auto-renew-account", "0"); + auto auto_renew_period_string = form.get("account-auto-renew-period", "604800"); + auto account_initial_balance_string = form.get("account-initial-balance", "0"); - private_key = DataTypeConverter::hexToBin(privateKeyString); - public_key = DataTypeConverter::hexToBin(publicKeyString); - - - KeyPairHedera key_pair(private_key, public_key); - auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); - - if(crypto_key.isNull()) { - crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); - if(!crypto_key->getModel()->insertIntoDB(true)) { - addError(new Error("DB Error", "Error saving crypto key in DB")); - } + if(!sm->isValid(auto_renew_account_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account", "auto renew account id not an integer")); } else { - printf("crypto key found in db\n"); - } - if(0 == errorCount()) { - - if(hedera_id->isExistInDB()) { - auto hedera_account = controller::HederaAccount::load(hedera_id); - if(hedera_account.isNull()) { - addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); - } else { - addError(new Error("Hedera Account", "Account already exist (same account id")); - } - - } else { - auto hedera_account = controller::HederaAccount::create( - user->getModel()->getID(), - hedera_id->getModel()->getID(), - crypto_key->getModel()->getID(), - 0, - (model::table::HederaNetworkType)networkType - ); - if(!hedera_account->getModel()->insertIntoDB(false)) { - addError(new Error("DB Error", "Error saving hedera account into DB")); - } + if(DataTypeConverter::strToInt(auto_renew_account_string, auto_renew_account) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew account id to int")); } } - mm->releaseMemory(private_key); - mm->releaseMemory(public_key); - } + if(!sm->isValid(auto_renew_period_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account", "auto renew period not an integer")); + } else { + if(DataTypeConverter::strToInt(auto_renew_period_string, auto_renew_period) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew period to int")); + } + } + + if(!sm->isValid(account_initial_balance_string, VALIDATE_ONLY_DECIMAL)) { + addError(new Error("Account", "initial balance not an decimal")); + } else { + if(DataTypeConverter::strToDouble(account_initial_balance_string, initial_balance) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Double convert error", "Error converting initial balance to double")); + } + } + if(0 == errorCount()) + { + } + + } else { + // collect + auto shardNumString = form.get("account-shard-num", "0"); + auto realmNumString = form.get("account-realm-num", "0"); + auto numString = form.get("account-num", "0"); + auto privateKeyString = form.get("account-private-key", ""); + auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); + auto publicKeyString = form.get("account-public-key", ""); + auto networkTypeString = form.get("account-network-type", "0"); + + //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); + + int shardNum = 0; + int realmNum = 0; + int num = 0; + int networkType = 0; + + MemoryBin* private_key = nullptr; + MemoryBin* public_key = nullptr; + + // validate + if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "shard num not integer")); + } else { + if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting shardNumString to int")); + } + } + if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "realm num not integer")); + } else { + if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting realmNumString to int")); + } + } + if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "num not integer")); + } else { + if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting num to int")); + } + } + if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "private key not hex")); + } + if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "public key not hex")); + } + if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Network Type", "not integer")); + } else { + if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting network type to int")); + } + if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { + addError(new Error("Network Type", "invalid value")); + } + } + + if(0 == errorCount()) { + + auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + + private_key = DataTypeConverter::hexToBin(privateKeyString); + public_key = DataTypeConverter::hexToBin(publicKeyString); + + + KeyPairHedera key_pair(private_key, public_key); + auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); + + if(crypto_key.isNull()) { + crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); + if(!crypto_key->getModel()->insertIntoDB(true)) { + addError(new Error("DB Error", "Error saving crypto key in DB")); + } + } else { + printf("crypto key found in db\n"); + } + if(0 == errorCount()) { + + if(hedera_id->isExistInDB()) { + auto hedera_account = controller::HederaAccount::load(hedera_id); + if(hedera_account.isNull()) { + addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); + } else { + addError(new Error("Hedera Account", "Account already exist (same account id")); + } + + } else { + auto hedera_account = controller::HederaAccount::create( + user->getModel()->getID(), + hedera_id->getModel()->getID(), + crypto_key->getModel()->getID(), + 0, + (model::table::HederaNetworkType)networkType + ); + if(!hedera_account->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving hedera account into DB")); + } + } + } + + mm->releaseMemory(private_key); + mm->releaseMemory(public_key); + } + } } if(!query_hedera_account.isNull()) { getErrors(query_hedera_account); @@ -262,7 +305,15 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t
"; // end include header_large.cpsp responseStream << "\n"; -#line 187 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << "\n"; +#line 238 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "
\n"; @@ -280,7 +331,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\t
Aktionen
\n"; responseStream << "\t\t\t
\n"; responseStream << "\t\t\t"; -#line 203 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 254 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) { auto hedera_account_model = (*it)->getModel(); auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID()); @@ -288,59 +339,63 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if(hedera_account_model->getUserId() == user->getModel()->getID()) { changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID()); } + auto isEncrypted = (*it)->getCryptoKey()->getModel()->isEncrypted(); //printf("change encryption: %s\n", changeEncryption.data()); responseStream << "\n"; responseStream << "\t\t\t\t
\n"; responseStream << "\t\t\t\t\t
"; -#line 213 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 265 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( (*it)->getHederaId()->getModel()->toString() ); responseStream << "
\n"; responseStream << "\t\t\t\t\t
"; -#line 214 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 266 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getBalanceDouble() ); responseStream << " hbar
\n"; responseStream << "\t\t\t\t\t
"; -#line 215 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 267 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) ); responseStream << "
\n"; - responseStream << "\t\t\t\t\t
"; -#line 216 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" - responseStream << ( (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" ); + responseStream << "\t\t\t\t\t
"; +#line 268 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << ( isEncrypted ? "Ja": "Nein" ); responseStream << "
\n"; responseStream << "\t\t\t\t\t
"; -#line 217 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 269 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getUpdatedString() ); responseStream << "
\n"; responseStream << "\t\t\t\t\t\n"; responseStream << "\t\t\t\t\t"; -#line 221 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 273 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" if(changeEncryption != "") { responseStream << "\n"; responseStream << "\t\t\t\t\t\t\n"; responseStream << "\t\t\t\t\t"; -#line 225 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 277 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t\t\t
\n"; responseStream << "\t\t\t"; -#line 227 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 279 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t
\n"; responseStream << "\t
\n"; responseStream << "\t
\n"; - responseStream << "\t

Einen neuen Account anlegen

\n"; + responseStream << "\t

Ein existierenden Account eintragen

\n"; responseStream << "\t
\n"; responseStream << "\t
\n"; responseStream << "\t\t
\n"; responseStream << "\t\t\t\n"; @@ -356,25 +411,75 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; - responseStream << "\t\t\t\n"; responseStream << "\t\t
\n"; responseStream << "\t
\n"; + responseStream << "\t
\n"; + responseStream << "\t\t

Ein neuen Account anlegen

\n"; + responseStream << "\t\t

Bei Hedera einen neuen Account anlegen und zum Start Hashbars von einem existierenden Account überweisen.

\n"; + responseStream << "\t
\n"; + responseStream << "\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\n"; + responseStream << "\t
\n"; responseStream << "
\n"; // begin include footer.cpsp responseStream << "
\n"; @@ -400,5 +505,18 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << ""; // end include footer.cpsp responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; if (_compressResponse) _gzipStream.close(); } diff --git a/src/cpp/SingletonManager/HederaTaskManager.cpp b/src/cpp/SingletonManager/HederaTaskManager.cpp new file mode 100644 index 000000000..f54ca58f3 --- /dev/null +++ b/src/cpp/SingletonManager/HederaTaskManager.cpp @@ -0,0 +1,17 @@ +#include "HederaTaskManager.h" + +HederaTaskManager* HederaTaskManager::getInstance() +{ + static HederaTaskManager one; + return &one; +} + +HederaTaskManager::HederaTaskManager() +{ + +} + +HederaTaskManager::~HederaTaskManager() +{ + +} \ No newline at end of file diff --git a/src/cpp/SingletonManager/HederaTaskManager.h b/src/cpp/SingletonManager/HederaTaskManager.h new file mode 100644 index 000000000..361ace551 --- /dev/null +++ b/src/cpp/SingletonManager/HederaTaskManager.h @@ -0,0 +1,23 @@ +#ifndef __GRADIDO_LOGIN_SINGLETON_MANAGER_HEDERA_TASK_MANAGER_H +#define __GRADIDO_LOGIN_SINGLETON_MANAGER_HEDERA_TASK_MANAGER_H + +/*! + * @author: Dario Rekowski + * + * @date: 11.09.2020 + * + * @brief: Manage Hedera Task, waiting on Consensus for Hedera Transactions + * +*/ + +class HederaTaskManager +{ +public: + ~HederaTaskManager(); + + static HederaTaskManager* getInstance(); +protected: + HederaTaskManager(); +}; + +#endif //__GRADIDO_LOGIN_SINGLETON_MANAGER_HEDERA_TASK_MANAGER_H \ No newline at end of file diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index bbeaf9052..4e99b85e4 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -48,6 +48,7 @@ bool SessionManager::init() case VALIDATE_PASSPHRASE: mValidations[i] = new Poco::RegularExpression("^(?:[a-z]* ){23}[a-z]*\s*$"); break; case VALIDATE_HAS_NUMBER: mValidations[i] = new Poco::RegularExpression(".*[0-9].*"); break; case VALIDATE_ONLY_INTEGER: mValidations[i] = new Poco::RegularExpression("^[0-9]*$"); break; + case VALIDATE_ONLY_DECIMAL: mValidations[i] = new Poco::RegularExpression("^[0-9]*(\.|,)[0-9]*$"); break; case VALIDATE_ONLY_HEX: mValidations[i] = new Poco::RegularExpression("^(0x)?[a-fA-F0-9]*$"); break; //case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}$"); break; case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\/?"); break; diff --git a/src/cpp/SingletonManager/SessionManager.h b/src/cpp/SingletonManager/SessionManager.h index 99ef301f0..4596d2064 100644 --- a/src/cpp/SingletonManager/SessionManager.h +++ b/src/cpp/SingletonManager/SessionManager.h @@ -29,6 +29,7 @@ enum SessionValidationTypes { VALIDATE_PASSPHRASE, VALIDATE_HAS_NUMBER, VALIDATE_ONLY_INTEGER, + VALIDATE_ONLY_DECIMAL, VALIDATE_ONLY_HEX, VALIDATE_ONLY_URL, VALIDATE_HAS_SPECIAL_CHARACTER, diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 22a82c929..25f3c7245 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -3,8 +3,13 @@ #include "NodeServer.h" #include "CryptoKey.h" #include "../model/hedera/Query.h" +//#include "../model/hedera/Tr" #include "HederaRequest.h" +#include "../SingletonManager/ErrorManager.h" + +using namespace Poco::Data::Keywords; + namespace controller { HederaAccount::HederaAccount(model::table::HederaAccount* dbModel) @@ -54,6 +59,51 @@ namespace controller { return nullptr; } + Poco::AutoPtr HederaAccount::pick(model::table::HederaNetworkType networkType, bool encrypted/* = false*/) + { + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + Poco::Data::Statement select(session); + + Poco::Tuple result_tuple; + int crypto_key_type = encrypted ? model::table::KEY_TYPE_ED25519_HEDERA_ENCRYPTED : model::table::KEY_TYPE_ED25519_HEDERA_CLEAR; + //id, user_id, account_hedera_id, account_key_id, balance, network_type, updated + + select << "SELECT account.id, account.user_id, account.account_hedera_id, account.account_key_id, account.balance, i.shardNum, i.realmNum, i.num FROM hedera_accounts as account " + << "JOIN hedera_ids as i ON(i.id = account.account_hedera_id) " + << "JOIN crypto_keys as k ON(k.id = account.account_key_id) " + << "WHERE account.network_type = ? AND k.crypto_key_type_id = ? ORDER BY RAND() LIMIT 1 ", + into(result_tuple), use(networkType), use(crypto_key_type); + + try { + select.executeAsync(); + select.wait(); + if (1 == select.rowsExtracted()) { + auto db = new model::table::HederaAccount( + result_tuple.get<1>(), result_tuple.get<2>(), result_tuple.get<3>(), + result_tuple.get<4>(), networkType + ); + db->setID(result_tuple.get<0>()); + Poco::AutoPtr hedera_account(new HederaAccount(db)); + auto hedera_id_db = new model::table::HederaId(result_tuple.get<5>(), result_tuple.get<6>(), result_tuple.get<7>()); + Poco::AutoPtr hedera_id(new HederaId(hedera_id_db)); + hedera_account->setHederaId(hedera_id); + return hedera_account; + } + } + catch (Poco::Exception& ex) { + auto em = ErrorManager::getInstance(); + static const char* function_name = "HederaAccount::pick"; + em->addError(new ParamError(function_name, "mysql error: ", ex.displayText())); + em->addError(new ParamError(function_name, "network type: ", networkType)); + em->addError(new ParamError(function_name, "encrypted: ", (int)encrypted)); + em->sendErrorsAsEmail(); + } + + return nullptr; + + } + std::vector> HederaAccount::listAll() { auto db = new model::table::HederaAccount(); @@ -140,11 +190,27 @@ namespace controller { printf("[HederaAccount::updateBalanceFromHedera] exception calling hedera request: %s\n", ex.displayText().data()); } - getErrors(&request); + if (0 == errorCount() && 0 == request.errorCount()) { + return true; + } + getErrors(&request); return false; } + bool HederaAccount::hederaAccountCreate(int autoRenewPeriodSeconds, double initialBalance) + { + auto account_model = getModel(); + auto new_key_pair = KeyPairHedera::create(); + auto transaction_body = createTransactionBody(); + //CryptoCreateTransaction(const unsigned char* publicKey, Poco::UInt64 initialBalance, int autoRenewPeriod); + model::hedera::CryptoCreateTransaction create_transaction(new_key_pair->getPublicKey(), initialBalance, autoRenewPeriodSeconds); + transaction_body->setCryptoCreate(create_transaction); + + + return false; + } + bool HederaAccount::changeEncryption(Poco::AutoPtr user) { assert(!user.isNull() && user->getModel()); @@ -166,6 +232,13 @@ namespace controller { } + std::unique_ptr HederaAccount::createTransactionBody() + { + auto account_model = getModel(); + auto hedera_node = NodeServer::pick(account_model->networkTypeToNodeServerType(account_model->getNetworkType())); + return std::make_unique(mHederaID, hedera_node); + } + std::string HederaAccount::toShortSelectOptionName() { diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index 77f34aa87..882800713 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -5,6 +5,8 @@ #include "User.h" #include "../model/table/HederaAccount.h" +#include "../model/hedera/TransactionBody.h" + #include "Poco/SharedPtr.h" #include "TableControllerBase.h" @@ -21,6 +23,8 @@ namespace controller { static std::vector> load(const std::string& fieldName, int fieldValue); static Poco::AutoPtr load(Poco::AutoPtr hederaId); static std::vector> listAll(); + //! \brief for picking a account for paying transaction, mostly consensusSendMessage + static Poco::AutoPtr pick(model::table::HederaNetworkType networkType, bool encrypted = false); inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } @@ -35,9 +39,14 @@ namespace controller { Poco::AutoPtr getCryptoKey() const; bool hederaAccountGetBalance(Poco::AutoPtr user); + bool hederaAccountCreate(int autoRenewPeriodSeconds, double initialBalance); bool changeEncryption(Poco::AutoPtr user); + //! \brief create Transaction body with this hedera account as operator + std::unique_ptr createTransactionBody(); + protected: + HederaAccount(model::table::HederaAccount* dbModel); Poco::AutoPtr mHederaID; diff --git a/src/cpp/controller/HederaId.cpp b/src/cpp/controller/HederaId.cpp index de2cf1dfa..3b9627c8b 100644 --- a/src/cpp/controller/HederaId.cpp +++ b/src/cpp/controller/HederaId.cpp @@ -1,4 +1,7 @@ #include "HederaId.h" +#include "../SingletonManager/ErrorManager.h" + +using namespace Poco::Data::Keywords; namespace controller { @@ -30,6 +33,42 @@ namespace controller { return nullptr; } + Poco::AutoPtr HederaId::find(int groupId, model::table::HederaNetworkType networkType) + { + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + model::table::HederaIdTuple result_tuple; + + Poco::Data::Statement select(session); + select << "SELECT h.id, h.shardNum, h.realmNum, h.num FROM hedera_ids as h " + << "JOIN hedera_topics as topic ON(topic.topic_hedera_id = h.id) " + << "JOIN hedera_accounts as account ON(account.id = topic.auto_renew_account_hedera_id) " + << "WHERE topic.group_id = ? AND account.network_type = ?" + , into(result_tuple), use(groupId), use(networkType); + + try { + /*select.executeAsync(); + select.wait(); + auto result_count = select.rowsExtracted();*/ + auto result_count = select.execute(); + if (1 == result_count) { + return new HederaId(new model::table::HederaId(result_tuple)); + } + else { + printf("[HederaId::find] result_count other as expected: %d\n", result_count); + } + } + catch (Poco::Exception& ex) { + auto em = ErrorManager::getInstance(); + static const char* function_name = "HederaId::find"; + em->addError(new ParamError(function_name, "mysql error: ", ex.displayText())); + em->addError(new ParamError(function_name, "group id: ", groupId)); + em->addError(new ParamError(function_name, "network type: ", (int)networkType)); + em->sendErrorsAsEmail(); + } + return nullptr; + } + void HederaId::copyToProtoAccountId(proto::AccountID* protoAccountId) const { auto model = getModel(); @@ -38,6 +77,14 @@ namespace controller { protoAccountId->set_accountnum(model->getNum()); } + void HederaId::copyToProtoTopicId(proto::TopicID* protoTopicId) const + { + auto model = getModel(); + protoTopicId->set_shardnum(model->getShardNum()); + protoTopicId->set_realmnum(model->getRealmNum()); + protoTopicId->set_topicnum(model->getNum()); + } + bool HederaId::isExistInDB() { auto model = getModel(); diff --git a/src/cpp/controller/HederaId.h b/src/cpp/controller/HederaId.h index 1cf967927..0bfc1f691 100644 --- a/src/cpp/controller/HederaId.h +++ b/src/cpp/controller/HederaId.h @@ -2,6 +2,7 @@ #define GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ID_INCLUDE #include "../model/table/HederaId.h" +#include "../model/table/HederaAccount.h" #include "Poco/SharedPtr.h" @@ -10,8 +11,10 @@ #include "../proto/hedera/BasicTypes.pb.h" namespace controller { + class HederaAccount; class HederaId : public TableControllerBase { + friend HederaAccount; public: ~HederaId(); @@ -19,6 +22,8 @@ namespace controller { static Poco::AutoPtr create(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num); static Poco::AutoPtr load(int id); + //! \return hedera topic id for group and network type (should exist only one) + static Poco::AutoPtr find(int groupId, model::table::HederaNetworkType networkType); bool isExistInDB(); @@ -28,6 +33,7 @@ namespace controller { inline const model::table::HederaId* getModel() const { return _getModel(); } void copyToProtoAccountId(proto::AccountID* protoAccountId) const; + void copyToProtoTopicId(proto::TopicID* protoTopicId) const; protected: diff --git a/src/cpp/controller/HederaRequest.cpp b/src/cpp/controller/HederaRequest.cpp index 64998fa6a..7ddb95800 100644 --- a/src/cpp/controller/HederaRequest.cpp +++ b/src/cpp/controller/HederaRequest.cpp @@ -1,5 +1,6 @@ #include "HederaRequest.h" #include "../proto/hedera/CryptoService.grpc.pb.h" +#include "../proto/hedera/ConsensusService.grpc.pb.h" #include "../lib/DataTypeConverter.h" @@ -71,6 +72,33 @@ HederaRequestReturn HederaRequest::request(model::hedera::Transaction* transacti return HEDERA_REQUEST_RETURN_OK; } +HederaRequestReturn HederaRequest::request(model::hedera::Transaction* transaction, HederaTask* task) +{ + assert(transaction && task); + auto channel = grpc::CreateChannel(transaction->getConnectionString(), grpc::InsecureChannelCredentials()); + + grpc::ClientContext context; + std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + + std::chrono::milliseconds(5000); + context.set_deadline(deadline); + auto transaction_type = transaction->getType(); + if (model::hedera::TRANSACTION_CONSENSUS_SUBMIT_MESSAGE == transaction_type) { + auto stub = proto::ConsensusService::NewStub(channel); + + auto status = stub->submitMessage(&context, *transaction->getTransaction(), task->getTransactionResponse()->getProtoResponse()); + if (status.ok()) { + return HEDERA_REQUEST_RETURN_OK; + } + else { + addError(new ParamError("Hedera Request", "consensus service submit message error message:", status.error_message())); + addError(new ParamError("Hedera Request", "details: ", status.error_details())); + return HEDERA_REQUEST_RETURN_ERROR; + } + } + addError(new ParamError("Hedera Request", "not implemnetet or unknown transaction type", transaction_type)); + return HEDERA_REQUEST_UNKNOWN_TRANSACTION; +} + #include "Poco/JSON/Object.h" #include "../lib/JsonRequest.h" diff --git a/src/cpp/controller/HederaRequest.h b/src/cpp/controller/HederaRequest.h index 34bd304a1..56adf3c79 100644 --- a/src/cpp/controller/HederaRequest.h +++ b/src/cpp/controller/HederaRequest.h @@ -14,12 +14,16 @@ #include "../model/hedera/Query.h" #include "../model/hedera/Transaction.h" #include "../model/hedera/Response.h" +#include "../model/hedera/TransactionResponse.h" +#include "../tasks/HederaTask.h" enum HederaRequestReturn { HEDERA_REQUEST_RETURN_OK, HEDERA_REQUEST_RETURN_PARSE_ERROR, HEDERA_REQUEST_RETURN_ERROR, + HEDERA_REQUEST_UNKNOWN_TRANSACTION, + HEDERA_REQUEST_UNKNOWN_QUERY, HEDERA_REQUEST_CONNECT_ERROR }; @@ -32,6 +36,9 @@ public: HederaRequestReturn request(model::hedera::Query* query, model::hedera::Response* response, Poco::UInt64 fee = 0); HederaRequestReturn request(model::hedera::Transaction* transaction, model::hedera::Response* response); + //! + //! \param task goes into HederaTaskManager and will be run after transaction + HederaRequestReturn request(model::hedera::Transaction* transaction, HederaTask* task); //! for testing, didn't work server say invalid json :/ HederaRequestReturn requestViaPHPRelay(model::hedera::Query* query); diff --git a/src/cpp/controller/HederaTopic.cpp b/src/cpp/controller/HederaTopic.cpp index 31d18a94c..d852b57e7 100644 --- a/src/cpp/controller/HederaTopic.cpp +++ b/src/cpp/controller/HederaTopic.cpp @@ -19,6 +19,8 @@ namespace controller { return Poco::AutoPtr(hedera_topic); } + + Poco::UInt64 HederaTopic::hederaCreateTopic() { return 0; diff --git a/src/cpp/controller/HederaTopic.h b/src/cpp/controller/HederaTopic.h index 4c2ebefb6..c7b169b4b 100644 --- a/src/cpp/controller/HederaTopic.h +++ b/src/cpp/controller/HederaTopic.h @@ -13,6 +13,7 @@ #include "TableControllerBase.h" #include "../model/table/HederaTopic.h" + namespace controller { class HederaTopic : public TableControllerBase { @@ -27,6 +28,7 @@ namespace controller { inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + inline Poco::AutoPtr getModel() { return _getModel(); } @@ -36,4 +38,4 @@ namespace controller { }; } -#endif //__GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H \ No newline at end of file +#endif //__GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H diff --git a/src/cpp/lib/DataTypeConverter.cpp b/src/cpp/lib/DataTypeConverter.cpp index 72e6aceb8..0e84b4be4 100644 --- a/src/cpp/lib/DataTypeConverter.cpp +++ b/src/cpp/lib/DataTypeConverter.cpp @@ -55,6 +55,34 @@ namespace DataTypeConverter } } + NumberParseState strToDouble(const std::string& input, double& result) + { + auto comma_position = input.find(','); + std::string input_filtered = input; + if (comma_position > 0 && comma_position != input.npos) { + input_filtered = input_filtered.replace(comma_position, 0, 1, '.'); + } + try { + result = stod(input_filtered); + return NUMBER_PARSE_OKAY; + } + catch (const std::invalid_argument& ia) + { + printf("[strToDouble] exception: invalid argument: %s\n", ia.what()); + return NUMBER_PARSE_INVALID_ARGUMENT; + } + catch (const std::out_of_range& oor) + { + printf("[strToDouble] exception: out or range: %s\n", oor.what()); + return NUMBER_PARSE_OUT_OF_RANGE; + } + catch (const std::logic_error & ler) + { + printf("[strToDouble] exception: logical error: %s\n", ler.what()); + return NUMBER_PARSE_LOGIC_ERROR; + } + } + const char* numberParseStateToString(NumberParseState state) { switch (state) { diff --git a/src/cpp/lib/DataTypeConverter.h b/src/cpp/lib/DataTypeConverter.h index d970d697d..933fdfb74 100644 --- a/src/cpp/lib/DataTypeConverter.h +++ b/src/cpp/lib/DataTypeConverter.h @@ -23,6 +23,7 @@ namespace DataTypeConverter { NumberParseState strToInt(const std::string& input, int& result); NumberParseState strToInt(const std::string& input, unsigned long long& result); + NumberParseState strToDouble(const std::string& input, double& result); MemoryBin* hexToBin(const std::string& hexString); MemoryBin* base64ToBin(const std::string& base64String); diff --git a/src/cpp/model/hedera/ConsensusSubmitMessage.cpp b/src/cpp/model/hedera/ConsensusSubmitMessage.cpp index e69de29bb..18da97c73 100644 --- a/src/cpp/model/hedera/ConsensusSubmitMessage.cpp +++ b/src/cpp/model/hedera/ConsensusSubmitMessage.cpp @@ -0,0 +1,42 @@ +#include "ConsensusSubmitMessage.h" + +namespace model { + namespace hedera { + ConsensusSubmitMessage::ConsensusSubmitMessage(Poco::AutoPtr topicID) + : mConsensusMessageBody(nullptr) + { + mConsensusMessageBody = new proto::ConsensusSubmitMessageTransactionBody; + topicID->copyToProtoTopicId(mConsensusMessageBody->mutable_topicid()); + } + + ConsensusSubmitMessage::~ConsensusSubmitMessage() + { + if (mConsensusMessageBody) { + delete mConsensusMessageBody; + mConsensusMessageBody = nullptr; + } + } + + bool ConsensusSubmitMessage::validate() + { + // TODO: unpack gradido transaction and make simple validation check + assert(mConsensusMessageBody); + if (0 == mConsensusMessageBody->message().size()) { + printf("[ConsensusSubmitMessage::validate] empty message\n"); + return false; + } + if (!mConsensusMessageBody->has_topicid()) { + printf("[ConsensusSubmitMessage::validate] empty topic id\n"); + return false; + } + + return true; + } + + void ConsensusSubmitMessage::setMessage(std::string byteString) + { + assert(mConsensusMessageBody); + mConsensusMessageBody->set_message(byteString); + } + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/ConsensusSubmitMessage.h b/src/cpp/model/hedera/ConsensusSubmitMessage.h index e69de29bb..d08b72279 100644 --- a/src/cpp/model/hedera/ConsensusSubmitMessage.h +++ b/src/cpp/model/hedera/ConsensusSubmitMessage.h @@ -0,0 +1,32 @@ +#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_SUBMIT_MESSAGE_H +#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_SUBMIT_MESSAGE_H + +#include "../../proto/hedera/ConsensusSubmitMessage.pb.h" +#include "../../controller/HederaId.h" + +namespace model { + namespace hedera { + + class ConsensusSubmitMessage + { + public: + ConsensusSubmitMessage(Poco::AutoPtr topicID); + ~ConsensusSubmitMessage(); + + inline proto::ConsensusSubmitMessageTransactionBody* getProtoTransactionBody() { return mConsensusMessageBody; } + inline void resetPointer() { mConsensusMessageBody = nullptr; } + void setMessage(std::string byteString); + inline void setMessage(const MemoryBin* message) { setMessage(std::string((const char*)message->data(), message->size())); } + + bool validate(); + + + + protected: + proto::ConsensusSubmitMessageTransactionBody* mConsensusMessageBody; + + }; + } +} + +#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_SUBMIT_MESSAGE_H \ No newline at end of file diff --git a/src/cpp/model/hedera/CryptoCreateTransaction.cpp b/src/cpp/model/hedera/CryptoCreateTransaction.cpp index 696a8d6e7..1c5d58e11 100644 --- a/src/cpp/model/hedera/CryptoCreateTransaction.cpp +++ b/src/cpp/model/hedera/CryptoCreateTransaction.cpp @@ -3,14 +3,32 @@ namespace model { namespace hedera { - CryptoCreateTransaction::CryptoCreateTransaction() + CryptoCreateTransaction::CryptoCreateTransaction(const unsigned char* publicKey, Poco::UInt64 initialBalance, int autoRenewPeriod) { + mCryptoCreateBody = new proto::CryptoCreateTransactionBody; + // public key + auto key = mCryptoCreateBody->mutable_key(); + auto public_key = new std::string((const char*)publicKey, KeyPairHedera::getPublicKeySize()); + key->set_allocated_ed25519(public_key); + + mCryptoCreateBody->set_initialbalance(initialBalance); + + auto auto_renew_period = mCryptoCreateBody->mutable_autorenewperiod(); + auto_renew_period->set_seconds(autoRenewPeriod); + } CryptoCreateTransaction::~CryptoCreateTransaction() { - + if (mCryptoCreateBody) { + delete mCryptoCreateBody; + mCryptoCreateBody = nullptr; + } } + bool CryptoCreateTransaction::validate() + { + return true; + } } } \ No newline at end of file diff --git a/src/cpp/model/hedera/CryptoCreateTransaction.h b/src/cpp/model/hedera/CryptoCreateTransaction.h index e1425ebf5..7182f3506 100644 --- a/src/cpp/model/hedera/CryptoCreateTransaction.h +++ b/src/cpp/model/hedera/CryptoCreateTransaction.h @@ -3,15 +3,23 @@ #include "../../proto/hedera/CryptoCreate.pb.h" +#include "../Crypto/KeyPairHedera.h" + namespace model { namespace hedera { class CryptoCreateTransaction { public: - CryptoCreateTransaction(); + //! \param publicKey newly created public key from ed25519 public-private key pair for hedera + CryptoCreateTransaction(const unsigned char* publicKey, Poco::UInt64 initialBalance, int autoRenewPeriod); ~CryptoCreateTransaction(); + proto::CryptoCreateTransactionBody* getProtoTransactionBody() { return mCryptoCreateBody; } + inline void resetPointer() { mCryptoCreateBody = nullptr; } + + bool validate(); + protected: proto::CryptoCreateTransactionBody* mCryptoCreateBody; }; diff --git a/src/cpp/model/hedera/CryptoTransferTransaction.cpp b/src/cpp/model/hedera/CryptoTransferTransaction.cpp index 828a85645..171e239f4 100644 --- a/src/cpp/model/hedera/CryptoTransferTransaction.cpp +++ b/src/cpp/model/hedera/CryptoTransferTransaction.cpp @@ -43,11 +43,6 @@ namespace model { } return 0 == sum && transfers->accountamounts_size() > 0; } - - void CryptoTransferTransaction::resetPointer() - { - mCryptoTransfer = nullptr; - } } } diff --git a/src/cpp/model/hedera/CryptoTransferTransaction.h b/src/cpp/model/hedera/CryptoTransferTransaction.h index 04aacafea..21d9bd3c3 100644 --- a/src/cpp/model/hedera/CryptoTransferTransaction.h +++ b/src/cpp/model/hedera/CryptoTransferTransaction.h @@ -26,7 +26,7 @@ namespace model { bool validate(); // set pointer to zero, after hand over pointer to transaction body - void resetPointer(); + inline void resetPointer() { mCryptoTransfer = nullptr; } inline proto::CryptoTransferTransactionBody* getProtoTransactionBody() { return mCryptoTransfer; } diff --git a/src/cpp/model/hedera/Transaction.cpp b/src/cpp/model/hedera/Transaction.cpp index 4699e71ea..ab786e44f 100644 --- a/src/cpp/model/hedera/Transaction.cpp +++ b/src/cpp/model/hedera/Transaction.cpp @@ -18,6 +18,8 @@ namespace model { bool Transaction::sign(std::unique_ptr keyPairHedera, const TransactionBody* transactionBody) { + mType = transactionBody->getType(); + auto mm = MemoryManager::getInstance(); mConnection = transactionBody->getConnection(); auto transaction_body_proto = transactionBody->getProtoTransactionBody(); @@ -40,5 +42,32 @@ namespace model { mm->releaseMemory(sign); return true; } + + bool Transaction::sign(std::unique_ptr keyPairHedera, std::unique_ptr transactionBody) + { + mType = transactionBody->getType(); + + auto mm = MemoryManager::getInstance(); + mConnection = transactionBody->getConnection(); + auto transaction_body_proto = transactionBody->getProtoTransactionBody(); + auto body_bytes = transaction_body_proto->SerializeAsString(); + mTransaction->set_bodybytes(body_bytes.data(), body_bytes.size()); + auto signature_map = mTransaction->mutable_sigmap(); + auto signature_pairs = signature_map->mutable_sigpair(); + signature_map->add_sigpair(); + auto signature_pair = signature_pairs->Mutable(0); + auto public_key = keyPairHedera->getPublicKey(); + + auto sign = keyPairHedera->sign(body_bytes); + if (!sign) { + printf("[Query::sign] error signing message\n"); + return false; + } + signature_pair->set_pubkeyprefix(public_key, keyPairHedera->getPublicKeySize()); + signature_pair->set_ed25519(*sign, sign->size()); + + mm->releaseMemory(sign); + return true; + } } } \ No newline at end of file diff --git a/src/cpp/model/hedera/Transaction.h b/src/cpp/model/hedera/Transaction.h index d5e9434bd..fe1bfed51 100644 --- a/src/cpp/model/hedera/Transaction.h +++ b/src/cpp/model/hedera/Transaction.h @@ -23,14 +23,17 @@ namespace model { ~Transaction(); bool sign(std::unique_ptr keyPairHedera, const TransactionBody* transactionBody); + bool sign(std::unique_ptr keyPairHedera, std::unique_ptr transactionBody); inline proto::Transaction* getTransaction() { return mTransaction; } inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } void resetPointer() { mTransaction = nullptr; } + inline TransactionBodyType getType() const { return mType; } protected: proto::Transaction* mTransaction; controller::NodeServerConnection mConnection; + TransactionBodyType mType; }; } } diff --git a/src/cpp/model/hedera/TransactionBody.cpp b/src/cpp/model/hedera/TransactionBody.cpp index f215ada23..ea44915a8 100644 --- a/src/cpp/model/hedera/TransactionBody.cpp +++ b/src/cpp/model/hedera/TransactionBody.cpp @@ -3,7 +3,7 @@ namespace model { namespace hedera { TransactionBody::TransactionBody(Poco::AutoPtr operatorAccountId, const controller::NodeServerConnection& connection) - : mConnection(connection) + : mConnection(connection), mHasBody(false) { connection.hederaId->copyToProtoAccountId(mTransactionBody.mutable_nodeaccountid()); auto transaction_id = mTransactionBody.mutable_transactionid(); @@ -22,9 +22,15 @@ namespace model { bool TransactionBody::setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction) { + if (mHasBody) { + printf("[TransactionBody::setCryptoTransfer] has already a body\n"); + return false; + } if (cryptoTransferTransaction.validate()) { mTransactionBody.set_allocated_cryptotransfer(cryptoTransferTransaction.getProtoTransactionBody()); cryptoTransferTransaction.resetPointer(); + mHasBody = true; + mType = TRANSACTION_CRYPTO_TRANSFER; return true; } return false; @@ -32,9 +38,47 @@ namespace model { bool TransactionBody::setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction) { + if (mHasBody) { + printf("[TransactionBody::setCreateTopic] has already a body\n"); + return false; + } if (consensusCreateTopicTransaction.validate()) { mTransactionBody.set_allocated_consensuscreatetopic(consensusCreateTopicTransaction.getProtoTransactionBody()); consensusCreateTopicTransaction.resetPointer(); + mHasBody = true; + mType = TRANSACTION_CONSENSUS_CREATE_TOPIC; + return true; + } + return false; + } + + bool TransactionBody::setCryptoCreate(CryptoCreateTransaction& cryptoCreateTransaction) + { + if (mHasBody) { + printf("[TransactionBody::setCryptoCreate] has already a body\n"); + return false; + } + if (cryptoCreateTransaction.validate()) { + mTransactionBody.set_allocated_cryptocreateaccount(cryptoCreateTransaction.getProtoTransactionBody()); + cryptoCreateTransaction.resetPointer(); + mHasBody = true; + mType = TRANSACTION_CRYPTO_CREATE; + return true; + } + return false; + } + + bool TransactionBody::setConsensusSubmitMessage(ConsensusSubmitMessage& consensusSubmitMessageTransaction) + { + if (mHasBody) { + printf("[TransactionBody::setConsensusSubmitMessage] has already a body\n"); + return false; + } + if (consensusSubmitMessageTransaction.validate()) { + mTransactionBody.set_allocated_consensussubmitmessage(consensusSubmitMessageTransaction.getProtoTransactionBody()); + consensusSubmitMessageTransaction.resetPointer(); + mHasBody = true; + mType = TRANSACTION_CONSENSUS_SUBMIT_MESSAGE; return true; } return false; diff --git a/src/cpp/model/hedera/TransactionBody.h b/src/cpp/model/hedera/TransactionBody.h index 7be8d2105..9a5406af7 100644 --- a/src/cpp/model/hedera/TransactionBody.h +++ b/src/cpp/model/hedera/TransactionBody.h @@ -13,12 +13,23 @@ #include "../../controller/NodeServer.h" #include "CryptoTransferTransaction.h" +#include "CryptoCreateTransaction.h" #include "ConsensusCreateTopic.h" +#include "ConsensusSubmitMessage.h" #include "../../proto/hedera/TransactionBody.pb.h" namespace model { namespace hedera { + + enum TransactionBodyType + { + TRANSACTION_CRYPTO_TRANSFER, + TRANSACTION_CRYPTO_CREATE, + TRANSACTION_CONSENSUS_CREATE_TOPIC, + TRANSACTION_CONSENSUS_SUBMIT_MESSAGE + }; + class TransactionBody { public: @@ -29,17 +40,22 @@ namespace model { void setFee(Poco::UInt64 fee); bool setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction); + bool setCryptoCreate(CryptoCreateTransaction& cryptoCreateTransaction); bool setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction); + bool setConsensusSubmitMessage(ConsensusSubmitMessage& consensusSubmitMessageTransaction); //bool inline const proto::TransactionBody* getProtoTransactionBody() const { return &mTransactionBody; } inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } inline controller::NodeServerConnection getConnection() const { return mConnection; } + inline TransactionBodyType getType() const { return mType; } protected: void updateTimestamp(); proto::TransactionBody mTransactionBody; controller::NodeServerConnection mConnection; + bool mHasBody; + TransactionBodyType mType; }; } } diff --git a/src/cpp/model/hedera/TransactionResponse.cpp b/src/cpp/model/hedera/TransactionResponse.cpp new file mode 100644 index 000000000..2e9a66ea1 --- /dev/null +++ b/src/cpp/model/hedera/TransactionResponse.cpp @@ -0,0 +1,18 @@ +#include "TransactionResponse.h" + +namespace model { + namespace hedera { + + TransactionResponse::TransactionResponse() + { + + } + + TransactionResponse::~TransactionResponse() + { + + } + + + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/TransactionResponse.h b/src/cpp/model/hedera/TransactionResponse.h new file mode 100644 index 000000000..325cbe73f --- /dev/null +++ b/src/cpp/model/hedera/TransactionResponse.h @@ -0,0 +1,30 @@ +#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RESPONSE_H +#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RESPONSE_H + +#include "../../proto/hedera/TransactionResponse.pb.h" +#include "Poco/Types.h" + +namespace model { + namespace hedera { + + class TransactionResponse + { + public: + TransactionResponse(); + ~TransactionResponse(); + + inline proto::ResponseCodeEnum getPrecheckCode() const { return mProtoResponse.nodetransactionprecheckcode();} + inline std::string getPrecheckCodeString() const { return proto::ResponseCodeEnum_Name(mProtoResponse.nodetransactionprecheckcode()); } + inline Poco::UInt64 getCost() const { return mProtoResponse.cost(); } + + proto::TransactionResponse* getProtoResponse() { return &mProtoResponse; } + protected: + proto::TransactionResponse mProtoResponse; + + }; + } +} + + + +#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RESPONSE_H \ No newline at end of file diff --git a/src/cpp/model/table/HederaId.cpp b/src/cpp/model/table/HederaId.cpp index d6ceb8cb7..fce86a541 100644 --- a/src/cpp/model/table/HederaId.cpp +++ b/src/cpp/model/table/HederaId.cpp @@ -16,6 +16,13 @@ namespace model { } + HederaId::HederaId(const HederaIdTuple& tuple) + : ModelBase(tuple.get<0>()), + mShardNum(tuple.get<1>()), mRealmNum(tuple.get<2>()), mNum(tuple.get<3>()) + { + + } + HederaId::~HederaId() { diff --git a/src/cpp/model/table/HederaId.h b/src/cpp/model/table/HederaId.h index 9dc2029bc..bed00168f 100644 --- a/src/cpp/model/table/HederaId.h +++ b/src/cpp/model/table/HederaId.h @@ -7,11 +7,14 @@ namespace model { namespace table { + typedef Poco::Tuple HederaIdTuple; + class HederaId : public ModelBase { public: HederaId(); HederaId(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num); + HederaId(const HederaIdTuple& tuple); ~HederaId(); // generic db operations @@ -25,7 +28,6 @@ namespace model { inline Poco::UInt64 getRealmNum() const { return mRealmNum; } inline Poco::UInt64 getNum() const { return mNum; } - protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); diff --git a/src/cpp/tasks/HederaTask.cpp b/src/cpp/tasks/HederaTask.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/tasks/HederaTask.h b/src/cpp/tasks/HederaTask.h new file mode 100644 index 000000000..0c22da226 --- /dev/null +++ b/src/cpp/tasks/HederaTask.h @@ -0,0 +1,15 @@ +#ifndef __GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H +#define __GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H + +#include "../model/hedera/TransactionResponse.h" + +class HederaTask +{ +public: + inline model::hedera::TransactionResponse* getTransactionResponse() { return &mTransactionResponse; } + +protected: + model::hedera::TransactionResponse mTransactionResponse; +}; + +#endif //__GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H \ No newline at end of file diff --git a/src/cpp/tasks/SigningTransaction.cpp b/src/cpp/tasks/SigningTransaction.cpp index df317a270..ab1196a54 100644 --- a/src/cpp/tasks/SigningTransaction.cpp +++ b/src/cpp/tasks/SigningTransaction.cpp @@ -20,6 +20,12 @@ #include "Poco/Net/HTTPRequest.h" #include "Poco/Net/HTTPResponse.h" +// stuff for hedera transaction +#include "../controller/HederaAccount.h" +#include "../controller/HederaRequest.h" +#include "../model/hedera/TransactionBody.h" +#include "../model/hedera/Transaction.h" + SigningTransaction::SigningTransaction(Poco::AutoPtr processingeTransaction, Poco::AutoPtr newUser) : mProcessingeTransaction(processingeTransaction), mNewUser(newUser) { @@ -152,6 +158,41 @@ int SigningTransaction::run() { return -6; } + auto network_type = model::table::HEDERA_TESTNET; + auto topic_id = controller::HederaId::find(1, network_type); + auto hedera_operator_account = controller::HederaAccount::pick(network_type, false); + + if (!topic_id.isNull() && !hedera_operator_account.isNull()) { + auto crypto_key = hedera_operator_account->getCryptoKey(); + if (!crypto_key.isNull()) { + model::hedera::ConsensusSubmitMessage consensus_submit_message(topic_id); + consensus_submit_message.setMessage(finalTransactionBin); + auto hedera_transaction_body = hedera_operator_account->createTransactionBody(); + hedera_transaction_body->setConsensusSubmitMessage(consensus_submit_message); + model::hedera::Transaction hedera_transaction; + hedera_transaction.sign(crypto_key->getKeyPair(), std::move(hedera_transaction_body)); + + HederaRequest hedera_request; + HederaTask hedera_task;// placeholder + if (HEDERA_REQUEST_RETURN_OK != hedera_request.request(&hedera_transaction, &hedera_task)) { + addError(new Error("SigningTransaction", "error send transaction to hedera")); + getErrors(&hedera_request); + sendErrorsAsEmail(); + } + else { + auto hedera_precheck_code_string = hedera_task.getTransactionResponse()->getPrecheckCodeString(); + printf("hedera response: %s\n", hedera_precheck_code_string.data()); + } + //model::hedera::TransactionBody hedera_transaction_body() + } + else { + printf("[SigningTransaction] crypto key not found\n"); + } + } + else { + printf("[SigningTransaction] hedera topic id or operator account not found\n"); + } + // finale to base64 auto finalBase64Size = sodium_base64_encoded_len(finalTransactionBin.size(), sodium_base64_VARIANT_URLSAFE_NO_PADDING); auto finalBase64Bin = mm->getFreeMemory(finalBase64Size); diff --git a/src/cpsp/adminHederaAccount.cpsp b/src/cpsp/adminHederaAccount.cpsp index b55701b1b..d3d68b82c 100644 --- a/src/cpsp/adminHederaAccount.cpsp +++ b/src/cpsp/adminHederaAccount.cpsp @@ -24,6 +24,9 @@ auto sm = SessionManager::getInstance(); auto mm = MemoryManager::getInstance(); auto user = mSession->getNewUser(); + int auto_renew_period = 604800; // 7 Tage + int auto_renew_account = 0; + double initial_balance = 0.0; Profiler hedera_time; std::string hedera_time_string; @@ -59,8 +62,11 @@ if(action == "updateBalance") { hedera_time.reset(); - query_hedera_account->hederaAccountGetBalance(user); - addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + if(query_hedera_account->hederaAccountGetBalance(user)) { + addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + } else { + addError(new ParamError("Hedera", "crypto get balance failed in ", hedera_time.string())); + } } else if(action == "changeEncryption") { @@ -69,113 +75,150 @@ } } } - else if(!form.empty()) // add + else if(!form.empty()) // add or create { - // collect - auto shardNumString = form.get("account-shard-num", "0"); - auto realmNumString = form.get("account-realm-num", "0"); - auto numString = form.get("account-num", "0"); - auto privateKeyString = form.get("account-private-key", ""); - auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); - auto publicKeyString = form.get("account-public-key", ""); - auto networkTypeString = form.get("account-network-type", "0"); + auto creationButton = form.get("create",""); + if(creationButton != "") { - //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); - - int shardNum = 0; - int realmNum = 0; - int num = 0; - int networkType = 0; - - MemoryBin* private_key = nullptr; - MemoryBin* public_key = nullptr; - - // validate - if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "shard num not integer")); - } else { - if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting shardNumString to int")); - } - } - if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "realm num not integer")); - } else { - if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting realmNumString to int")); - } - } - if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "num not integer")); - } else { - if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting num to int")); - } - } - if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { - addError(new Error("Account Keys", "private key not hex")); - } - if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { - addError(new Error("Account Keys", "public key not hex")); - } - if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Network Type", "not integer")); - } else { - if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting network type to int")); - } - if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { - addError(new Error("Network Type", "invalid value")); - } - } - - if(0 == errorCount()) { - - auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + // collect + auto auto_renew_account_string = form.get("account-auto-renew-account", "0"); + auto auto_renew_period_string = form.get("account-auto-renew-period", "604800"); + auto account_initial_balance_string = form.get("account-initial-balance", "0"); - private_key = DataTypeConverter::hexToBin(privateKeyString); - public_key = DataTypeConverter::hexToBin(publicKeyString); - - - KeyPairHedera key_pair(private_key, public_key); - auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); - - if(crypto_key.isNull()) { - crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); - if(!crypto_key->getModel()->insertIntoDB(true)) { - addError(new Error("DB Error", "Error saving crypto key in DB")); - } + if(!sm->isValid(auto_renew_account_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account", "auto renew account id not an integer")); } else { - printf("crypto key found in db\n"); - } - if(0 == errorCount()) { - - if(hedera_id->isExistInDB()) { - auto hedera_account = controller::HederaAccount::load(hedera_id); - if(hedera_account.isNull()) { - addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); - } else { - addError(new Error("Hedera Account", "Account already exist (same account id")); - } - - } else { - auto hedera_account = controller::HederaAccount::create( - user->getModel()->getID(), - hedera_id->getModel()->getID(), - crypto_key->getModel()->getID(), - 0, - (model::table::HederaNetworkType)networkType - ); - if(!hedera_account->getModel()->insertIntoDB(false)) { - addError(new Error("DB Error", "Error saving hedera account into DB")); - } + if(DataTypeConverter::strToInt(auto_renew_account_string, auto_renew_account) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew account id to int")); } } - mm->releaseMemory(private_key); - mm->releaseMemory(public_key); - } + if(!sm->isValid(auto_renew_period_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account", "auto renew period not an integer")); + } else { + if(DataTypeConverter::strToInt(auto_renew_period_string, auto_renew_period) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew period to int")); + } + } + + if(!sm->isValid(account_initial_balance_string, VALIDATE_ONLY_DECIMAL)) { + addError(new Error("Account", "initial balance not an decimal")); + } else { + if(DataTypeConverter::strToDouble(account_initial_balance_string, initial_balance) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Double convert error", "Error converting initial balance to double")); + } + } + if(0 == errorCount()) + { + } + + } else { + // collect + auto shardNumString = form.get("account-shard-num", "0"); + auto realmNumString = form.get("account-realm-num", "0"); + auto numString = form.get("account-num", "0"); + auto privateKeyString = form.get("account-private-key", ""); + auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); + auto publicKeyString = form.get("account-public-key", ""); + auto networkTypeString = form.get("account-network-type", "0"); + + //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); + + int shardNum = 0; + int realmNum = 0; + int num = 0; + int networkType = 0; + + MemoryBin* private_key = nullptr; + MemoryBin* public_key = nullptr; + + // validate + if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "shard num not integer")); + } else { + if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting shardNumString to int")); + } + } + if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "realm num not integer")); + } else { + if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting realmNumString to int")); + } + } + if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "num not integer")); + } else { + if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting num to int")); + } + } + if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "private key not hex")); + } + if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "public key not hex")); + } + if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Network Type", "not integer")); + } else { + if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting network type to int")); + } + if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { + addError(new Error("Network Type", "invalid value")); + } + } + + if(0 == errorCount()) { + + auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + + private_key = DataTypeConverter::hexToBin(privateKeyString); + public_key = DataTypeConverter::hexToBin(publicKeyString); + + + KeyPairHedera key_pair(private_key, public_key); + auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); + + if(crypto_key.isNull()) { + crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); + if(!crypto_key->getModel()->insertIntoDB(true)) { + addError(new Error("DB Error", "Error saving crypto key in DB")); + } + } else { + printf("crypto key found in db\n"); + } + if(0 == errorCount()) { + + if(hedera_id->isExistInDB()) { + auto hedera_account = controller::HederaAccount::load(hedera_id); + if(hedera_account.isNull()) { + addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); + } else { + addError(new Error("Hedera Account", "Account already exist (same account id")); + } + + } else { + auto hedera_account = controller::HederaAccount::create( + user->getModel()->getID(), + hedera_id->getModel()->getID(), + crypto_key->getModel()->getID(), + 0, + (model::table::HederaNetworkType)networkType + ); + if(!hedera_account->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving hedera account into DB")); + } + } + } + + mm->releaseMemory(private_key); + mm->releaseMemory(public_key); + } + } } if(!query_hedera_account.isNull()) { getErrors(query_hedera_account); @@ -184,6 +227,14 @@ auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID()); %><%@ include file="header_large.cpsp" %> + <%= getErrorsHtml() %>
@@ -207,13 +258,14 @@ if(hedera_account_model->getUserId() == user->getModel()->getID()) { changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID()); } + auto isEncrypted = (*it)->getCryptoKey()->getModel()->isEncrypted(); //printf("change encryption: %s\n", changeEncryption.data()); %>
<%= (*it)->getHederaId()->getModel()->toString() %>
<%= hedera_account_model->getBalanceDouble() %> hbar
<%= model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) %>
-
<%= (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" %>
+
"><%= isEncrypted ? "Ja": "Nein" %>
<%= hedera_account_model->getUpdatedString() %>
-

Einen neuen Account anlegen

+

Ein existierenden Account eintragen

@@ -248,8 +300,39 @@ <% } %> - "> + "> +
+
+
+

Ein neuen Account anlegen

+

Bei Hedera einen neuen Account anlegen und zum Start Hashbars von einem existierenden Account überweisen.

+
+
+
+ + + +
+ + + ">
<%@ include file="footer.cpsp" %> + +