diff --git a/src/Makefile.am b/src/Makefile.am index 1e99260b2e..f2e3da3ec4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -134,11 +134,12 @@ DYNAMIC_CORE_H = \ flat-database.h \ fluid/banaccount.h \ fluid/fluid.h \ - fluid/fluiddb.h \ - fluid/fluiddynode.h \ - fluid/fluidmining.h \ - fluid/fluidmint.h \ - fluid/fluidsovereign.h \ + fluid/db.h \ + fluid/dynode.h \ + fluid/mining.h \ + fluid/mint.h \ + fluid/script.h \ + fluid/sovereign.h \ fluid/operations.h \ governance.h \ governance-classes.h \ @@ -297,11 +298,12 @@ libdynamic_server_a_SOURCES = \ dynodeman.cpp \ fluid/banaccount.cpp \ fluid/fluid.cpp \ - fluid/fluiddb.cpp \ - fluid/fluiddynode.cpp \ - fluid/fluidmining.cpp \ - fluid/fluidmint.cpp \ - fluid/fluidsovereign.cpp \ + fluid/db.cpp \ + fluid/dynode.cpp \ + fluid/mining.cpp \ + fluid/mint.cpp \ + fluid/script.cpp \ + fluid/sovereign.cpp \ fluid/operations.cpp \ governance.cpp \ governance-classes.cpp \ diff --git a/src/base58.h b/src/base58.h index b249f38924..a438752282 100644 --- a/src/base58.h +++ b/src/base58.h @@ -125,6 +125,7 @@ class CDynamicAddress : public CBase58Data bool IsValidStealthAddress(const CChainParams& params) const; CDynamicAddress() {} + CDynamicAddress(const CPubKey& pk) { Set(pk.GetID()); } // Dynamic: Add the ability to directly import from pubkey CDynamicAddress(const CTxDestination& dest) { Set(dest); } CDynamicAddress(const std::string& strAddress) { SetString(strAddress); } CDynamicAddress(const char* pszAddress) { SetString(pszAddress); } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 317ceb7205..0f474b0891 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -236,6 +236,13 @@ class CMainParams : public CChainParams vSporkAddresses = {"DDDax6fjzoCqHj9nwTgNdAQsucFBJUJ3Jk"}; nMinSporkKeys = 1; + fluidSignatureKeys = { + "032f31a815c3bbb8c2386d6006542bb1367073013639161d5e406034203ab9178b", + "03d7f7b945571672b6d6cd06d0abde805a1578872e436cbd4d4624c74cc7c86aef", + "02dab261cd65669d09e83db22d16308f17e99c1c3fe25af2b5b6a105332ce60bbb", + "02e267ae5cc5f7ea05769dacc5c7d0fc61d7a4c0b9bb8a213e77663d8ce002da5e" + }; + checkpointData = (CCheckpointData){ boost::assign::map_list_of (0, uint256S("0x00000e140b0c3028f898431890e9dea79ae6ca537ac9362c65b45325db712de2")) @@ -392,6 +399,14 @@ class CTestNetParams : public CChainParams vSporkAddresses = {"DLWYuC7SNhnqZeY87UMqJzVdMVyLzwebhE"}; // QVdXi1qyxxQwTuZ8h3Dh3YRdpMDBWv6oMs9dTmvJmGzQcnsKtdGm nMinSporkKeys = 1; + fluidSignatureKeys = { + "0246227f26c5a71881ba3312fd443db06b39bdb5f8b6d66cd82e3268f127ebe642", + "0330876a6d45b4b988bc13863ee99d6b8e96022a75979010b46f22ea1cc5551350", + "0359cedc78b59a750641d51c70a30b760b5a0da37ff84a850e7925138c191ab261", + "020506608829abecdb3a61b9ff64a65ea400f882f39dfb2dbb95a71d3b5e3c3434", + "03714874801166849c6dce7bf23b46dc36e05a3cfd06dd5edf038151ffd6c725c0" + }; + checkpointData = (CCheckpointData){ boost::assign::map_list_of (0, uint256S("0x00ff3a06390940bc3fffb7948cc6d0ede8fde544a5fa9eeeafbc4ac65d21f087")) @@ -508,6 +523,14 @@ class CRegTestParams : public CChainParams vSporkAddresses = {"ygUqnUfyRnRfBUks3EBc937tgmYBwQYE2S"}; //private key: cT21Wm3oozS7HpP9K9g1SDxdgr2vw9TBPSTxjxeArLjYxGastsf9 nMinSporkKeys = 1; + fluidSignatureKeys = { + "0246227f26c5a71881ba3312fd443db06b39bdb5f8b6d66cd82e3268f127ebe642", + "0330876a6d45b4b988bc13863ee99d6b8e96022a75979010b46f22ea1cc5551350", + "0359cedc78b59a750641d51c70a30b760b5a0da37ff84a850e7925138c191ab261", + "020506608829abecdb3a61b9ff64a65ea400f882f39dfb2dbb95a71d3b5e3c3434", + "03714874801166849c6dce7bf23b46dc36e05a3cfd06dd5edf038151ffd6c725c0" + }; + checkpointData = (CCheckpointData){ boost::assign::map_list_of(0, uint256S("0x000ab751d858e116043e741d097311f2382e600c219483cfda8f25c7f369cc2c"))}; @@ -656,6 +679,14 @@ class CPrivateNetParams : public CChainParams vSporkAddresses = {"D777Y4eMXrf1NgDSY1Q7kjoZuVso1ed7HL"}; nMinSporkKeys = 1; + fluidSignatureKeys = { + "02f5e52b333f5a4b312785d63fabb86540649cdfa8d3e462e43eb1a77a58416129", + "02a20a6ab3830d007b9658be2dbf2117c8967c5cb98774e0f514f5ae21fe26c037", + "02edd019d81bc33c868540624561ced215d2b31681947cc1ea7c8ae0f882659d26", + "028386691a85811d91f314d01d17cea0d8afda1b82c7b5068310c720d87f6b6628", + "0327490dff2869b81f46cf7801b582b5ade6d2546b6d5a8818135f4b4f24eff245" + }; + checkpointData = (CCheckpointData){ boost::assign::map_list_of(0, uint256S("0x00ff3a06390940bc3fffb7948cc6d0ede8fde544a5fa9eeeafbc4ac65d21f087"))}; diff --git a/src/chainparams.h b/src/chainparams.h index ff9f03bc5c..adacd6daa1 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -96,6 +96,7 @@ class CChainParams const std::vector& SporkAddresses() const { return vSporkAddresses; } int MinSporkKeys() const { return nMinSporkKeys; } uint64_t DifficultySwitchBlock() const { return nSwitchDifficultyBlock; } + std::set FluidSignatureKeys() const { std::set pkVch; for (auto& pk : fluidSignatureKeys) { pkVch.insert(CPubKey(ParseHex(pk))); } return pkVch; } protected: CChainParams() {} @@ -130,6 +131,7 @@ class CChainParams int64_t nTargetPosSpacing; int nFutureTimeDriftPoS; uint64_t nSwitchDifficultyBlock; + std::vector fluidSignatureKeys; }; /** diff --git a/src/dynode-payments.cpp b/src/dynode-payments.cpp index 2ab81c7f99..f123498d09 100644 --- a/src/dynode-payments.cpp +++ b/src/dynode-payments.cpp @@ -10,7 +10,7 @@ #include "consensus/validation.h" #include "dynode-sync.h" #include "dynodeman.h" -#include "fluid/fluiddb.h" +#include "fluid/db.h" #include "governance-classes.h" #include "init.h" #include "messagesigner.h" diff --git a/src/dynode.cpp b/src/dynode.cpp index 2e7de1716f..fa97109fcd 100644 --- a/src/dynode.cpp +++ b/src/dynode.cpp @@ -12,7 +12,7 @@ #include "dynode-payments.h" #include "dynode-sync.h" #include "dynodeman.h" -#include "fluid/fluiddb.h" +#include "fluid/db.h" #include "init.h" #include "messagesigner.h" #include "netbase.h" diff --git a/src/fluid/banaccount.cpp b/src/fluid/banaccount.cpp index 6fd3688c9f..710398f5aa 100644 --- a/src/fluid/banaccount.cpp +++ b/src/fluid/banaccount.cpp @@ -13,27 +13,15 @@ CBanAccountDB* pBanAccountDB = NULL; -bool CheckBanAccountDB() -{ - if (!pBanAccountDB) - return false; - - return true; -} - bool AddBanAccountEntry(const CBanAccount& entry) { - if (!CheckBanAccountDB()) - return false; - + assert(pBanAccountDB); return pBanAccountDB->AddBanAccountEntry(entry); } bool GetAllBanAccountRecords(std::vector& entries) { - if (!CheckBanAccountDB()) - return false; - + assert(pBanAccountDB); return pBanAccountDB->GetAllBanAccountRecords(entries); } diff --git a/src/fluid/banaccount.h b/src/fluid/banaccount.h index 214a52db24..4ce4c11bb8 100644 --- a/src/fluid/banaccount.h +++ b/src/fluid/banaccount.h @@ -107,7 +107,6 @@ class CBanAccountDB : public CDBWrapper bool RecordExists(const std::vector& vchFluidScript); }; -bool CheckBanAccountDB(); bool AddBanAccountEntry(const CBanAccount& entry); bool GetAllBanAccountRecords(std::vector& entries); diff --git a/src/fluid/fluiddb.cpp b/src/fluid/db.cpp similarity index 53% rename from src/fluid/fluiddb.cpp rename to src/fluid/db.cpp index c96cf5d850..7bfc5ec808 100644 --- a/src/fluid/fluiddb.cpp +++ b/src/fluid/db.cpp @@ -1,62 +1,43 @@ // Copyright (c) 2019-2021 Duality Blockchain Solutions Developers -#include "fluiddb.h" +#include "fluid/db.h" #include "base58.h" -#include "fluid.h" -#include "fluiddynode.h" -#include "fluidmining.h" -#include "fluidmint.h" -#include "fluidsovereign.h" +#include "fluid/fluid.h" +#include "fluid/dynode.h" +#include "fluid/mining.h" +#include "fluid/mint.h" +#include "fluid/sovereign.h" CAmount GetFluidDynodeReward(const int nHeight) { - if (fluid.FLUID_ACTIVATE_HEIGHT > nHeight) - return GetStandardDynodePayment(nHeight); - - if (!CheckFluidDynodeDB()) - return GetStandardDynodePayment(nHeight); - - if (pFluidDynodeDB->IsEmpty()) - return GetStandardDynodePayment(nHeight); - CFluidDynode lastDynodeRecord; - if (!pFluidDynodeDB->GetLastFluidDynodeRecord(lastDynodeRecord, nHeight)) { - return GetStandardDynodePayment(nHeight); - } - if (lastDynodeRecord.DynodeReward > 0) { - return lastDynodeRecord.DynodeReward; - } else { - return GetStandardDynodePayment(nHeight); + + assert(pFluidDynodeDB); + if (pFluidDynodeDB->GetLastFluidDynodeRecord(lastDynodeRecord, nHeight) && !pFluidDynodeDB->IsEmpty()) { + return (lastDynodeRecord.GetReward() > 0 && FLUID_ACTIVATE_HEIGHT > nHeight) ? + lastDynodeRecord.GetReward() : GetStandardDynodePayment(nHeight); } + + return GetStandardDynodePayment(nHeight); } CAmount GetFluidMiningReward(const int nHeight) { - if (fluid.FLUID_ACTIVATE_HEIGHT > nHeight) - return GetStandardPoWBlockPayment(nHeight); - - if (!CheckFluidMiningDB()) - return GetStandardPoWBlockPayment(nHeight); - - if (pFluidMiningDB->IsEmpty()) - return GetStandardPoWBlockPayment(nHeight); - CFluidMining lastMiningRecord; - if (!pFluidMiningDB->GetLastFluidMiningRecord(lastMiningRecord, nHeight)) { - return GetStandardPoWBlockPayment(nHeight); - } - if (lastMiningRecord.MiningReward > 0) { - return lastMiningRecord.MiningReward; - } else { - return GetStandardPoWBlockPayment(nHeight); + + assert(pFluidMiningDB); + if (pFluidMiningDB->GetLastFluidMiningRecord(lastMiningRecord, nHeight) && !pFluidMiningDB->IsEmpty()) { + return (lastMiningRecord.GetReward() > 0 && FLUID_ACTIVATE_HEIGHT > nHeight) ? + lastMiningRecord.GetReward() : GetStandardPoWBlockPayment(nHeight); } + + return GetStandardDynodePayment(nHeight); } bool GetMintingInstructions(const int nHeight, CFluidMint& fluidMint) { - if (!CheckFluidMintDB()) - return false; + assert(pFluidDynodeDB); if (pFluidMintDB->IsEmpty()) return false; @@ -66,8 +47,8 @@ bool GetMintingInstructions(const int nHeight, CFluidMint& fluidMint) return false; } - if ((int)getFluidMint.nHeight == (nHeight - 1)) { - fluidMint = getFluidMint; + if (getFluidMint.GetHeight() == (nHeight - 1)) { + getFluidMint = fluidMint; return true; } return false; @@ -76,91 +57,57 @@ bool GetMintingInstructions(const int nHeight, CFluidMint& fluidMint) /** Checks if any given address is a current sovereign wallet address (invoked by RPC) */ bool IsSovereignAddress(const CDynamicAddress& inputAddress) { - if (!inputAddress.IsValid()) { - return false; - } - - if (!CheckFluidSovereignDB()) { - return false; - } - CFluidSovereign lastSovereign; - if (!pFluidSovereignDB->GetLastFluidSovereignRecord(lastSovereign)) { + + if (!inputAddress.IsValid()) { return false; } - for (const std::vector& vchAddress : lastSovereign.SovereignAddresses) { - CDynamicAddress attemptKey(StringFromCharVector(vchAddress)); - if (attemptKey.IsValid() && inputAddress == attemptKey) { - return true; + assert(pFluidSovereignDB); + if (pFluidSovereignDB->GetLastFluidSovereignRecord(lastSovereign)) { + for (const std::vector& vchAddress : lastSovereign.obj_sigs) { + CDynamicAddress attemptKey(StringFromCharVector(vchAddress)); + return attemptKey.IsValid() && inputAddress == attemptKey; } } + return false; } bool GetAllFluidDynodeRecords(std::vector& dynodeEntries) { - if (CheckFluidDynodeDB()) { - if (!pFluidDynodeDB->GetAllFluidDynodeRecords(dynodeEntries)) { - return false; - } - } else { - return false; - } - return true; + assert(pFluidDynodeDB); + return pFluidDynodeDB->GetAllFluidDynodeRecords(dynodeEntries); } bool GetAllFluidMiningRecords(std::vector& miningEntries) { - if (CheckFluidMiningDB()) { - if (!pFluidMiningDB->GetAllFluidMiningRecords(miningEntries)) { - return false; - } - } else { - return false; - } - return true; + assert(pFluidMiningDB); + return pFluidMiningDB->GetAllFluidMiningRecords(miningEntries); } bool GetAllFluidMintRecords(std::vector& mintEntries) { - if (CheckFluidMintDB()) { - if (!pFluidMintDB->GetAllFluidMintRecords(mintEntries)) { - return false; - } - } else { - return false; - } - return true; + assert(pFluidMintDB); + return pFluidMintDB->GetAllFluidMintRecords(mintEntries); } bool GetAllFluidSovereignRecords(std::vector& sovereignEntries) { - if (CheckFluidSovereignDB()) { - if (pFluidSovereignDB->IsEmpty()) { - return false; - } - if (!pFluidSovereignDB->GetAllFluidSovereignRecords(sovereignEntries)) { - return false; - } - } else { - return false; - } - return true; + assert(pFluidSovereignDB); + return pFluidSovereignDB->GetAllFluidSovereignRecords(sovereignEntries) && !pFluidSovereignDB->IsEmpty(); } bool GetLastFluidSovereignAddressStrings(std::vector& sovereignAddresses) { - if (!CheckFluidSovereignDB()) { - return false; - } - + assert(pFluidSovereignDB); CFluidSovereign lastSovereign; - if (!pFluidSovereignDB->GetLastFluidSovereignRecord(lastSovereign)) { - return false; + if (pFluidSovereignDB->GetLastFluidSovereignRecord(lastSovereign)) + { + sovereignAddresses = lastSovereign.SovereignAddressesStrings(); + return true; } - sovereignAddresses = lastSovereign.SovereignAddressesStrings(); - return true; + return false; } /** Checks whether 3 of 5 sovereign addresses signed the token in the script to meet the quorum requirements */ diff --git a/src/fluid/fluiddb.h b/src/fluid/db.h similarity index 100% rename from src/fluid/fluiddb.h rename to src/fluid/db.h diff --git a/src/fluid/fluiddynode.cpp b/src/fluid/dynode.cpp similarity index 52% rename from src/fluid/fluiddynode.cpp rename to src/fluid/dynode.cpp index 1526cf5f3f..5930e33cea 100644 --- a/src/fluid/fluiddynode.cpp +++ b/src/fluid/dynode.cpp @@ -1,10 +1,11 @@ // Copyright (c) 2019-2021 Duality Blockchain Solutions Developers -#include "fluiddynode.h" +#include "fluid/dynode.h" #include "core_io.h" -#include "fluid.h" +#include "fluid/fluid.h" +#include "fluid/script.h" #include "operations.h" #include "script/script.h" @@ -12,77 +13,15 @@ CFluidDynodeDB* pFluidDynodeDB = NULL; -bool GetFluidDynodeData(const CScript& scriptPubKey, CFluidDynode& entry) -{ - std::string fluidOperationString = ScriptToAsmStr(scriptPubKey); - std::string strOperationCode = GetRidOfScriptStatement(fluidOperationString, 0); - std::string verificationWithoutOpCode = GetRidOfScriptStatement(fluidOperationString); - std::vector splitString; - HexFunctions hexConvert; - hexConvert.ConvertToString(verificationWithoutOpCode); - SeparateString(verificationWithoutOpCode, splitString, false); - std::string messageTokenKey = splitString.at(0); - std::vector vecSplitScript; - SeparateFluidOpString(verificationWithoutOpCode, vecSplitScript); - - if (vecSplitScript.size() == 5 && strOperationCode == "OP_REWARD_DYNODE") { - std::vector vchFluidOperation = CharVectorFromString(fluidOperationString); - entry.FluidScript.insert(entry.FluidScript.end(), vchFluidOperation.begin(), vchFluidOperation.end()); - std::string strAmount = vecSplitScript[0]; - CAmount fluidAmount; - if (ParseFixedPoint(strAmount, 8, &fluidAmount)) { - entry.DynodeReward = fluidAmount; - } - std::string strTimeStamp = vecSplitScript[1]; - int64_t tokenTimeStamp; - if (ParseInt64(strTimeStamp, &tokenTimeStamp)) { - entry.nTimeStamp = tokenTimeStamp; - } - entry.SovereignAddresses.clear(); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[2], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[3], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[4], messageTokenKey).ToString())); - - LogPrintf("GetFluidDynodeData: strAmount = %s, strTimeStamp = %d, Addresses1 = %s, Addresses2 = %s, Addresses3 = %s \n", - strAmount, entry.nTimeStamp, StringFromCharVector(entry.SovereignAddresses[0]), - StringFromCharVector(entry.SovereignAddresses[1]), StringFromCharVector(entry.SovereignAddresses[2])); - - return true; - } - return false; -} - -bool GetFluidDynodeData(const CTransaction& tx, CFluidDynode& entry, int& nOut) -{ - int n = 0; - for (const CTxOut& txout : tx.vout) { - CScript txOut = txout.scriptPubKey; - if (IsTransactionFluid(txOut)) { - nOut = n; - return GetFluidDynodeData(txOut, entry); - } - n++; - } - return false; -} - bool CFluidDynode::UnserializeFromTx(const CTransaction& tx) { int nOut; - if (!GetFluidDynodeData(tx, *this, nOut)) { - SetNull(); - return false; - } - return true; + return ParseData(tx, *this, nOut); } bool CFluidDynode::UnserializeFromScript(const CScript& fluidScript) { - if (!GetFluidDynodeData(fluidScript, *this)) { - SetNull(); - return false; - } - return true; + return ParseScript(fluidScript, *this); } void CFluidDynode::Serialize(std::vector& vchData) @@ -101,7 +40,7 @@ bool CFluidDynodeDB::AddFluidDynodeEntry(const CFluidDynode& entry, const int op bool writeState = false; { LOCK(cs_fluid_dynode); - writeState = Write(make_pair(std::string("script"), entry.FluidScript), entry) && Write(make_pair(std::string("txid"), entry.txHash), entry.FluidScript); + writeState = Write(make_pair(std::string("script"), entry.GetTransactionScript()), entry) && Write(make_pair(std::string("txid"), entry.GetTransactionHash()), entry.GetTransactionScript()); } return writeState; @@ -123,7 +62,7 @@ bool CFluidDynodeDB::GetLastFluidDynodeRecord(CFluidDynode& returnEntry, const i if (entry.IsNull()) { return false; } - if (entry.nHeight > returnEntry.nHeight && (int)(entry.nHeight + 1) < nHeight) { + if (entry.GetHeight() > returnEntry.GetHeight() && (int)(entry.GetHeight() + 1) < nHeight) { returnEntry = entry; } } @@ -186,11 +125,3 @@ bool CFluidDynodeDB::RecordExists(const std::vector& vchFluidScri CFluidDynode fluidDynode; return CDBWrapper::Read(make_pair(std::string("script"), vchFluidScript), fluidDynode); } - -bool CheckFluidDynodeDB() -{ - if (!pFluidDynodeDB) - return false; - - return true; -} diff --git a/src/fluid/dynode.h b/src/fluid/dynode.h new file mode 100644 index 0000000000..e1bd801650 --- /dev/null +++ b/src/fluid/dynode.h @@ -0,0 +1,59 @@ +// Copyright (c) 2019-2021 Duality Blockchain Solutions Developers + +#ifndef FLUID_DYNODE_H +#define FLUID_DYNODE_H + +#include "amount.h" +#include "dbwrapper.h" +#include "serialize.h" +#include "fluid/fluid.h" + +#include "sync.h" +#include "uint256.h" + +class CScript; +class CTransaction; + +class CFluidDynode : public DSFluidObject +{ +public: + CFluidDynode() = default; + CFluidDynode(const CTransaction& tx) { UnserializeFromTx(tx); } + CFluidDynode(const CScript& fluidScript) { UnserializeFromScript(fluidScript); } + ~CFluidDynode() = default; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(this->version); + READWRITE(tx_script); + READWRITE(obj_reward); + READWRITE(VARINT(obj_time)); + READWRITE(obj_sigs); + READWRITE(tx_hash); + READWRITE(VARINT(tx_height)); + } + + bool UnserializeFromTx(const CTransaction& tx); + bool UnserializeFromScript(const CScript& fluidScript); + void Serialize(std::vector& vchData); +}; + +static CCriticalSection cs_fluid_dynode; + +class CFluidDynodeDB : public CDBWrapper +{ +public: + CFluidDynodeDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate); + bool AddFluidDynodeEntry(const CFluidDynode& entry, const int op); + bool GetLastFluidDynodeRecord(CFluidDynode& returnEntry, const int nHeight); + bool GetAllFluidDynodeRecords(std::vector& entries); + bool IsEmpty(); + bool RecordExists(const std::vector& vchFluidScript); +}; + +extern CFluidDynodeDB* pFluidDynodeDB; + +#endif // FLUID_DYNODE_H diff --git a/src/fluid/fluid.cpp b/src/fluid/fluid.cpp index f23b193e75..6184fe2c6c 100644 --- a/src/fluid/fluid.cpp +++ b/src/fluid/fluid.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2016-2021 Duality Blockchain Solutions Developers -#include "fluid.h" +#include "fluid/fluid.h" #include "bdap/domainentry.h" #include "bdap/domainentrydb.h" @@ -16,6 +16,11 @@ #include "utilmoneystr.h" #include "utiltime.h" #include "validation.h" +#include "fluid/dynode.h" +#include "fluid/mint.h" +#include "fluid/mining.h" +#include "fluid/script.h" +#include "fluid/sovereign.h" #include "wallet/wallet.h" #include "wallet/walletdb.h" @@ -26,17 +31,11 @@ CFluid fluid; extern CWallet* pwalletMain; #endif //ENABLE_WALLET -bool IsTransactionFluid(const CScript& txOut) -{ - return (txOut.IsProtocolInstruction(MINT_TX) || txOut.IsProtocolInstruction(DYNODE_MODFIY_TX) || txOut.IsProtocolInstruction(MINING_MODIFY_TX) || - txOut.IsProtocolInstruction(BDAP_REVOKE_TX)); -} - bool IsTransactionFluid(const CTransaction& tx, CScript& fluidScript) { for (const CTxOut& txout : tx.vout) { CScript txOut = txout.scriptPubKey; - if (IsTransactionFluid(txOut)) { + if (WithinFluidRange(txOut.GetFlag())) { fluidScript = txOut; return true; } @@ -46,187 +45,101 @@ bool IsTransactionFluid(const CTransaction& tx, CScript& fluidScript) int GetFluidOpCode(const CScript& fluidScript) { - if (fluidScript.IsProtocolInstruction(MINT_TX)) { - return OP_MINT; - } else if (fluidScript.IsProtocolInstruction(DYNODE_MODFIY_TX)) { - return OP_REWARD_DYNODE; - } else if (fluidScript.IsProtocolInstruction(MINING_MODIFY_TX)) { - return OP_REWARD_MINING; - } else if (fluidScript.IsProtocolInstruction(BDAP_REVOKE_TX)) { - return OP_BDAP_REVOKE; - } - return 0; -} - -/** Initialise sovereign identities that are able to run fluid commands */ -std::vector > CFluidParameters::InitialiseSovereignIdentities() -{ - std::vector > x; - if (Params().NetworkIDString() == CBaseChainParams::MAIN) { - x.push_back(std::make_pair("CEO", CDynamicAddress("D9avNWVBmaUNevMNnkcLMrQpze8M2mKURu"))); - x.push_back(std::make_pair("CTO", CDynamicAddress("DRoyjRoxP4qfeAiiZHX1dmSkbUJiBSXBt7"))); - x.push_back(std::make_pair("CFO", CDynamicAddress("DHkD6oBQ5PtCiKo4wX8CRWrG61Vy5hEu4t"))); - x.push_back(std::make_pair("COO", CDynamicAddress("DKyqamefa7YdbqrP5pdTfNVVuq1gerNhMH"))); - x.push_back(std::make_pair("CDOO", CDynamicAddress("DUDE1zFKK4fezCgcxdGbFh4yHJMcg8qpoP"))); - } else if (Params().NetworkIDString() == CBaseChainParams::TESTNET) { - x.push_back(std::make_pair("Test01", CDynamicAddress("DSCex4e189aULrig3nLd42gVf7AbjTwnP5"))); //importprivkey QVKXuZ2hSo2cT9BhkN3CApLuZYVsuzNvidJRt1ucyniHheZ2Pfq5 - x.push_back(std::make_pair("Test02", CDynamicAddress("DMAh37n3RUdDxox3uiWAnc1zEPp5yFbHiL"))); //importprivkey QU4VGDcVoej7nDZiyaSgoL7foG8xKiaVyk5odHnJdtyv4tYkmBw1 - x.push_back(std::make_pair("Test03", CDynamicAddress("DN4KvqtXyygooPV3oha72TyBB5nqBbkxwj"))); //importprivkey QWjTe6sCFVtKBsXfrYDyrHzn7eBeJktsQnWzfiANkMd9PhVM4Qnp - x.push_back(std::make_pair("Test04", CDynamicAddress("DHVmS621KBBZJTJSxGDdLxoU7LCmpexWDa"))); //importprivkey QScWuazWgWDTj8cXXz1YFKJW7mNJHJgMFY2FB6hkNyh3SJDUhPZt - x.push_back(std::make_pair("Test05", CDynamicAddress("DCZXDSRB3cJdCCUSerE4pvSfGQoXUivUxo"))); //importprivkey QUt4pEDanRPzos3meoiNGUG9g7RctCtiwLoPjhDKfNPK99oLuzcU - } else if (Params().NetworkIDString() == CBaseChainParams::REGTEST) { - x.push_back(std::make_pair("RegTest01", CDynamicAddress("DSCex4e189aULrig3nLd42gVf7AbjTwnP5"))); //importprivkey QVKXuZ2hSo2cT9BhkN3CApLuZYVsuzNvidJRt1ucyniHheZ2Pfq5 - x.push_back(std::make_pair("RegTest02", CDynamicAddress("DMAh37n3RUdDxox3uiWAnc1zEPp5yFbHiL"))); //importprivkey QU4VGDcVoej7nDZiyaSgoL7foG8xKiaVyk5odHnJdtyv4tYkmBw1 - x.push_back(std::make_pair("RegTest03", CDynamicAddress("DN4KvqtXyygooPV3oha72TyBB5nqBbkxwj"))); //importprivkey QWjTe6sCFVtKBsXfrYDyrHzn7eBeJktsQnWzfiANkMd9PhVM4Qnp - x.push_back(std::make_pair("RegTest04", CDynamicAddress("DHVmS621KBBZJTJSxGDdLxoU7LCmpexWDa"))); //importprivkey QScWuazWgWDTj8cXXz1YFKJW7mNJHJgMFY2FB6hkNyh3SJDUhPZt - x.push_back(std::make_pair("RegTest05", CDynamicAddress("DCZXDSRB3cJdCCUSerE4pvSfGQoXUivUxo"))); //importprivkey QUt4pEDanRPzos3meoiNGUG9g7RctCtiwLoPjhDKfNPK99oLuzcU - } - else if (Params().NetworkIDString() == CBaseChainParams::PRIVATENET) { - x.push_back(std::make_pair("Priv01", CDynamicAddress("D6wUMdGtoXtj4zjyk4kYu6cL8LM5j6bEd7"))); //importprivkey QUQsWaE1LRdW95gLgyQgjkUjR4eqhbigmDHENzyTVYy7JCgQcYMd - x.push_back(std::make_pair("Priv02", CDynamicAddress("DKLWazjY91KKWekxPxwjznx56tX1KYtTiy"))); //importprivkey QWR6WRSKZZrpDBM3q2jqyhB5xmE5YDdc72trHzznTLwBEJBbeWKm - x.push_back(std::make_pair("Priv03", CDynamicAddress("DNsEXkNEdzvNbR3zjaDa3TEVPtwR6Efbmd"))); //importprivkey QPWaY6RAm44zFQ9gktpHFwaCLQc1nCGwPaVAnXAZsFMyGXzLce35 - x.push_back(std::make_pair("Priv04", CDynamicAddress("DG2NCt5Z35cLRYnNCDXdVJTbPh3NSScAmF"))); //importprivkey QRF11rngYqeVv4mSE4SCGU8P3MQgZwJaRQQJsknjVa5QqhkFCGW4 - x.push_back(std::make_pair("Priv05", CDynamicAddress("DRqqngX1mPUjKFXPQDdHRmy2jBk9DKUjkx"))); //importprivkey QQja2KMbhyaat4HJLUiEr2PVmb33CtuVN7KgbmTq9ivVwnaZvFUE - } - return x; -} - -std::vector InitialiseAddresses() -{ - CFluidParameters params; - return params.InitialiseAddresses(); -} - -std::vector CFluidParameters::InitialiseAddresses() -{ - std::vector initialSovereignAddresses; - std::vector > fluidIdentities = InitialiseSovereignIdentities(); - for (const std::pair& sovereignId : fluidIdentities) { - initialSovereignAddresses.push_back(sovereignId.second.ToString()); - } - return initialSovereignAddresses; -} - -std::vector > CFluidParameters::InitialiseAddressCharVector() -{ - std::vector > initialSovereignAddresses; - std::vector > fluidIdentities = InitialiseSovereignIdentities(); - for (const std::pair& sovereignId : fluidIdentities) { - initialSovereignAddresses.push_back(CharVectorFromString(sovereignId.second.ToString())); - } - return initialSovereignAddresses; + return fluidScript.GetFlag(); } /** Checks fluid transactoin operation script amount for invalid values. */ -bool CFluid::CheckFluidOperationScript(const CScript& fluidScriptPubKey, const int64_t& timeStamp, std::string& errorMessage, const bool fSkipTimeStampCheck) +bool CFluid::CheckFluidOperationScript(const CScript& fluidScriptPubKey, const int64_t& timeStamp, const bool fSkipTimeStampCheck) { std::string strFluidOpScript = ScriptToAsmStr(fluidScriptPubKey); std::string verificationWithoutOpCode = GetRidOfScriptStatement(strFluidOpScript); - std::string strOperationCode = GetRidOfScriptStatement(strFluidOpScript, 0); if (!fSkipTimeStampCheck) { - if (!ExtractCheckTimestamp(strOperationCode, strFluidOpScript, timeStamp)) { - errorMessage = "CheckFluidOperationScript fluid timestamp is too old."; - return false; + if (!ExtractCheckTimestamp(TranslationTable(fluidScriptPubKey.GetFlag()), strFluidOpScript, timeStamp)) { + return error("%s: Timestamp is too old", __PRETTY_FUNCTION__); } } - if (IsHex(verificationWithoutOpCode)) { - std::string strUnHexedFluidOpScript = HexToString(verificationWithoutOpCode); - std::vector vecSplitScript; - SeparateString(strUnHexedFluidOpScript, vecSplitScript, "$"); - if (strOperationCode == "OP_MINT" || strOperationCode == "OP_REWARD_MINING" || strOperationCode == "OP_REWARD_DYNODE") { - if (vecSplitScript.size() > 1) { - std::string strAmount = vecSplitScript[0]; - CAmount fluidAmount; - if (ParseFixedPoint(strAmount, 8, &fluidAmount)) { - if ((strOperationCode == "OP_REWARD_MINING" || strOperationCode == "OP_REWARD_DYNODE") && fluidAmount < 0) { - errorMessage = "CheckFluidOperationScript fluid reward amount is less than zero: " + strAmount; - return false; - } else if (strOperationCode == "OP_MINT" && (fluidAmount > FLUID_MAX_FOR_MINT)) { - errorMessage = "CheckFluidOperationScript fluid OP_MINT amount exceeds maximum: " + strAmount; - return false; - } else if (strOperationCode == "OP_REWARD_MINING" && (fluidAmount > FLUID_MAX_REWARD_FOR_MINING)) { - errorMessage = "CheckFluidOperationScript fluid OP_REWARD_MINING amount exceeds maximum: " + strAmount; - return false; - } else if (strOperationCode == "OP_REWARD_DYNODE" && (fluidAmount > FLUID_MAX_REWARD_FOR_DYNODE)) { - errorMessage = "CheckFluidOperationScript fluid OP_REWARD_DYNODE amount exceeds maximum: " + strAmount; - return false; - } - } - } else { - errorMessage = "CheckFluidOperationScript fluid token invalid. " + strUnHexedFluidOpScript; - return false; - } - } - else if (strOperationCode == "OP_BDAP_REVOKE") { + + if (!IsHex(verificationWithoutOpCode)) + return error("%s: Not encoded in valid format", __PRETTY_FUNCTION__); + + std::string strUnHexedFluidOpScript = stringFromVch(ParseHex(verificationWithoutOpCode)); + std::vector vecSplitScript; + SeparateString(strUnHexedFluidOpScript, vecSplitScript, "$"); + std::string strAmount = vecSplitScript[0]; + CAmount fluidAmount; + switch (fluidScriptPubKey.GetFlag()) { + case OP_MINT: + case OP_REWARD_MINING: + case OP_REWARD_DYNODE: + if (vecSplitScript.size() < 1) + return error("%s: Token string is an invalid size", __PRETTY_FUNCTION__); + + if (!ParseFixedPoint(strAmount, 8, &fluidAmount)) + return error("%s: Unable to parse \"%s\" as integer", __PRETTY_FUNCTION__, strAmount); + + if (fluidScriptPubKey.GetFlag() == OP_REWARD_MINING || fluidScriptPubKey.GetFlag() == OP_REWARD_DYNODE && fluidAmount < 0) + return error("%s: Reward cannot be less than zero, attempted to set as \"%s\" instead", __PRETTY_FUNCTION__, strAmount); + + if (fluidScriptPubKey.GetFlag() == OP_MINT && (fluidAmount > FLUID_MAX_FOR_MINT)) + return error("%s: Reward cannot exceed %s, attempted to set as \"%s\" instead", __PRETTY_FUNCTION__, FLUID_MAX_FOR_MINT, strAmount); + + if (fluidScriptPubKey.GetFlag() == OP_REWARD_MINING && (fluidAmount > FLUID_MAX_REWARD_FOR_MINING)) + return error("%s: Reward cannot exceed %s, attempted to set as \"%s\" instead", __PRETTY_FUNCTION__, FLUID_MAX_REWARD_FOR_MINING, strAmount); + + if (fluidScriptPubKey.GetFlag() == OP_REWARD_DYNODE && (fluidAmount > FLUID_MAX_REWARD_FOR_DYNODE)) + return error("%s: Reward cannot exceed %s, attempted to set as \"%s\" instead", __PRETTY_FUNCTION__, FLUID_MAX_REWARD_FOR_DYNODE, strAmount); + break; + case OP_BDAP_REVOKE: if (vecSplitScript.size() > 1) { if (!fSkipTimeStampCheck) { for (uint32_t iter = 1; iter != vecSplitScript.size(); iter++) { - CDomainEntry entry; - std::string strBanAccountFQDN = DecodeBase64(vecSplitScript[iter]); - std::vector vchBanAccountFQDN = vchFromString(strBanAccountFQDN); - if (!DomainEntryExists(vchBanAccountFQDN)) { - LogPrintf("%s -- Can't ban %s account because it was not found.\n", __func__, strBanAccountFQDN); - errorMessage = strprintf("Skipping... Can't ban %s account because it was not found.", strBanAccountFQDN); + if (!DomainEntryExists(vchFromString(DecodeBase64(vecSplitScript[iter])))) { + LogPrintf("%s: Unable to ban at index %d, not found\n", __PRETTY_FUNCTION__, iter); } } } } else { - errorMessage = strprintf("CheckFluidOperationScript fluid OP_BDAP_REVOKE incorrect paramaters %d", vecSplitScript.size()); - return false; + return error("%s: OP_BDAP_REVOKE met with incorrect parameter size %d", __PRETTY_FUNCTION__, vecSplitScript.size()); } - } - else { - errorMessage = strprintf("%s -- %s is an unknown fluid operation", __func__, strOperationCode); - return false; - } - } else { - errorMessage = "CheckFluidOperationScript fluid token is not hex. " + verificationWithoutOpCode; - return false; + break; + default: + return error("%s: Invalid opcode \"%s\" called in Fluid routine", __PRETTY_FUNCTION__, TranslationTable(fluidScriptPubKey.GetFlag())); + break; } return true; } /** Checks whether fluid transaction is in the memory pool already */ -bool CFluid::CheckIfExistsInMemPool(const CTxMemPool& pool, const CScript& fluidScriptPubKey, std::string& errorMessage) +bool CFluid::CheckIfExistsInMemPool(const CTxMemPool& pool, const CScript& fluidScriptPubKey) { for (const CTxMemPoolEntry& e : pool.mapTx) { const CTransaction& tx = e.GetTx(); for (const CTxOut& txOut : tx.vout) { - if (IsTransactionFluid(txOut.scriptPubKey)) { - std::string strNewFluidScript = ScriptToAsmStr(fluidScriptPubKey); - std::string strMemPoolFluidScript = ScriptToAsmStr(txOut.scriptPubKey); - std::string strNewTxWithoutOpCode = GetRidOfScriptStatement(strNewFluidScript); - std::string strMemPoolTxWithoutOpCode = GetRidOfScriptStatement(strMemPoolFluidScript); - if (strNewTxWithoutOpCode == strMemPoolTxWithoutOpCode) { - errorMessage = "CheckIfExistsInMemPool: fluid transaction is already in the memory pool!"; - LogPrintf("CheckIfExistsInMemPool: fluid transaction, %s is already in the memory pool! %s\n", tx.GetHash().ToString(), strNewTxWithoutOpCode); - return true; - } + if (WithinFluidRange(txOut.scriptPubKey.GetFlag())) { + return (GetRidOfScriptStatement(ScriptToAsmStr(fluidScriptPubKey)) == GetRidOfScriptStatement(ScriptToAsmStr(txOut.scriptPubKey))); } } } - return false; } -bool CFluid::CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::vector& vBanAccounts, std::string& strErrorMessage) +bool CFluid::CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::vector& vBanAccounts) { std::string strFluidOpScript = ScriptToAsmStr(fluidScript); std::string verificationWithoutOpCode = GetRidOfScriptStatement(strFluidOpScript); - if (!IsHex(verificationWithoutOpCode)) { - strErrorMessage = "Fluid token is not a valid hexidecimal value."; - return false; - } - std::string strUnHexedFluidOpScript = HexToString(verificationWithoutOpCode); + + if (!IsHex(verificationWithoutOpCode)) + return error("%s: Not encoded in valid format", __PRETTY_FUNCTION__); + + std::string strUnHexedFluidOpScript = stringFromVch(ParseHex(verificationWithoutOpCode)); std::vector vecSplitScript; SeparateString(strUnHexedFluidOpScript, vecSplitScript, "$"); if (vecSplitScript.size() == 0) { - strErrorMessage = "Could not split fluid command script."; - return false; + return error("%s: Message payload is of invalid length, reported size: %d", vecSplitScript.size());; } - + for (uint32_t iter = 1; iter != vecSplitScript.size(); iter++) { CDomainEntry entry; std::string strBanAccountFQDN = DecodeBase64(vecSplitScript[iter]); @@ -235,7 +148,7 @@ bool CFluid::CheckAccountBanScript(const CScript& fluidScript, const uint256& tx vBanAccounts.push_back(entry); } else { - LogPrintf("%s -- Skipping... Can't ban %s account because it was not found.\n", __func__, strBanAccountFQDN); + LogPrintf("%s -- Skipping... Can't ban %s account because it was not found.\n", __PRETTY_FUNCTION__, strBanAccountFQDN); } } @@ -255,11 +168,9 @@ bool CFluid::CheckIfQuorumExists(const std::string& consentToken, std::string& m GetLastBlockIndex(chainActive.Tip()); CBlockIndex* pindex = chainActive.Tip(); - if (pindex != NULL) { - //TODO fluid - fluidSovereigns = InitialiseAddresses(); - } else - fluidSovereigns = InitialiseAddresses(); + for (const auto& pk : Params().FluidSignatureKeys()) { + fluidSovereigns.push_back(CDynamicAddress(pk).ToString()); + } for (const std::string& address : fluidSovereigns) { CDynamicAddress attemptKey, xAddress(address); @@ -313,15 +224,15 @@ bool CFluid::GenericConsentMessage(const std::string& message, std::string& sign if (token == "") return false; - + if (!SignTokenMessage(signer, token, digest, false)) return false; std::string strConvertedMessage = message; - ConvertToString(strConvertedMessage); + strConvertedMessage = stringFromVch(ParseHex(strConvertedMessage)); signedString = StitchString(strConvertedMessage, digest, false); - ConvertToHex(signedString); + signedString = HexStr(signedString); return true; } @@ -330,7 +241,7 @@ bool CFluid::GenericConsentMessage(const std::string& message, std::string& sign bool CFluid::ExtractCheckTimestamp(const std::string& strOpCode, const std::string& consentToken, const int64_t& timeStamp) { std::string consentTokenNoScript = GetRidOfScriptStatement(consentToken); - std::string dehexString = HexToString(consentTokenNoScript); + std::string dehexString = stringFromVch(ParseHex(consentTokenNoScript)); std::vector strs, ptrs; SeparateString(dehexString, strs, false); if (strs.size() == 0) @@ -353,7 +264,7 @@ bool CFluid::ExtractCheckTimestamp(const std::string& strOpCode, const std::stri ScrubString(ls, true); int64_t tokenTimeStamp; ParseInt64(ls, &tokenTimeStamp); - if (timeStamp > tokenTimeStamp + fluid.MAX_FLUID_TIME_DISTORT) + if (timeStamp > tokenTimeStamp + MAX_FLUID_TIME_DISTORT) return false; return true; @@ -367,7 +278,7 @@ bool CFluid::ProcessFluidToken(const std::string& consentToken, std::vector strs; SeparateString(dehexString, strs, false); @@ -394,7 +305,7 @@ bool CFluid::GenericParseNumber(const std::string consentToken, const int64_t ti int64_t tokenTimeStamp; ParseInt64(ls, &tokenTimeStamp); - if (timeStamp > tokenTimeStamp + fluid.MAX_FLUID_TIME_DISTORT && !txCheckPurpose) + if (timeStamp > tokenTimeStamp + MAX_FLUID_TIME_DISTORT && !txCheckPurpose) return false; ParseFixedPoint(lr, 8, &coinAmount); @@ -408,7 +319,7 @@ CDynamicAddress CFluid::GetAddressFromDigestSignature(const std::string& digestS std::vector vchSig = DecodeBase64(digestSignature.c_str(), &fInvalid); if (fInvalid) { - LogPrintf("GetAddressFromDigestSignature(): Digest Signature Found Invalid, Signature: %s \n", digestSignature); + LogPrintf("%s: Digest Signature Found Invalid, Signature: %s \n", __PRETTY_FUNCTION__, digestSignature); return nullptr; } @@ -419,7 +330,7 @@ CDynamicAddress CFluid::GetAddressFromDigestSignature(const std::string& digestS CPubKey pubkey; if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) { - LogPrintf("GetAddressFromDigestSignature(): Public Key Recovery Failed! Hash: %s\n", ss.GetHash().ToString()); + LogPrintf("%s: Public Key recovery failed, hash: %s\n", __PRETTY_FUNCTION__, ss.GetHash().ToString()); return nullptr; } CDynamicAddress newAddress; @@ -434,7 +345,7 @@ bool CFluid::GenericVerifyInstruction(const std::string& consentToken, CDynamicA messageTokenKey = ""; std::vector strs; - ConvertToString(consentTokenNoScript); + consentTokenNoScript = stringFromVch(ParseHex(consentTokenNoScript)); SeparateString(consentTokenNoScript, strs, false); messageTokenKey = strs.at(0); @@ -467,7 +378,7 @@ bool CFluid::ParseMintKey(const int64_t& nTime, CDynamicAddress& destination, CA int64_t tokenTimeStamp; ParseInt64(ls, &tokenTimeStamp); - if (nTime > tokenTimeStamp + fluid.MAX_FLUID_TIME_DISTORT && !txCheckPurpose) + if (nTime > tokenTimeStamp + MAX_FLUID_TIME_DISTORT && !txCheckPurpose) return false; ParseFixedPoint(lr, 8, &coinAmount); @@ -508,7 +419,7 @@ bool CFluid::GetMintingInstructions(const CBlockIndex* pblockindex, CDynamicAddr if (GetFluidBlock(pblockindex, block)) { for (const CTransactionRef& tx : block.vtx) { for (const CTxOut& txout : tx->vout) { - if (txout.scriptPubKey.IsProtocolInstruction(MINT_TX)) { + if (txout.scriptPubKey.GetFlag() == OP_MINT) { std::string message; if (CheckIfQuorumExists(ScriptToAsmStr(txout.scriptPubKey), message)) return ParseMintKey(block.nTime, toMintAddress, mintAmount, ScriptToAsmStr(txout.scriptPubKey)); @@ -522,7 +433,7 @@ bool CFluid::GetMintingInstructions(const CBlockIndex* pblockindex, CDynamicAddr /* Check if transaction exists in record */ bool CFluid::CheckTransactionInRecord(const CScript& fluidInstruction, CBlockIndex* pindex) { - if (IsTransactionFluid(fluidInstruction)) { + if (WithinFluidRange(fluidInstruction.GetFlag())) { std::string verificationString = ScriptToAsmStr(fluidInstruction); std::vector transactionRecord; std::string verificationWithoutOpCode = GetRidOfScriptStatement(verificationString); @@ -574,18 +485,18 @@ bool CFluid::ValidationProcesses(CValidationState& state, const CScript& txOut, CAmount mintAmount; CDynamicAddress toMintAddress; - if (IsTransactionFluid(txOut)) { + if (WithinFluidRange(txOut.GetFlag())) { if (!CheckIfQuorumExists(ScriptToAsmStr(txOut), message)) { return state.DoS(100, false, REJECT_INVALID, "bad-txns-fluid-auth-failure"); } - if (txOut.IsProtocolInstruction(MINT_TX) && + if (txOut.GetFlag() == OP_MINT && !ParseMintKey(0, toMintAddress, mintAmount, ScriptToAsmStr(txOut), true)) { return state.DoS(100, false, REJECT_INVALID, "bad-txns-fluid-mint-auth-failure"); } - if ((txOut.IsProtocolInstruction(DYNODE_MODFIY_TX) || - txOut.IsProtocolInstruction(MINING_MODIFY_TX)) && + if ((txOut.GetFlag() == OP_REWARD_DYNODE || + txOut.GetFlag() == OP_REWARD_MINING) && !GenericParseNumber(ScriptToAsmStr(txOut), 0, mintAmount, true)) { return state.DoS(100, false, REJECT_INVALID, "bad-txns-fluid-modify-parse-failure"); } @@ -599,7 +510,7 @@ bool CFluid::ProvisionalCheckTransaction(const CTransaction& transaction) for (const CTxOut& txout : transaction.vout) { CScript txOut = txout.scriptPubKey; - if (IsTransactionFluid(txOut) && CheckTransactionInRecord(txOut)) { + if (WithinFluidRange(txOut.GetFlag()) && CheckTransactionInRecord(txOut)) { LogPrintf("ProvisionalCheckTransaction(): Fluid Transaction %s has already been executed!\n", transaction.GetHash().ToString()); return false; } @@ -624,7 +535,7 @@ bool CFluid::CheckTransactionToBlock(const CTransaction& transaction, const uint for (const CTxOut& txout : transaction.vout) { CScript txOut = txout.scriptPubKey; - if (IsTransactionFluid(txOut) && CheckTransactionInRecord(txOut, pblockindex)) { + if (WithinFluidRange(txOut.GetFlag()) && CheckTransactionInRecord(txOut, pblockindex)) { LogPrintf("CheckTransactionToBlock(): Fluid Transaction %s has already been executed!\n", transaction.GetHash().ToString()); return false; } @@ -659,7 +570,7 @@ bool CFluid::ExtractTimestampWithAddresses(const std::string& strOpCode, const C { std::string fluidOperationString = ScriptToAsmStr(fluidScript); std::string consentTokenNoScript = GetRidOfScriptStatement(fluidOperationString); - std::string strDehexedToken = HexToString(consentTokenNoScript); + std::string strDehexedToken = stringFromVch(ParseHex(consentTokenNoScript)); std::vector strs, ptrs; SeparateString(strDehexedToken, strs, false); if (strs.size() == 0) @@ -670,12 +581,19 @@ bool CFluid::ExtractTimestampWithAddresses(const std::string& strOpCode, const C return false; std::string strTimeStamp; - if (strOpCode == "OP_MINT" || strOpCode == "OP_REWARD_MINING" || strOpCode == "OP_REWARD_DYNODE") { - strTimeStamp = ptrs.at(1); - } else if (strOpCode == "OP_BDAP_REVOKE") { - strTimeStamp = ptrs.at(0); - } else { - return false; + + switch (fluidScript.GetFlag()) { + case OP_MINT: + case OP_REWARD_MINING: + case OP_REWARD_DYNODE: + strTimeStamp = ptrs.at(1); + break; + case OP_BDAP_REVOKE: + strTimeStamp = ptrs.at(0); + break; + default: + return false; + break; } ScrubString(strTimeStamp, true); @@ -692,4 +610,88 @@ bool CFluid::ExtractTimestampWithAddresses(const std::string& strOpCode, const C return false; } return true; -} \ No newline at end of file +} + +template +bool ParseScript(const CScript& scriptPubKey, T1& object) +{ + std::vector ser_fields; + std::string payload; int s, e; + payload = stringFromVch(ParseHex(GetRidOfScriptStatement(ScriptToAsmStr(scriptPubKey)))); + SeparateString(payload, ser_fields, false); + payload = ser_fields.at(0); ser_fields ={}; + SeparateFluidOpString(payload, ser_fields); + + if (ser_fields.size() != 5 && scriptPubKey.GetFlag() != OP_MINT) + return false; + + try { + switch (scriptPubKey.GetFlag()) + { + case OP_MINT: + object.obj_address = CharVectorFromString(ser_fields[2]); + case OP_REWARD_DYNODE: + case OP_REWARD_MINING: + object.Initialise( + CharVectorFromString(ScriptToAsmStr(scriptPubKey)), /* Byte Vector of Script */ + ParseFixedPoint(ser_fields[0]), /* int64_t field one */ + ParseInt64(ser_fields[1]) /* int64_t field two */ + ); + (scriptPubKey.GetFlag() == OP_MINT) ? s = 3, e = 6 : s = 2, e = 5; + break; + case OP_SWAP_SOVEREIGN_ADDRESS: + object.Initialise( + CharVectorFromString(ScriptToAsmStr(scriptPubKey)), /* Byte Vector of Script */ + ParseInt64(ser_fields[5]), /* int64_t field two */ + 0 /* null */ + ); s = 0; e = 5; + break; + default: + return false; + } + } catch (...) { + return false; + } + + for (; s > e; s++) { + object.obj_sigs.insert( + CharVectorFromString( + fluid.GetAddressFromDigestSignature(ser_fields[s], payload).ToString() + ) + ); + } + + // Debug + LogPrintf("%s: vector contents: ", __PRETTY_FUNCTION__); + for (auto& value : ser_fields) { + LogPrintf("%s, ", value); + } + LogPrintf("\n"); + // End Debug + + return object.IsNull(); +} + +template +bool ParseData(const CTransaction& tx, T1& entry, int& nOut) +{ + nOut = 0; + for (const CTxOut& txout : tx.vout) { + CScript txOut = txout.scriptPubKey; + if (WithinFluidRange(txOut.GetFlag())) { + return ParseScript(txOut, entry); + } + nOut++; + } + return false; +} + +template bool ParseScript(const CScript& scriptPubKey, CFluidMint& object); +template bool ParseScript(const CScript& scriptPubKey, CFluidMining& object); +template bool ParseScript(const CScript& scriptPubKey, CFluidDynode& object); +template bool ParseScript(const CScript& scriptPubKey, CFluidSovereign& object); + +template bool ParseData(const CTransaction& tx, CFluidMint& entry, int& nOut); +template bool ParseData(const CTransaction& tx, CFluidMining& entry, int& nOut); +template bool ParseData(const CTransaction& tx, CFluidDynode& entry, int& nOut); +template bool ParseData(const CTransaction& tx, CFluidSovereign& entry, int& nOut); diff --git a/src/fluid/fluid.h b/src/fluid/fluid.h index 1d7d9b9a3d..1197c740e3 100644 --- a/src/fluid/fluid.h +++ b/src/fluid/fluid.h @@ -10,6 +10,7 @@ #include "operations.h" #include "script/script.h" #include "utilstrencodings.h" +#include "bdap/utils.h" #include #include @@ -24,33 +25,21 @@ class CTxMemPool; struct CBlockTemplate; class CTransaction; -/** Configuration Framework */ -class CFluidParameters -{ -public: - static const int FLUID_ACTIVATE_HEIGHT = 10; - static const int64_t MAX_FLUID_TIME_DISTORT = 60 * 60; // Maximum time distort = 1 hour. - static const CAmount FLUID_TRANSACTION_COST = 100000 * COIN; // Cost to send a fluid transaction - static const CAmount FLUID_MAX_REWARD_FOR_DYNODE = 1000 * COIN; // Max dynode block reward using fluid OP_REWARD_DYNODE - static const CAmount FLUID_MAX_REWARD_FOR_MINING = 1000 * COIN; // Max mining block reward using fluid OP_REWARD_MINING - static const CAmount FLUID_MAX_FOR_MINT = 1000000000 * COIN; // Max minting amount per fluid transaction - - std::vector > InitialiseSovereignIdentities(); - - std::vector InitialiseAddresses(); - std::vector > InitialiseAddressCharVector(); -}; - -std::vector InitialiseAddresses(); +static const int FLUID_ACTIVATE_HEIGHT = 10; +static const int64_t MAX_FLUID_TIME_DISTORT = 60 * 60; // Maximum time distort = 1 hour. +static const CAmount FLUID_TRANSACTION_COST = 100000 * COIN; // Cost to send a fluid transaction +static const CAmount FLUID_MAX_REWARD_FOR_DYNODE = 1000 * COIN; // Max dynode block reward using fluid OP_REWARD_DYNODE +static const CAmount FLUID_MAX_REWARD_FOR_MINING = 1000 * COIN; // Max mining block reward using fluid OP_REWARD_MINING +static const CAmount FLUID_MAX_FOR_MINT = 1000000000 * COIN; // Max minting amount per fluid transaction /** Fluid Asset Management Framework */ -class CFluid : public CFluidParameters, public COperations +class CFluid { public: void ReplaceFluidSovereigns(const CBlockHeader& blockHeader, std::vector& fluidSovereigns); - bool CheckFluidOperationScript(const CScript& fluidScriptPubKey, const int64_t& timeStamp, std::string& errorMessage, const bool fSkipTimeStampCheck = false); - bool CheckIfExistsInMemPool(const CTxMemPool& pool, const CScript& fluidScriptPubKey, std::string& errorMessage); + bool CheckFluidOperationScript(const CScript& fluidScriptPubKey, const int64_t& timeStamp, const bool fSkipTimeStampCheck = false); + bool CheckIfExistsInMemPool(const CTxMemPool& pool, const CScript& fluidScriptPubKey); bool CheckIfQuorumExists(const std::string& consentToken, std::string& message, const bool individual = false); bool CheckNonScriptQuorum(const std::string& consentToken, std::string& message, const bool individual = false); bool CheckTransactionInRecord(const CScript& fluidInstruction, CBlockIndex* pindex = NULL); @@ -71,24 +60,153 @@ class CFluid : public CFluidParameters, public COperations bool ProvisionalCheckTransaction(const CTransaction& transaction); CDynamicAddress GetAddressFromDigestSignature(const std::string& digestSignature, const std::string& messageTokenKey); - bool CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::vector& vBanAccounts, std::string& strErrorMessage); + bool CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::vector& vBanAccounts); bool ExtractTimestampWithAddresses(const std::string& strOpCode, const CScript& fluidScript, int64_t& nTimeStamp, std::vector>& vSovereignAddresses); }; +class DSFluidObject +{ + typedef std::vector byte_vec; + static constexpr int CURRENT_VERSION = 1; + + friend class CFluidDynode; + friend class CFluidMining; + friend class CFluidMint; + friend class CFluidSovereign; + +private: + int version; + + uint256 tx_hash; + uint32_t tx_height; + byte_vec tx_script; + + uint64_t obj_reward; + uint64_t obj_time; + +protected: + DSFluidObject Null() + { + DSFluidObject obj; + version = DSFluidObject::CURRENT_VERSION; + tx_hash.SetNull(); + tx_script.clear(); + tx_height = 0; + obj_reward = -1; + obj_time = 0; + obj_sigs.clear(); + obj_address.clear(); + + return obj; + } + +public: + byte_vec obj_address; + std::set obj_sigs; + + DSFluidObject() + { + *this = Null(); + } + + DSFluidObject(DSFluidObject&& obj) + { + std::swap(version, obj.version); + std::swap(tx_hash, obj.tx_hash); + std::swap(tx_script, obj.tx_script); + std::swap(obj_reward, obj.obj_reward); + std::swap(obj_time, obj.obj_time); + std::swap(obj_sigs, obj.obj_sigs); + std::swap(obj_address, obj.obj_address); + } + + DSFluidObject& operator=(DSFluidObject&& obj) + { + std::swap(version, obj.version); + std::swap(tx_hash, obj.tx_hash); + std::swap(tx_script, obj.tx_script); + std::swap(obj_reward, obj.obj_reward); + std::swap(obj_time, obj.obj_time); + std::swap(obj_sigs, obj.obj_sigs); + std::swap(obj_address, obj.obj_address); + return *this; + } + + DSFluidObject(const DSFluidObject& obj) = default; + DSFluidObject& operator=(const DSFluidObject& obj) = default; + + bool operator>(const DSFluidObject& obj) const + { + return obj_time > obj.obj_time; + } + + bool operator<(const DSFluidObject& obj) const + { + return obj_time < obj.obj_time; + } + + bool operator==(const DSFluidObject& obj) const + { + return tx_script == obj.tx_script; + } + + bool operator!=(const DSFluidObject& obj) const + { + return !((*this) == obj); + } + + void Initialise(byte_vec _vch, CAmount _amt, int64_t _t) + { + return InitialiseScriptRewardTime(_vch, _amt, _t); + } + + void InitialiseScriptRewardTime(byte_vec _vch, CAmount _amt, int64_t _t) + { + tx_script = _vch; + obj_reward = _amt; + obj_time = _t; + } + + void InitialiseHeightHash(CAmount _ht, uint256 _hash) + { + tx_height = _ht; + tx_hash = _hash; + } + + void SetAddress(byte_vec _vch) + { + obj_address = _vch; + } + + uint64_t GetTime() const { return obj_time; } + uint64_t GetHeight() const { return tx_height; } + uint64_t GetReward() const { return obj_reward; } + uint256 GetTransactionHash() const { return tx_hash; } + uint32_t GetTransactionHeight() const { return tx_height; } + byte_vec GetTransactionScript() const { return tx_script; } + + bool IsNull() { return *this == Null(); } + void SetNull() const { DSFluidObject(); } +}; + /** Standard Reward Payment Determination Functions */ CAmount GetStandardPoWBlockPayment(const int& nHeight); CAmount GetStandardDynodePayment(const int& nHeight); void BuildFluidInformationIndex(CBlockIndex* pindex, CAmount& nExpectedBlockValue, bool fDynodePaid); -bool IsTransactionFluid(const CScript& txOut); bool IsTransactionFluid(const CTransaction& tx, CScript& fluidScript); int GetFluidOpCode(const CScript& fluidScript); std::vector CharVectorFromString(const std::string& str); std::string StringFromCharVector(const std::vector& vch); std::vector FluidScriptToCharVector(const CScript& fluidScript); -bool GetFluidBlock(const CBlockIndex* pblockindex, CBlock& block); + +template +bool ParseScript(const CScript& scriptPubKey, T1& object); + +template +bool ParseData(const CTransaction& tx, T1& entry, int& nOut); extern CFluid fluid; diff --git a/src/fluid/fluiddynode.h b/src/fluid/fluiddynode.h deleted file mode 100644 index 41057d31b6..0000000000 --- a/src/fluid/fluiddynode.h +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2019-2021 Duality Blockchain Solutions Developers - -#ifndef FLUID_DYNODE_H -#define FLUID_DYNODE_H - -#include "amount.h" -#include "dbwrapper.h" -#include "serialize.h" - -#include "sync.h" -#include "uint256.h" - -class CScript; -class CTransaction; - -class CFluidDynode -{ -public: - static const int CURRENT_VERSION = 1; - int nVersion; - std::vector FluidScript; - CAmount DynodeReward; - int64_t nTimeStamp; - std::vector > SovereignAddresses; - uint256 txHash; - unsigned int nHeight; - - CFluidDynode() - { - SetNull(); - } - - CFluidDynode(const CTransaction& tx) - { - SetNull(); - UnserializeFromTx(tx); - } - - CFluidDynode(const CScript& fluidScript) - { - SetNull(); - UnserializeFromScript(fluidScript); - } - - inline void SetNull() - { - nVersion = CFluidDynode::CURRENT_VERSION; - FluidScript.clear(); - DynodeReward = -1; - nTimeStamp = 0; - SovereignAddresses.clear(); - txHash.SetNull(); - nHeight = 0; - } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) - { - READWRITE(this->nVersion); - READWRITE(FluidScript); - READWRITE(DynodeReward); - READWRITE(VARINT(nTimeStamp)); - READWRITE(SovereignAddresses); - READWRITE(txHash); - READWRITE(VARINT(nHeight)); - } - - inline friend bool operator==(const CFluidDynode& a, const CFluidDynode& b) - { - return (a.FluidScript == b.FluidScript && a.DynodeReward == b.DynodeReward && a.nTimeStamp == b.nTimeStamp); - } - - inline friend bool operator!=(const CFluidDynode& a, const CFluidDynode& b) - { - return !(a == b); - } - - friend bool operator<(const CFluidDynode& a, const CFluidDynode& b) - { - return (a.nTimeStamp < b.nTimeStamp); - } - - friend bool operator>(const CFluidDynode& a, const CFluidDynode& b) - { - return (a.nTimeStamp > b.nTimeStamp); - } - - inline CFluidDynode operator=(const CFluidDynode& b) - { - FluidScript = b.FluidScript; - DynodeReward = b.DynodeReward; - nTimeStamp = b.nTimeStamp; - SovereignAddresses.clear(); //clear out previous entries - for (const std::vector& vchAddress : b.SovereignAddresses) { - SovereignAddresses.push_back(vchAddress); - } - txHash = b.txHash; - nHeight = b.nHeight; - return *this; - } - - inline bool IsNull() const { return (nTimeStamp == 0); } - bool UnserializeFromTx(const CTransaction& tx); - bool UnserializeFromScript(const CScript& fluidScript); - void Serialize(std::vector& vchData); -}; - -static CCriticalSection cs_fluid_dynode; - -class CFluidDynodeDB : public CDBWrapper -{ -public: - CFluidDynodeDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate); - bool AddFluidDynodeEntry(const CFluidDynode& entry, const int op); - bool GetLastFluidDynodeRecord(CFluidDynode& returnEntry, const int nHeight); - bool GetAllFluidDynodeRecords(std::vector& entries); - bool IsEmpty(); - bool RecordExists(const std::vector& vchFluidScript); -}; - -bool GetFluidDynodeData(const CScript& scriptPubKey, CFluidDynode& entry); -bool GetFluidDynodeData(const CTransaction& tx, CFluidDynode& entry, int& nOut); -bool CheckFluidDynodeDB(); - -extern CFluidDynodeDB* pFluidDynodeDB; - -#endif // FLUID_DYNODE_H diff --git a/src/fluid/fluidmining.h b/src/fluid/fluidmining.h deleted file mode 100644 index 59facb519a..0000000000 --- a/src/fluid/fluidmining.h +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2019-2021 Duality Blockchain Solutions Developers - -#ifndef FLUID_MINING -#define FLUID_MINING - -#include "amount.h" -#include "dbwrapper.h" -#include "serialize.h" - -#include "sync.h" -#include "uint256.h" - -class CScript; -class CTransaction; - -class CFluidMining -{ -public: - static const int CURRENT_VERSION = 1; - int nVersion; - std::vector FluidScript; - CAmount MiningReward; - int64_t nTimeStamp; - std::vector > SovereignAddresses; - uint256 txHash; - unsigned int nHeight; - - CFluidMining() - { - SetNull(); - } - - CFluidMining(const CTransaction& tx) - { - SetNull(); - UnserializeFromTx(tx); - } - - CFluidMining(const CScript& fluidScript) - { - SetNull(); - UnserializeFromScript(fluidScript); - } - - inline void SetNull() - { - nVersion = CFluidMining::CURRENT_VERSION; - FluidScript.clear(); - MiningReward = -1; - nTimeStamp = 0; - SovereignAddresses.clear(); - txHash.SetNull(); - nHeight = 0; - } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) - { - READWRITE(this->nVersion); - READWRITE(FluidScript); - READWRITE(MiningReward); - READWRITE(VARINT(nTimeStamp)); - READWRITE(SovereignAddresses); - READWRITE(txHash); - READWRITE(VARINT(nHeight)); - } - - inline friend bool operator==(const CFluidMining& a, const CFluidMining& b) - { - return (a.FluidScript == b.FluidScript && a.MiningReward == b.MiningReward && a.nTimeStamp == b.nTimeStamp); - } - - inline friend bool operator!=(const CFluidMining& a, const CFluidMining& b) - { - return !(a == b); - } - - friend bool operator<(const CFluidMining& a, const CFluidMining& b) - { - return (a.nTimeStamp < b.nTimeStamp); - } - - friend bool operator>(const CFluidMining& a, const CFluidMining& b) - { - return (a.nTimeStamp > b.nTimeStamp); - } - - inline CFluidMining operator=(const CFluidMining& b) - { - FluidScript = b.FluidScript; - MiningReward = b.MiningReward; - nTimeStamp = b.nTimeStamp; - SovereignAddresses.clear(); //clear out previous entries - for (const std::vector& vchAddress : b.SovereignAddresses) { - SovereignAddresses.push_back(vchAddress); - } - txHash = b.txHash; - nHeight = b.nHeight; - return *this; - } - - inline bool IsNull() const { return (nTimeStamp == 0); } - bool UnserializeFromTx(const CTransaction& tx); - bool UnserializeFromScript(const CScript& fluidScript); - void Serialize(std::vector& vchData); -}; - -static CCriticalSection cs_fluid_mining; - -class CFluidMiningDB : public CDBWrapper -{ -public: - CFluidMiningDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate); - bool AddFluidMiningEntry(const CFluidMining& entry, const int op); - bool GetLastFluidMiningRecord(CFluidMining& returnEntry, const int nHeight); - bool GetAllFluidMiningRecords(std::vector& entries); - bool IsEmpty(); - bool RecordExists(const std::vector& vchFluidScript); -}; - -bool GetFluidMiningData(const CScript& scriptPubKey, CFluidMining& entry); -bool GetFluidMiningData(const CTransaction& tx, CFluidMining& entry, int& nOut); -bool CheckFluidMiningDB(); - -extern CFluidMiningDB* pFluidMiningDB; - -#endif // FLUID_MINING diff --git a/src/fluid/fluidmint.cpp b/src/fluid/fluidmint.cpp deleted file mode 100644 index 4b08c65a4b..0000000000 --- a/src/fluid/fluidmint.cpp +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2017 Duality Blockchain Solutions Developers - - -#include "fluidmint.h" - -#include "base58.h" -#include "core_io.h" -#include "fluid.h" -#include "operations.h" -#include "script/script.h" - -#include - -CFluidMintDB* pFluidMintDB = NULL; - -bool GetFluidMintData(const CScript& scriptPubKey, CFluidMint& entry) -{ - std::string fluidOperationString = ScriptToAsmStr(scriptPubKey); - std::string strOperationCode = GetRidOfScriptStatement(fluidOperationString, 0); - std::string verificationWithoutOpCode = GetRidOfScriptStatement(fluidOperationString); - std::vector splitString; - HexFunctions hexConvert; - hexConvert.ConvertToString(verificationWithoutOpCode); - SeparateString(verificationWithoutOpCode, splitString, false); - std::string messageTokenKey = splitString.at(0); - std::vector vecSplitScript; - SeparateFluidOpString(verificationWithoutOpCode, vecSplitScript); - - if (vecSplitScript.size() >= 6 && strOperationCode == "OP_MINT") { - std::vector vchFluidOperation = CharVectorFromString(fluidOperationString); - entry.FluidScript.insert(entry.FluidScript.end(), vchFluidOperation.begin(), vchFluidOperation.end()); - std::string strAmount = vecSplitScript[0]; - CAmount fluidAmount; - if (ParseFixedPoint(strAmount, 8, &fluidAmount)) { - entry.MintAmount = fluidAmount; - } - std::string strTimeStamp = vecSplitScript[1]; - int64_t tokenTimeStamp; - if (ParseInt64(strTimeStamp, &tokenTimeStamp)) { - entry.nTimeStamp = tokenTimeStamp; - } - std::vector vchDestinationAddress = CharVectorFromString(vecSplitScript[2]); - entry.DestinationAddress.insert(entry.DestinationAddress.end(), vchDestinationAddress.begin(), vchDestinationAddress.end()); - entry.SovereignAddresses.clear(); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[3], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[4], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[5], messageTokenKey).ToString())); - - LogPrintf("GetFluidMintData: strAmount = %s, strTimeStamp = %d, DestinationAddress = %s, Addresses1 = %s, Addresses2 = %s, Addresses3 = %s \n", - strAmount, entry.nTimeStamp, - StringFromCharVector(entry.DestinationAddress), StringFromCharVector(entry.SovereignAddresses[0]), - StringFromCharVector(entry.SovereignAddresses[1]), StringFromCharVector(entry.SovereignAddresses[2])); - - return true; - } - return false; -} - -bool GetFluidMintData(const CTransaction& tx, CFluidMint& entry, int& nOut) -{ - int n = 0; - for (const CTxOut& txout : tx.vout) { - CScript txOut = txout.scriptPubKey; - if (IsTransactionFluid(txOut)) { - nOut = n; - return GetFluidMintData(txOut, entry); - } - n++; - } - return false; -} - -bool CFluidMint::UnserializeFromTx(const CTransaction& tx) -{ - int nOut; - if (!GetFluidMintData(tx, *this, nOut)) { - SetNull(); - return false; - } - return true; -} - -bool CFluidMint::UnserializeFromScript(const CScript& fluidScript) -{ - if (!GetFluidMintData(fluidScript, *this)) { - SetNull(); - return false; - } - return true; -} - -void CFluidMint::Serialize(std::vector& vchData) -{ - CDataStream dsFluidOp(SER_NETWORK, PROTOCOL_VERSION); - dsFluidOp << *this; - vchData = std::vector(dsFluidOp.begin(), dsFluidOp.end()); -} - -CDynamicAddress CFluidMint::GetDestinationAddress() const -{ - return CDynamicAddress(StringFromCharVector(DestinationAddress)); -} - -CFluidMintDB::CFluidMintDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate) : CDBWrapper(GetDataDir() / "blocks" / "fluid-mint", nCacheSize, fMemory, fWipe, obfuscate) -{ -} - -bool CFluidMintDB::AddFluidMintEntry(const CFluidMint& entry, const int op) -{ - bool writeState = false; - { - LOCK(cs_fluid_mint); - writeState = Write(make_pair(std::string("script"), entry.FluidScript), entry) && Write(make_pair(std::string("txid"), entry.txHash), entry.FluidScript); - } - - return writeState; -} - -bool CFluidMintDB::GetLastFluidMintRecord(CFluidMint& returnEntry) -{ - LOCK(cs_fluid_mint); - returnEntry.SetNull(); - std::pair > key; - std::unique_ptr pcursor(NewIterator()); - pcursor->SeekToFirst(); - while (pcursor->Valid()) { - boost::this_thread::interruption_point(); - CFluidMint entry; - try { - if (pcursor->GetKey(key) && key.first == "script") { - pcursor->GetValue(entry); - if (entry.nHeight > returnEntry.nHeight) { - returnEntry = entry; - } - } - pcursor->Next(); - } catch (std::exception& e) { - return error("%s() : deserialize error", __PRETTY_FUNCTION__); - } - } - return true; -} - -bool CFluidMintDB::GetAllFluidMintRecords(std::vector& entries) -{ - LOCK(cs_fluid_mint); - std::pair > key; - std::unique_ptr pcursor(NewIterator()); - pcursor->SeekToFirst(); - while (pcursor->Valid()) { - boost::this_thread::interruption_point(); - CFluidMint entry; - try { - if (pcursor->GetKey(key) && key.first == "script") { - pcursor->GetValue(entry); - if (!entry.IsNull()) { - entries.push_back(entry); - } - } - pcursor->Next(); - } catch (std::exception& e) { - return error("%s() : deserialize error", __PRETTY_FUNCTION__); - } - } - return true; -} - -bool CFluidMintDB::IsEmpty() -{ - LOCK(cs_fluid_mint); - std::unique_ptr pcursor(NewIterator()); - pcursor->SeekToFirst(); - if (pcursor->Valid()) { - CFluidMint entry; - try { - std::pair > key; - if (pcursor->GetKey(key) && key.first == "script") { - pcursor->GetValue(entry); - } - pcursor->Next(); - } catch (std::exception& e) { - return true; - } - return false; - } - return true; -} - -bool CFluidMintDB::RecordExists(const std::vector& vchFluidScript) -{ - LOCK(cs_fluid_mint); - CFluidMint fluidMint; - return CDBWrapper::Read(make_pair(std::string("script"), vchFluidScript), fluidMint); -} - -bool CheckFluidMintDB() -{ - if (!pFluidMintDB) - return false; - - return true; -} diff --git a/src/fluid/fluidmint.h b/src/fluid/fluidmint.h deleted file mode 100644 index 52c89687c5..0000000000 --- a/src/fluid/fluidmint.h +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2019-2021 Duality Blockchain Solutions Developers - -#ifndef FLUID_MINT_H -#define FLUID_MINT_H - -#include "amount.h" -#include "dbwrapper.h" -#include "serialize.h" - -#include "sync.h" -#include "uint256.h" - -class CDynamicAddress; -class CScript; -class CTransaction; - -class CFluidMint -{ -public: - static const int CURRENT_VERSION = 1; - int nVersion; - std::vector FluidScript; - CAmount MintAmount; - std::vector DestinationAddress; - int64_t nTimeStamp; - std::vector > SovereignAddresses; - uint256 txHash; - unsigned int nHeight; - - CFluidMint() - { - SetNull(); - } - - CFluidMint(const CTransaction& tx) - { - SetNull(); - UnserializeFromTx(tx); - } - - CFluidMint(const CScript& fluidScript) - { - SetNull(); - UnserializeFromScript(fluidScript); - } - - inline void SetNull() - { - nVersion = CFluidMint::CURRENT_VERSION; - FluidScript.clear(); - MintAmount = -1; - DestinationAddress.clear(); - nTimeStamp = 0; - SovereignAddresses.clear(); - txHash.SetNull(); - nHeight = 0; - } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) - { - READWRITE(this->nVersion); - READWRITE(FluidScript); - READWRITE(MintAmount); - READWRITE(DestinationAddress); - READWRITE(VARINT(nTimeStamp)); - READWRITE(SovereignAddresses); - READWRITE(txHash); - READWRITE(VARINT(nHeight)); - } - - inline friend bool operator==(const CFluidMint& a, const CFluidMint& b) - { - return (a.FluidScript == b.FluidScript && a.MintAmount == b.MintAmount && a.DestinationAddress == b.DestinationAddress && a.nTimeStamp == b.nTimeStamp); - } - - inline friend bool operator!=(const CFluidMint& a, const CFluidMint& b) - { - return !(a == b); - } - - friend bool operator<(const CFluidMint& a, const CFluidMint& b) - { - return (a.nTimeStamp < b.nTimeStamp); - } - - friend bool operator>(const CFluidMint& a, const CFluidMint& b) - { - return (a.nTimeStamp > b.nTimeStamp); - } - - inline CFluidMint operator=(const CFluidMint& b) - { - FluidScript = b.FluidScript; - MintAmount = b.MintAmount; - DestinationAddress = b.DestinationAddress; - nTimeStamp = b.nTimeStamp; - SovereignAddresses.clear(); //clear out previous entries - for (const std::vector& vchAddress : b.SovereignAddresses) { - SovereignAddresses.push_back(vchAddress); - } - txHash = b.txHash; - nHeight = b.nHeight; - return *this; - } - - inline bool IsNull() const { return (nTimeStamp == 0); } - bool UnserializeFromTx(const CTransaction& tx); - bool UnserializeFromScript(const CScript& fluidScript); - void Serialize(std::vector& vchData); - CDynamicAddress GetDestinationAddress() const; -}; - -static CCriticalSection cs_fluid_mint; - -class CFluidMintDB : public CDBWrapper -{ -public: - CFluidMintDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate); - bool AddFluidMintEntry(const CFluidMint& entry, const int op); - bool GetLastFluidMintRecord(CFluidMint& returnEntry); - bool GetAllFluidMintRecords(std::vector& entries); - bool IsEmpty(); - bool RecordExists(const std::vector& vchFluidScript); -}; - -bool GetFluidMintData(const CScript& scriptPubKey, CFluidMint& entry); -bool GetFluidMintData(const CTransaction& tx, CFluidMint& entry, int& nOut); -bool CheckFluidMintDB(); - -extern CFluidMintDB* pFluidMintDB; - -#endif // FLUID_MINT_H \ No newline at end of file diff --git a/src/fluid/fluidsovereign.h b/src/fluid/fluidsovereign.h deleted file mode 100644 index de9c735ac0..0000000000 --- a/src/fluid/fluidsovereign.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2019-2021 Duality Blockchain Solutions Developers - -#ifndef FLUID_SOVEREIGN_H -#define FLUID_SOVEREIGN_H - -#include "amount.h" -#include "dbwrapper.h" -#include "serialize.h" - -#include "sync.h" -#include "uint256.h" - -class CScript; -class CTransaction; - -class CFluidSovereign -{ -public: - static const int CURRENT_VERSION = 1; - int nVersion; - std::vector FluidScript; - int64_t nTimeStamp; - std::vector > SovereignAddresses; - uint256 txHash; - unsigned int nHeight; - - CFluidSovereign() - { - SetNull(); - } - - CFluidSovereign(const CTransaction& tx) - { - SetNull(); - UnserializeFromTx(tx); - } - - CFluidSovereign(const CScript& fluidScript) - { - SetNull(); - UnserializeFromScript(fluidScript); - } - - inline void SetNull() - { - nVersion = CFluidSovereign::CURRENT_VERSION; - FluidScript.clear(); - nTimeStamp = 0; - SovereignAddresses.clear(); - txHash.SetNull(); - nHeight = 0; - } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) - { - READWRITE(this->nVersion); - READWRITE(FluidScript); - READWRITE(VARINT(nTimeStamp)); - READWRITE(SovereignAddresses); - READWRITE(txHash); - READWRITE(VARINT(nHeight)); - } - - inline friend bool operator==(const CFluidSovereign& a, const CFluidSovereign& b) - { - return (a.FluidScript == b.FluidScript && a.SovereignAddresses == b.SovereignAddresses && a.nTimeStamp == b.nTimeStamp); - } - - inline friend bool operator!=(const CFluidSovereign& a, const CFluidSovereign& b) - { - return !(a == b); - } - - inline CFluidSovereign operator=(const CFluidSovereign& b) - { - FluidScript = b.FluidScript; - nTimeStamp = b.nTimeStamp; - for (const std::vector& vchAddress : b.SovereignAddresses) { - SovereignAddresses.push_back(vchAddress); - } - txHash = b.txHash; - nHeight = b.nHeight; - return *this; - } - - inline bool IsNull() const { return (nTimeStamp == 0); } - bool UnserializeFromTx(const CTransaction& tx); - bool UnserializeFromScript(const CScript& fluidScript); - void Serialize(std::vector& vchData); - std::vector SovereignAddressesStrings(); -}; - -static CCriticalSection cs_fluid_sovereign; - -class CFluidSovereignDB : public CDBWrapper -{ -public: - CFluidSovereignDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate); - bool AddFluidSovereignEntry(const CFluidSovereign& entry); - bool GetLastFluidSovereignRecord(CFluidSovereign& returnEntry); - bool GetAllFluidSovereignRecords(std::vector& entries); - bool IsEmpty(); - -private: - void InitEmpty(); -}; -bool GetFluidSovereignData(const CScript& scriptPubKey, CFluidSovereign& entry); -bool GetFluidSovereignData(const CTransaction& tx, CFluidSovereign& entry, int& nOut); -bool CheckFluidSovereignDB(); - -extern CFluidSovereignDB* pFluidSovereignDB; - -#endif // FLUID_SOVEREIGN_H diff --git a/src/fluid/fluidmining.cpp b/src/fluid/mining.cpp similarity index 52% rename from src/fluid/fluidmining.cpp rename to src/fluid/mining.cpp index d455a9ca3d..c923684887 100644 --- a/src/fluid/fluidmining.cpp +++ b/src/fluid/mining.cpp @@ -1,10 +1,11 @@ // Copyright (c) 2019-2021 Duality Blockchain Solutions Developers -#include "fluidmining.h" +#include "fluid/mining.h" #include "core_io.h" -#include "fluid.h" +#include "fluid/fluid.h" +#include "fluid/script.h" #include "operations.h" #include "script/script.h" @@ -12,77 +13,15 @@ CFluidMiningDB* pFluidMiningDB = NULL; -bool GetFluidMiningData(const CScript& scriptPubKey, CFluidMining& entry) -{ - std::string fluidOperationString = ScriptToAsmStr(scriptPubKey); - std::string strOperationCode = GetRidOfScriptStatement(fluidOperationString, 0); - std::string verificationWithoutOpCode = GetRidOfScriptStatement(fluidOperationString); - std::vector splitString; - HexFunctions hexConvert; - hexConvert.ConvertToString(verificationWithoutOpCode); - SeparateString(verificationWithoutOpCode, splitString, false); - std::string messageTokenKey = splitString.at(0); - std::vector vecSplitScript; - SeparateFluidOpString(verificationWithoutOpCode, vecSplitScript); - - if (vecSplitScript.size() == 5 && strOperationCode == "OP_REWARD_MINING") { - std::vector vchFluidOperation = CharVectorFromString(fluidOperationString); - entry.FluidScript.insert(entry.FluidScript.end(), vchFluidOperation.begin(), vchFluidOperation.end()); - std::string strAmount = vecSplitScript[0]; - CAmount fluidAmount; - if (ParseFixedPoint(strAmount, 8, &fluidAmount)) { - entry.MiningReward = fluidAmount; - } - std::string strTimeStamp = vecSplitScript[1]; - int64_t tokenTimeStamp; - if (ParseInt64(strTimeStamp, &tokenTimeStamp)) { - entry.nTimeStamp = tokenTimeStamp; - } - entry.SovereignAddresses.clear(); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[2], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[3], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[4], messageTokenKey).ToString())); - - LogPrintf("GetFluidMiningData: strAmount = %s, strTimeStamp = %d, Addresses1 = %s, Addresses2 = %s, Addresses3 = %s \n", - strAmount, entry.nTimeStamp, StringFromCharVector(entry.SovereignAddresses[0]), - StringFromCharVector(entry.SovereignAddresses[1]), StringFromCharVector(entry.SovereignAddresses[2])); - - return true; - } - return false; -} - -bool GetFluidMiningData(const CTransaction& tx, CFluidMining& entry, int& nOut) -{ - int n = 0; - for (const CTxOut& txout : tx.vout) { - CScript txOut = txout.scriptPubKey; - if (IsTransactionFluid(txOut)) { - nOut = n; - return GetFluidMiningData(txOut, entry); - } - n++; - } - return false; -} - bool CFluidMining::UnserializeFromTx(const CTransaction& tx) { int nOut; - if (!GetFluidMiningData(tx, *this, nOut)) { - SetNull(); - return false; - } - return true; + return ParseData(tx, *this, nOut); } bool CFluidMining::UnserializeFromScript(const CScript& fluidScript) { - if (!GetFluidMiningData(fluidScript, *this)) { - SetNull(); - return false; - } - return true; + return ParseScript(fluidScript, *this); } void CFluidMining::Serialize(std::vector& vchData) @@ -101,7 +40,7 @@ bool CFluidMiningDB::AddFluidMiningEntry(const CFluidMining& entry, const int op bool writeState = false; { LOCK(cs_fluid_mining); - writeState = Write(make_pair(std::string("script"), entry.FluidScript), entry) && Write(make_pair(std::string("txid"), entry.txHash), entry.FluidScript); + writeState = Write(make_pair(std::string("script"), entry.GetTransactionScript()), entry) && Write(make_pair(std::string("txid"), entry.GetTransactionHash()), entry.GetTransactionScript()); } return writeState; @@ -123,7 +62,7 @@ bool CFluidMiningDB::GetLastFluidMiningRecord(CFluidMining& returnEntry, const i if (entry.IsNull()) { return false; } - if (entry.nHeight > returnEntry.nHeight && (int)(entry.nHeight + 1) < nHeight) { + if (entry.GetHeight() > returnEntry.GetHeight() && (int)(entry.GetHeight() + 1) < nHeight) { returnEntry = entry; } } @@ -186,11 +125,3 @@ bool CFluidMiningDB::RecordExists(const std::vector& vchFluidScri CFluidMining fluidMining; return CDBWrapper::Read(make_pair(std::string("script"), vchFluidScript), fluidMining); } - -bool CheckFluidMiningDB() -{ - if (!pFluidMiningDB) - return false; - - return true; -} diff --git a/src/fluid/mining.h b/src/fluid/mining.h new file mode 100644 index 0000000000..e02a07e686 --- /dev/null +++ b/src/fluid/mining.h @@ -0,0 +1,59 @@ +// Copyright (c) 2019-2021 Duality Blockchain Solutions Developers + +#ifndef FLUID_MINING +#define FLUID_MINING + +#include "amount.h" +#include "dbwrapper.h" +#include "serialize.h" +#include "fluid/fluid.h" + +#include "sync.h" +#include "uint256.h" + +class CScript; +class CTransaction; + +class CFluidMining : public DSFluidObject +{ +public: + CFluidMining() = default; + CFluidMining(const CTransaction& tx) { UnserializeFromTx(tx); } + CFluidMining(const CScript& fluidScript) { UnserializeFromScript(fluidScript); } + ~CFluidMining() = default; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(this->version); + READWRITE(tx_script); + READWRITE(obj_reward); + READWRITE(VARINT(obj_time)); + READWRITE(obj_sigs); + READWRITE(tx_hash); + READWRITE(VARINT(tx_height)); + } + + bool UnserializeFromTx(const CTransaction& tx); + bool UnserializeFromScript(const CScript& fluidScript); + void Serialize(std::vector& vchData); +}; + +static CCriticalSection cs_fluid_mining; + +class CFluidMiningDB : public CDBWrapper +{ +public: + CFluidMiningDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate); + bool AddFluidMiningEntry(const CFluidMining& entry, const int op); + bool GetLastFluidMiningRecord(CFluidMining& returnEntry, const int nHeight); + bool GetAllFluidMiningRecords(std::vector& entries); + bool IsEmpty(); + bool RecordExists(const std::vector& vchFluidScript); +}; + +extern CFluidMiningDB* pFluidMiningDB; + +#endif // FLUID_MINING diff --git a/src/fluid/mint.cpp b/src/fluid/mint.cpp new file mode 100644 index 0000000000..0db9316a63 --- /dev/null +++ b/src/fluid/mint.cpp @@ -0,0 +1,129 @@ +// Copyright (c) 2017 Duality Blockchain Solutions Developers + + +#include "fluid/mint.h" + +#include "base58.h" +#include "core_io.h" +#include "fluid/fluid.h" +#include "fluid/script.h" +#include "operations.h" +#include "script/script.h" + +#include + +CFluidMintDB* pFluidMintDB = NULL; + +bool CFluidMint::UnserializeFromTx(const CTransaction& tx) +{ + int nOut; + return ParseData(tx, *this, nOut); +} + +bool CFluidMint::UnserializeFromScript(const CScript& fluidScript) +{ + return ParseScript(fluidScript, *this); +} + +void CFluidMint::Serialize(std::vector& vchData) +{ + CDataStream dsFluidOp(SER_NETWORK, PROTOCOL_VERSION); + dsFluidOp << *this; + vchData = std::vector(dsFluidOp.begin(), dsFluidOp.end()); +} + +CDynamicAddress CFluidMint::GetDestinationAddress() const +{ + return CDynamicAddress(StringFromCharVector(obj_address)); +} + +CFluidMintDB::CFluidMintDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate) : CDBWrapper(GetDataDir() / "blocks" / "fluid-mint", nCacheSize, fMemory, fWipe, obfuscate) +{ +} + +bool CFluidMintDB::AddFluidMintEntry(const CFluidMint& entry, const int op) +{ + bool writeState = false; + { + LOCK(cs_fluid_mint); + writeState = Write(make_pair(std::string("script"), entry.GetTransactionScript()), entry) && Write(make_pair(std::string("txid"), entry.GetTransactionHash()), entry.GetTransactionScript()); + } + return writeState; +} + +bool CFluidMintDB::GetLastFluidMintRecord(CFluidMint& returnEntry) +{ + LOCK(cs_fluid_mint); + returnEntry.SetNull(); + std::pair > key; + std::unique_ptr pcursor(NewIterator()); + pcursor->SeekToFirst(); + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + CFluidMint entry; + try { + if (pcursor->GetKey(key) && key.first == "script") { + pcursor->GetValue(entry); + if (entry.GetHeight() > returnEntry.GetHeight()) { + returnEntry = entry; + } + } + pcursor->Next(); + } catch (std::exception& e) { + return error("%s() : deserialize error", __PRETTY_FUNCTION__); + } + } + return true; +} + +bool CFluidMintDB::GetAllFluidMintRecords(std::vector& entries) +{ + LOCK(cs_fluid_mint); + std::pair > key; + std::unique_ptr pcursor(NewIterator()); + pcursor->SeekToFirst(); + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + CFluidMint entry; + try { + if (pcursor->GetKey(key) && key.first == "script") { + pcursor->GetValue(entry); + if (!entry.IsNull()) { + entries.push_back(entry); + } + } + pcursor->Next(); + } catch (std::exception& e) { + return error("%s() : deserialize error", __PRETTY_FUNCTION__); + } + } + return true; +} + +bool CFluidMintDB::IsEmpty() +{ + LOCK(cs_fluid_mint); + std::unique_ptr pcursor(NewIterator()); + pcursor->SeekToFirst(); + if (pcursor->Valid()) { + CFluidMint entry; + try { + std::pair > key; + if (pcursor->GetKey(key) && key.first == "script") { + pcursor->GetValue(entry); + } + pcursor->Next(); + } catch (std::exception& e) { + return true; + } + return false; + } + return true; +} + +bool CFluidMintDB::RecordExists(const std::vector& vchFluidScript) +{ + LOCK(cs_fluid_mint); + CFluidMint fluidMint; + return CDBWrapper::Read(make_pair(std::string("script"), vchFluidScript), fluidMint); +} diff --git a/src/fluid/mint.h b/src/fluid/mint.h new file mode 100644 index 0000000000..900a695158 --- /dev/null +++ b/src/fluid/mint.h @@ -0,0 +1,63 @@ +// Copyright (c) 2019-2021 Duality Blockchain Solutions Developers + +#ifndef FLUID_MINT_H +#define FLUID_MINT_H + +#include "amount.h" +#include "dbwrapper.h" +#include "serialize.h" +#include "fluid/fluid.h" + +#include "sync.h" +#include "uint256.h" + +class CDynamicAddress; +class CScript; +class CTransaction; + +class CFluidMint : public DSFluidObject +{ +public: + CFluidMint() = default; + CFluidMint(const CTransaction& tx) { UnserializeFromTx(tx); } + CFluidMint(const CScript& fluidScript) { UnserializeFromScript(fluidScript); } + ~CFluidMint() = default; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(this->version); + READWRITE(tx_script); + READWRITE(obj_reward); + READWRITE(obj_address); + READWRITE(VARINT(obj_time)); + READWRITE(obj_sigs); + READWRITE(tx_hash); + READWRITE(VARINT(tx_height)); + } + + bool UnserializeFromTx(const CTransaction& tx); + bool UnserializeFromScript(const CScript& fluidScript); + void Serialize(std::vector& vchData); + + CDynamicAddress GetDestinationAddress() const; +}; + +static CCriticalSection cs_fluid_mint; + +class CFluidMintDB : public CDBWrapper +{ +public: + CFluidMintDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate); + bool AddFluidMintEntry(const CFluidMint& entry, const int op); + bool GetLastFluidMintRecord(CFluidMint& returnEntry); + bool GetAllFluidMintRecords(std::vector& entries); + bool IsEmpty(); + bool RecordExists(const std::vector& vchFluidScript); +}; + +extern CFluidMintDB* pFluidMintDB; + +#endif // FLUID_MINT_H \ No newline at end of file diff --git a/src/fluid/operations.cpp b/src/fluid/operations.cpp index c51be72af2..f6d97654d8 100644 --- a/src/fluid/operations.cpp +++ b/src/fluid/operations.cpp @@ -20,10 +20,6 @@ extern CWallet* pwalletMain; // ///////////////////////////////////////////////////////////// -std::string SignatureDelimiter = " "; -std::string PrimaryDelimiter = "@"; -std::string SubDelimiter = "$"; - void ScrubString(std::string& input, bool forInteger) { input.erase(std::remove(input.begin(), input.end(), '@'), input.end()); @@ -90,7 +86,7 @@ std::string GetRidOfScriptStatement(const std::string& input, const int& positio // ///////////////////////////////////////////////////////////// -bool COperations::VerifyAddressOwnership(const CDynamicAddress& dynamicAddress) +bool VerifyAddressOwnership(const CDynamicAddress& dynamicAddress) { #ifdef ENABLE_WALLET LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); @@ -111,7 +107,7 @@ bool COperations::VerifyAddressOwnership(const CDynamicAddress& dynamicAddress) #endif //ENABLE_WALLET } -bool COperations::SignTokenMessage(const CDynamicAddress& address, std::string unsignedMessage, std::string& stitchedMessage, bool stitch) +bool SignTokenMessage(const CDynamicAddress& address, std::string unsignedMessage, std::string& stitchedMessage, bool stitch) { #ifdef ENABLE_WALLET CHashWriter ss(SER_GETHASH, 0); @@ -142,12 +138,29 @@ bool COperations::SignTokenMessage(const CDynamicAddress& address, std::string u #endif //ENABLE_WALLET } -bool COperations::GenericSignMessage(const std::string& message, std::string& signedString, const CDynamicAddress& signer) +bool GenericSignMessage(const std::string& message, std::string& signedString, const CDynamicAddress& signer) { if (!SignTokenMessage(signer, message, signedString, true)) return false; else - ConvertToHex(signedString); + signedString = HexStr(signedString); return true; } + +/* Unsafe Parsing Variants */ +CAmount ParseFixedPoint(std::string str) +{ + CAmount val; + if (!ParseFixedPoint(str, 8, &val)) + throw std::runtime_error("Invalid value"); + return val; +} + +CAmount ParseInt64(std::string str) +{ + CAmount val; + if (!ParseInt64(str, &val)) + throw std::runtime_error("Invalid value"); + return val; +} diff --git a/src/fluid/operations.h b/src/fluid/operations.h index 4f654593dc..ce9d49ad56 100644 --- a/src/fluid/operations.h +++ b/src/fluid/operations.h @@ -12,48 +12,9 @@ #include #include -class HexFunctions -{ -public: - std::string StringToHex(const std::string& input) - { - static const char* const lut = "0123456789ABCDEF"; - size_t len = input.length(); - std::string output; - output.reserve(2 * len); - for (size_t i = 0; i < len; ++i) { - const unsigned char c = input[i]; - output.push_back(lut[c >> 4]); - output.push_back(lut[c & 15]); - } - - return output; - } - - std::string HexToString(const std::string& hex) - { - int len = hex.length(); - std::string newString; - for (int i = 0; i < len; i += 2) { - std::string byte = hex.substr(i, 2); - char chr = (char)(int)strtol(byte.c_str(), nullptr, 16); - newString.push_back(chr); - } - - return newString; - } - - void ConvertToHex(std::string& input) - { - std::string output = StringToHex(input); - input = output; - } - void ConvertToString(std::string& input) - { - std::string output = HexToString(input); - input = output; - } -}; +static const std::string SignatureDelimiter = " "; +static const std::string PrimaryDelimiter = "@"; +static const std::string SubDelimiter = "$"; void ScrubString(std::string& input, bool forInteger = false); void SeparateString(const std::string& input, std::vector& output, bool subDelimiter = false); @@ -62,16 +23,11 @@ std::string StitchString(const std::string& stringOne, const std::string& string std::string StitchString(const std::string& stringOne, const std::string& stringTwo, const std::string& stringThree, const bool subDelimiter = false); std::string GetRidOfScriptStatement(const std::string& input, const int& position = 1); -extern std::string PrimaryDelimiter; -extern std::string SubDelimiter; -extern std::string SignatureDelimiter; +bool VerifyAddressOwnership(const CDynamicAddress& dynamicAddress); +bool SignTokenMessage(const CDynamicAddress& address, std::string unsignedMessage, std::string& stitchedMessage, bool stitch = true); +bool GenericSignMessage(const std::string& message, std::string& signedString, const CDynamicAddress& signer); -class COperations : public HexFunctions -{ -public: - bool VerifyAddressOwnership(const CDynamicAddress& dynamicAddress); - bool SignTokenMessage(const CDynamicAddress& address, std::string unsignedMessage, std::string& stitchedMessage, bool stitch = true); - bool GenericSignMessage(const std::string& message, std::string& signedString, const CDynamicAddress& signer); -}; +CAmount ParseFixedPoint(std::string str); +CAmount ParseInt64(std::string str); #endif // OPERATIONS_H diff --git a/src/fluid/script.cpp b/src/fluid/script.cpp new file mode 100644 index 0000000000..a35be2c601 --- /dev/null +++ b/src/fluid/script.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2021 Duality Blockchain Solutions + +#include "fluid/script.h" + +#include "utilstrencodings.h" + +bool WithinFluidRange(opcodetype op) +{ + return op >= OP_MINT && op <= OP_RESERVED_0006; +} + +std::string TranslationTable(opcodetype op) +{ + return GetOpName(op); +} + +uint64_t TranslationTable(std::string str) +{ + str = SanitizeString(str, SAFE_CHARS_SCRIPT); // Remove invalid characters + if (str == "OP_MINT") { return OP_MINT; } + else if (str == "OP_REWARD_DYNODE") { return OP_REWARD_DYNODE; } + else if (str == "OP_REWARD_MINING") { return OP_REWARD_MINING; } + else if (str == "OP_SWAP_SOVEREIGN_ADDRESS") { return OP_SWAP_SOVEREIGN_ADDRESS; } + else if (str == "OP_UPDATE_FEES") { return OP_UPDATE_FEES; } + else if (str == "OP_FREEZE_ADDRESS") { return OP_FREEZE_ADDRESS; } + else if (str == "OP_RELEASE_ADDRESS") { return OP_RELEASE_ADDRESS; } + else if (str == "OP_BDAP_REVOKE") { return OP_BDAP_REVOKE; } + else if (str == "OP_RESERVED_0001") { return OP_RESERVED_0001; } + else if (str == "OP_RESERVED_0002") { return OP_RESERVED_0002; } + else if (str == "OP_RESERVED_0003") { return OP_RESERVED_0003; } + else if (str == "OP_RESERVED_0004") { return OP_RESERVED_0004; } + else if (str == "OP_RESERVED_0005") { return OP_RESERVED_0005; } + else if (str == "OP_RESERVED_0006") { return OP_RESERVED_0006; } + else { return OP_INVALIDOPCODE; } +} diff --git a/src/fluid/script.h b/src/fluid/script.h new file mode 100644 index 0000000000..bcb19d6531 --- /dev/null +++ b/src/fluid/script.h @@ -0,0 +1,16 @@ +// Copyright (c) 2021 Duality Blockchain Solutions + +#ifndef BITCOIN_FLUID_SCRIPT_H +#define BITCOIN_FLUID_SCRIPT_H + +#include "script/script.h" + +#include +#include + +bool WithinFluidRange(opcodetype op); + +std::string TranslationTable(opcodetype op); +uint64_t TranslationTable(std::string str); + +#endif // BITCOIN_FLUID_SCRIPT_H \ No newline at end of file diff --git a/src/fluid/fluidsovereign.cpp b/src/fluid/sovereign.cpp similarity index 51% rename from src/fluid/fluidsovereign.cpp rename to src/fluid/sovereign.cpp index 16158d3093..b284e76f3c 100644 --- a/src/fluid/fluidsovereign.cpp +++ b/src/fluid/sovereign.cpp @@ -1,10 +1,11 @@ // Copyright (c) 2019-2021 Duality Blockchain Solutions Developers -#include "fluidsovereign.h" +#include "fluid/sovereign.h" #include "core_io.h" -#include "fluid.h" +#include "fluid/fluid.h" +#include "fluid/script.h" #include "operations.h" #include "script/script.h" @@ -12,69 +13,15 @@ CFluidSovereignDB* pFluidSovereignDB = NULL; -bool GetFluidSovereignData(const CScript& scriptPubKey, CFluidSovereign& entry) -{ - std::string fluidOperationString = ScriptToAsmStr(scriptPubKey); - std::string strOperationCode = GetRidOfScriptStatement(fluidOperationString, 0); - std::string verificationWithoutOpCode = GetRidOfScriptStatement(fluidOperationString); - std::vector splitString; - HexFunctions hexConvert; - hexConvert.ConvertToString(verificationWithoutOpCode); - SeparateString(verificationWithoutOpCode, splitString, false); - std::string messageTokenKey = splitString.at(0); - std::vector vecSplitScript; - SeparateFluidOpString(verificationWithoutOpCode, vecSplitScript); - - if (vecSplitScript.size() == 5 && strOperationCode == "OP_SWAP_SOVEREIGN_ADDRESS") { - std::vector vchFluidOperation = CharVectorFromString(fluidOperationString); - entry.FluidScript.insert(entry.FluidScript.end(), vchFluidOperation.begin(), vchFluidOperation.end()); - entry.SovereignAddresses.clear(); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[0], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[1], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[2], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[3], messageTokenKey).ToString())); - entry.SovereignAddresses.push_back(CharVectorFromString(fluid.GetAddressFromDigestSignature(vecSplitScript[4], messageTokenKey).ToString())); - std::string strTimeStamp = vecSplitScript[5]; - int64_t tokenTimeStamp; - if (ParseInt64(strTimeStamp, &tokenTimeStamp)) { - entry.nTimeStamp = tokenTimeStamp; - } - return true; - } - return false; -} - -bool GetFluidSovereignData(const CTransaction& tx, CFluidSovereign& entry, int& nOut) -{ - int n = 0; - for (const CTxOut& txout : tx.vout) { - CScript txOut = txout.scriptPubKey; - if (IsTransactionFluid(txOut)) { - nOut = n; - return GetFluidSovereignData(txOut, entry); - } - n++; - } - return false; -} - bool CFluidSovereign::UnserializeFromTx(const CTransaction& tx) { int nOut; - if (!GetFluidSovereignData(tx, *this, nOut)) { - SetNull(); - return false; - } - return true; + return ParseData(tx, *this, nOut); } bool CFluidSovereign::UnserializeFromScript(const CScript& fluidScript) { - if (!GetFluidSovereignData(fluidScript, *this)) { - SetNull(); - return false; - } - return true; + return ParseScript(fluidScript, *this); } void CFluidSovereign::Serialize(std::vector& vchData) @@ -87,7 +34,7 @@ void CFluidSovereign::Serialize(std::vector& vchData) std::vector CFluidSovereign::SovereignAddressesStrings() { std::vector vchAddressStrings; - for (const std::vector& vchAddress : SovereignAddresses) { + for (const std::vector& vchAddress : obj_sigs) { vchAddressStrings.push_back(StringFromCharVector(vchAddress)); } return vchAddressStrings; @@ -102,15 +49,12 @@ void CFluidSovereignDB::InitEmpty() { if (IsEmpty()) { LOCK(cs_fluid_sovereign); - CFluidParameters initSovereign; - std::vector > vchAddresses = initSovereign.InitialiseAddressCharVector(); CFluidSovereign fluidSovereign; - for (const std::vector& sovereignId : vchAddresses) { - fluidSovereign.SovereignAddresses.push_back(sovereignId); + for (const auto& pk : Params().FluidSignatureKeys()) { + fluidSovereign.obj_sigs.insert( + CharVectorFromString(CDynamicAddress(pk).ToString()) + ); } - fluidSovereign.FluidScript = CharVectorFromString("init sovereign"); - fluidSovereign.nTimeStamp = 1; - fluidSovereign.nHeight = 1; if (!AddFluidSovereignEntry(fluidSovereign)) { LogPrintf("CFluidSovereignDB::InitEmpty add failed.\n"); } @@ -122,7 +66,7 @@ bool CFluidSovereignDB::AddFluidSovereignEntry(const CFluidSovereign& entry) bool writeState = false; { LOCK(cs_fluid_sovereign); - writeState = Write(make_pair(std::string("script"), entry.FluidScript), entry) && Write(make_pair(std::string("txid"), entry.txHash), entry.FluidScript); + writeState = Write(make_pair(std::string("script"), entry.GetTransactionScript()), entry) && Write(make_pair(std::string("txid"), entry.GetTransactionHash()), entry.GetTransactionScript()); } return writeState; } @@ -140,7 +84,7 @@ bool CFluidSovereignDB::GetLastFluidSovereignRecord(CFluidSovereign& returnEntry try { if (pcursor->GetKey(key) && key.first == "script") { pcursor->GetValue(entry); - if (entry.nHeight > returnEntry.nHeight) { + if (entry.GetHeight() > returnEntry.GetHeight()) { returnEntry = entry; } } @@ -196,11 +140,3 @@ bool CFluidSovereignDB::IsEmpty() } return true; } - -bool CheckFluidSovereignDB() -{ - if (!pFluidSovereignDB) - return false; - - return true; -} diff --git a/src/fluid/sovereign.h b/src/fluid/sovereign.h new file mode 100644 index 0000000000..b79510b6c7 --- /dev/null +++ b/src/fluid/sovereign.h @@ -0,0 +1,62 @@ +// Copyright (c) 2019-2021 Duality Blockchain Solutions Developers + +#ifndef FLUID_SOVEREIGN_H +#define FLUID_SOVEREIGN_H + +#include "amount.h" +#include "dbwrapper.h" +#include "serialize.h" +#include "fluid/fluid.h" + +#include "sync.h" +#include "uint256.h" + +class CScript; +class CTransaction; + +class CFluidSovereign : public DSFluidObject +{ +public: + CFluidSovereign() = default; + CFluidSovereign(const CTransaction& tx) { UnserializeFromTx(tx); } + CFluidSovereign(const CScript& fluidScript) { UnserializeFromScript(fluidScript); } + ~CFluidSovereign() = default; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(this->version); + READWRITE(tx_script); + READWRITE(VARINT(obj_time)); + READWRITE(obj_sigs); + READWRITE(tx_hash); + READWRITE(VARINT(tx_height)); + } + + bool UnserializeFromTx(const CTransaction& tx); + bool UnserializeFromScript(const CScript& fluidScript); + void Serialize(std::vector& vchData); + + std::vector SovereignAddressesStrings(); +}; + +static CCriticalSection cs_fluid_sovereign; + +class CFluidSovereignDB : public CDBWrapper +{ +public: + CFluidSovereignDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate); + bool AddFluidSovereignEntry(const CFluidSovereign& entry); + bool GetLastFluidSovereignRecord(CFluidSovereign& returnEntry); + bool GetAllFluidSovereignRecords(std::vector& entries); + bool IsEmpty(); + +private: + void InitEmpty(); +}; + +extern CFluidSovereignDB* pFluidSovereignDB; + +#endif // FLUID_SOVEREIGN_H diff --git a/src/init.cpp b/src/init.cpp index b1f6ad2b90..1c285a176f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -31,10 +31,10 @@ #include "dynodeman.h" #include "flat-database.h" #include "fluid/banaccount.h" -#include "fluid/fluiddynode.h" -#include "fluid/fluidmining.h" -#include "fluid/fluidmint.h" -#include "fluid/fluidsovereign.h" +#include "fluid/dynode.h" +#include "fluid/mining.h" +#include "fluid/mint.h" +#include "fluid/sovereign.h" #include "governance.h" #include "httprpc.h" #include "httpserver.h" diff --git a/src/miner/miner-util.cpp b/src/miner/miner-util.cpp index 252f8b7185..6441b00e39 100644 --- a/src/miner/miner-util.cpp +++ b/src/miner/miner-util.cpp @@ -10,9 +10,9 @@ #include "consensus/merkle.h" #include "consensus/validation.h" #include "dynode-payments.h" -#include "fluid/fluiddb.h" -#include "fluid/fluidmining.h" -#include "fluid/fluidmint.h" +#include "fluid/db.h" +#include "fluid/mining.h" +#include "fluid/mint.h" #include "governance.h" #include "policy/policy.h" #include "pow.h" @@ -287,7 +287,7 @@ std::unique_ptr CreateNewBlock(const CChainParams& chainparams, if (areWeMinting) { mintAddress = fluidMint.GetDestinationAddress(); - fluidIssuance = fluidMint.MintAmount; + fluidIssuance = fluidMint.GetReward(); txNew.vout[0].nValue = blockReward + fluidIssuance; } else { txNew.vout[0].nValue = blockReward; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 17c6ba325d..391fac0159 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -13,6 +13,7 @@ #include "bdap/x509certificate.h" #include "consensus/consensus.h" #include "fluid/fluid.h" +#include "fluid/script.h" #include "instantsend.h" #include "policy/policy.h" #include "privatesend.h" @@ -70,7 +71,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet* sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } - if (IsTransactionFluid(txout.scriptPubKey)) { + if (WithinFluidRange(txout.scriptPubKey.GetFlag())) { // Fluid type sub.type = TransactionRecord::Fluid; } @@ -147,7 +148,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet* sub.type = TransactionRecord::PrivateSendCreateDenominations; break; } - if (IsTransactionFluid(txout.scriptPubKey)) { + if (WithinFluidRange(txout.scriptPubKey.GetFlag())) { sub.type = TransactionRecord::Fluid; break; } @@ -263,7 +264,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet* } } } - if (IsTransactionFluid(txout.scriptPubKey)) { + if (WithinFluidRange(txout.scriptPubKey.GetFlag())) { sub.type = TransactionRecord::Fluid; } else if (mapValue["PS"] == "1") { sub.type = TransactionRecord::PrivateSend; diff --git a/src/rpc/fluid.cpp b/src/rpc/fluid.cpp index 7fe3d5f020..68707a8da7 100644 --- a/src/rpc/fluid.cpp +++ b/src/rpc/fluid.cpp @@ -8,11 +8,12 @@ #include "dynode-sync.h" #include "fluid/banaccount.h" #include "fluid/fluid.h" -#include "fluid/fluiddb.h" -#include "fluid/fluiddynode.h" -#include "fluid/fluidmining.h" -#include "fluid/fluidmint.h" -#include "fluid/fluidsovereign.h" +#include "fluid/db.h" +#include "fluid/dynode.h" +#include "fluid/mining.h" +#include "fluid/mint.h" +#include "fluid/sovereign.h" +#include "fluid/script.h" #include "init.h" #include "keepass.h" #include "net.h" @@ -38,48 +39,24 @@ extern void SendBurnTransaction(const CScript& burnScript, CWalletTx& wtxNew, co struct DynodeCompareTimeStamp { bool operator()(const CFluidDynode& a, const CFluidDynode& b) { - return (a.nTimeStamp < b.nTimeStamp); + return (a.GetTime() < b.GetTime()); } }; struct MintCompareTimeStamp { bool operator()(const CFluidMint& a, const CFluidMint& b) { - return (a.nTimeStamp < b.nTimeStamp); + return (a.GetTime() < b.GetTime()); } }; struct MiningCompareTimeStamp { bool operator()(const CFluidMining& a, const CFluidMining& b) { - return (a.nTimeStamp < b.nTimeStamp); + return (a.GetTime() < b.GetTime()); } }; -opcodetype getOpcodeFromString(std::string input) -{ - if (input == "OP_MINT") - return OP_MINT; - else if (input == "OP_REWARD_DYNODE") - return OP_REWARD_DYNODE; - else if (input == "OP_REWARD_MINING") - return OP_REWARD_MINING; - else if (input == "OP_SWAP_SOVEREIGN_ADDRESS") - return OP_SWAP_SOVEREIGN_ADDRESS; - else if (input == "OP_UPDATE_FEES") - return OP_UPDATE_FEES; - else if (input == "OP_FREEZE_ADDRESS") - return OP_FREEZE_ADDRESS; - else if (input == "OP_RELEASE_ADDRESS") - return OP_RELEASE_ADDRESS; - else if (input == "OP_BDAP_REVOKE") - return OP_BDAP_REVOKE; - else - return OP_RETURN; - - return OP_RETURN; -}; - UniValue maketoken(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2) { @@ -99,7 +76,7 @@ UniValue maketoken(const JSONRPCRequest& request) } result.pop_back(); - fluid.ConvertToHex(result); + result = HexStr(result); return result; } @@ -140,7 +117,7 @@ UniValue banaccountstoken(const JSONRPCRequest& request) } strResult.pop_back(); - fluid.ConvertToHex(strResult); + strResult = HexStr(strResult); return strResult; } @@ -196,7 +173,7 @@ UniValue burndynamic(const JSONRPCRequest& request) } std::string result = std::to_string(nAmount); - fluid.ConvertToHex(result); + result = HexStr(result); CScript destroyScript = CScript() << OP_RETURN << ParseHex(result); SendBurnTransaction(destroyScript, wtx, nAmount, scriptSendFrom); @@ -225,7 +202,7 @@ UniValue sendfluidtransaction(const JSONRPCRequest& request) CScript finalScript; EnsureWalletIsUnlocked(); - opcodetype opcode = getOpcodeFromString(request.params[0].get_str()); + opcodetype opcode = (opcodetype)TranslationTable(request.params[0].get_str()); if (negatif == opcode) throw std::runtime_error("OP_CODE is either not a Fluid OP_CODE or is invalid"); @@ -241,7 +218,7 @@ UniValue sendfluidtransaction(const JSONRPCRequest& request) if (opcode == OP_MINT || opcode == OP_REWARD_MINING || opcode == OP_REWARD_DYNODE || opcode == OP_BDAP_REVOKE) { CWalletTx wtx; - SendCustomTransaction(finalScript, wtx, fluid.FLUID_TRANSACTION_COST, false); + SendCustomTransaction(finalScript, wtx, FLUID_TRANSACTION_COST, false); return wtx.GetHash().GetHex(); } else { throw std::runtime_error(strprintf("OP_CODE, %s, not implemented yet!", request.params[0].get_str())); @@ -267,10 +244,10 @@ UniValue signtoken(const JSONRPCRequest& request) if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dynamic address"); - if (!fluid.VerifyAddressOwnership(address)) + if (!VerifyAddressOwnership(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Address is not fluid protocol sovereign address"); - if (!fluid.VerifyAddressOwnership(address)) + if (!VerifyAddressOwnership(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Address is not possessed by wallet!"); std::string r = request.params[1].get_str(); @@ -278,9 +255,9 @@ UniValue signtoken(const JSONRPCRequest& request) if (!IsHex(r)) throw std::runtime_error("Hex isn't even valid! Cannot process ahead..."); - fluid.ConvertToString(r); + r = stringFromVch(ParseHex(r)); - if (!fluid.GenericSignMessage(r, result, address)) + if (!GenericSignMessage(r, result, address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Message signing failed"); return result; @@ -311,7 +288,7 @@ UniValue consenttoken(const JSONRPCRequest& request) if (!IsSovereignAddress(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Address is not fluid protocol sovereign address"); - if (!fluid.VerifyAddressOwnership(address)) + if (!VerifyAddressOwnership(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Address is not possessed by wallet!"); std::string message; @@ -375,11 +352,11 @@ UniValue getfluidhistoryraw(const JSONRPCRequest& request) int x = 1; for (const CFluidMint& mintEntry : mintEntries) { UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("fluid_script", StringFromCharVector(mintEntry.FluidScript))); + obj.push_back(Pair("fluid_script", StringFromCharVector(mintEntry.GetTransactionScript()))); std::string addLabel = "mint_" + std::to_string(x); oMints.push_back(Pair(addLabel, obj)); - totalMintedCoins = totalMintedCoins + mintEntry.MintAmount; - totalFluidTxCost = totalFluidTxCost + fluid.FLUID_TRANSACTION_COST; + totalMintedCoins = totalMintedCoins + mintEntry.GetReward(); + totalFluidTxCost = totalFluidTxCost + FLUID_TRANSACTION_COST; x++; nTotal++; } @@ -395,10 +372,10 @@ UniValue getfluidhistoryraw(const JSONRPCRequest& request) int x = 1; for (const CFluidDynode& dynEntry : dynodeEntries) { UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("fluid_script", StringFromCharVector(dynEntry.FluidScript))); + obj.push_back(Pair("fluid_script", StringFromCharVector(dynEntry.GetTransactionScript()))); std::string addLabel = "reward_update_" + std::to_string(x); oDynodes.push_back(Pair(addLabel, obj)); - totalFluidTxCost = totalFluidTxCost + fluid.FLUID_TRANSACTION_COST; + totalFluidTxCost = totalFluidTxCost + FLUID_TRANSACTION_COST; x++; nTotal++; } @@ -414,10 +391,10 @@ UniValue getfluidhistoryraw(const JSONRPCRequest& request) int x = 1; for (const CFluidMining& miningEntry : miningEntries) { UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("fluid_script", StringFromCharVector(miningEntry.FluidScript))); + obj.push_back(Pair("fluid_script", StringFromCharVector(miningEntry.GetTransactionScript()))); std::string addLabel = "reward_update_" + std::to_string(x); oMining.push_back(Pair(addLabel, obj)); - totalFluidTxCost = totalFluidTxCost + fluid.FLUID_TRANSACTION_COST; + totalFluidTxCost = totalFluidTxCost + FLUID_TRANSACTION_COST; x++; nTotal++; } @@ -501,22 +478,22 @@ UniValue getfluidhistory(const JSONRPCRequest& request) for (const CFluidMint& mintEntry : mintEntries) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("operation", "Mint")); - obj.push_back(Pair("amount", FormatMoney(mintEntry.MintAmount))); - obj.push_back(Pair("timestamp", mintEntry.nTimeStamp)); - obj.push_back(Pair("display_date", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", mintEntry.nTimeStamp))); - obj.push_back(Pair("block_height", (int)mintEntry.nHeight)); - obj.push_back(Pair("txid", mintEntry.txHash.GetHex())); - obj.push_back(Pair("destination_address", StringFromCharVector(mintEntry.DestinationAddress))); + obj.push_back(Pair("amount", FormatMoney(mintEntry.GetReward()))); + obj.push_back(Pair("timestamp", mintEntry.GetTime())); + obj.push_back(Pair("display_date", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", mintEntry.GetTime()))); + obj.push_back(Pair("block_height", (int)mintEntry.GetHeight())); + obj.push_back(Pair("txid", mintEntry.GetTransactionHash().GetHex())); + obj.push_back(Pair("destination_address", StringFromCharVector(mintEntry.obj_address))); int index = 1; - for (const std::vector& vchAddress : mintEntry.SovereignAddresses) { + for (const std::vector& vchAddress : mintEntry.obj_sigs) { std::string addLabel = "sovereign_address_" + std::to_string(index); obj.push_back(Pair(addLabel, StringFromCharVector(vchAddress))); index++; } std::string addLabel = "mint_" + std::to_string(x); oMints.push_back(Pair(addLabel, obj)); - totalMintedCoins = totalMintedCoins + mintEntry.MintAmount; - totalFluidTxCost = totalFluidTxCost + fluid.FLUID_TRANSACTION_COST; + totalMintedCoins = totalMintedCoins + mintEntry.GetReward(); + totalFluidTxCost = totalFluidTxCost + FLUID_TRANSACTION_COST; x++; nTotal++; } @@ -534,20 +511,20 @@ UniValue getfluidhistory(const JSONRPCRequest& request) for (const CFluidDynode& dynEntry : dynodeEntries) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("operation", "Dynode Reward Update")); - obj.push_back(Pair("amount", FormatMoney(dynEntry.DynodeReward))); - obj.push_back(Pair("timestamp", dynEntry.nTimeStamp)); - obj.push_back(Pair("display_date", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", dynEntry.nTimeStamp))); - obj.push_back(Pair("block_height", (int)dynEntry.nHeight)); - obj.push_back(Pair("txid", dynEntry.txHash.GetHex())); + obj.push_back(Pair("amount", FormatMoney(dynEntry.GetReward()))); + obj.push_back(Pair("timestamp", dynEntry.GetTime())); + obj.push_back(Pair("display_date", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", dynEntry.GetTime()))); + obj.push_back(Pair("block_height", (int)dynEntry.GetHeight())); + obj.push_back(Pair("txid", dynEntry.GetTransactionHash().GetHex())); int index = 1; - for (const std::vector& vchAddress : dynEntry.SovereignAddresses) { + for (const std::vector& vchAddress : dynEntry.obj_sigs) { std::string addLabel = "sovereign_address_" + std::to_string(index); obj.push_back(Pair(addLabel, StringFromCharVector(vchAddress))); index++; } std::string addLabel = "reward_update_" + std::to_string(x); oDynodes.push_back(Pair(addLabel, obj)); - totalFluidTxCost = totalFluidTxCost + fluid.FLUID_TRANSACTION_COST; + totalFluidTxCost = totalFluidTxCost + FLUID_TRANSACTION_COST; x++; nTotal++; } @@ -565,20 +542,20 @@ UniValue getfluidhistory(const JSONRPCRequest& request) for (const CFluidMining& miningEntry : miningEntries) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("operation", "Mining Reward Update")); - obj.push_back(Pair("amount", FormatMoney(miningEntry.MiningReward))); - obj.push_back(Pair("timestamp", miningEntry.nTimeStamp)); - obj.push_back(Pair("display_date", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", miningEntry.nTimeStamp))); - obj.push_back(Pair("block_height", (int)miningEntry.nHeight)); - obj.push_back(Pair("txid", miningEntry.txHash.GetHex())); + obj.push_back(Pair("amount", FormatMoney(miningEntry.GetReward()))); + obj.push_back(Pair("timestamp", miningEntry.GetTime())); + obj.push_back(Pair("display_date", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", miningEntry.GetTime()))); + obj.push_back(Pair("block_height", (int)miningEntry.GetHeight())); + obj.push_back(Pair("txid", miningEntry.GetTransactionHash().GetHex())); int index = 1; - for (const std::vector& vchAddress : miningEntry.SovereignAddresses) { + for (const std::vector& vchAddress : miningEntry.obj_sigs) { std::string addLabel = "sovereign_address_" + std::to_string(index); obj.push_back(Pair(addLabel, StringFromCharVector(vchAddress))); index++; } std::string addLabel = "reward_update_" + std::to_string(x); oMining.push_back(Pair(addLabel, obj)); - totalFluidTxCost = totalFluidTxCost + fluid.FLUID_TRANSACTION_COST; + totalFluidTxCost = totalFluidTxCost + FLUID_TRANSACTION_COST; x++; nTotal++; } @@ -658,7 +635,7 @@ UniValue getfluidsovereigns(const JSONRPCRequest& request) for (const CFluidSovereign& sovereignEntry : sovereignEntries) { int index = 1; UniValue oEntry(UniValue::VOBJ); - for (const std::vector& vchAddress : sovereignEntry.SovereignAddresses) { + for (const std::vector& vchAddress : sovereignEntry.obj_sigs) { std::string addLabel = "address_" + std::to_string(index); oEntry.push_back(Pair(addLabel, StringFromCharVector(vchAddress))); index++; @@ -692,8 +669,7 @@ UniValue readfluidtoken(const JSONRPCRequest& request) std::string strFluidToken = request.params[0].get_str(); if (IsHex(strFluidToken)) { bool fBanAccount = false; - HexFunctions fluidFunctions; - std::string strUnHexedFluidOpScript = fluidFunctions.HexToString(strFluidToken); + std::string strUnHexedFluidOpScript = stringFromVch(ParseHex(strFluidToken)); std::vector vecSplitScript; SeparateString(strUnHexedFluidOpScript, vecSplitScript, true); if (vecSplitScript.size() > 1) { diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 3a5421b543..4f9926c411 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -15,8 +15,8 @@ #include "consensus/validation.h" #include "core_io.h" #include "fluid/fluid.h" -#include "fluid/fluiddb.h" -#include "fluid/fluidmint.h" +#include "fluid/db.h" +#include "fluid/mint.h" #include "init.h" #include "miner/miner.h" #include "net.h" diff --git a/src/script/script.h b/src/script/script.h index 27ab08f547..7584eaec1f 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -194,6 +194,12 @@ enum opcodetype { OP_FREEZE_ADDRESS = 0xc7, OP_RELEASE_ADDRESS = 0xc8, OP_BDAP_REVOKE = 0xc9, // = BDAP delete using fluid protocol + OP_RESERVED_0001 = 0xca, + OP_RESERVED_0002 = 0xcb, + OP_RESERVED_0003 = 0xcc, + OP_RESERVED_0004 = 0xcd, + OP_RESERVED_0005 = 0xce, + OP_RESERVED_0006 = 0xcf, // BDAP directory access, user identity and certificate system OP_BDAP_NEW = 0x01, // = BDAP new entry @@ -223,9 +229,6 @@ const char* GetOpName(opcodetype opcode); // Identification codes for Fluid and BDAP Transactions enum ProtocolCodes { - MINT_TX = 1, - DYNODE_MODFIY_TX = 2, - MINING_MODIFY_TX = 3, BDAP_NEW_TX = 4, BDAP_DELETE_TX = 5, BDAP_REVOKE_TX = 6, @@ -675,25 +678,9 @@ class CScript : public CScriptBase return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE); } - bool IsProtocolInstruction(const ProtocolCodes& code) const + opcodetype GetFlag() const { - switch (code) { - case MINT_TX: - return (size() > 0 && *begin() == OP_MINT); - break; - case DYNODE_MODFIY_TX: - return (size() > 0 && *begin() == OP_REWARD_DYNODE); - break; - case MINING_MODIFY_TX: - return (size() > 0 && *begin() == OP_REWARD_MINING); - break; - case BDAP_REVOKE_TX: - return (size() > 0 && *begin() == OP_BDAP_REVOKE); - break; - default: - throw std::runtime_error("Protocol code is invalid!"); - } - return false; + return size() > 0 ? static_cast(*begin()) : OP_INVALIDOPCODE; } //TODO: (bdap) test if this is working diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 905dc8a64b..aeb9c167f3 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -19,7 +19,8 @@ static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJ static const std::string SAFE_CHARS[] = { CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT - CHARS_ALPHA_NUM + " .,;-_?@" // SAFE_CHARS_UA_COMMENT + CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT + CHARS_ALPHA_NUM + "_" // SAFE_CHARS_SCRIPT }; std::string SanitizeString(const std::string& str, int rule) diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 0e1fd160e3..e45d2322f8 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -30,7 +30,8 @@ /** Used by SanitizeString() */ enum SafeChars { SAFE_CHARS_DEFAULT, //!< The full set of allowed chars - SAFE_CHARS_UA_COMMENT //!< BIP-0014 subset + SAFE_CHARS_UA_COMMENT,//!< BIP-0014 subset + SAFE_CHARS_SCRIPT //!< Set of characters allowed in a script opcode }; /** diff --git a/src/validation.cpp b/src/validation.cpp index 2818dd3b8a..326ee2ab91 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -29,10 +29,11 @@ #include "dynodeman.h" #include "fluid/banaccount.h" #include "fluid/fluid.h" -#include "fluid/fluiddb.h" -#include "fluid/fluiddynode.h" -#include "fluid/fluidmining.h" -#include "fluid/fluidmint.h" +#include "fluid/db.h" +#include "fluid/dynode.h" +#include "fluid/mining.h" +#include "fluid/mint.h" +#include "fluid/script.h" #include "hash.h" #include "init.h" #include "instantsend.h" @@ -274,14 +275,14 @@ bool IsFinalTx(const CTransaction& tx, int nBlockHeight, int64_t nBlockTime) if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime)) return true; - if (nBlockHeight >= fluid.FLUID_ACTIVATE_HEIGHT) { + if (nBlockHeight >= FLUID_ACTIVATE_HEIGHT) { if (!fluid.ProvisionalCheckTransaction(tx)) return false; CScript scriptFluid; if (IsTransactionFluid(tx, scriptFluid)) { std::string strErrorMessage; - if (!fluid.CheckFluidOperationScript(scriptFluid, nBlockTime, strErrorMessage)) { + if (!fluid.CheckFluidOperationScript(scriptFluid, nBlockTime)) { return false; } } @@ -573,8 +574,8 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state) nValueOut += txout.nValue; if (!MoneyRange(nValueOut)) return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge"); - if (IsTransactionFluid(txout.scriptPubKey)) { - if (fluid.FLUID_TRANSACTION_COST > txout.nValue) + if (WithinFluidRange(txout.scriptPubKey.GetFlag())) { + if (FLUID_TRANSACTION_COST > txout.nValue) return state.DoS(100, false, REJECT_INVALID, "bad-txns-fluid-vout-amount-toolow"); if (!fluid.ValidationProcesses(state, txout.scriptPubKey, txout.nValue)) return state.DoS(100, false, REJECT_INVALID, "bad-txns-fluid-validate-failure"); @@ -955,11 +956,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C return false; for (const CTxOut& txout : tx.vout) { - if (IsTransactionFluid(txout.scriptPubKey)) { + if (WithinFluidRange(txout.scriptPubKey.GetFlag())) { fluidTransaction = true; std::string strErrorMessage; // Check if fluid transaction is already in the mempool - if (fluid.CheckIfExistsInMemPool(pool, txout.scriptPubKey, strErrorMessage)) { + if (fluid.CheckIfExistsInMemPool(pool, txout.scriptPubKey)) { // fluid transaction is already in the mempool. Reject tx. return state.DoS(100, false, REJECT_INVALID, strErrorMessage); } @@ -972,7 +973,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C if (!fluid.ExtractCheckTimestamp(strOperationCode, ScriptToAsmStr(txout.scriptPubKey), GetTime())) { return state.DoS(100, false, REJECT_INVALID, "fluid-tx-timestamp-error"); } - if (!fluid.CheckFluidOperationScript(txout.scriptPubKey, GetTime(), strErrorMessage, true)) { + if (!fluid.CheckFluidOperationScript(txout.scriptPubKey, GetTime(), true)) { return state.DoS(100, false, REJECT_INVALID, strErrorMessage); } } @@ -1748,9 +1749,9 @@ bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState& state, const return false; BOOST_FOREACH (const CTxOut& txout, tx->vout) { - if (IsTransactionFluid(txout.scriptPubKey)) { + if (WithinFluidRange(txout.scriptPubKey.GetFlag())) { std::string strErrorMessage; - if (!fluid.CheckFluidOperationScript(txout.scriptPubKey, GetTime(), strErrorMessage)) { + if (!fluid.CheckFluidOperationScript(txout.scriptPubKey, GetTime())) { fluidTimestampCheck = false; } } @@ -2941,12 +2942,12 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd CAmount newMintIssuance = 0; CDynamicAddress mintAddress; - if (prevIndex->nHeight + 1 >= fluid.FLUID_ACTIVATE_HEIGHT) { + if (prevIndex->nHeight + 1 >= FLUID_ACTIVATE_HEIGHT) { CFluidMint fluidMint; if (GetMintingInstructions(pindex->nHeight, fluidMint)) { - newMintIssuance = fluidMint.MintAmount; + newMintIssuance = fluidMint.GetReward(); mintAddress = fluidMint.GetDestinationAddress(); - LogPrintf("ConnectBlock, GetMintingInstructions MintAmount = %u\n", fluidMint.MintAmount); + LogPrintf("ConnectBlock, GetMintingInstructions MintAmount = %u\n", fluidMint.GetReward()); } } nExpectedBlockValue = newMintIssuance + newMiningReward + newDynodeReward; @@ -2961,40 +2962,32 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd } } for (unsigned int i = 0; i < block.vtx.size(); i++) { + assert(pFluidDynodeDB); const CTransaction& tx = *block.vtx[i]; CScript scriptFluid; if (IsTransactionFluid(tx, scriptFluid)) { - int OpCode = GetFluidOpCode(scriptFluid); + int OpCode = scriptFluid.GetFlag(); if (OpCode == OP_REWARD_DYNODE) { CFluidDynode fluidDynode(scriptFluid); - fluidDynode.nHeight = pindex->nHeight; - fluidDynode.txHash = tx.GetHash(); - if (CheckFluidDynodeDB()) { - if (!CheckSignatureQuorum(fluidDynode.FluidScript, strError)) { - return state.DoS(0, error("ConnectBlock(DYN): %s", strError), REJECT_INVALID, "invalid-fluid-dynode-address-signature"); - } - pFluidDynodeDB->AddFluidDynodeEntry(fluidDynode, OP_REWARD_DYNODE); + fluidDynode.InitialiseHeightHash(pindex->nHeight, tx.GetHash()); + if (!CheckSignatureQuorum(fluidDynode.GetTransactionScript(), strError)) { + return state.DoS(0, error("ConnectBlock(DYN): %s", strError), REJECT_INVALID, "invalid-fluid-dynode-address-signature"); } + pFluidDynodeDB->AddFluidDynodeEntry(fluidDynode, OP_REWARD_DYNODE); } else if (OpCode == OP_REWARD_MINING) { CFluidMining fluidMining(scriptFluid); - fluidMining.nHeight = pindex->nHeight; - fluidMining.txHash = tx.GetHash(); - if (CheckFluidMiningDB()) { - if (!CheckSignatureQuorum(fluidMining.FluidScript, strError)) { - return state.DoS(0, error("ConnectBlock(DYN): %s", strError), REJECT_INVALID, "invalid-fluid-mining-address-signature"); - } - pFluidMiningDB->AddFluidMiningEntry(fluidMining, OP_REWARD_MINING); + fluidMining.InitialiseHeightHash(pindex->nHeight, tx.GetHash()); + if (!CheckSignatureQuorum(fluidMining.GetTransactionScript(), strError)) { + return state.DoS(0, error("ConnectBlock(DYN): %s", strError), REJECT_INVALID, "invalid-fluid-mining-address-signature"); } + pFluidMiningDB->AddFluidMiningEntry(fluidMining, OP_REWARD_MINING); } else if (OpCode == OP_MINT) { CFluidMint fluidMint(scriptFluid); - fluidMint.nHeight = pindex->nHeight; - fluidMint.txHash = tx.GetHash(); - if (CheckFluidMintDB()) { - if (!CheckSignatureQuorum(fluidMint.FluidScript, strError)) { - return state.DoS(0, error("ConnectBlock(DYN): %s", strError), REJECT_INVALID, "invalid-fluid-mint-address-signature"); - } - pFluidMintDB->AddFluidMintEntry(fluidMint, OP_MINT); + fluidMint.InitialiseHeightHash(pindex->nHeight, tx.GetHash()); + if (!CheckSignatureQuorum(fluidMint.GetTransactionScript(), strError)) { + return state.DoS(0, error("ConnectBlock(DYN): %s", strError), REJECT_INVALID, "invalid-fluid-mint-address-signature"); } + pFluidMintDB->AddFluidMintEntry(fluidMint, OP_MINT); } else if (OpCode == OP_BDAP_REVOKE) { if (!CheckSignatureQuorum(FluidScriptToCharVector(scriptFluid), strError)) return state.DoS(0, error("%s: %s", __func__, strError), REJECT_INVALID, "invalid-fluid-ban-address-signature"); @@ -3003,7 +2996,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd // return state.DoS(0, error("%s: BDAP spork is inactive.", __func__), REJECT_INVALID, "bdap-spork-inactive"); std::vector vBanAccounts; - if (!fluid.CheckAccountBanScript(scriptFluid, tx.GetHash(), pindex->nHeight, vBanAccounts, strError)) + if (!fluid.CheckAccountBanScript(scriptFluid, tx.GetHash(), pindex->nHeight, vBanAccounts)) return state.DoS(0, error("%s -- CheckAccountBanScript failed: %s", __func__, strError), REJECT_INVALID, "fluid-ban-script-invalid"); int64_t nTimeStamp; @@ -4119,9 +4112,9 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage())); for (const auto& txout : tx->vout) { - if (IsTransactionFluid(txout.scriptPubKey)) { + if (WithinFluidRange(txout.scriptPubKey.GetFlag())) { std::string strErrorMessage; - if (!fluid.CheckFluidOperationScript(txout.scriptPubKey, block.nTime, strErrorMessage)) { + if (!fluid.CheckFluidOperationScript(txout.scriptPubKey, block.nTime)) { return error("CheckBlock(): %s, Block %s failed with %s", strErrorMessage, tx->GetHash().ToString(), diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 86ffdb14ab..3b6d768bc2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -24,7 +24,8 @@ #include "core_io.h" #include "dynode-sync.h" #include "fluid/fluid.h" -#include "fluid/fluiddb.h" +#include "fluid/db.h" +#include "fluid/script.h" #include "governance.h" #include "init.h" #include "instantsend.h" @@ -4062,14 +4063,14 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT for (const auto& recipient : vecSend) { CTxOut txout(recipient.nAmount, recipient.scriptPubKey); - if (IsTransactionFluid(recipient.scriptPubKey)) { + if (WithinFluidRange(recipient.scriptPubKey.GetFlag())) { // Check if fluid transaction is already in the mempool - if (fluid.CheckIfExistsInMemPool(mempool, recipient.scriptPubKey, strFailReason)) { + if (fluid.CheckIfExistsInMemPool(mempool, recipient.scriptPubKey)) { // fluid transaction is already in the mempool. Invalid transaction. return false; } // Check the validity of the fluid transaction's public script. - if (!fluid.CheckFluidOperationScript(recipient.scriptPubKey, GetTime(), strFailReason)) { + if (!fluid.CheckFluidOperationScript(recipient.scriptPubKey, GetTime())) { return false; } }