complete new gradido transaction live circle, at least for group add member transaction

This commit is contained in:
Dario 2020-10-15 14:07:39 +02:00 committed by Ulf Gebhardt
parent 064acee487
commit 28926b9507
No known key found for this signature in database
GPG Key ID: 81308EFE29ABFEBD
15 changed files with 177 additions and 72 deletions

View File

@ -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<SecretKeyCryptography> password) const MemoryBin* KeyPairEd25519::getCryptedPrivKey(const Poco::AutoPtr<SecretKeyCryptography> password) const
{ {
if (password.isNull()) return nullptr; if (password.isNull()) return nullptr;

View File

@ -37,6 +37,8 @@ public:
inline MemoryBin* sign(const std::string& bodyBytes) const { return sign((const unsigned char*)bodyBytes.data(), bodyBytes.size()); } 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; 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 const unsigned char* getPublicKey() const { return mSodiumPublic; }
inline std::string getPublicKeyHex() const { return DataTypeConverter::binToHex(mSodiumPublic, getPublicKeySize()); } inline std::string getPublicKeyHex() const { return DataTypeConverter::binToHex(mSodiumPublic, getPublicKeySize()); }
const static size_t getPublicKeySize() { return crypto_sign_PUBLICKEYBYTES; } const static size_t getPublicKeySize() { return crypto_sign_PUBLICKEYBYTES; }

View File

@ -1,6 +1,7 @@
#include "PendingTask.h" #include "PendingTask.h"
#include "../tasks/GradidoGroupAddMemberTask.h" #include "../tasks/GradidoGroupAddMemberTask.h"
#include "../model/gradido/Transaction.h"
namespace controller { namespace controller {
@ -37,6 +38,23 @@ namespace controller {
} }
/*Poco::AutoPtr<PendingTask> PendingTask::loadCorrectDerivedClass(model::table::PendingTask* dbModel)
{
if (dbModel->isGradidoTransaction()) {
return model::gradido::Transaction::load(dbModel);
}
}*/
Poco::AutoPtr<PendingTask> 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<Poco::AutoPtr<PendingTask>> PendingTask::loadAll() std::vector<Poco::AutoPtr<PendingTask>> PendingTask::loadAll()
{ {
auto db = new model::table::PendingTask(); auto db = new model::table::PendingTask();
@ -55,15 +73,4 @@ namespace controller {
} }
return resultVector; return resultVector;
} }
Poco::AutoPtr<PendingTask> 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;
}
} }

View File

