diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index 14389feead..b01dc1c31e 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -199,31 +199,16 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, CAssetsCa if (!TransferAssetFromScript(txout.scriptPubKey, transfer, address)) return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-asset-bad-deserialize"); - // If we aren't reindexing - if (!fReindex) { - // If the transfer is an ownership asset. Check to make sure that it is OWNER_ASSET_AMOUNT - if (IsAssetNameAnOwner(transfer.strName)) { - if (transfer.nAmount != OWNER_ASSET_AMOUNT) - return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-owner-amount-was-not-1"); - } else { - // For all other types of assets, make sure they are sending the right type of units - CNewAsset asset; - if (!assetCache->GetAssetIfExists(transfer.strName, asset)) - return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-asset-not-exist"); - - if (asset.strName != transfer.strName) - return state.DoS(100, false, REJECT_INVALID, "bad-txns-asset-database-corrupted"); - - if (transfer.nAmount % int64_t(pow(10, (MAX_UNIT - asset.units))) != 0) - return state.DoS(100, false, REJECT_INVALID, - "bad-txns-transfer-asset-amount-not-match-units"); - } + // If the transfer is an ownership asset. Check to make sure that it is OWNER_ASSET_AMOUNT + if (IsAssetNameAnOwner(transfer.strName)) { + if (transfer.nAmount != OWNER_ASSET_AMOUNT) + return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-owner-amount-was-not-1"); } } } } - /** RVN END */ } + /** RVN END */ // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock if (fCheckDuplicateInputs) { @@ -384,6 +369,35 @@ bool Consensus::CheckTxAssets(const CTransaction& tx, CValidationState& state, c totalOutputs.at(transfer.strName) += transfer.nAmount; else totalOutputs.insert(make_pair(transfer.strName, transfer.nAmount)); + + if (IsAssetNameAnOwner(transfer.strName)) { + if (transfer.nAmount != OWNER_ASSET_AMOUNT) + return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-owner-amount-was-not-1"); + } else { + // For all other types of assets, make sure they are sending the right type of units + CNewAsset asset; + if (!passets->GetAssetIfExists(transfer.strName, asset)) + return state.DoS(100, false, REJECT_INVALID, "bad-txns-transfer-asset-not-exist"); + + if (asset.strName != transfer.strName) + return state.DoS(100, false, REJECT_INVALID, "bad-txns-asset-database-corrupted"); + + if (transfer.nAmount % int64_t(pow(10, (MAX_UNIT - asset.units))) != 0) + return state.DoS(100, false, REJECT_INVALID, + "bad-txns-transfer-asset-amount-not-match-units"); + } + } else if (txout.scriptPubKey.IsReissueAsset()) { + CReissueAsset reissue; + std::string address; + if (!ReissueAssetFromScript(txout.scriptPubKey, reissue, address)) + return state.DoS(100, false, REJECT_INVALID, "bad-tx-asset-reissue-bad-deserialize"); + + std::string strError; + if (!reissue.IsValid(strError, *passets)) { + return state.DoS(100, false, REJECT_INVALID, + "bad-txns" + strError); + } + } } diff --git a/src/core_io.h b/src/core_io.h index 0840e8e926..03645fa2c8 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -31,7 +31,6 @@ std::vector ParseHexUV(const UniValue& v, const std::string& strN std::string ValueFromAmountString(const CAmount& amount, const int8_t units); UniValue ValueFromAmount(const CAmount& amount, const int8_t units); UniValue ValueFromAmount(const CAmount& amount); -std::string StringFromAmount(const CAmount& amount, const int8_t units); std::string FormatScript(const CScript& script); std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0); void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); diff --git a/src/core_write.cpp b/src/core_write.cpp index ca514da7c5..97b917a328 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -13,6 +13,7 @@ #include "serialize.h" #include "streams.h" #include +#include #include "util.h" #include "utilmoneystr.h" #include "utilstrencodings.h" @@ -23,6 +24,7 @@ std::string ValueFromAmountString(const CAmount& amount, const int8_t units) int64_t n_abs = (sign ? -amount : amount); int64_t quotient = n_abs / COIN; int64_t remainder = n_abs % COIN; + remainder = remainder / pow(10, 8 - units); if (units == 0 && remainder == 0) { return strprintf("%s%d", sign ? "-" : "", quotient); @@ -42,21 +44,6 @@ UniValue ValueFromAmount(const CAmount& amount) return ValueFromAmount(amount, 8); } -std::string StringFromAmount(const CAmount& amount, const int8_t units) -{ - bool sign = amount < 0; - int64_t n_abs = (sign ? -amount : amount); - int64_t quotient = n_abs / COIN; - int64_t remainder = n_abs % COIN; - - if (units == 0 && remainder == 0) { - return strprintf("%s%d", sign ? "-" : "", quotient); - } - else { - return strprintf("%s%d.%0" + std::to_string(units) + "d", sign ? "-" : "", quotient, remainder); - } -} - std::string FormatScript(const CScript& script) { std::string ret; diff --git a/src/qt/assetrecord.h b/src/qt/assetrecord.h index 5178c9f040..501e384871 100644 --- a/src/qt/assetrecord.h +++ b/src/qt/assetrecord.h @@ -28,12 +28,17 @@ class AssetRecord } std::string formattedQuantity() { - int64_t quotient = quantity / COIN; - if (units == 0) { - return strprintf("%d", quotient); - } else { - int64_t remainder = quantity % COIN; - return strprintf("%d.%0" + std::to_string(units) + "d", quotient, remainder); + bool sign = quantity < 0; + int64_t n_abs = (sign ? -quantity : quantity); + int64_t quotient = n_abs / COIN; + int64_t remainder = n_abs % COIN; + remainder = remainder / pow(10, 8 - units); + + if (units == 0 && remainder == 0) { + return strprintf("%s%d", sign ? "-" : "", quotient); + } + else { + return strprintf("%s%d.%0" + std::to_string(units) + "d", sign ? "-" : "", quotient, remainder); } } diff --git a/src/qt/assetsdialog.cpp b/src/qt/assetsdialog.cpp index dabbdf1523..f881b094cd 100644 --- a/src/qt/assetsdialog.cpp +++ b/src/qt/assetsdialog.cpp @@ -306,7 +306,7 @@ void AssetsDialog::on_sendButton_clicked() for (SendAssetsRecipient &rcp : recipients) { // generate bold amount string - QString amount = "" + QString::fromStdString(StringFromAmount(rcp.amount, 8)) + " " + rcp.assetName; + QString amount = "" + QString::fromStdString(ValueFromAmountString(rcp.amount, 8)) + " " + rcp.assetName; amount.append(""); // generate monospace address string QString address = "" + rcp.address; diff --git a/src/qt/createassetdialog.cpp b/src/qt/createassetdialog.cpp index 113443feb2..3bf963a30b 100644 --- a/src/qt/createassetdialog.cpp +++ b/src/qt/createassetdialog.cpp @@ -273,7 +273,7 @@ void CreateAssetDialog::onCreateAssetClicked() QStringList formatted; // generate bold amount string - QString amount = "" + QString::fromStdString(StringFromAmount(GetIssueAssetBurnAmount(), 8)) + " RVN"; + QString amount = "" + QString::fromStdString(ValueFromAmountString(GetIssueAssetBurnAmount(), 8)) + " RVN"; amount.append(""); // generate monospace address string QString addressburn = "" + QString::fromStdString(Params().IssueAssetBurnAddress()); @@ -284,7 +284,7 @@ void CreateAssetDialog::onCreateAssetClicked() formatted.append(recipientElement1); // generate the bold asset amount - QString assetAmount = "" + QString::fromStdString(StringFromAmount(asset.nAmount, asset.units)) + " " + QString::fromStdString(asset.strName); + QString assetAmount = "" + QString::fromStdString(ValueFromAmountString(asset.nAmount, asset.units)) + " " + QString::fromStdString(asset.strName); assetAmount.append(""); // generate the monospace address string diff --git a/src/qt/reissueassetdialog.cpp b/src/qt/reissueassetdialog.cpp index 97b6f29c9e..120043fa16 100644 --- a/src/qt/reissueassetdialog.cpp +++ b/src/qt/reissueassetdialog.cpp @@ -383,7 +383,7 @@ void ReissueAssetDialog::onReissueAssetClicked() QStringList formatted; // generate bold amount string - QString amount = "" + QString::fromStdString(StringFromAmount(GetReissueAssetBurnAmount(), 8)) + " RVN"; + QString amount = "" + QString::fromStdString(ValueFromAmountString(GetReissueAssetBurnAmount(), 8)) + " RVN"; amount.append(""); // generate monospace address string QString addressburn = "" + QString::fromStdString(Params().ReissueAssetBurnAddress()); @@ -394,7 +394,7 @@ void ReissueAssetDialog::onReissueAssetClicked() formatted.append(recipientElement1); // generate the bold asset amount - QString assetAmount = "" + QString::fromStdString(StringFromAmount(reissueAsset.nAmount, 8)) + " " + QString::fromStdString(reissueAsset.strName); + QString assetAmount = "" + QString::fromStdString(ValueFromAmountString(reissueAsset.nAmount, 8)) + " " + QString::fromStdString(reissueAsset.strName); assetAmount.append(""); // generate the monospace address string diff --git a/src/qt/sendassetsentry.cpp b/src/qt/sendassetsentry.cpp index aff5473065..927a6f587f 100644 --- a/src/qt/sendassetsentry.cpp +++ b/src/qt/sendassetsentry.cpp @@ -284,7 +284,7 @@ void SendAssetsEntry::onAssetSelected(int index) } ui->assetAmountLabel->setText( - "Balance: " + QString::fromStdString(StringFromAmount(amount, units)) + " " + name + bang); + "Balance: " + QString::fromStdString(ValueFromAmountString(amount, units)) + " " + name + bang); ui->messageLabel->hide(); ui->messageTextLabel->hide(); diff --git a/src/rpc/test.json b/src/rpc/test.json index 9f0fdebeda..ec51a42acd 100644 --- a/src/rpc/test.json +++ b/src/rpc/test.json @@ -38,3 +38,5 @@ reissue example "[{\"txid\":\"3f3c22a0544369698d3428ba11a29bbbfe8508938f9a0974b0eff086be24a02e\",\"vout\":0}, {\"txid\":\"f0028b85cc2ca694d2fd0f96c65b4312fb67cc32e056069da3462bf6d32400fc\",\"vout\":2}]" "{\"n2NKWBsA2wFqK7yBuazviueHGT7GXu7KtS\": 4899.988, \"n1ReissueAssetXXXXXXXXXXXXXXWG9NLd\": 100.00, \"mwfL6voyJhhPngjQG2HvaL9Kero4jwmxeZ\": {\"reissue\": {\"asset_name\": \"TEST\", \"asset_quantity\": 25, \"reissuable\": 5}}}" + +"[{\"txid\":\"21dfb847aa9779f955b605d843f91653aa34ea5f0e28bb73092cd512283b3332\",\"vout\":0}, {\"txid\":\"79daec18288aee4d50091d1f68ce322530240184ac5e67dc13419979814f6af6\",\"vout\":3}]" "{\"mxECLZdXBztyL7nLQBYbFszmDrBE2P9Yt2\": 4999.998, \"mgwGxrmCfzjvBiCQ9dvCEMet6JDb8vJWqN\": {\"transfer\": {\"BLOND\": 500.0001}}, \"mun1hF7VM3iWqWKV8EH7AsKWfu7Nfa7pyg\": {\"transfer\": {\"BLOND\": 499.9999}}}" diff --git a/src/test/assets/asset_tests.cpp b/src/test/assets/asset_tests.cpp index f9b62b9dec..0c581ab4c9 100644 --- a/src/test/assets/asset_tests.cpp +++ b/src/test/assets/asset_tests.cpp @@ -7,6 +7,7 @@ #include #include +#include "core_write.cpp" #include #include @@ -218,4 +219,26 @@ BOOST_FIXTURE_TEST_SUITE(asset_tests, BasicTestingSetup) BOOST_CHECK_MESSAGE(shifted == 3, "New version didn't equal 3"); } + BOOST_AUTO_TEST_CASE(asset_formatting) { + + CAmount amount = 50000010000; + BOOST_CHECK(ValueFromAmountString(amount, 4) == "500.0001"); + + amount = 100; + BOOST_CHECK(ValueFromAmountString(amount, 6) == "0.000001"); + + amount = 1000; + BOOST_CHECK(ValueFromAmountString(amount, 6) == "0.000010"); + + amount = 50010101010; + BOOST_CHECK(ValueFromAmountString(amount, 8) == "500.10101010"); + + amount = 111111111; + BOOST_CHECK(ValueFromAmountString(amount, 8) == "1.11111111"); + + amount = 1; + BOOST_CHECK(ValueFromAmountString(amount, 8) == "0.00000001"); + + } + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/validation.cpp b/src/validation.cpp index 35d997f635..394713fea9 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3521,10 +3521,6 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c std::string strAddress; if (!ReissueAssetFromTransaction(*tx, reissue, strAddress)) return state.DoS(100, false, REJECT_INVALID, "bad-txns-reissue-asset"); - - std::string strError = ""; - if (!reissue.IsValid(strError, *assetCache)) - return state.DoS(100, false, REJECT_INVALID, "bad-txns-" + strError); } }