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
{
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()); }
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; }

View File

@ -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> 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()
{
auto db = new model::table::PendingTask();
@ -55,15 +73,4 @@ namespace controller {
}
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,22 +1,79 @@
#include "Transaction.h"
#include "../../SingletonManager/ErrorManager.h"
#include "../../SingletonManager/PendingTasksManager.h"
namespace model {
namespace gradido {
Transaction::Transaction(Poco::AutoPtr<TransactionBody> 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<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)
{
static const char function_name[] = "Transaction::addSign";
Poco::ScopedLock<Poco::Mutex> _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<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()
{
Poco::ScopedLock<Poco::Mutex> _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;
}
}
}

View File

@ -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<TransactionBody> body);
Transaction(const std::string& protoMessageBin, model::table::PendingTask* dbModel);
~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);
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:
Poco::AutoPtr<TransactionBody> mTransactionBody;

View File

@ -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

View File

@ -35,13 +35,11 @@ namespace model {
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;
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 "<uninitalized>";
}
void TransactionBody::setMemo(const std::string& memo)
{
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
mTransactionBody.set_memo(memo);
}
std::string TransactionBody::getBodyBytes()
{
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);

View File

@ -29,11 +29,11 @@ namespace model {
~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 MemoryBin* protoMessageBin);
static Poco::AutoPtr<TransactionBody> 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<Poco::Mutex> _lock(mWorkMutex); return mType == TRANSACTION_CREATION; }
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()
@ -54,6 +59,13 @@ namespace model
}
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)
{

View File

@ -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<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);
protected:
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"
GradidoTask::GradidoTask(model::table::PendingTask* dbModel, Poco::AutoPtr<model::gradido::TransactionBody> transactionBody)
: controller::PendingTask(dbModel), mGradidoTransactionBody(transactionBody)
GradidoTask::GradidoTask()
: 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
{
public:
GradidoTask(model::table::PendingTask* dbModel, Poco::AutoPtr<model::gradido::TransactionBody> transactionBody);
GradidoTask();
GradidoTask(model::table::PendingTask* dbModel);
bool isTimeoutTask() { return false; }
protected:
Poco::AutoPtr<model::gradido::TransactionBody> mGradidoTransactionBody;
};
#endif //GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_TASK

View File

@ -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()) {