@ -1,5 +1,6 @@
#include "Transaction.h" #include "Transaction.h"
#include "../../SingletonManager/ErrorManager.h" #include "../../SingletonManager/ErrorManager.h"
#include "../../SingletonManager/PendingTasksManager.h"
namespace model { namespace model {
namespace gradido { namespace gradido {
@ -9,14 +10,70 @@ namespace model {
} }
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() Transaction::~Transaction()
{ {
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
}
Poco::AutoPtr<Transaction> Transaction::create(Poco::AutoPtr<controller::User> user, Poco::AutoPtr<controller::Group> 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<Transaction> 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> Transaction::load(model::table::PendingTask* dbModel)
{
proto::gradido::GradidoTransaction transaction_temp;
Poco::AutoPtr<Transaction> transaction = new Transaction(dbModel->getRequestCopy(), dbModel);
PendingTasksManager::getInstance()->addTask(transaction);
return transaction;
}
bool Transaction::insertPendingTaskIntoDB(Poco::AutoPtr<controller::User> 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<controller::User> user) bool Transaction::addSign(Poco::AutoPtr<controller::User> user)
{ {
static const char function_name[] = "Transaction::addSign"; static const char function_name[] = "Transaction::addSign";
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
if (user.isNull() || !user->getModel()) 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!")); addError(new Error(function_name, "body bytes hash has changed and signature(s) exist already!"));
return false; return false;
} }
if (mBodyBytesHash != hash) {
mProtoTransaction.set_body_bytes(bodyBytes.data(), bodyBytes.size());
}
mBodyBytesHash = hash; mBodyBytesHash = hash;
auto pubkeyBin = user->getModel()->getPublicKey(); auto pubkeyBin = user->getModel()->getPublicKey();
@ -103,11 +163,38 @@ namespace model {
*sigBytes = std::string((char*)*sign, sign->size()); *sigBytes = std::string((char*)*sign, sign->size());
mm->releaseMemory(sign); mm->releaseMemory(sign);
updateRequestInDB();
//getModel()->updateIntoDB("request", )
return true; return true;
} }
bool Transaction::updateRequestInDB()
{
Poco::ScopedLock<Poco::Mutex> _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() TransactionValidation Transaction::validate()
{ {
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
auto sig_map = mProtoTransaction.sig_map(); 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 transaction_base = mTransactionBody->getTransactionBase();
auto result = transaction_base->checkRequiredSignatures(&sig_map); auto result = transaction_base->checkRequiredSignatures(&sig_map);
@ -119,5 +206,7 @@ namespace model {
} }
} }
} }

View File

@ -11,20 +11,31 @@
#include "../../proto/gradido/GradidoTransaction.pb.h" #include "../../proto/gradido/GradidoTransaction.pb.h"
#include "TransactionBody.h" #include "TransactionBody.h"
#include "../../tasks/GradidoTask.h"
#include "../../controller/User.h" #include "../../controller/User.h"
namespace model { namespace model {
namespace gradido { namespace gradido {
class Transaction : public NotificationList class Transaction : public GradidoTask
{ {
public: public:
Transaction(Poco::AutoPtr<TransactionBody> body); Transaction(Poco::AutoPtr<TransactionBody> body);
Transaction(const std::string& protoMessageBin, model::table::PendingTask* dbModel);
~Transaction(); ~Transaction();
// create group add member transaction
static Poco::AutoPtr<Transaction> create(Poco::AutoPtr<controller::User> user, Poco::AutoPtr<controller::Group> group);
static Poco::AutoPtr<Transaction> load(model::table::PendingTask* dbModel);
bool addSign(Poco::AutoPtr<controller::User> user); bool addSign(Poco::AutoPtr<controller::User> user);
TransactionValidation validate(); TransactionValidation validate();
inline Poco::AutoPtr<TransactionBody> getTransactionBody() { Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex); return mTransactionBody; }
//! \brief get current body bytes from proto transaction and save it into db
bool updateRequestInDB();
bool insertPendingTaskIntoDB(Poco::AutoPtr<controller::User> user, model::table::TaskType type);
protected: protected:
Poco::AutoPtr<TransactionBody> mTransactionBody; Poco::AutoPtr<TransactionBody> mTransactionBody;

View File

@ -28,7 +28,8 @@ namespace model {
TRANSACTION_VALID_CREATION_OUT_OF_BORDER, TRANSACTION_VALID_CREATION_OUT_OF_BORDER,
TRANSACTION_VALID_INVALID_AMOUNT, TRANSACTION_VALID_INVALID_AMOUNT,
TRANSCATION_VALID_INVALID_PUBKEY, 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 class TransactionBase : public NotificationList, public UniLib::lib::MultithreadContainer

View File

@ -35,13 +35,11 @@ namespace model {
return obj; return obj;
} }
Poco::AutoPtr<TransactionBody> TransactionBody::create(const MemoryBin* protoMessageBin) Poco::AutoPtr<TransactionBody> TransactionBody::load(const std::string& protoMessageBin)
{ {
Poco::AutoPtr<TransactionBody> obj = new TransactionBody; Poco::AutoPtr<TransactionBody> obj = new TransactionBody;
std::string binString((char*)protoMessageBin, protoMessageBin->size()); if (!obj->mTransactionBody.ParseFromString(protoMessageBin)) {
if (!obj->mTransactionBody.ParseFromString(binString)) {
return nullptr; return nullptr;
} }
@ -73,6 +71,12 @@ namespace model {
return "<uninitalized>"; return "<uninitalized>";
} }
void TransactionBody::setMemo(const std::string& memo)
{
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
mTransactionBody.set_memo(memo);
}
std::string TransactionBody::getBodyBytes() std::string TransactionBody::getBodyBytes()
{ {
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex); Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);

View File

@ -29,11 +29,11 @@ namespace model {
~TransactionBody(); ~TransactionBody();
static Poco::AutoPtr<TransactionBody> create(const std::string& memo, Poco::AutoPtr<controller::User> user, proto::gradido::GroupMemberUpdate_MemberUpdateType type, const std::string& targetGroupAlias); static Poco::AutoPtr<TransactionBody> create(const std::string& memo, Poco::AutoPtr<controller::User> user, proto::gradido::GroupMemberUpdate_MemberUpdateType type, const std::string& targetGroupAlias);
static Poco::AutoPtr<TransactionBody> create(const MemoryBin* protoMessageBin); static Poco::AutoPtr<TransactionBody> load(const std::string& protoMessageBin);
inline TransactionType getType() { lock(); auto t = mType; unlock(); return t; } inline TransactionType getType() { lock(); auto t = mType; unlock(); return t; }
std::string getMemo(); std::string getMemo();
void setMemo(const std::string& memo);
bool isCreation() { Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex); return mType == TRANSACTION_CREATION; } bool isCreation() { Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex); return mType == TRANSACTION_CREATION; }
bool isTransfer() { Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex); return mType == TRANSACTION_TRANSFER; } bool isTransfer() { Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex); return mType == TRANSACTION_TRANSFER; }

View File

@ -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() std::string PendingTask::toString()
@ -55,6 +60,13 @@ namespace model
return "<invalid>"; return "<invalid>";
} }
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) Poco::Data::Statement PendingTask::_loadFromDB(Poco::Data::Session session, const std::string& fieldName)
{ {
Poco::Data::Statement select(session); Poco::Data::Statement select(session);

View File

@ -38,8 +38,16 @@ namespace model {
std::string toString(); std::string toString();
inline int getUserId() const { SHARED_LOCK; return mUserId; } 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<unsigned char>& 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); static const char* typeToString(TaskType type);
protected: protected:
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);

View File

@ -1,27 +0,0 @@
#include "GradidoGroupAddMemberTask.h"
#include "../model/gradido/GroupMemberUpdate.h"
GradidoGroupAddMemberTask::GradidoGroupAddMemberTask(model::table::PendingTask* dbModel, Poco::AutoPtr<model::gradido::TransactionBody> transactionBody)
: GradidoTask(dbModel, transactionBody)
{
}
Poco::AutoPtr<controller::PendingTask> GradidoGroupAddMemberTask::create(Poco::AutoPtr<controller::User> user, Poco::AutoPtr<controller::Group> 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);
}

View File

@ -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<model::gradido::TransactionBody> transactionBody);
static Poco::AutoPtr<controller::PendingTask> create(Poco::AutoPtr<controller::User> user, Poco::AutoPtr<controller::Group> group, const std::string& memo);
protected:
};
#endif //GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_GROUP_ADD_MEMBER_TASK_H

