From e9adc51f9608d39168e360fb1504af24aa1efa3c Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 27 Aug 2024 13:40:43 +0200 Subject: [PATCH] make validation exception messages better understable and more detailed --- .../gradido_blockchain/blockchain/InMemory.h | 11 --- .../interaction/validate/AbstractRole.h | 3 +- .../interaction/validate/Exceptions.h | 10 ++- src/interaction/validate/AbstractRole.cpp | 4 +- .../validate/ConfirmedTransactionRole.cpp | 69 ++++++++++++---- src/interaction/validate/Exceptions.cpp | 56 +++++++++++-- .../validate/GradidoCreationRole.cpp | 78 +++++++++++++++---- .../validate/GradidoDeferredTransferRole.cpp | 24 +++++- .../validate/GradidoTransactionRole.cpp | 12 ++- .../validate/GradidoTransferRole.cpp | 3 +- .../validate/RegisterAddressRole.cpp | 2 +- .../validate/TransactionBodyRole.cpp | 40 ++++++++-- .../validate/TransferAmountRole.cpp | 14 +++- 13 files changed, 261 insertions(+), 65 deletions(-) diff --git a/include/gradido_blockchain/blockchain/InMemory.h b/include/gradido_blockchain/blockchain/InMemory.h index 518f4ca6..1c4bf4f4 100644 --- a/include/gradido_blockchain/blockchain/InMemory.h +++ b/include/gradido_blockchain/blockchain/InMemory.h @@ -37,17 +37,6 @@ namespace gradido { //! \return false if transaction already exist bool addGradidoTransaction(data::ConstGradidoTransactionPtr gradidoTransaction, memory::ConstBlockPtr messageId, Timepoint confirmedAt); - struct UserBalance - { - UserBalance(memory::ConstBlockPtr _userPubkey, GradidoUnit _balance, Timepoint _balanceDate) - : userPubkey(_userPubkey), balance(_balance), balanceDate(_balanceDate) {} - memory::ConstBlockPtr userPubkey; - GradidoUnit balance; - Timepoint balanceDate; - }; - - //std::string getUserTransactionsDebugString(const std::string& groupAlias, const std::string& pubkeyHex); - // get all transactions sorted by id const TransactionEntries& getSortedTransactions(); diff --git a/include/gradido_blockchain/interaction/validate/AbstractRole.h b/include/gradido_blockchain/interaction/validate/AbstractRole.h index 4dfceaac..bffd59c2 100644 --- a/include/gradido_blockchain/interaction/validate/AbstractRole.h +++ b/include/gradido_blockchain/interaction/validate/AbstractRole.h @@ -7,7 +7,7 @@ namespace gradido { namespace interaction { namespace validate { - + class AbstractRole { public: @@ -38,6 +38,7 @@ namespace gradido { void isPublicKeyForbidden(memory::ConstBlockPtr pubkey) const; + const static std::string mCommunityIdRegexString; data::TimestampSeconds mConfirmedAt; data::Timestamp mCreatedAt; uint32_t mMinSignatureCount; diff --git a/include/gradido_blockchain/interaction/validate/Exceptions.h b/include/gradido_blockchain/interaction/validate/Exceptions.h index 3889cce1..2ee48045 100644 --- a/include/gradido_blockchain/interaction/validate/Exceptions.h +++ b/include/gradido_blockchain/interaction/validate/Exceptions.h @@ -38,7 +38,13 @@ namespace gradido { class GRADIDOBLOCKCHAIN_EXPORT TransactionValidationInvalidInputException : public TransactionValidationException { public: - explicit TransactionValidationInvalidInputException(const char* what, const char* fieldname, const char* fieldType = nullptr) noexcept; + explicit TransactionValidationInvalidInputException( + const char* what, + const char* fieldName, + const char* fieldType = nullptr, + const char* expected = nullptr, + const char* actual = nullptr + ) noexcept; std::string getFullString() const noexcept; //! mainly for return as details for json requests rapidjson::Value getDetails(rapidjson::Document::AllocatorType& alloc) const; @@ -48,6 +54,8 @@ namespace gradido { protected: std::string mFieldName; std::string mFieldType; + std::string mExpected; + std::string mActual; }; class GRADIDOBLOCKCHAIN_EXPORT TransactionValidationInvalidSignatureException : public TransactionValidationException diff --git a/src/interaction/validate/AbstractRole.cpp b/src/interaction/validate/AbstractRole.cpp index 92b4f4db..414020e9 100644 --- a/src/interaction/validate/AbstractRole.cpp +++ b/src/interaction/validate/AbstractRole.cpp @@ -9,7 +9,9 @@ namespace gradido { namespace interaction { namespace validate { - std::regex g_RegExCommunityAlias("^[a-z0-9-]{3,120}$"); + #define COMMUNITY_ID_REGEX_STRING "^[a-z0-9-]{3,120}$" + const std::string AbstractRole::mCommunityIdRegexString = COMMUNITY_ID_REGEX_STRING; + std::regex g_RegExCommunityAlias(COMMUNITY_ID_REGEX_STRING); bool AbstractRole::isValidCommunityAlias(std::string_view communityAlias) const { diff --git a/src/interaction/validate/ConfirmedTransactionRole.cpp b/src/interaction/validate/ConfirmedTransactionRole.cpp index e889ff4c..e2a91379 100644 --- a/src/interaction/validate/ConfirmedTransactionRole.cpp +++ b/src/interaction/validate/ConfirmedTransactionRole.cpp @@ -1,7 +1,8 @@ -#include "gradido_blockchain/interaction/validate/ConfirmedTransactionRole.h" #include "gradido_blockchain/const.h" +#include "gradido_blockchain/interaction/validate/ConfirmedTransactionRole.h" #include "gradido_blockchain/interaction/validate/Exceptions.h" #include "gradido_blockchain/interaction/validate/GradidoTransactionRole.h" +#include "gradido_blockchain/lib/DataTypeConverter.h" using namespace std::chrono; @@ -21,23 +22,38 @@ namespace gradido { if ((type & Type::SINGLE) == Type::SINGLE) { if (mConfirmedTransaction.getVersionNumber() != GRADIDO_CONFIRMED_TRANSACTION_V3_3_VERSION_STRING) { - TransactionValidationInvalidInputException exception("wrong version in gradido block", "version_number", "uint64"); + TransactionValidationInvalidInputException exception( + "wrong version", + "version_number", + "string", + GRADIDO_CONFIRMED_TRANSACTION_V3_3_VERSION_STRING, + mConfirmedTransaction.getVersionNumber().data() + ); exception.setTransactionBody(*body); throw exception; } auto messageId = mConfirmedTransaction.getMessageId(); // with iota it is a BLAKE2b-256 hash with 256 Bits or 32 Bytes if (messageId && messageId->size() != 32) { - TransactionValidationInvalidInputException exception("wrong size", "message_id", "binary"); + TransactionValidationInvalidInputException exception( + "wrong size", + "message_id", + "bytes", + "32", + std::to_string(messageId->size()).data() + ); exception.setTransactionBody(*body); throw exception; } if (confirmedAt - createdAt < duration::zero()) { + std::string expected = ">= " + DataTypeConverter::timePointToString(createdAt); TransactionValidationInvalidInputException exception( "timespan between created and received are negative", - "iota milestone timestamp", - std::to_string(mConfirmedTransaction.getConfirmedAt().getSeconds()).data() + "confirmed_at", + "TimestampSeconds", + expected.data(), + DataTypeConverter::timePointToString(confirmedAt).data() ); exception.setTransactionBody(*body); throw exception; @@ -65,21 +81,48 @@ namespace gradido { if (previousCreated > createdAt) { auto timespanBetweenCreatedAndReceived = duration_cast(confirmedAt - createdAt); if (timespanBetweenCreatedAndReceived > MAGIC_NUMBER_MAX_TIMESPAN_BETWEEN_CREATING_AND_RECEIVING_TRANSACTION) { + std::string message = "timespan between created and received are more than " + DataTypeConverter::timespanToString(MAGIC_NUMBER_MAX_TIMESPAN_BETWEEN_CREATING_AND_RECEIVING_TRANSACTION); + std::string expected = "<= (" + DataTypeConverter::timePointToString(createdAt) + " + " + DataTypeConverter::timespanToString(MAGIC_NUMBER_MAX_TIMESPAN_BETWEEN_CREATING_AND_RECEIVING_TRANSACTION) + ")"; TransactionValidationInvalidInputException exception( - "timespan between created and received are more than 2 minutes", - "received/iota milestone timestamp", - "int64" + message.data(), + "confirmed_at", + "TimestampSeconds", + expected.data(), + DataTypeConverter::timePointToString(confirmedAt).data() ); exception.setTransactionBody(*body); throw exception; } } - auto txHash = mConfirmedTransaction.calculateRunningHash(previousConfirmedTransaction); - if (!mConfirmedTransaction.getRunningHash() || txHash->size() != mConfirmedTransaction.getRunningHash()->size()) { - throw TransactionValidationException("tx hash size isn't equal"); + auto runningHash = mConfirmedTransaction.calculateRunningHash(previousConfirmedTransaction); + if (!mConfirmedTransaction.getRunningHash() || runningHash->size() != mConfirmedTransaction.getRunningHash()->size()) { + std::string fieldTypeWithSize = "binary[" + std::to_string(crypto_generichash_BYTES) + "]"; + std::string actual = "0"; + if(mConfirmedTransaction.getRunningHash()) { + actual = std::to_string(mConfirmedTransaction.getRunningHash()->size()); + } + throw TransactionValidationInvalidInputException( + "stored running hash size isn't equal to calculated running hash size", + "running_hash", + fieldTypeWithSize.data(), + std::to_string(runningHash->size()).data(), + actual.data() + ); } - if(!txHash->isTheSame(mConfirmedTransaction.getRunningHash())) { - throw TransactionValidationInvalidInputException("stored tx hash isn't equal to calculated txHash", "txHash", "binary"); + if(!runningHash->isTheSame(mConfirmedTransaction.getRunningHash())) { + std::string fieldTypeWithSize = "binary[" + std::to_string(crypto_generichash_BYTES) + "]"; + std::string actual = ""; + if(mConfirmedTransaction.getRunningHash()) { + actual = mConfirmedTransaction.getRunningHash()->convertToHex(); + } + + throw TransactionValidationInvalidInputException( + "stored tx hash isn't equal to calculated txHash", + "running_hash", + fieldTypeWithSize.data(), + runningHash->convertToHex().data(), + actual.data() + ); } } } diff --git a/src/interaction/validate/Exceptions.cpp b/src/interaction/validate/Exceptions.cpp index 44be050c..004c37bb 100644 --- a/src/interaction/validate/Exceptions.cpp +++ b/src/interaction/validate/Exceptions.cpp @@ -33,30 +33,73 @@ namespace gradido { //************* Invalid Input ******************* TransactionValidationInvalidInputException::TransactionValidationInvalidInputException( - const char* what, const char* fieldname, const char* fieldType/* = nullptr*/ + const char* what, + const char* fieldName, + const char* fieldType/* = nullptr*/, + const char* expected/* = nullptr*/, + const char* actual/* = nullptr*/ ) noexcept - : TransactionValidationException(what), mFieldName(fieldname) + : TransactionValidationException(what), mFieldName(fieldName) { if (fieldType) { mFieldType = fieldType; } + if(expected) { + mExpected = expected; + } + if(actual) { + mActual = actual; + } } std::string TransactionValidationInvalidInputException::getFullString() const noexcept { std::string result; auto whatString = what(); - result.reserve(mFieldName.size() + mFieldType.size() + strlen(whatString) + 10); + size_t stringSize = mFieldName.size() + mFieldType.size() + strlen(whatString) + 10; + if(!mTransactionMemo.empty()) { + stringSize += mTransactionMemo.size() + 17; + } + if(!mExpected.empty()) { + stringSize += mExpected.size() + 10 + 2; + } + if(!mActual.empty()) { + stringSize += mActual.size() + 8 + 2; + } + result.reserve(stringSize); result = whatString; + if(!mTransactionMemo.empty()) { + result += " with memo: " + mTransactionMemo + " and "; + } result += " with " + mFieldName + ": " + mFieldType; + if(!mExpected.empty()) { + if(!result.empty()) result += ", "; + result += "expected: " + mExpected; + } + if(!mActual.empty()) { + if(!result.empty()) result += ", "; + result += "actual: " + mActual; + } return result; } Value TransactionValidationInvalidInputException::getDetails(Document::AllocatorType& alloc) const { Value detailsObjs(kObjectType); detailsObjs.AddMember("what", Value(what(), alloc), alloc); + if(!mTransactionMemo.empty()) { + detailsObjs.AddMember("memo", Value(mTransactionMemo.data(), alloc), alloc); + } detailsObjs.AddMember("fieldName", Value(mFieldName.data(), alloc), alloc); - detailsObjs.AddMember("fieldType", Value(mFieldType.data(), alloc), alloc); + if(!mFieldType.empty()) { + detailsObjs.AddMember("fieldType", Value(mFieldType.data(), alloc), alloc); + } + if(!mExpected.empty()) { + detailsObjs.AddMember("expected", Value(mExpected.data(), alloc), alloc); + } + if(!mActual.empty()) { + detailsObjs.AddMember("actual", Value(mActual.data(), alloc), alloc); + } + return std::move(detailsObjs); } @@ -137,7 +180,10 @@ namespace gradido { result += "transaction with memo: " + mTransactionMemo; } if (forbiddenPubkeyHex.size()) { - result += ", this forbidden pubkey was used for signing: " + forbiddenPubkeyHex; + if(result.size()) { + result += ", "; + } + result += "this forbidden pubkey was used for signing: " + forbiddenPubkeyHex; } return result; } diff --git a/src/interaction/validate/GradidoCreationRole.cpp b/src/interaction/validate/GradidoCreationRole.cpp index 02d19cfb..0c5c072f 100644 --- a/src/interaction/validate/GradidoCreationRole.cpp +++ b/src/interaction/validate/GradidoCreationRole.cpp @@ -1,7 +1,8 @@ +#include "gradido_blockchain/blockchain/FilterBuilder.h" #include "gradido_blockchain/interaction/validate/GradidoCreationRole.h" #include "gradido_blockchain/interaction/validate/Exceptions.h" #include "gradido_blockchain/interaction/validate/TransferAmountRole.h" -#include "gradido_blockchain/blockchain/FilterBuilder.h" +#include "gradido_blockchain/lib/DataTypeConverter.h" #include "date/date.h" @@ -33,10 +34,22 @@ namespace gradido { validateEd25519PublicKey(recipient.getPubkey(), "recipient pubkey"); auto recipientAmount = recipient.getAmount(); if (recipientAmount > GradidoUnit(1000.0)) { - throw TransactionValidationInvalidInputException("creation amount to high, max 1000 per month", "amount", "string"); + throw TransactionValidationInvalidInputException( + "creation amount to high, max 1000 per month", + "amount", + "string", + "<= 10000", + recipientAmount.toString().data() + ); } if (recipientAmount < GradidoUnit(1.0)) { - throw TransactionValidationInvalidInputException("creation amount to low, min 1 GDD", "amount", "string"); + throw TransactionValidationInvalidInputException( + "creation amount to low, min 1 GDD", + "amount", + "string", + ">= 1", + recipientAmount.toString().data() + ); } } @@ -144,33 +157,70 @@ namespace gradido { if (target_date.year() == received.year()) { if (static_cast(target_date.month()) + targetDateReceivedDistanceMonth < static_cast(received.month())) { - std::string errorMessage = - "year is the same, target date month is more than " + std::string expected = ">= " + + DataTypeConverter::timePointToString(createdAtTimePoint) + + " - " + std::to_string(static_cast(targetDateReceivedDistanceMonth)) - + " month in past"; - throw TransactionValidationInvalidInputException(errorMessage.data(), "target_date", "date time"); + + " months" + ; + throw TransactionValidationInvalidInputException( + "year is the same, target date month is invalid", + "target_date", + "TimestampSeconds", + expected.data(), + DataTypeConverter::timePointToString(mGradidoCreation->getTargetDate().getAsTimepoint()).data() + ); } if (target_date.month() > received.month()) { - throw TransactionValidationInvalidInputException("year is the same, target date month is in future", "target_date", "date time"); + std::string expected = "<= " + std::to_string(static_cast(received.month())); + throw TransactionValidationInvalidInputException( + "year is the same, target date month is invalid", + "target_date", + "TimestampSeconds", + expected.data(), + std::to_string(static_cast(target_date.month())).data() + ); } } else if (target_date.year() > received.year()) { - throw TransactionValidationInvalidInputException("target date year is in future", "target_date", "date time"); + std::string expected = "<= " + std::to_string(static_cast(received.year())); + throw TransactionValidationInvalidInputException( + "target date year is in future", + "target_date", + "TimestampSeconds", + expected.data(), + std::to_string(static_cast(target_date.year())).data() + ); } else if (static_cast(target_date.year()) + 1 < static_cast(received.year())) { - throw TransactionValidationInvalidInputException("target date year is in past", "target_date", "date time"); + std::string expected = " >= " + std::to_string(static_cast(received.year())) + " - 1 year"; + throw TransactionValidationInvalidInputException( + "target date year is in past", + "target_date", + "TimestampSeconds", + expected.data(), + std::to_string(static_cast(target_date.year())).data() + ); } else { // target_date.year +1 == now.year if (static_cast(target_date.month()) + targetDateReceivedDistanceMonth < static_cast(received.month()) + 12) { - std::string errorMessage = - "target date month is more than " + std::string expected = ">= " + + DataTypeConverter::timePointToString(createdAtTimePoint) + + " - " + std::to_string(static_cast(targetDateReceivedDistanceMonth)) - + " month in past"; - throw TransactionValidationInvalidInputException(errorMessage.data(), "target_date", "date time"); + + " months" + ; + throw TransactionValidationInvalidInputException( + "target date month is invalid", + "target_date", + "TimestampSeconds", + expected.data(), + DataTypeConverter::timePointToString(mGradidoCreation->getTargetDate().getAsTimepoint()).data() + ); } } } diff --git a/src/interaction/validate/GradidoDeferredTransferRole.cpp b/src/interaction/validate/GradidoDeferredTransferRole.cpp index 7d1be466..51507729 100644 --- a/src/interaction/validate/GradidoDeferredTransferRole.cpp +++ b/src/interaction/validate/GradidoDeferredTransferRole.cpp @@ -1,7 +1,8 @@ +#include "gradido_blockchain/const.h" #include "gradido_blockchain/interaction/validate/GradidoDeferredTransferRole.h" #include "gradido_blockchain/interaction/validate/GradidoTransferRole.h" #include "gradido_blockchain/interaction/validate/Exceptions.h" -#include "gradido_blockchain/const.h" +#include "gradido_blockchain/lib/DataTypeConverter.h" #include "date/date.h" @@ -26,11 +27,28 @@ namespace gradido { ) { if ((type & Type::SINGLE) == Type::SINGLE) { if (mDeferredTransfer->getTimeout().getAsTimepoint() - mConfirmedAt.getAsTimepoint() > GRADIDO_DEFERRED_TRANSFER_MAX_TIMEOUT_INTERVAL) { - throw TransactionValidationInvalidInputException("timeout is to far away from confirmed date", "timeout", "timestamp"); + std::string expected = "<= " + + DataTypeConverter::timePointToString(mConfirmedAt.getAsTimepoint()) + + " + " + + DataTypeConverter::timespanToString(GRADIDO_DEFERRED_TRANSFER_MAX_TIMEOUT_INTERVAL); + throw TransactionValidationInvalidInputException( + "timeout is to far away from confirmed date", + "timeout", + "TimestampSeconds", + expected.data(), + DataTypeConverter::timePointToString(mDeferredTransfer->getTimeout().getAsTimepoint()).data() + ); } if (senderPreviousConfirmedTransaction) { if (senderPreviousConfirmedTransaction->getConfirmedAt() >= mDeferredTransfer->getTimeout()) { - throw TransactionValidationInvalidInputException("timeout is already in the past", "timeout", "timestamp"); + std::string expected = "> " + DataTypeConverter::timePointToString(senderPreviousConfirmedTransaction->getConfirmedAt()); + throw TransactionValidationInvalidInputException( + "timeout must be greater than the confirmedAt date from the previous transaction of sender user", + "timeout", + "TimestampSeconds", + expected.data(), + DataTypeConverter::timePointToString(mDeferredTransfer->getTimeout().getAsTimepoint()).data() + ); } } } diff --git a/src/interaction/validate/GradidoTransactionRole.cpp b/src/interaction/validate/GradidoTransactionRole.cpp index a137b297..0b4bd01d 100644 --- a/src/interaction/validate/GradidoTransactionRole.cpp +++ b/src/interaction/validate/GradidoTransactionRole.cpp @@ -1,8 +1,8 @@ -#include "gradido_blockchain/interaction/validate/GradidoTransactionRole.h" +#include "gradido_blockchain/blockchain/TransactionEntry.h" +#include "gradido_blockchain/crypto/KeyPairEd25519.h" +#include "gradido_blockchain/interaction/validate/GradidoTransactionRole.h" #include "gradido_blockchain/interaction/validate/TransactionBodyRole.h" #include "gradido_blockchain/interaction/validate/Exceptions.h" -#include "gradido_blockchain/blockchain/TransactionEntry.h" -#include "gradido_blockchain/crypto/KeyPairEd25519.h" #include "magic_enum/magic_enum.hpp" @@ -61,7 +61,11 @@ namespace gradido { case data::CrossGroupType::OUTBOUND: case data::CrossGroupType::CROSS: if (!mGradidoTransaction.getParingMessageId()) { - throw TransactionValidationInvalidInputException("paring message id not set for outbound", "paring message id", "binary"); + throw TransactionValidationInvalidInputException( + "parent message id not set for outbound or cross", + "parent_message_id", + "bytes[32]" + ); } else { pairTransactionEntry = otherBlockchain->findByMessageId(mGradidoTransaction.getParingMessageId()); diff --git a/src/interaction/validate/GradidoTransferRole.cpp b/src/interaction/validate/GradidoTransferRole.cpp index 70e819ea..5a19d68e 100644 --- a/src/interaction/validate/GradidoTransferRole.cpp +++ b/src/interaction/validate/GradidoTransferRole.cpp @@ -1,10 +1,9 @@ +#include "gradido_blockchain/blockchain/FilterBuilder.h" #include "gradido_blockchain/interaction/validate/GradidoTransferRole.h" #include "gradido_blockchain/interaction/validate/Exceptions.h" #include "gradido_blockchain/interaction/calculateAccountBalance/Context.h" #include "gradido_blockchain/interaction/validate/TransferAmountRole.h" -#include "gradido_blockchain/blockchain/FilterBuilder.h" - #include #include "date/date.h" diff --git a/src/interaction/validate/RegisterAddressRole.cpp b/src/interaction/validate/RegisterAddressRole.cpp index a0f20d6c..004a6896 100644 --- a/src/interaction/validate/RegisterAddressRole.cpp +++ b/src/interaction/validate/RegisterAddressRole.cpp @@ -1,6 +1,6 @@ +#include "gradido_blockchain/blockchain/FilterBuilder.h" #include "gradido_blockchain/interaction/validate/RegisterAddressRole.h" #include "gradido_blockchain/interaction/validate/Exceptions.h" -#include "gradido_blockchain/blockchain/FilterBuilder.h" #include "date/date.h" #include "magic_enum/magic_enum.hpp" diff --git a/src/interaction/validate/TransactionBodyRole.cpp b/src/interaction/validate/TransactionBodyRole.cpp index d7d52f01..7919bb31 100644 --- a/src/interaction/validate/TransactionBodyRole.cpp +++ b/src/interaction/validate/TransactionBodyRole.cpp @@ -1,12 +1,13 @@ -#include "gradido_blockchain/interaction/validate/TransactionBodyRole.h" - +#include "gradido_blockchain/const.h" +#include "gradido_blockchain/interaction/validate/TransactionBodyRole.h" #include "gradido_blockchain/interaction/validate/CommunityRootRole.h" #include "gradido_blockchain/interaction/validate/Exceptions.h" #include "gradido_blockchain/interaction/validate/GradidoCreationRole.h" #include "gradido_blockchain/interaction/validate/GradidoDeferredTransferRole.h" #include "gradido_blockchain/interaction/validate/GradidoTransferRole.h" #include "gradido_blockchain/interaction/validate/RegisterAddressRole.h" -#include "gradido_blockchain/const.h" +#include "gradido_blockchain/lib/DataTypeConverter.h" + #include "magic_enum/magic_enum.hpp" #include "magic_enum/magic_enum_flags.hpp" @@ -32,18 +33,36 @@ namespace gradido { try { if ((type & Type::SINGLE) == Type::SINGLE) { if (mBody.getVersionNumber() != GRADIDO_TRANSACTION_BODY_V3_3_VERSION_STRING) { - throw TransactionValidationInvalidInputException("wrong version", "version_number", "string"); + throw TransactionValidationInvalidInputException( + "wrong version", + "version_number", + "string", + GRADIDO_TRANSACTION_BODY_V3_3_VERSION_STRING, + mBody.getVersionNumber().data() + ); } // memo is only mandatory for transfer and creation transactions if (mBody.isDeferredTransfer() || mBody.isTransfer() || mBody.isCreation()) { auto memoSize = mBody.getMemo().size(); if (memoSize < 5 || memoSize > 450) { - throw TransactionValidationInvalidInputException("not in expected range [5;450]", "memo", "string"); + throw TransactionValidationInvalidInputException( + "not in expected range [5;450]", + "memo", + "string", + ">= 5 && <= 450", + std::to_string(memoSize).data() + ); } } auto& otherGroup = mBody.getOtherGroup(); if (!otherGroup.empty() && !isValidCommunityAlias(otherGroup)) { - throw TransactionValidationInvalidInputException("invalid character, only ascii", "other_group", "string"); + throw TransactionValidationInvalidInputException( + "invalid character, only lowercase english latin letter, numbers and -", + "other_group", + "string", + mCommunityIdRegexString.data(), + otherGroup.data() + ); } } @@ -91,7 +110,14 @@ namespace gradido { { auto deferredTransfer = mBody.getDeferredTransfer(); if (mBody.getCreatedAt().getAsTimepoint() >= deferredTransfer->getTimeout().getAsTimepoint()) { - throw TransactionValidationInvalidInputException("already reached", "timeout", "Timestamp"); + std::string expected = "> " + DataTypeConverter::timePointToString(mBody.getCreatedAt().getAsTimepoint()); + throw TransactionValidationInvalidInputException( + "already reached", + "timeout", + "TimestampSeconds", + expected.data(), + DataTypeConverter::timePointToString(deferredTransfer->getTimeout().getAsTimepoint()).data() + ); } mSpecificTransactionRole = std::make_unique(mBody.getDeferredTransfer()); } diff --git a/src/interaction/validate/TransferAmountRole.cpp b/src/interaction/validate/TransferAmountRole.cpp index 721e8256..8596eea1 100644 --- a/src/interaction/validate/TransferAmountRole.cpp +++ b/src/interaction/validate/TransferAmountRole.cpp @@ -14,12 +14,22 @@ namespace gradido { if ((type & Type::SINGLE) == Type::SINGLE) { auto& coinCommunityId = mTransferAmount.getCommunityId(); if (!coinCommunityId.empty() && !isValidCommunityAlias(coinCommunityId)) { - throw TransactionValidationInvalidInputException("invalid character, only ascii", "coinCommunityId", "string"); + throw TransactionValidationInvalidInputException( + "invalid character, only lowercase english latin letter, numbers and -", + "community_id", + "string", + mCommunityIdRegexString.data(), + coinCommunityId.data() + ); } if (!communityId.empty() && coinCommunityId == communityId) { + std::string expected = "!= " + std::string(communityId); throw TransactionValidationInvalidInputException( "coin communityId shouldn't be set if it is the same as blockchain communityId", - "communityId", "hex" + "community_id", + "string", + expected.data(), + coinCommunityId.data() ); } if (mTransferAmount.getAmount() <= GradidoUnit(0.0)) {