From 28926b9507d6cf38df508d35e08aa2b65a891662 Mon Sep 17 00:00:00 2001 From: Dario Date: Thu, 15 Oct 2020 14:07:39 +0200 Subject: [PATCH] complete new gradido transaction live circle, at least for group add member transaction --- src/cpp/Crypto/KeyPairEd25519.cpp | 9 +++ src/cpp/Crypto/KeyPairEd25519.h | 2 + src/cpp/controller/PendingTask.cpp | 31 ++++--- src/cpp/model/gradido/Transaction.cpp | 89 +++++++++++++++++++++ src/cpp/model/gradido/Transaction.h | 13 ++- src/cpp/model/gradido/TransactionBase.h | 3 +- src/cpp/model/gradido/TransactionBody.cpp | 12 ++- src/cpp/model/gradido/TransactionBody.h | 4 +- src/cpp/model/table/PendingTask.cpp | 12 +++ src/cpp/model/table/PendingTask.h | 10 ++- src/cpp/tasks/GradidoGroupAddMemberTask.cpp | 27 ------- src/cpp/tasks/GradidoGroupAddMemberTask.h | 19 ----- src/cpp/tasks/GradidoTask.cpp | 10 ++- src/cpp/tasks/GradidoTask.h | 5 +- src/cpp/tasks/ProcessingTransaction.cpp | 3 +- 15 files changed, 177 insertions(+), 72 deletions(-) delete mode 100644 src/cpp/tasks/GradidoGroupAddMemberTask.cpp delete mode 100644 src/cpp/tasks/GradidoGroupAddMemberTask.h diff --git a/src/cpp/Crypto/KeyPairEd25519.cpp b/src/cpp/Crypto/KeyPairEd25519.cpp index 392bf5e8e..72212e87e 100644 --- a/src/cpp/Crypto/KeyPairEd25519.cpp +++ b/src/cpp/Crypto/KeyPairEd25519.cpp @@ -151,6 +151,15 @@ MemoryBin* KeyPairEd25519::sign(const unsigned char* message, size_t messageSize } +bool KeyPairEd25519::verify(const std::string& message, const std::string& signature) const +{ + if (message != "" || signature != "") return false; + if (crypto_sign_verify_detached((const unsigned char*)signature.data(), (const unsigned char*)message.data(), message.size(), mSodiumPublic) != 0) { + return false; + } + return true; +} + MemoryBin* KeyPairEd25519::getCryptedPrivKey(const Poco::AutoPtr password) const { if (password.isNull()) return nullptr; diff --git a/src/cpp/Crypto/KeyPairEd25519.h b/src/cpp/Crypto/KeyPairEd25519.h index efe26b914..a8faca381 100644 --- a/src/cpp/Crypto/KeyPairEd25519.h +++ b/src/cpp/Crypto/KeyPairEd25519.h @@ -37,6 +37,8 @@ public: inline MemoryBin* sign(const std::string& bodyBytes) const { return sign((const unsigned char*)bodyBytes.data(), bodyBytes.size()); } MemoryBin* sign(const unsigned char* message, size_t messageSize) const; + bool verify(const std::string& message, const std::string& signature) const; + inline const unsigned char* getPublicKey() const { return mSodiumPublic; } inline std::string getPublicKeyHex() const { return DataTypeConverter::binToHex(mSodiumPublic, getPublicKeySize()); } const static size_t getPublicKeySize() { return crypto_sign_PUBLICKEYBYTES; } diff --git a/src/cpp/controller/PendingTask.cpp b/src/cpp/controller/PendingTask.cpp index 41bff15d6..e17d9205b 100644 --- a/src/cpp/controller/PendingTask.cpp +++ b/src/cpp/controller/PendingTask.cpp @@ -1,6 +1,7 @@ #include "PendingTask.h" #include "../tasks/GradidoGroupAddMemberTask.h" +#include "../model/gradido/Transaction.h" namespace controller { @@ -36,7 +37,24 @@ namespace controller { } - + + /*Poco::AutoPtr PendingTask::loadCorrectDerivedClass(model::table::PendingTask* dbModel) + { + if (dbModel->isGradidoTransaction()) { + return model::gradido::Transaction::load(dbModel); + } + }*/ + Poco::AutoPtr PendingTask::loadCorrectDerivedClass(model::table::PendingTask* dbModel) + { + if (!dbModel) return nullptr; + auto type = dbModel->getTaskType(); + switch (type) { + case model::table::TASK_TYPE_GROUP_ADD_MEMBER: return new GradidoGroupAddMemberTask(dbModel); + default: return nullptr; + } + return nullptr; + } + std::vector> PendingTask::loadAll() { auto db = new model::table::PendingTask(); @@ -55,15 +73,4 @@ namespace controller { } return resultVector; } - - Poco::AutoPtr PendingTask::loadCorrectDerivedClass(model::table::PendingTask* dbModel) - { - if (!dbModel) return nullptr; - auto type = dbModel->getTaskType(); - switch (type) { - case model::table::TASK_TYPE_GROUP_ADD_MEMBER: return new GradidoGroupAddMemberTask(dbModel); - default: return nullptr; - } - return nullptr; - } } \ No newline at end of file diff --git a/src/cpp/model/gradido/Transaction.cpp b/src/cpp/model/gradido/Transaction.cpp index 4ca8a705e..0606a0d31 100644 --- a/src/cpp/model/gradido/Transaction.cpp +++ b/src/cpp/model/gradido/Transaction.cpp @@ -1,22 +1,79 @@ #include "Transaction.h" #include "../../SingletonManager/ErrorManager.h" +#include "../../SingletonManager/PendingTasksManager.h" namespace model { namespace gradido { Transaction::Transaction(Poco::AutoPtr body) : mTransactionBody(body), mBodyBytesHash(0) { + + } + Transaction::Transaction(const std::string& protoMessageBin, model::table::PendingTask* dbModel) + : GradidoTask(dbModel) + { + if (!mProtoTransaction.ParseFromString(protoMessageBin)) { + throw new Poco::Exception("error parse from string"); + } + mTransactionBody = TransactionBody::load(mProtoTransaction.body_bytes()); + auto body_bytes = mTransactionBody->getBodyBytes(); + mBodyBytesHash = DRMakeStringHash(body_bytes.data(), body_bytes.size()); } Transaction::~Transaction() { + Poco::ScopedLock _lock(mWorkMutex); + } + Poco::AutoPtr Transaction::create(Poco::AutoPtr user, Poco::AutoPtr group) + { + if (user.isNull() || !user->getModel() || group.isNull() || !group->getModel()) { + return nullptr; + } + auto group_model = group->getModel(); + auto body = TransactionBody::create("", user, proto::gradido::GroupMemberUpdate_MemberUpdateType_ADD_USER, group_model->getAlias()); + Poco::AutoPtr result = new Transaction(body); + auto model = result->getModel(); + result->insertPendingTaskIntoDB(user, model::table::TASK_TYPE_GROUP_ADD_MEMBER); + PendingTasksManager::getInstance()->addTask(result); + return result; + } + + Poco::AutoPtr Transaction::load(model::table::PendingTask* dbModel) + { + proto::gradido::GradidoTransaction transaction_temp; + + Poco::AutoPtr transaction = new Transaction(dbModel->getRequestCopy(), dbModel); + PendingTasksManager::getInstance()->addTask(transaction); + return transaction; + } + + bool Transaction::insertPendingTaskIntoDB(Poco::AutoPtr user, model::table::TaskType type) + { + static const char* function_name = "Transaction::insertPendingTaskIntoDB"; + auto model = getModel(); + if (model->getID()) { + addError(new Error("Transaction::insertPendingTaskIntoDB", "pending task already inserted into db")); + return false; + } + if (user.isNull() || !user->getModel()) { + addError(new Error(function_name, "invalid user")); + return false; + } + model->setUserId(user->getModel()->getID()); + model->setTaskType(type); + model->setRequest(mProtoTransaction.body_bytes()); + if (!model->insertIntoDB(true)) { + return false; + } + return true; } bool Transaction::addSign(Poco::AutoPtr user) { static const char function_name[] = "Transaction::addSign"; + Poco::ScopedLock _lock(mWorkMutex); if (user.isNull() || !user->getModel()) { @@ -40,6 +97,9 @@ namespace model { addError(new Error(function_name, "body bytes hash has changed and signature(s) exist already!")); return false; } + if (mBodyBytesHash != hash) { + mProtoTransaction.set_body_bytes(bodyBytes.data(), bodyBytes.size()); + } mBodyBytesHash = hash; auto pubkeyBin = user->getModel()->getPublicKey(); @@ -103,11 +163,38 @@ namespace model { *sigBytes = std::string((char*)*sign, sign->size()); mm->releaseMemory(sign); + updateRequestInDB(); + + //getModel()->updateIntoDB("request", ) + return true; } + + bool Transaction::updateRequestInDB() + { + Poco::ScopedLock _lock(mWorkMutex); + auto size = mProtoTransaction.ByteSize(); + std::string transaction_serialized = std::string(size, 0); + mProtoTransaction.SerializeToString(&transaction_serialized); + auto model = getModel(); + model->setRequest(transaction_serialized); + return 1 == model->updateIntoDB("request", model->getRequest()); + } + TransactionValidation Transaction::validate() { + Poco::ScopedLock _lock(mWorkMutex); auto sig_map = mProtoTransaction.sig_map(); + + // check if all signatures belong to current body bytes + auto body_bytes = mProtoTransaction.body_bytes(); + for (auto it = sig_map.sigpair().begin(); it != sig_map.sigpair().end(); it++) { + KeyPairEd25519 key_pair((const unsigned char*)it->pubkey().data()); + if (!key_pair.verify(body_bytes, it->ed25519())) { + return TRANSACTION_VALID_INVALID_SIGN; + } + } + auto transaction_base = mTransactionBody->getTransactionBase(); auto result = transaction_base->checkRequiredSignatures(&sig_map); @@ -118,6 +205,8 @@ namespace model { return result; } + + } } \ No newline at end of file diff --git a/src/cpp/model/gradido/Transaction.h b/src/cpp/model/gradido/Transaction.h index 8ba557eb9..21490e4c4 100644 --- a/src/cpp/model/gradido/Transaction.h +++ b/src/cpp/model/gradido/Transaction.h @@ -11,20 +11,31 @@ #include "../../proto/gradido/GradidoTransaction.pb.h" #include "TransactionBody.h" +#include "../../tasks/GradidoTask.h" #include "../../controller/User.h" namespace model { namespace gradido { - class Transaction : public NotificationList + class Transaction : public GradidoTask { public: Transaction(Poco::AutoPtr body); + Transaction(const std::string& protoMessageBin, model::table::PendingTask* dbModel); ~Transaction(); + // create group add member transaction + static Poco::AutoPtr create(Poco::AutoPtr user, Poco::AutoPtr group); + static Poco::AutoPtr load(model::table::PendingTask* dbModel); + bool addSign(Poco::AutoPtr user); TransactionValidation validate(); + inline Poco::AutoPtr getTransactionBody() { Poco::ScopedLock _lock(mWorkMutex); return mTransactionBody; } + + //! \brief get current body bytes from proto transaction and save it into db + bool updateRequestInDB(); + bool insertPendingTaskIntoDB(Poco::AutoPtr user, model::table::TaskType type); protected: Poco::AutoPtr mTransactionBody; diff --git a/src/cpp/model/gradido/TransactionBase.h b/src/cpp/model/gradido/TransactionBase.h index 83e0c9157..e832f8fe6 100644 --- a/src/cpp/model/gradido/TransactionBase.h +++ b/src/cpp/model/gradido/TransactionBase.h @@ -28,7 +28,8 @@ namespace model { TRANSACTION_VALID_CREATION_OUT_OF_BORDER, TRANSACTION_VALID_INVALID_AMOUNT, TRANSCATION_VALID_INVALID_PUBKEY, - TRANSACTION_VALID_INVALID_GROUP_ALIAS + TRANSACTION_VALID_INVALID_GROUP_ALIAS, + TRANSACTION_VALID_INVALID_SIGN }; class TransactionBase : public NotificationList, public UniLib::lib::MultithreadContainer diff --git a/src/cpp/model/gradido/TransactionBody.cpp b/src/cpp/model/gradido/TransactionBody.cpp index 010353315..44052fb1e 100644 --- a/src/cpp/model/gradido/TransactionBody.cpp +++ b/src/cpp/model/gradido/TransactionBody.cpp @@ -35,13 +35,11 @@ namespace model { return obj; } - Poco::AutoPtr TransactionBody::create(const MemoryBin* protoMessageBin) + Poco::AutoPtr TransactionBody::load(const std::string& protoMessageBin) { Poco::AutoPtr obj = new TransactionBody; - std::string binString((char*)protoMessageBin, protoMessageBin->size()); - - if (!obj->mTransactionBody.ParseFromString(binString)) { + if (!obj->mTransactionBody.ParseFromString(protoMessageBin)) { return nullptr; } @@ -73,6 +71,12 @@ namespace model { return ""; } + void TransactionBody::setMemo(const std::string& memo) + { + Poco::ScopedLock _lock(mWorkMutex); + mTransactionBody.set_memo(memo); + } + std::string TransactionBody::getBodyBytes() { Poco::ScopedLock _lock(mWorkMutex); diff --git a/src/cpp/model/gradido/TransactionBody.h b/src/cpp/model/gradido/TransactionBody.h index 42641fb66..e58fcd019 100644 --- a/src/cpp/model/gradido/TransactionBody.h +++ b/src/cpp/model/gradido/TransactionBody.h @@ -29,11 +29,11 @@ namespace model { ~TransactionBody(); static Poco::AutoPtr create(const std::string& memo, Poco::AutoPtr user, proto::gradido::GroupMemberUpdate_MemberUpdateType type, const std::string& targetGroupAlias); - static Poco::AutoPtr create(const MemoryBin* protoMessageBin); + static Poco::AutoPtr load(const std::string& protoMessageBin); inline TransactionType getType() { lock(); auto t = mType; unlock(); return t; } std::string getMemo(); - + void setMemo(const std::string& memo); bool isCreation() { Poco::ScopedLock _lock(mWorkMutex); return mType == TRANSACTION_CREATION; } bool isTransfer() { Poco::ScopedLock _lock(mWorkMutex); return mType == TRANSACTION_TRANSFER; } diff --git a/src/cpp/model/table/PendingTask.cpp b/src/cpp/model/table/PendingTask.cpp index dda0b6b5d..7c49c5e32 100644 --- a/src/cpp/model/table/PendingTask.cpp +++ b/src/cpp/model/table/PendingTask.cpp @@ -30,6 +30,11 @@ namespace model } + void PendingTask::setRequest(const std::string& serializedProto) + { + UNIQUE_LOCK; + mRequest.assignRaw((const unsigned char*)serializedProto.data(), serializedProto.size()); + } std::string PendingTask::toString() @@ -54,6 +59,13 @@ namespace model } return ""; } + + bool PendingTask::isGradidoTransaction(TaskType type) + { + if (type && type < TASK_TYPE_HEDERA_TOPIC_CREATE) + return true; + return false; + } Poco::Data::Statement PendingTask::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { diff --git a/src/cpp/model/table/PendingTask.h b/src/cpp/model/table/PendingTask.h index d8a4842a9..0876a26b0 100644 --- a/src/cpp/model/table/PendingTask.h +++ b/src/cpp/model/table/PendingTask.h @@ -38,8 +38,16 @@ namespace model { std::string toString(); inline int getUserId() const { SHARED_LOCK; return mUserId; } - TaskType getTaskType() const { SHARED_LOCK; return (TaskType)mTaskTypeId; } + inline TaskType getTaskType() const { SHARED_LOCK; return (TaskType)mTaskTypeId; } + inline const std::vector& getRequest() const { SHARED_LOCK; return mRequest.content(); } + inline std::string getRequestCopy() const { SHARED_LOCK; return std::string((const char*)mRequest.content().data(), mRequest.content().size()); } + inline void setUserId(int userId) { UNIQUE_LOCK; mUserId = userId; } + inline void setTaskType(TaskType type) { UNIQUE_LOCK; mTaskTypeId = type; } + void setRequest(const std::string& serializedProto); + inline bool isGradidoTransaction() { SHARED_LOCK; return isGradidoTransaction((TaskType)mTaskTypeId); } + + static bool isGradidoTransaction(TaskType type); static const char* typeToString(TaskType type); protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); diff --git a/src/cpp/tasks/GradidoGroupAddMemberTask.cpp b/src/cpp/tasks/GradidoGroupAddMemberTask.cpp deleted file mode 100644 index 7028dd741..000000000 --- a/src/cpp/tasks/GradidoGroupAddMemberTask.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "GradidoGroupAddMemberTask.h" -#include "../model/gradido/GroupMemberUpdate.h" - -GradidoGroupAddMemberTask::GradidoGroupAddMemberTask(model::table::PendingTask* dbModel, Poco::AutoPtr transactionBody) - : GradidoTask(dbModel, transactionBody) -{ - -} - - -Poco::AutoPtr GradidoGroupAddMemberTask::create(Poco::AutoPtr user, Poco::AutoPtr group, const std::string& memo) -{ - if (user.isNull() || !user->getModel() || group.isNull() || !group->getModel()) { - return nullptr; - } - static const char* function_name = "GradidoGroupAddMemberTask::create"; - auto group_model = group->getModel(); - auto transaction = model::gradido::TransactionBody::create(memo, user, proto::gradido::GroupMemberUpdate_MemberUpdateType_ADD_USER, group_model->getAlias()); - auto user_model = user->getModel(); - auto dbModel = new model::table::PendingTask(user_model->getID(), transaction->getBodyBytes(), model::table::TASK_TYPE_GROUP_ADD_MEMBER); - if (!dbModel->insertIntoDB(true)) { - dbModel->addError(new Error(function_name, "error inserting pending task into db, abort")); - dbModel->sendErrorsAsEmail(); - return nullptr; - } - return new GradidoGroupAddMemberTask(dbModel, transaction); -} \ No newline at end of file diff --git a/src/cpp/tasks/GradidoGroupAddMemberTask.h b/src/cpp/tasks/GradidoGroupAddMemberTask.h deleted file mode 100644 index d532f7913..000000000 --- a/src/cpp/tasks/GradidoGroupAddMemberTask.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_GROUP_ADD_MEMBER_TASK_H -#define GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_GROUP_ADD_MEMBER_TASK_H - -#include "GradidoTask.h" -#include "../controller/User.h" -#include "../controller/Group.h" - -class GradidoGroupAddMemberTask : public GradidoTask -{ -public: - GradidoGroupAddMemberTask(model::table::PendingTask* dbModel, Poco::AutoPtr transactionBody); - - static Poco::AutoPtr create(Poco::AutoPtr user, Poco::AutoPtr group, const std::string& memo); - -protected: - -}; - -#endif //GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_GROUP_ADD_MEMBER_TASK_H \ No newline at end of file diff --git a/src/cpp/tasks/GradidoTask.cpp b/src/cpp/tasks/GradidoTask.cpp index 6481d9f4a..cd68a6e19 100644 --- a/src/cpp/tasks/GradidoTask.cpp +++ b/src/cpp/tasks/GradidoTask.cpp @@ -1,7 +1,13 @@ #include "GradidoTask.h" -GradidoTask::GradidoTask(model::table::PendingTask* dbModel, Poco::AutoPtr transactionBody) - : controller::PendingTask(dbModel), mGradidoTransactionBody(transactionBody) +GradidoTask::GradidoTask() + : controller::PendingTask(new model::table::PendingTask) { +} + +GradidoTask::GradidoTask(model::table::PendingTask* dbModel) + : controller::PendingTask(dbModel) +{ + } \ No newline at end of file diff --git a/src/cpp/tasks/GradidoTask.h b/src/cpp/tasks/GradidoTask.h index dc5a017e4..f91855249 100644 --- a/src/cpp/tasks/GradidoTask.h +++ b/src/cpp/tasks/GradidoTask.h @@ -7,12 +7,13 @@ class GradidoTask : public controller::PendingTask, public NotificationList { public: - GradidoTask(model::table::PendingTask* dbModel, Poco::AutoPtr transactionBody); + GradidoTask(); + GradidoTask(model::table::PendingTask* dbModel); bool isTimeoutTask() { return false; } protected: - Poco::AutoPtr mGradidoTransactionBody; + }; #endif //GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_TASK \ No newline at end of file diff --git a/src/cpp/tasks/ProcessingTransaction.cpp b/src/cpp/tasks/ProcessingTransaction.cpp index 74fca7e0a..4ed9c3c6e 100644 --- a/src/cpp/tasks/ProcessingTransaction.cpp +++ b/src/cpp/tasks/ProcessingTransaction.cpp @@ -98,7 +98,8 @@ int ProcessingTransaction::run() unlock(); return -1; } - mTransactionBody = model::gradido::TransactionBody::create(protoMessageBin); + auto proto_message_string = std::string((const char*)protoMessageBin->data(), protoMessageBin->size()); + mTransactionBody = model::gradido::TransactionBody::load(proto_message_string); mm->releaseMemory(protoMessageBin); } if (mTransactionBody.isNull()) {