View File

@ -1,7 +1,13 @@
#include "GradidoTask.h" #include "GradidoTask.h"
GradidoTask::GradidoTask(model::table::PendingTask* dbModel, Poco::AutoPtr<model::gradido::TransactionBody> transactionBody) GradidoTask::GradidoTask()
: controller::PendingTask(dbModel), mGradidoTransactionBody(transactionBody) : controller::PendingTask(new model::table::PendingTask)
{
}
GradidoTask::GradidoTask(model::table::PendingTask* dbModel)
: controller::PendingTask(dbModel)
{ {
} }

View File

@ -7,12 +7,13 @@
class GradidoTask : public controller::PendingTask, public NotificationList class GradidoTask : public controller::PendingTask, public NotificationList
{ {
public: public:
GradidoTask(model::table::PendingTask* dbModel, Poco::AutoPtr<model::gradido::TransactionBody> transactionBody); GradidoTask();
GradidoTask(model::table::PendingTask* dbModel);
bool isTimeoutTask() { return false; } bool isTimeoutTask() { return false; }
protected: protected:
Poco::AutoPtr<model::gradido::TransactionBody> mGradidoTransactionBody;
}; };
#endif //GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_TASK #endif //GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_TASK

View File

@ -98,7 +98,8 @@ int ProcessingTransaction::run()
unlock(); unlock();
return -1; 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); mm->releaseMemory(protoMessageBin);
} }
if (mTransactionBody.isNull()) { if (mTransactionBody.isNull()) {