From 5029feb8cb260f91e60cf38e18f7aa6a419f982a Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Thu, 16 May 2019 00:32:41 -0500 Subject: [PATCH 01/36] [BDAP] Use stealth address for account link wallet address --- src/bdap/rpcdomainentry.cpp | 24 +++++----------------- src/bdap/rpcrawbdap.cpp | 21 ++++++------------- src/wallet/rpcwallet.cpp | 6 ++---- src/wallet/wallet.cpp | 41 ++++++++++++++++++++++--------------- src/wallet/wallet.h | 7 +++++-- src/wallet/walletdb.cpp | 2 -- 6 files changed, 43 insertions(+), 58 deletions(-) diff --git a/src/bdap/rpcdomainentry.cpp b/src/bdap/rpcdomainentry.cpp index 035cc70950..6fde09482d 100644 --- a/src/bdap/rpcdomainentry.cpp +++ b/src/bdap/rpcdomainentry.cpp @@ -48,39 +48,25 @@ static UniValue AddDomainEntry(const JSONRPCRequest& request, BDAP::ObjectType b if (GetDomainEntry(txDomainEntry.vchFullObjectPath(), txDomainEntry)) throw std::runtime_error("BDAP_ADD_PUBLIC_ENTRY_RPC_ERROR: ERRCODE: 3500 - " + txDomainEntry.GetFullObjectPath() + _(" entry already exists. Can not add duplicate.")); - //now using GetKeyFromPool instead of MakeNewKey CPubKey pubWalletKey; CharString vchDHTPubKey; - if (!pwalletMain->GetKeysFromPool(pubWalletKey, vchDHTPubKey, true)) + CStealthAddress sxAddr; + if (!pwalletMain->GetKeysFromPool(pubWalletKey, vchDHTPubKey, sxAddr, true)) throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); CKeyID keyWalletID = pubWalletKey.GetID(); CDynamicAddress walletAddress = CDynamicAddress(keyWalletID); pwalletMain->SetAddressBook(keyWalletID, strObjectID, "bdap-wallet"); - - CharString vchWalletAddress = vchFromString(walletAddress.ToString()); - txDomainEntry.WalletAddress = vchWalletAddress; + txDomainEntry.WalletAddress = vchFromString(walletAddress.ToString()); txDomainEntry.DHTPublicKey = vchDHTPubKey; CKeyID vchDHTPubKeyID = GetIdFromCharVector(vchDHTPubKey); pwalletMain->SetAddressBook(vchDHTPubKeyID, strObjectID, "bdap-dht-key"); - // TODO: Add ability to pass in the link address - // TODO: Use stealth address for the link address so linking will be private - //now using GetKeyFromPool instead of MakeNewKey - CPubKey pubLinkKey; - CharString NAvchDHTPubKey; //not really used - if (!pwalletMain->GetKeysFromPool(pubLinkKey, NAvchDHTPubKey, true)) - throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); - - CKeyID keyLinkID = pubLinkKey.GetID(); - CDynamicAddress linkAddress = CDynamicAddress(keyLinkID); + //pwalletMain->SetAddressBook(keyLinkID, strObjectID, "bdap-link"); - pwalletMain->SetAddressBook(keyLinkID, strObjectID, "bdap-link"); - - CharString vchLinkAddress = vchFromString(linkAddress.ToString()); - txDomainEntry.LinkAddress = vchLinkAddress; + txDomainEntry.LinkAddress = vchFromString(sxAddr.ToString()); int64_t nDays = DEFAULT_REGISTRATION_DAYS; // default to 2 years. if (request.params.size() >= 3) { diff --git a/src/bdap/rpcrawbdap.cpp b/src/bdap/rpcrawbdap.cpp index cf762038f9..40756265ef 100644 --- a/src/bdap/rpcrawbdap.cpp +++ b/src/bdap/rpcrawbdap.cpp @@ -89,7 +89,8 @@ UniValue createrawbdapaccount(const JSONRPCRequest& request) // TODO: Add ability to pass in the wallet address std::vector vchDHTPubKey; CPubKey pubWalletKey; - if (!pwalletMain->GetKeysFromPool(pubWalletKey, vchDHTPubKey, true)) + CStealthAddress sxAddr; + if (!pwalletMain->GetKeysFromPool(pubWalletKey, vchDHTPubKey, sxAddr, true)) throw std::runtime_error("Error: Keypool ran out, please call keypoolrefill first"); CKeyID keyWalletID = pubWalletKey.GetID(); CDynamicAddress walletAddress = CDynamicAddress(keyWalletID); @@ -103,19 +104,8 @@ UniValue createrawbdapaccount(const JSONRPCRequest& request) txDomainEntry.DHTPublicKey = vchDHTPubKey; pwalletMain->SetAddressBook(vchDHTPubKeyID, strObjectID, "bdap-dht-key"); - // TODO: Add ability to pass in the link address - // TODO: Use stealth address for the link address so linking will be private - CPubKey pubLinkKey; - std::vector newEdKey2; - if (!pwalletMain->GetKeysFromPool(pubLinkKey, newEdKey2, true)) - throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); - CKeyID keyLinkID = pubLinkKey.GetID(); - CDynamicAddress linkAddress = CDynamicAddress(keyLinkID); - - pwalletMain->SetAddressBook(keyLinkID, strObjectID, "bdap-link"); - - CharString vchLinkAddress = vchFromString(linkAddress.ToString()); - txDomainEntry.LinkAddress = vchLinkAddress; + //pwalletMain->SetAddressBook(keyLinkID, strObjectID, "bdap-link"); + txDomainEntry.LinkAddress = vchFromString(sxAddr.ToString()); CMutableTransaction rawTx; rawTx.nVersion = BDAP_TX_VERSION; @@ -142,8 +132,9 @@ UniValue createrawbdapaccount(const JSONRPCRequest& request) scriptData << OP_RETURN << data; // Create script to fund link transaction for this account + CTxDestination destLinkAddress = DecodeDestination(sxAddr.ToString()); CScript scriptLinkDestination; - scriptLinkDestination = GetScriptForDestination(linkAddress.Get()); + scriptLinkDestination = GetScriptForDestination(destLinkAddress); // TODO (bdap): decrease this amount after BDAP fee structure is implemented. CAmount nLinkAmount(30 * COIN); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ba98b858b3..9fe9b79233 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -215,12 +215,10 @@ static UniValue getnewstealthaddress(const JSONRPCRequest &request) CPubKey walletPubKey; CStealthAddress sxAddr; - if (!pwalletMain->GetStealthAddressFromPool(walletPubKey, sxAddr, false)) + std::vector vchEd25519PubKey; + if (!pwalletMain->GetKeysFromPool(walletPubKey, vchEd25519PubKey, sxAddr, false)) throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); - if (!pwalletMain->AddStealthAddress(sxAddr)) - throw std::runtime_error(strprintf("%s -- Failed to write stealth address to local wallet.\n", __func__)); - return sxAddr.ToString(); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e9e2e5958f..22b8c663a1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -198,6 +198,25 @@ void CWallet::DeriveEd25519ChildKey(const CKey& seed, CKeyEd25519& secretEdRet) } //DeriveEd25519ChildKey +bool CWallet::DeriveChildStealthKey(const CKey& key) +{ + CKey spendKey, scanKey; + if (!key.DeriveChildKey(spendKey)) + return false; + + if (!spendKey.DeriveChildKey(scanKey)) + return false; + + if (!AddKeyPubKey(spendKey, spendKey.GetPubKey())) + return false; + + if (!AddKeyPubKey(scanKey, scanKey.GetPubKey())) + return false; + + CStealthAddress sxAddr(scanKey, spendKey); + return AddStealthAddress(sxAddr); +} + void CWallet::DeriveNewChildKey(const CKeyMetadata& metadata, CKey& secretRet, uint32_t nAccountIndex, bool fInternal) { CHDChain hdChainTmp; @@ -228,6 +247,7 @@ void CWallet::DeriveNewChildKey(const CKeyMetadata& metadata, CKey& secretRet, u CKeyEd25519 secretEdRet; DeriveEd25519ChildKey(secretRet,secretEdRet); //Derive Ed25519 key + DeriveChildStealthKey(secretRet); CPubKey pubkey = secretRet.GetPubKey(); assert(secretRet.VerifyPubKey(pubkey)); @@ -4793,12 +4813,8 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal) LogPrintf("keypool return %d\n", nIndex); } -bool CWallet::GetStealthAddressFromPool(CPubKey& pubkeyWallet, CStealthAddress& sxAddr, bool fInternal) +bool CWallet::GetKeysFromPool(CPubKey& pubkeyWallet, std::vector& vchEd25519PubKey, CStealthAddress& sxAddr, bool fInternal) { - if (IsLocked()) - return false; - - std::vector vchEd25519PubKey; if (!GetKeysFromPool(pubkeyWallet, vchEd25519PubKey, fInternal)) return false; @@ -4812,18 +4828,12 @@ bool CWallet::GetStealthAddressFromPool(CPubKey& pubkeyWallet, CStealthAddress& if (!spendKey.DeriveChildKey(scanKey)) return false; - if (!AddKeyPubKey(spendKey, spendKey.GetPubKey())) - return false; - - if (!AddKeyPubKey(scanKey, scanKey.GetPubKey())) - return false; - CStealthAddress sx(scanKey, spendKey); sxAddr = sx; return true; } -bool CWallet::GetKeysFromPool(CPubKey& result, std::vector& vchEd25519PubKey, bool fInternal) +bool CWallet::GetKeysFromPool(CPubKey& pubkeyWallet, std::vector& vchEd25519PubKey, bool fInternal) { int64_t nIndex = 0; int64_t nEdIndex = 0; @@ -4837,15 +4847,15 @@ bool CWallet::GetKeysFromPool(CPubKey& result, std::vector& vchEd if (IsLocked(true)) return false; // TODO: implement keypool for all accouts? - result = GenerateNewKey(0, fInternal); + pubkeyWallet = GenerateNewKey(0, fInternal); } else { KeepKey(nIndex); - result = keypool.vchPubKey; + pubkeyWallet = keypool.vchPubKey; } CKey keyRetrieved; - GetKey(result.GetID(), keyRetrieved); + GetKey(pubkeyWallet.GetID(), keyRetrieved); if (nEdIndex == -1) { if (IsLocked(true)) @@ -6086,7 +6096,6 @@ bool CWallet::ScanForOwnedOutputs(const CTransaction& tx) bool CWallet::AddStealthAddress(const CStealthAddress& sxAddr) { - LogPrintf("%s: %s\n", __func__, sxAddr.Encoded()); CWalletDB* pwdb = GetWalletDB(); LOCK(cs_mapStealthAddresses); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index a296e1d21d..879e86c55d 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -780,6 +780,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void DeriveEd25519ChildKey(const CKey& seed, CKeyEd25519& secretEdRet); + /* HD derive new child stealth key from */ + bool DeriveChildStealthKey(const CKey& key); + void ReserveEdKeyFromKeyPool(int64_t& nIndex, CEdKeyPool& edkeypool, bool fInternal); void ReserveEdKeyForTransactions(); @@ -1137,7 +1140,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void KeepKey(int64_t nIndex); void KeepEdKey(int64_t nIndex); void ReturnKey(int64_t nIndex, bool fInternal); - bool GetKeysFromPool(CPubKey& result, std::vector& vchEd25519PubKey, bool fInternal); + bool GetKeysFromPool(CPubKey& pubkeyWallet, std::vector& vchEd25519PubKey, bool fInternal); + bool GetKeysFromPool(CPubKey& pubkeyWallet, std::vector& vchEd25519PubKey, CStealthAddress& sxAddr, bool fInternal); int64_t GetOldestKeyPoolTime(); void GetAllReserveKeys(std::set& setAddress) const; void UpdateKeyPoolsFromTransactions(const std::string& strOpType, const std::vector>& vvchOpParameters); @@ -1307,7 +1311,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool AddToStealthQueue(const std::pair& pairStealthQueue); CWalletDB* GetWalletDB(); bool HaveStealthAddress(const CKeyID& address) const; - bool GetStealthAddressFromPool(CPubKey& pubkeyWallet, CStealthAddress& sxAddr, bool fInternal); }; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 3e087ed054..0e0cf69e19 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -658,7 +658,6 @@ bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, CW ssKey >> keyID; CStealthAddress sxAddr; ssValue >> sxAddr; - LogPrintf("%s -- AddStealthToMap \n", __func__); pwallet->AddStealthToMap(std::make_pair(keyID, sxAddr)); } else if (strType == "sxqueue") { @@ -666,7 +665,6 @@ bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, CW ssKey >> keyID; CStealthKeyQueueData stealthData; ssValue >> stealthData; - LogPrintf("%s -- AddToStealthQueue \n", __func__); pwallet->AddToStealthQueue(std::make_pair(keyID, stealthData)); } From b9c8a203cd12ae1275ad68a34937af9dd8643a3f Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Thu, 16 May 2019 03:36:00 -0500 Subject: [PATCH 02/36] [BDAP] Handle stealth address when sending link request and accept --- src/bdap/rpclinking.cpp | 69 ++++++++++++++++++++++++++++++++++------ src/wallet/rpcwallet.cpp | 12 ++++--- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/src/bdap/rpclinking.cpp b/src/bdap/rpclinking.cpp index 9f5400b639..e69c3a9264 100644 --- a/src/bdap/rpclinking.cpp +++ b/src/bdap/rpclinking.cpp @@ -30,7 +30,7 @@ #ifdef ENABLE_WALLET -extern void SendLinkingTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, const CScript& sendAddress, +extern void SendLinkingTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, const CScript& stealthScript, CWalletTx& wtxNew, const CAmount& nOPValue, const CAmount& nDataValue, const bool fUseInstantSend); static bool BuildJsonLinkRequestInfo(const CLinkRequest& link, const CDomainEntry& requestor, const CDomainEntry& recipient, UniValue& oLink) @@ -212,16 +212,40 @@ static UniValue SendLinkRequest(const JSONRPCRequest& request) CScript scriptPubKey; scriptPubKey << CScript::EncodeOP_N(OP_BDAP_NEW) << CScript::EncodeOP_N(OP_BDAP_LINK_REQUEST) << vchDHTPubKey << vchSharedPubKey << txLink.nExpireTime << OP_2DROP << OP_2DROP << OP_DROP; - CScript scriptDest = GetScriptForDestination(entryRecipient.GetLinkAddress().Get()); + + // Create OP Script with destination address + bool fStealthAddress = false; + CTxDestination dest = DecodeDestination(entryRecipient.GetLinkAddress().ToString()); + if (!IsValidDestination(dest)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid destination address %s", entryRecipient.GetLinkAddress().ToString())); + + CScript scriptDest; + std::vector vStealthData; + if (dest.type() == typeid(CStealthAddress)) + { + CStealthAddress sxAddr = boost::get(dest); + std::string sError; + if (0 != PrepareStealthOutput(sxAddr, scriptDest, vStealthData, sError)) { + LogPrintf("%s -- PrepareStealthOutput failed. Error = %s\n", __func__, sError); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid stealth destination address %s", entryRecipient.GetLinkAddress().ToString())); + } + fStealthAddress = true; + } + else + { + scriptDest = GetScriptForDestination(dest); + } scriptPubKey += scriptDest; - CScript scriptSend = GetScriptForDestination(entryRequestor.GetLinkAddress().Get()); + CScript stealthScript; + if (fStealthAddress) { + stealthScript << OP_RETURN << vStealthData; + } // check BDAP values std::string strMessage; if (!txLink.ValidateValues(strMessage)) throw std::runtime_error("BDAP_SEND_LINK_RPC_ERROR: ERRCODE: 4010 - Error validating link request values: " + strMessage); - // TODO (bdap): encrypt data before adding it to OP_RETURN. // Create BDAP OP_RETURN script CharString data; txLink.Serialize(data); @@ -245,10 +269,10 @@ static UniValue SendLinkRequest(const JSONRPCRequest& request) CWalletTx wtx; float fYears = ((float)nDays/365.25); CAmount nOperationFee = GetBDAPFee(scriptPubKey) * powf(3.1, fYears); - CAmount nDataFee = GetBDAPFee(scriptData) * powf(3.1, fYears); + CAmount nDataFee = (GetBDAPFee(scriptData) * powf(3.1, fYears)) + (GetBDAPFee(stealthScript) * powf(3.1, fYears)); bool fUseInstantSend = false; - SendLinkingTransaction(scriptData, scriptPubKey, scriptSend, wtx, nOperationFee, nDataFee, fUseInstantSend); + SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, nOperationFee, nDataFee, fUseInstantSend); txLink.txHash = wtx.GetHash(); UniValue oLink(UniValue::VOBJ); @@ -368,9 +392,34 @@ static UniValue SendLinkAccept(const JSONRPCRequest& request) CScript scriptPubKey; scriptPubKey << CScript::EncodeOP_N(OP_BDAP_NEW) << CScript::EncodeOP_N(OP_BDAP_LINK_ACCEPT) << vchDHTPubKey << vchSharedPubKey << txLinkAccept.nExpireTime << OP_2DROP << OP_2DROP << OP_DROP; - CScript scriptDest = GetScriptForDestination(entryRequestor.GetLinkAddress().Get()); + + // Create OP Script with destination address + bool fStealthAddress = false; + CTxDestination dest = DecodeDestination(entryAcceptor.GetLinkAddress().ToString()); + if (!IsValidDestination(dest)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid destination address %s", entryAcceptor.GetLinkAddress().ToString())); + + CScript scriptDest; + std::vector vStealthData; + if (dest.type() == typeid(CStealthAddress)) + { + CStealthAddress sxAddr = boost::get(dest); + std::string sError; + if (0 != PrepareStealthOutput(sxAddr, scriptDest, vStealthData, sError)) { + LogPrintf("%s -- PrepareStealthOutput failed. Error = %s\n", __func__, sError); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid stealth destination address %s", entryAcceptor.GetLinkAddress().ToString())); + } + fStealthAddress = true; + } + else + { + scriptDest = GetScriptForDestination(dest); + } scriptPubKey += scriptDest; - CScript scriptSend = GetScriptForDestination(entryAcceptor.GetLinkAddress().Get()); + CScript stealthScript; + if (fStealthAddress) { + stealthScript << OP_RETURN << vStealthData; + } // check BDAP values std::string strMessage; @@ -398,9 +447,9 @@ static UniValue SendLinkAccept(const JSONRPCRequest& request) CWalletTx wtx; float fYears = ((float)nDays/365.25); CAmount nOperationFee = GetBDAPFee(scriptPubKey) * powf(3.1, fYears); - CAmount nDataFee = GetBDAPFee(scriptData) * powf(3.1, fYears); + CAmount nDataFee = (GetBDAPFee(scriptData) * powf(3.1, fYears)) + (GetBDAPFee(stealthScript) * powf(3.1, fYears)); bool fUseInstantSend = false; - SendLinkingTransaction(scriptData, scriptPubKey, scriptSend, wtx, nOperationFee, nDataFee, fUseInstantSend); + SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, nOperationFee, nDataFee, fUseInstantSend); txLinkAccept.txHash = wtx.GetHash(); UniValue oLink(UniValue::VOBJ); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 9fe9b79233..1bf3e63ccb 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -500,7 +500,7 @@ void SendBDAPTransaction(const CScript& bdapDataScript, const CScript& bdapOPScr } } -void SendLinkingTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, const CScript& sendAddress, +void SendLinkingTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, const CScript& stealthScript, CWalletTx& wtxNew, const CAmount& nOPValue, const CAmount& nDataValue, const bool fUseInstantSend) { CAmount curBalance = pwalletMain->GetBalance(); @@ -524,12 +524,16 @@ void SendLinkingTransaction(const CScript& bdapDataScript, const CScript& bdapOP if (nDataValue > 0) { CRecipient recDataScript = {bdapDataScript, 0, false}; - vecSend.push_back(recDataScript); + vecSend.push_back(recDataScript); + if (stealthScript.size() > 0) { + CRecipient sendStealthData = {stealthScript, 0, false}; + vecSend.push_back(sendStealthData); + LogPrintf("Sending Stealth Script: %s\n", ScriptToAsmStr(stealthScript)); + } } - CRecipient recOPScript = {bdapOPScript, DEFAULT_MIN_RELAY_TX_FEE, false}; vecSend.push_back(recOPScript); - // TODO (bdap) Make sure sendAddress is used to fund the transaction. + // TODO (BDAP) Make sure it uses privatesend funds if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosInOut, strError, NULL, true, ALL_COINS, fUseInstantSend, true)) { if (DEFAULT_MIN_RELAY_TX_FEE + nFeeRequired > pwalletMain->GetBalance()) From 0e810ff5d87d53a7f4ce839137eafdb81915dcf6 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Thu, 16 May 2019 16:25:41 -0500 Subject: [PATCH 03/36] [BDAP] Fix createrawbdapaccount RPC after using stealth address --- src/bdap/rpcrawbdap.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/bdap/rpcrawbdap.cpp b/src/bdap/rpcrawbdap.cpp index 40756265ef..2b4c44002f 100644 --- a/src/bdap/rpcrawbdap.cpp +++ b/src/bdap/rpcrawbdap.cpp @@ -132,20 +132,30 @@ UniValue createrawbdapaccount(const JSONRPCRequest& request) scriptData << OP_RETURN << data; // Create script to fund link transaction for this account - CTxDestination destLinkAddress = DecodeDestination(sxAddr.ToString()); - CScript scriptLinkDestination; - scriptLinkDestination = GetScriptForDestination(destLinkAddress); + CScript scriptDest; + std::vector vStealthData; + std::string sError; + if (0 != PrepareStealthOutput(sxAddr, scriptDest, vStealthData, sError)) { + LogPrintf("%s -- PrepareStealthOutput failed. Error = %s\n", __func__, sError); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid stealth destination address %s", sxAddr.ToString())); + } + CScript stealthScript; + stealthScript << OP_RETURN << vStealthData; + // TODO (bdap): decrease this amount after BDAP fee structure is implemented. CAmount nLinkAmount(30 * COIN); - // Add the BDAP operation output - CTxOut outOP(nBDAPDeposit, scriptPubKey); - rawTx.vout.push_back(outOP); + // Add the Stealth OP return data + CTxOut outStealthData(0, stealthScript); + rawTx.vout.push_back(outStealthData); // Add the BDAP data output CTxOut outData(nBDAPRegistrationFee, scriptData); rawTx.vout.push_back(outData); + // Add the BDAP operation output + CTxOut outOP(nBDAPDeposit, scriptPubKey); + rawTx.vout.push_back(outOP); // Add the BDAP link funds output - CTxOut outLinkFunds(nLinkAmount, scriptLinkDestination); + CTxOut outLinkFunds(nLinkAmount, scriptDest); rawTx.vout.push_back(outLinkFunds); return EncodeHexTx(rawTx); From 63d0a86ada0d2a991bd780d165063b34270cd3fa Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Mon, 20 May 2019 17:30:32 -0500 Subject: [PATCH 04/36] [Fluid] Update maketoken help example --- src/fluid/rpcfluid.cpp | 43 ++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/fluid/rpcfluid.cpp b/src/fluid/rpcfluid.cpp index 72e4ba0874..7657326eb8 100644 --- a/src/fluid/rpcfluid.cpp +++ b/src/fluid/rpcfluid.cpp @@ -82,7 +82,8 @@ UniValue maketoken(const JSONRPCRequest& request) "\nArguments:\n" "1. \"string\" (string, required) String that has to be converted to hex.\n" "\nExamples:\n" + - HelpExampleCli("maketoken", "\"Hello World!\"") + HelpExampleRpc("maketoken", "\"Hello World!\"")); + HelpExampleCli("maketoken", "300000 1558389600 DNsEXkNEdzvNbR3zjaDa3TEVPtwR6Efbmd") + + HelpExampleRpc("maketoken", "300000 1558389600 DNsEXkNEdzvNbR3zjaDa3TEVPtwR6Efbmd")); } std::string result; @@ -103,7 +104,8 @@ UniValue gettime(const JSONRPCRequest& request) "gettime\n" "\nReturns the current Epoch time (https://www.epochconverter.com).\n" "\nExamples:\n" + - HelpExampleCli("gettime", "\"1535543210\"") + HelpExampleRpc("gettime", "\"1535543210\"")); + HelpExampleCli("gettime", "\"1535543210\"") + + HelpExampleRpc("gettime", "\"1535543210\"")); } return GetTime(); } @@ -117,7 +119,9 @@ UniValue getrawpubkey(const JSONRPCRequest& request) "\nArguments:\n" "1. \"address\" (string, required) The Dynamic Address from which the pubkey is to recovered.\n" "\nExamples:\n" + - HelpExampleCli("getrawpubkey", "D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf") + HelpExampleRpc("getrawpubkey", "D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf")); + HelpExampleCli("getrawpubkey", "D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf") + + HelpExampleRpc("getrawpubkey", "D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf")); + UniValue ret(UniValue::VOBJ); CDynamicAddress address(request.params[0].get_str()); @@ -145,7 +149,8 @@ UniValue burndynamic(const JSONRPCRequest& request) "1. \"amount\" (numeric, required) The amount of coins to be burned.\n" "2. \"address\" (string, optional) The address to burn funds. You must have the address private key in the wallet file.\n" "\nExamples:\n" + - HelpExampleCli("burndynamic", "\"123.456\" \"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\"") + HelpExampleRpc("burndynamic", "\"123.456\" \"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\"")); + HelpExampleCli("burndynamic", "\"123.456\" \"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\"") + + HelpExampleRpc("burndynamic", "\"123.456\" \"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\"")); if (!EnsureWalletIsAvailable(request.fHelp)) return NullUniValue; @@ -194,7 +199,9 @@ UniValue sendfluidtransaction(const JSONRPCRequest& request) "1. \"opcode\" (string, required) The Fluid operation to be executed.\n" "2. \"hexstring\" (string, required) The token for that opearation.\n" "\nExamples:\n" + - HelpExampleCli("sendfluidtransaction", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + HelpExampleRpc("sendfluidtransaction", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + HelpExampleCli("sendfluidtransaction", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + + HelpExampleRpc("sendfluidtransaction", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + CScript finalScript; EnsureWalletIsUnlocked(); @@ -232,7 +239,9 @@ UniValue signtoken(const JSONRPCRequest& request) "1. \"address\" (string, required) The Dynamic Address which will be used to sign.\n" "2. \"tokenkey\" (string, required) The token which has to be initially signed\n" "\nExamples:\n" + - HelpExampleCli("signtoken", "\"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + HelpExampleRpc("signtoken", "\"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + HelpExampleCli("signtoken", "\"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + + HelpExampleRpc("signtoken", "\"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + std::string result; CDynamicAddress address(request.params[0].get_str()); @@ -267,7 +276,9 @@ UniValue verifyquorum(const JSONRPCRequest& request) "\nArguments:\n" "1. \"tokenkey\" (string, required) The token which has to be initially signed\n" "\nExamples:\n" + - HelpExampleCli("verifyquorum", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + HelpExampleRpc("verifyquorum", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + HelpExampleCli("verifyquorum", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + + HelpExampleRpc("verifyquorum", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + std::string message; if (!fluid.CheckNonScriptQuorum(request.params[0].get_str(), message, false)) @@ -286,7 +297,9 @@ UniValue consenttoken(const JSONRPCRequest& request) "1. \"address\" (string, required) The Dynamic Address which will be used to give consent.\n" "2. \"tokenkey\" (string, required) The token which has to be been signed by one party\n" "\nExamples:\n" + - HelpExampleCli("consenttoken", "\"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + HelpExampleRpc("consenttoken", "\"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + HelpExampleCli("consenttoken", "\"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + + HelpExampleRpc("consenttoken", "\"D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + std::string result; CDynamicAddress address(request.params[0].get_str()); @@ -324,7 +337,9 @@ UniValue getfluidhistoryraw(const JSONRPCRequest& request) " \"fluid_command\" (string) The operation code and raw fluid script command\n" "}, ...\n" "\nExamples\n" + - HelpExampleCli("getfluidhistoryraw", "") + HelpExampleRpc("getfluidhistoryraw", "")); + HelpExampleCli("getfluidhistoryraw", "") + + HelpExampleRpc("getfluidhistoryraw", "")); + UniValue ret(UniValue::VOBJ); CAmount totalMintedCoins = 0; CAmount totalFluidTxCost = 0; @@ -427,7 +442,9 @@ UniValue getfluidhistory(const JSONRPCRequest& request) " }, ...\n" "]\n" "\nExamples\n" + - HelpExampleCli("getfluidhistory", "") + HelpExampleRpc("getfluidhistory", "")); + HelpExampleCli("getfluidhistory", "") + + HelpExampleRpc("getfluidhistory", "")); + UniValue ret(UniValue::VOBJ); CAmount totalMintedCoins = 0; CAmount totalFluidTxCost = 0; @@ -557,7 +574,8 @@ UniValue getfluidsovereigns(const JSONRPCRequest& request) " \"sovereign address\" (string) A sovereign address with permission to co-sign a fluid command\n" "}, ...\n" "\nExamples\n" + - HelpExampleCli("getfluidsovereigns", "") + HelpExampleRpc("getfluidsovereigns", "")); + HelpExampleCli("getfluidsovereigns", "") + + HelpExampleRpc("getfluidsovereigns", "")); UniValue ret(UniValue::VOBJ); std::vector sovereignEntries; @@ -596,7 +614,8 @@ UniValue readfluidtoken(const JSONRPCRequest& request) " \"sovereign address\" (string) A sovereign address with permission to co-sign a fluid command\n" "}, ...\n" "\nExamples\n" + - HelpExampleCli("readfluidtoken", "tokenkey") + HelpExampleRpc("readfluidtoken", "tokenkey")); + HelpExampleCli("readfluidtoken", "tokenkey") + + HelpExampleRpc("readfluidtoken", "tokenkey")); UniValue ret(UniValue::VOBJ); std::string strFluidToken = request.params[0].get_str(); From 6bb7c1613f3758292c6795912b57e3b19bc1843a Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Mon, 20 May 2019 17:31:29 -0500 Subject: [PATCH 05/36] [Fluid] Remove getrawpubkey RPC command --- src/fluid/rpcfluid.cpp | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/fluid/rpcfluid.cpp b/src/fluid/rpcfluid.cpp index 7657326eb8..5954dd54e1 100644 --- a/src/fluid/rpcfluid.cpp +++ b/src/fluid/rpcfluid.cpp @@ -110,34 +110,6 @@ UniValue gettime(const JSONRPCRequest& request) return GetTime(); } -UniValue getrawpubkey(const JSONRPCRequest& request) -{ - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - "getrawpubkey \"address\"\n" - "\nGet (un)compressed raw public key of an address of the wallet\n" - "\nArguments:\n" - "1. \"address\" (string, required) The Dynamic Address from which the pubkey is to recovered.\n" - "\nExamples:\n" + - HelpExampleCli("getrawpubkey", "D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf") + - HelpExampleRpc("getrawpubkey", "D5nRy9Tf7Zsef8gMGL2fhWA9ZslrP4K5tf")); - - UniValue ret(UniValue::VOBJ); - - CDynamicAddress address(request.params[0].get_str()); - bool isValid = address.IsValid(); - - if (isValid) { - CTxDestination dest = address.Get(); - CScript scriptPubKey = GetScriptForDestination(dest); - ret.push_back(Pair("pubkey", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); - } else { - ret.push_back(Pair("errors", "Dynamic address is not valid!")); - } - - return ret; -} - UniValue burndynamic(const JSONRPCRequest& request) { @@ -678,7 +650,6 @@ static const CRPCCommand commands[] = {"fluid", "sendfluidtransaction", &sendfluidtransaction, true, {"opcode", "hexstring"}}, {"fluid", "signtoken", &signtoken, true, {"address", "tokenkey"}}, {"fluid", "consenttoken", &consenttoken, true, {"address", "tokenkey"}}, - {"fluid", "getrawpubkey", &getrawpubkey, true, {"address"}}, {"fluid", "burndynamic", &burndynamic, true, {"amount", "address"}}, #endif //ENABLE_WALLET {"fluid", "verifyquorum", &verifyquorum, true, {"tokenkey"}}, From bce235a5e666b50c079ddb19941bb43881d7799e Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Mon, 20 May 2019 19:06:52 -0500 Subject: [PATCH 06/36] [Fluid] Add banaccountstoken for revoking BDAP accounts with fluid --- src/bdap/domainentrydb.cpp | 8 ++++++ src/bdap/domainentrydb.h | 1 + src/fluid/rpcfluid.cpp | 51 +++++++++++++++++++++++++++++++++++++- src/rpcprotocol.h | 4 +++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/bdap/domainentrydb.cpp b/src/bdap/domainentrydb.cpp index ffa02c942a..b50becff66 100644 --- a/src/bdap/domainentrydb.cpp +++ b/src/bdap/domainentrydb.cpp @@ -43,6 +43,14 @@ bool GetDomainEntryPubKey(const std::vector& vchPubKey, CDomainEn return !entry.IsNull(); } +bool DomainEntryExists(const std::vector& vchObjectPath) +{ + if (!pDomainEntryDB) + return false; + + return pDomainEntryDB->DomainEntryExists(vchObjectPath); +} + bool CDomainEntryDB::AddDomainEntry(const CDomainEntry& entry, const int op) { bool writeState = false; diff --git a/src/bdap/domainentrydb.h b/src/bdap/domainentrydb.h index 8a665ca883..40ff333412 100644 --- a/src/bdap/domainentrydb.h +++ b/src/bdap/domainentrydb.h @@ -41,6 +41,7 @@ class CDomainEntryDB : public CDBWrapper { bool GetDomainEntry(const std::vector& vchObjectPath, CDomainEntry& entry); bool GetDomainEntryPubKey(const std::vector& vchPubKey, CDomainEntry& entry); +bool DomainEntryExists(const std::vector& vchObjectPath); bool CheckDomainEntryDB(); bool FlushLevelDB(); void CleanupLevelDB(int& nRemoved); diff --git a/src/fluid/rpcfluid.cpp b/src/fluid/rpcfluid.cpp index 5954dd54e1..ebeaaf19f9 100644 --- a/src/fluid/rpcfluid.cpp +++ b/src/fluid/rpcfluid.cpp @@ -2,8 +2,11 @@ #include "fluid.h" +#include "bdap/domainentrydb.h" +#include "bdap/utils.h" #include "chain.h" #include "core_io.h" +#include "dynode-sync.h" #include "fluiddb.h" #include "fluiddynode.h" #include "fluidmining.h" @@ -14,6 +17,7 @@ #include "net.h" #include "netbase.h" #include "rpcserver.h" +#include "spork.h" #include "timedata.h" #include "util.h" #include "utilmoneystr.h" @@ -24,6 +28,8 @@ #include +#include + extern bool EnsureWalletIsAvailable(bool avoidException); extern void SendCustomTransaction(const CScript& generatedScript, CWalletTx& wtxNew, CAmount nValue, bool fUseInstantSend = false); extern void SendBurnTransaction(const CScript& burnScript, CWalletTx& wtxNew, const CAmount& nValue, const CScript& sendAddress); @@ -67,6 +73,8 @@ opcodetype getOpcodeFromString(std::string input) 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; @@ -85,8 +93,8 @@ UniValue maketoken(const JSONRPCRequest& request) HelpExampleCli("maketoken", "300000 1558389600 DNsEXkNEdzvNbR3zjaDa3TEVPtwR6Efbmd") + HelpExampleRpc("maketoken", "300000 1558389600 DNsEXkNEdzvNbR3zjaDa3TEVPtwR6Efbmd")); } - std::string result; + std::string result = ""; for (uint32_t iter = 0; iter != request.params.size(); iter++) { result += request.params[iter].get_str() + SubDelimiter; } @@ -97,6 +105,46 @@ UniValue maketoken(const JSONRPCRequest& request) return result; } +UniValue banaccountstoken(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() < 2) { + throw std::runtime_error( + "banaccountstoken \"FQDN\"\n" + "\nCreates a token to ban a list of BDAP accounts\n" + "\nArguments:\n" + "1. \"timestamp\" (int, required) Fluid transaction timestamp.\n" + "2. \"account_fqdn1\" (string, required) The BDAP account fully qualified domain name.\n" + "\nExamples:\n" + + HelpExampleCli("banaccountstoken", "1558389600 \"badaccount@public.bdap.io\" \"banme@public.bdap.io\"") + + HelpExampleRpc("banaccountstoken", "1558389600 \"badaccount@public.bdap.io\" \"banme@public.bdap.io\"")); + } + + if (!sporkManager.IsSporkActive(SPORK_30_ACTIVATE_BDAP)) + throw JSONRPCError(RPC_SPORK_INACTIVE, strprintf("Can not create BDAP revoke account token until SPORK_30_ACTIVATE_BDAP is active.")); + + if (!dynodeSync.IsBlockchainSynced()) + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, strprintf("Can not create BDAP revoke account token until the blockchain is fully synced.")); + + std::string strResult; + for (uint32_t iter = 0; iter != request.params.size(); iter++) { + if (iter == 0) { + strResult += request.params[iter].get_str() + SubDelimiter; + } else { + std::string strAccountFQDN = request.params[iter].get_str(); + ToLowerCase(strAccountFQDN); + if (!DomainEntryExists(vchFromString(strAccountFQDN))) + throw JSONRPCError(RPC_BDAP_ACCOUNT_NOT_FOUND, strprintf("The %s BDAP account was not found", strAccountFQDN)); + + // base64 encode the BDAP account FQDN so that the @ character doesn't interfere with the standard token delimiter + strResult += EncodeBase64(strAccountFQDN) + SubDelimiter; + } + } + + strResult.pop_back(); + fluid.ConvertToHex(strResult); + return strResult; +} + UniValue gettime(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) { @@ -659,6 +707,7 @@ static const CRPCCommand commands[] = {"fluid", "getfluidsovereigns", &getfluidsovereigns, true, {}}, {"fluid", "gettime", &gettime, true, {}}, {"fluid", "readfluidtoken", &readfluidtoken, true, {"tokenkey"}}, + {"fluid", "banaccountstoken", &banaccountstoken, true, {"timestamp", "account1", "account2"}}, }; void RegisterFluidRPCCommands(CRPCTable& tableRPC) diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index ced2471ab6..fd9c83a139 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -46,6 +46,7 @@ enum RPCErrorCode { RPC_OUT_OF_MEMORY = -7, //! Ran out of memory during operation RPC_INVALID_PARAMETER = -8, //! Invalid, missing or duplicate parameter RPC_DATABASE_ERROR = -20, //! Database error + RPC_SPORK_INACTIVE = -21, //! Required spork inactivate RPC_DESERIALIZATION_ERROR = -22, //! Error parsing or validating structure in raw format RPC_VERIFY_ERROR = -25, //! General error during transaction or block submission RPC_VERIFY_REJECTED = -26, //! Transaction or block was rejected by network rules @@ -92,6 +93,9 @@ enum RPCErrorCode { RPC_DHT_INVALID_RECORD = -406, //! Invalid DHT record information RPC_DHT_RECORD_LOCKED = -407, //! DHT record locked RPC_DHT_PUBKEY_MISMATCH = -408, //! DHT public key mismatch + //! Fluid errors + RPC_FLUID_ERROR = -500, //! Unspecified fluid error + RPC_FLUID_INVALID_TIMESTAMP = -501, //! Invalid fluid timestamp }; UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id); From cba1b556baee0e3de7cae9a0694c477fe0ba8b1e Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Tue, 21 May 2019 15:30:21 -0500 Subject: [PATCH 07/36] [Fluid] Handle OP_BDAP_REVOKE as fluid command --- src/fluid/fluid.cpp | 54 ++++++++++++++++++++++-------------------- src/fluid/fluid.h | 24 +++++++++---------- src/fluid/rpcfluid.cpp | 17 +++++++------ src/script/script.h | 5 +++- 4 files changed, 52 insertions(+), 48 deletions(-) diff --git a/src/fluid/fluid.cpp b/src/fluid/fluid.cpp index 4911b0f928..9dcd24db6b 100644 --- a/src/fluid/fluid.cpp +++ b/src/fluid/fluid.cpp @@ -25,7 +25,7 @@ extern CWallet* pwalletMain; bool IsTransactionFluid(const CScript& txOut) { - return (txOut.IsProtocolInstruction(MINT_TX) || txOut.IsProtocolInstruction(DYNODE_MODFIY_TX) || txOut.IsProtocolInstruction(MINING_MODIFY_TX)); + 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) @@ -48,6 +48,8 @@ int GetFluidOpCode(const CScript& fluidScript) 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; } @@ -92,7 +94,7 @@ std::vector InitialiseAddresses() } /** Checks if any given address is a current master key (invoked by RPC) */ -bool CFluid::IsGivenKeyMaster(CDynamicAddress inputKey) +bool CFluid::IsGivenKeyMaster(const CDynamicAddress& inputKey) { if (!inputKey.IsValid()) { return false; @@ -140,7 +142,7 @@ std::vector > CFluidParameters::InitialiseAddressChar } /** Checks fluid transactoin operation script amount for invalid values. */ -bool CFluid::CheckFluidOperationScript(const CScript& fluidScriptPubKey, const int64_t timeStamp, std::string& errorMessage, bool fSkipTimeStampCheck) +bool CFluid::CheckFluidOperationScript(const CScript& fluidScriptPubKey, const int64_t& timeStamp, std::string& errorMessage, const bool fSkipTimeStampCheck) { std::string strFluidOpScript = ScriptToAsmStr(fluidScriptPubKey); std::string verificationWithoutOpCode = GetRidOfScriptStatement(strFluidOpScript); @@ -210,7 +212,7 @@ bool CFluid::CheckIfExistsInMemPool(const CTxMemPool& pool, const CScript& fluid } /** Checks whether as to parties have actually signed it - please use this with ones with the OP_CODE */ -bool CFluid::CheckIfQuorumExists(const std::string consentToken, std::string& message, bool individual) +bool CFluid::CheckIfQuorumExists(const std::string& consentToken, std::string& message, const bool individual) { std::vector fluidSovereigns; std::pair keyOne; @@ -224,32 +226,32 @@ bool CFluid::CheckIfQuorumExists(const std::string consentToken, std::string& me if (pindex != NULL) { //TODO fluid - fluidSovereigns = InitialiseAddresses(); //pindex->fluidParams.fluidSovereigns; + fluidSovereigns = InitialiseAddresses(); } else fluidSovereigns = InitialiseAddresses(); for (const std::string& address : fluidSovereigns) { - CDynamicAddress attemptKey, xKey(address); + CDynamicAddress attemptKey, xAddress(address); - if (!xKey.IsValid()) + if (!xAddress.IsValid()) return false; - if (GenericVerifyInstruction(consentToken, attemptKey, message, 1) && xKey == attemptKey) { + if (GenericVerifyInstruction(consentToken, attemptKey, message, 1) && xAddress == attemptKey) { keyOne = std::make_pair(attemptKey.ToString(), true); } - if (GenericVerifyInstruction(consentToken, attemptKey, message, 2) && xKey == attemptKey) { + if (GenericVerifyInstruction(consentToken, attemptKey, message, 2) && xAddress == attemptKey) { keyTwo = std::make_pair(attemptKey.ToString(), true); } - if (GenericVerifyInstruction(consentToken, attemptKey, message, 3) && xKey == attemptKey) { + if (GenericVerifyInstruction(consentToken, attemptKey, message, 3) && xAddress == attemptKey) { keyThree = std::make_pair(attemptKey.ToString(), true); } } bool fValid = (keyOne.first.ToString() != keyTwo.first.ToString() && keyTwo.first.ToString() != keyThree.first.ToString() && keyOne.first.ToString() != keyThree.first.ToString()); - LogPrint("fluid", "CheckIfQuorumExists(): Addresses validating this consent token are: %s, %s and %s\n", keyOne.first.ToString(), keyTwo.first.ToString(), keyThree.first.ToString()); + LogPrintf("CheckIfQuorumExists(): Addresses validating this consent token are: %s, %s and %s\n", keyOne.first.ToString(), keyTwo.first.ToString(), keyThree.first.ToString()); if (individual) return (keyOne.second || keyTwo.second || keyThree.second); @@ -261,14 +263,14 @@ bool CFluid::CheckIfQuorumExists(const std::string consentToken, std::string& me /** Checks whether as to parties have actually signed it - please use this with ones **without** the OP_CODE */ -bool CFluid::CheckNonScriptQuorum(const std::string consentToken, std::string& message, bool individual) +bool CFluid::CheckNonScriptQuorum(const std::string& consentToken, std::string& message, const bool individual) { std::string result = "12345 " + consentToken; return CheckIfQuorumExists(result, message, individual); } /** It will append a signature of the new information */ -bool CFluid::GenericConsentMessage(std::string message, std::string& signedString, CDynamicAddress signer) +bool CFluid::GenericConsentMessage(const std::string& message, std::string& signedString, const CDynamicAddress& signer) { std::string token, digest; @@ -280,13 +282,13 @@ bool CFluid::GenericConsentMessage(std::string message, std::string& signedStrin if (token == "") return false; - - ConvertToString(message); - + if (!SignTokenMessage(signer, token, digest, false)) return false; - signedString = StitchString(message, digest, false); + std::string strConvertedMessage = message; + ConvertToString(strConvertedMessage); + signedString = StitchString(strConvertedMessage, digest, false); ConvertToHex(signedString); @@ -317,7 +319,7 @@ bool CFluid::ExtractCheckTimestamp(const std::string consentToken, const int64_t return true; } -bool CFluid::ProcessFluidToken(const std::string consentToken, std::vector& ptrs, int strVecNo) +bool CFluid::ProcessFluidToken(const std::string& consentToken, std::vector& ptrs, const int& strVecNo) { std::string consentTokenNoScript = GetRidOfScriptStatement(consentToken); @@ -360,13 +362,13 @@ bool CFluid::GenericParseNumber(const std::string consentToken, const int64_t ti return true; } -CDynamicAddress CFluid::GetAddressFromDigestSignature(const std::string digestSignature, const std::string messageTokenKey) +CDynamicAddress CFluid::GetAddressFromDigestSignature(const std::string& digestSignature, const std::string& messageTokenKey) { bool fInvalid = false; std::vector vchSig = DecodeBase64(digestSignature.c_str(), &fInvalid); if (fInvalid) { - LogPrintf("GenericVerifyInstruction(): Digest Signature Found Invalid, Signature: %s \n", digestSignature); + LogPrintf("GetAddressFromDigestSignature(): Digest Signature Found Invalid, Signature: %s \n", digestSignature); return nullptr; } @@ -377,7 +379,7 @@ CDynamicAddress CFluid::GetAddressFromDigestSignature(const std::string digestSi CPubKey pubkey; if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) { - LogPrintf("GenericVerifyInstruction(): Public Key Recovery Failed! Hash: %s\n", ss.GetHash().ToString()); + LogPrintf("GetAddressFromDigestSignature(): Public Key Recovery Failed! Hash: %s\n", ss.GetHash().ToString()); return nullptr; } CDynamicAddress newAddress; @@ -386,7 +388,7 @@ CDynamicAddress CFluid::GetAddressFromDigestSignature(const std::string digestSi } /** Individually checks the validity of an instruction */ -bool CFluid::GenericVerifyInstruction(const std::string consentToken, CDynamicAddress& signer, std::string& messageTokenKey, int whereToLook) +bool CFluid::GenericVerifyInstruction(const std::string& consentToken, CDynamicAddress& signer, std::string& messageTokenKey, const int& whereToLook) { std::string consentTokenNoScript = GetRidOfScriptStatement(consentToken); messageTokenKey = ""; @@ -408,7 +410,7 @@ bool CFluid::GenericVerifyInstruction(const std::string consentToken, CDynamicAd return true; } -bool CFluid::ParseMintKey(const int64_t nTime, CDynamicAddress& destination, CAmount& coinAmount, std::string uniqueIdentifier, bool txCheckPurpose) +bool CFluid::ParseMintKey(const int64_t& nTime, CDynamicAddress& destination, CAmount& coinAmount, const std::string& uniqueIdentifier, const bool txCheckPurpose) { std::vector ptrs; @@ -528,7 +530,7 @@ void CFluid::AddFluidTransactionsToRecord(const CBlockIndex* pblockindex, std::v } /* Check if transaction exists in record */ -bool CFluid::CheckTransactionInRecord(CScript fluidInstruction, CBlockIndex* pindex) +bool CFluid::CheckTransactionInRecord(const CScript& fluidInstruction, CBlockIndex* pindex) { if (IsTransactionFluid(fluidInstruction)) { std::string verificationString; @@ -567,7 +569,7 @@ bool CFluid::CheckTransactionInRecord(CScript fluidInstruction, CBlockIndex* pin } /* Insertion of transaction script to record */ -bool CFluid::InsertTransactionToRecord(CScript fluidInstruction, std::vector& transactionRecord) +bool CFluid::InsertTransactionToRecord(const CScript& fluidInstruction, std::vector& transactionRecord) { std::string verificationString; @@ -615,7 +617,7 @@ CAmount GetStandardDynodePayment(const int nHeight) } } -bool CFluid::ValidationProcesses(CValidationState& state, CScript txOut, CAmount txValue) +bool CFluid::ValidationProcesses(CValidationState& state, const CScript& txOut, const CAmount& txValue) { std::string message; CAmount mintAmount; diff --git a/src/fluid/fluid.h b/src/fluid/fluid.h index e08fbd42b0..cdbce55325 100644 --- a/src/fluid/fluid.h +++ b/src/fluid/fluid.h @@ -49,34 +49,34 @@ class CFluid : public CFluidParameters, public COperations void AddFluidTransactionsToRecord(const CBlockIndex* pblockindex, std::vector& transactionRecord); void ReplaceFluidSovereigns(const CBlockHeader& blockHeader, std::vector& fluidSovereigns); - bool IsGivenKeyMaster(CDynamicAddress inputKey); + bool IsGivenKeyMaster(const CDynamicAddress& inputKey); - bool CheckFluidOperationScript(const CScript& fluidScriptPubKey, const int64_t timeStamp, std::string& errorMessage, bool fSkipTimeStampCheck = false); + 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 CheckIfQuorumExists(const std::string consentToken, std::string& message, bool individual = false); - bool CheckNonScriptQuorum(const std::string consentToken, std::string& message, bool individual = false); - bool CheckTransactionInRecord(CScript fluidInstruction, CBlockIndex* pindex = NULL); + 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); - bool GenericConsentMessage(std::string message, std::string& signedString, CDynamicAddress signer); + bool GenericConsentMessage(const std::string& message, std::string& signedString, const CDynamicAddress& signer); bool GenericParseNumber(const std::string consentToken, const int64_t timeStamp, CAmount& howMuch, bool txCheckPurpose = false); - bool GenericVerifyInstruction(const std::string consentToken, CDynamicAddress& signer, std::string& messageTokenKey, int whereToLook = 1); + bool GenericVerifyInstruction(const std::string& consentToken, CDynamicAddress& signer, std::string& messageTokenKey, const int& whereToLook = 1); bool ExtractCheckTimestamp(const std::string consentToken, const int64_t timeStamp); - bool ParseMintKey(const int64_t nTime, CDynamicAddress& destination, CAmount& coinAmount, std::string uniqueIdentifier, bool txCheckPurpose = false); - bool ProcessFluidToken(const std::string consentToken, std::vector& ptrs, int strVecNo); + bool ParseMintKey(const int64_t& nTime, CDynamicAddress& destination, CAmount& coinAmount, const std::string& uniqueIdentifier, const bool txCheckPurpose = false); + bool ProcessFluidToken(const std::string& consentToken, std::vector& ptrs, const int& strVecNo); bool GetMintingInstructions(const CBlockIndex* pblockindex, CDynamicAddress& toMintAddress, CAmount& mintAmount); bool GetProofOverrideRequest(const CBlockIndex* pblockindex, CAmount& howMuch); bool GetDynodeOverrideRequest(const CBlockIndex* pblockindex, CAmount& howMuch); - bool ValidationProcesses(CValidationState& state, CScript txOut, CAmount txValue); + bool ValidationProcesses(CValidationState& state, const CScript& txOut, const CAmount& txValue); bool CheckTransactionToBlock(const CTransaction& transaction, const CBlockHeader& blockHeader); bool CheckTransactionToBlock(const CTransaction& transaction, const uint256 hash); bool ProvisionalCheckTransaction(const CTransaction& transaction); - bool InsertTransactionToRecord(CScript fluidInstruction, std::vector& transactionRecord); - CDynamicAddress GetAddressFromDigestSignature(const std::string digestSignature, const std::string messageTokenKey); + bool InsertTransactionToRecord(const CScript& fluidInstruction, std::vector& transactionRecord); + CDynamicAddress GetAddressFromDigestSignature(const std::string& digestSignature, const std::string& messageTokenKey); }; /** Standard Reward Payment Determination Functions */ diff --git a/src/fluid/rpcfluid.cpp b/src/fluid/rpcfluid.cpp index ebeaaf19f9..3363432901 100644 --- a/src/fluid/rpcfluid.cpp +++ b/src/fluid/rpcfluid.cpp @@ -208,9 +208,6 @@ opcodetype negatif = OP_RETURN; UniValue sendfluidtransaction(const JSONRPCRequest& request) { - if (!EnsureWalletIsAvailable(request.fHelp)) - return NullUniValue; - if (request.fHelp || request.params.size() != 2) throw std::runtime_error( "sendfluidtransaction \"OP_MINT || OP_REWARD_DYNODE || OP_REWARD_MINING\" \"hexstring\"\n" @@ -219,8 +216,11 @@ UniValue sendfluidtransaction(const JSONRPCRequest& request) "1. \"opcode\" (string, required) The Fluid operation to be executed.\n" "2. \"hexstring\" (string, required) The token for that opearation.\n" "\nExamples:\n" + - HelpExampleCli("sendfluidtransaction", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + - HelpExampleRpc("sendfluidtransaction", "\"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + HelpExampleCli("sendfluidtransaction", "\"OP_MINT\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"") + + HelpExampleRpc("sendfluidtransaction", "\"OP_MINT\" \"3130303030303030303030303a3a313439393336353333363a3a445148697036443655376d46335761795a32747337794478737a71687779367a5a6a20494f42447a557167773\"")); + + if (!EnsureWalletIsAvailable(request.fHelp)) + return NullUniValue; CScript finalScript; @@ -231,16 +231,15 @@ UniValue sendfluidtransaction(const JSONRPCRequest& request) throw std::runtime_error("OP_CODE is either not a Fluid OP_CODE or is invalid"); if (!IsHex(request.params[1].get_str())) - throw std::runtime_error("Hex isn't even valid!"); + throw std::runtime_error("Token hex is invalid"); else finalScript = CScript() << opcode << ParseHex(request.params[1].get_str()); std::string message; - if (!fluid.CheckIfQuorumExists(ScriptToAsmStr(finalScript), message)) - throw std::runtime_error("Instruction does not meet required quorum for validity"); + throw std::runtime_error(strprintf("Instruction does not meet required quorum for validity. %s", message)); - if (opcode == OP_MINT || opcode == OP_REWARD_MINING || opcode == OP_REWARD_DYNODE) { + 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); return wtx.GetHash().GetHex(); diff --git a/src/script/script.h b/src/script/script.h index bc142a8e7f..5750737e65 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -192,11 +192,11 @@ enum opcodetype { OP_UPDATE_FEES = 0xc6, OP_FREEZE_ADDRESS = 0xc7, OP_RELEASE_ADDRESS = 0xc8, + OP_BDAP_REVOKE = 0xc9, // = BDAP delete using fluid protocol // BDAP directory access, user identity and certificate system OP_BDAP_NEW = 0x01, // = BDAP create new entry OP_BDAP_DELETE = 0x02, // = BDAP user delete entry - OP_BDAP_REVOKE = 0x03, // = BDAP delete using fluid protocol OP_BDAP_MODIFY = 0x04, // = BDAP update entry OP_BDAP_MODIFY_RDN = 0x05, // = move BDAP entry OP_BDAP_ACCOUNT_ENTRY = 0x06, // = BDAP domain account entry (users and groups) @@ -678,6 +678,9 @@ class CScript : public CScriptBase 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!"); } From 34bda7097559240a1dd1678661c77c8fe99a9f69 Mon Sep 17 00:00:00 2001 From: dave-mann <19619811+dave-mann@users.noreply.github.com> Date: Tue, 21 May 2019 16:27:57 -0700 Subject: [PATCH 08/36] [Wallet] Add ability to upgrade wallet with corresponding Ed25519 keys if an older version is detected. WIP --- src/wallet/wallet.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++ src/wallet/wallet.h | 1 + 2 files changed, 81 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 13d5a39b91..2ac1d160a5 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4464,6 +4464,67 @@ size_t CWallet::EdKeypoolCountInternalKeys() return setInternalEdKeyPool.size(); } +bool CWallet::SyncEdKeyPool() +{ + CWalletDB walletdb(strWalletFile); + CKeyPool keypool; + CPubKey retrievedPubKey; + CKey retrievedKey; + + CKeyPool keypool2; + CPubKey retrievedPubKey2; + CKey retrievedKey2; + + LogPrintf("DEBUGGER WALLET %s - made it here!\n", __func__); + + + for (int64_t nIndex : setInternalKeyPool) { + if (!walletdb.ReadPool(nIndex, keypool)) { + throw std::runtime_error(std::string(__func__) + ": read failed"); + } + retrievedPubKey = keypool.vchPubKey; + GetKey(retrievedPubKey.GetID(), retrievedKey); + + // int64_t nEnd = 1; + // if (!setInternalEdKeyPool.empty()) { + // nEnd = *(--setInternalEdKeyPool.end()) + 1; + // } + + if (!walletdb.WriteEdPool(nIndex, CEdKeyPool(GenerateNewEdKey(0, true, retrievedKey), true))) + throw std::runtime_error("SyncEdKeyPool(): writing generated key failed"); + + setInternalEdKeyPool.insert(nIndex); + + LogPrintf("edkeypool added key %d, size=%u, internal=%d\n", nIndex, setInternalEdKeyPool.size() + setExternalEdKeyPool.size(), 1); + } + + for (int64_t nIndex : setExternalKeyPool) { + if (!walletdb.ReadPool(nIndex, keypool2)) { + throw std::runtime_error(std::string(__func__) + ": read failed"); + } + retrievedPubKey2 = keypool2.vchPubKey; + GetKey(retrievedPubKey2.GetID(), retrievedKey2); + + // int64_t nEnd = 1; + // if (!setInternalEdKeyPool.empty()) { + // nEnd = *(--setInternalEdKeyPool.end()) + 1; + // } + + if (!walletdb.WriteEdPool(nIndex, CEdKeyPool(GenerateNewEdKey(0, false, retrievedKey2), false))) + throw std::runtime_error("SyncEdKeyPool(): writing generated key failed"); + + setExternalEdKeyPool.insert(nIndex); + + LogPrintf("edkeypool added key %d, size=%u, internal=%d\n", nIndex, setInternalEdKeyPool.size() + setExternalEdKeyPool.size(), 0); + } + + return true; + +} //SyncEdKeyPool + + + + bool CWallet::TopUpKeyPool(unsigned int kpSize) { { @@ -5625,6 +5686,25 @@ bool CWallet::InitLoadWallet() } pwalletMain = pwallet; + LogPrintf("DEBUGGER WALLET %s - wallet version [%d]\n", __func__,pwallet->GetVersion()); + + if (pwallet->GetVersion() < FEATURE_HD) { + if (!pwallet->SyncEdKeyPool()) { + LogPrintf("DEBUGGER WALLET %s - SyncEdKeyPool is false\n", __func__); + } + else { + LogPrintf("DEBUGGER WALLET %s - SyncEdKeyPool is true\n", __func__); + LogPrintf("DEBUGGER WALLET %s - Upgrading wallet version\n", __func__); + pwallet->SetMinVersion(FEATURE_HD); + + LogPrintf("setExternalKeyPool.size() = %u\n", pwallet->KeypoolCountExternalKeys()); + LogPrintf("setInternalKeyPool.size() = %u\n", pwallet->KeypoolCountInternalKeys()); + LogPrintf("setExternalEdKeyPool.size() = %u\n", pwallet->EdKeypoolCountExternalKeys()); + LogPrintf("setInternalEdKeyPool.size() = %u\n", pwallet->EdKeypoolCountInternalKeys()); + } + } + + ProcessLinkQueue(); // Process links in queue. return true; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index e6f5ec0a77..4e4caf4874 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1133,6 +1133,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface size_t KeypoolCountInternalKeys(); size_t EdKeypoolCountExternalKeys(); size_t EdKeypoolCountInternalKeys(); + bool SyncEdKeyPool(); bool TopUpKeyPool(unsigned int kpSize = 0); bool TopUpEdKeyPool(unsigned int kpSize = 0); bool TopUpKeyPoolCombo(unsigned int kpSize = 0); From 95f0700f3f57083766796a416228590284a40679 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Tue, 21 May 2019 23:50:48 -0500 Subject: [PATCH 09/36] [Fluid] Add ban BDAP account to consensus checking --- src/bdap/domainentrydb.cpp | 10 +++ src/bdap/domainentrydb.h | 1 + src/fluid/fluid.cpp | 126 +++++++++++++++++++++++++++++-------- src/fluid/fluid.h | 5 +- src/fluid/operations.cpp | 9 ++- src/fluid/operations.h | 8 +-- src/validation.cpp | 23 ++++++- 7 files changed, 144 insertions(+), 38 deletions(-) diff --git a/src/bdap/domainentrydb.cpp b/src/bdap/domainentrydb.cpp index b50becff66..927ef14f40 100644 --- a/src/bdap/domainentrydb.cpp +++ b/src/bdap/domainentrydb.cpp @@ -51,6 +51,16 @@ bool DomainEntryExists(const std::vector& vchObjectPath) return pDomainEntryDB->DomainEntryExists(vchObjectPath); } +bool DeleteDomainEntry(const CDomainEntry& entry) +{ + if (!pDomainEntryDB) + return false; + + bool fEraseEntryResult = pDomainEntryDB->EraseDomainEntry(entry.vchFullObjectPath()); + bool fErasePubKeyResult = pDomainEntryDB->EraseDomainEntryPubKey(entry.DHTPublicKey);; + return (fEraseEntryResult && fErasePubKeyResult); +} + bool CDomainEntryDB::AddDomainEntry(const CDomainEntry& entry, const int op) { bool writeState = false; diff --git a/src/bdap/domainentrydb.h b/src/bdap/domainentrydb.h index 40ff333412..574b7c9675 100644 --- a/src/bdap/domainentrydb.h +++ b/src/bdap/domainentrydb.h @@ -42,6 +42,7 @@ class CDomainEntryDB : public CDBWrapper { bool GetDomainEntry(const std::vector& vchObjectPath, CDomainEntry& entry); bool GetDomainEntryPubKey(const std::vector& vchPubKey, CDomainEntry& entry); bool DomainEntryExists(const std::vector& vchObjectPath); +bool DeleteDomainEntry(const CDomainEntry& entry); bool CheckDomainEntryDB(); bool FlushLevelDB(); void CleanupLevelDB(int& nRemoved); diff --git a/src/fluid/fluid.cpp b/src/fluid/fluid.cpp index 9dcd24db6b..bee3049a5f 100644 --- a/src/fluid/fluid.cpp +++ b/src/fluid/fluid.cpp @@ -2,6 +2,9 @@ #include "fluid.h" +#include "bdap/domainentry.h" +#include "bdap/domainentrydb.h" +#include "bdap/utils.h" #include "chain.h" #include "core_io.h" #include "keepass.h" @@ -148,37 +151,61 @@ bool CFluid::CheckFluidOperationScript(const CScript& fluidScriptPubKey, const i std::string verificationWithoutOpCode = GetRidOfScriptStatement(strFluidOpScript); std::string strOperationCode = GetRidOfScriptStatement(strFluidOpScript, 0); if (!fSkipTimeStampCheck) { - if (!ExtractCheckTimestamp(strFluidOpScript, timeStamp)) { + if (!ExtractCheckTimestamp(strOperationCode, strFluidOpScript, timeStamp)) { errorMessage = "CheckFluidOperationScript fluid timestamp is too old."; return false; } } if (IsHex(verificationWithoutOpCode)) { - std::string strAmount; std::string strUnHexedFluidOpScript = HexToString(verificationWithoutOpCode); std::vector vecSplitScript; SeparateString(strUnHexedFluidOpScript, vecSplitScript, "$"); - if (vecSplitScript.size() > 1) { - 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; + 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 { - errorMessage = "CheckFluidOperationScript fluid token invalid. " + strUnHexedFluidOpScript; - return false; + } + else if (strOperationCode == "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("Can't ban %s account because it was not found.", strBanAccountFQDN); + return false; + } + } + } + } + else { + errorMessage = strprintf("CheckFluidOperationScript fluid OP_BDAP_REVOKE incorrect paramaters %d", vecSplitScript.size()); + return false; + } + } + else { + errorMessage = strprintf("%s -- %s is an unknown fluid operation", __func__, strOperationCode); } } else { errorMessage = "CheckFluidOperationScript fluid token is not hex. " + verificationWithoutOpCode; @@ -211,6 +238,40 @@ bool CFluid::CheckIfExistsInMemPool(const CTxMemPool& pool, const CScript& fluid return false; } +bool CFluid::CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::string& strErrorMessage) +{ + 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); + std::vector vecSplitScript; + SeparateString(strUnHexedFluidOpScript, vecSplitScript, "$"); + for (uint32_t iter = 1; iter != vecSplitScript.size(); iter++) { + CDomainEntry entry; + std::string strBanAccountFQDN = DecodeBase64(vecSplitScript[iter]); + std::vector vchBanAccountFQDN = vchFromString(strBanAccountFQDN); + if (GetDomainEntry(vchBanAccountFQDN, entry)) { + LogPrintf("%s -- Fluid command banning account %s\n", __func__, strBanAccountFQDN); + if (!DeleteDomainEntry(entry)) + LogPrintf("%s -- Error deleting account %s\n", __func__, strBanAccountFQDN); + + // TODO (Fluid): Keep a local LevelDB database with all banned accounts, txid and block height. + //CFluidBanTx fluidBanTx(fluidScript); + //fluidBanTx.nHeight = nHeight; + //fluidBanTx.txHash = txHashId; + } + else { + LogPrintf("%s -- Can't ban %s account because it was not found.\n", __func__, strBanAccountFQDN); + return false; + } + } + + return true; +} + /** Checks whether as to parties have actually signed it - please use this with ones with the OP_CODE */ bool CFluid::CheckIfQuorumExists(const std::string& consentToken, std::string& message, const bool individual) { @@ -296,23 +357,29 @@ bool CFluid::GenericConsentMessage(const std::string& message, std::string& sign } /** Extract timestamp from a Fluid Transaction */ -bool CFluid::ExtractCheckTimestamp(const std::string consentToken, const int64_t timeStamp) +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::vector strs, ptrs; SeparateString(dehexString, strs, false); SeparateString(strs.at(0), ptrs, true); - if (1 >= (int)strs.size()) return false; - std::string ls = ptrs.at(1); - + std::string ls; + if (strOpCode == "OP_MINT" || strOpCode == "OP_REWARD_MINING" || strOpCode == "OP_REWARD_DYNODE") { + ls = ptrs.at(1); + } + else if (strOpCode == "OP_BDAP_REVOKE") { + ls = ptrs.at(0); + } + else { + return false; + } ScrubString(ls, true); int64_t tokenTimeStamp; ParseInt64(ls, &tokenTimeStamp); - if (timeStamp > tokenTimeStamp + fluid.MAX_FLUID_TIME_DISTORT) return false; @@ -550,7 +617,6 @@ bool CFluid::CheckTransactionInRecord(const CScript& fluidInstruction, CBlockInd } */ std::vector transactionRecord; //fluidIndex.fluidHistory; - verificationString = ScriptToAsmStr(fluidInstruction); std::string verificationWithoutOpCode = GetRidOfScriptStatement(verificationString); std::string message; if (CheckIfQuorumExists(verificationString, message)) { @@ -696,4 +762,10 @@ std::string StringFromCharVector(const std::vector& vch) vi++; } return strReturn; +} + +std::vector FluidScriptToCharVector(const CScript& fluidScript) +{ + std::string fluidOperationString = ScriptToAsmStr(fluidScript); + return vchFromString(fluidOperationString); } \ No newline at end of file diff --git a/src/fluid/fluid.h b/src/fluid/fluid.h index cdbce55325..c4235be60d 100644 --- a/src/fluid/fluid.h +++ b/src/fluid/fluid.h @@ -61,7 +61,7 @@ class CFluid : public CFluidParameters, public COperations bool GenericParseNumber(const std::string consentToken, const int64_t timeStamp, CAmount& howMuch, bool txCheckPurpose = false); bool GenericVerifyInstruction(const std::string& consentToken, CDynamicAddress& signer, std::string& messageTokenKey, const int& whereToLook = 1); - bool ExtractCheckTimestamp(const std::string consentToken, const int64_t timeStamp); + bool ExtractCheckTimestamp(const std::string& strOpCode, const std::string& consentToken, const int64_t& timeStamp); bool ParseMintKey(const int64_t& nTime, CDynamicAddress& destination, CAmount& coinAmount, const std::string& uniqueIdentifier, const bool txCheckPurpose = false); bool ProcessFluidToken(const std::string& consentToken, std::vector& ptrs, const int& strVecNo); @@ -77,6 +77,8 @@ class CFluid : public CFluidParameters, public COperations bool ProvisionalCheckTransaction(const CTransaction& transaction); bool InsertTransactionToRecord(const CScript& fluidInstruction, std::vector& transactionRecord); CDynamicAddress GetAddressFromDigestSignature(const std::string& digestSignature, const std::string& messageTokenKey); + bool CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::string& strErrorMessage); + }; /** Standard Reward Payment Determination Functions */ @@ -90,6 +92,7 @@ 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); extern CFluid fluid; diff --git a/src/fluid/operations.cpp b/src/fluid/operations.cpp index 0db9949fac..c51be72af2 100644 --- a/src/fluid/operations.cpp +++ b/src/fluid/operations.cpp @@ -40,7 +40,7 @@ void SeparateString(const std::string& input, std::vector& output, boost::split(output, input, boost::is_any_of(PrimaryDelimiter)); } -void SeparateFluidOpString(std::string input, std::vector& output) +void SeparateFluidOpString(const std::string& input, std::vector& output) { std::vector firstSplit; SeparateString(input, firstSplit); @@ -60,7 +60,7 @@ void SeparateFluidOpString(std::string input, std::vector& output) } } -std::string StitchString(std::string stringOne, std::string stringTwo, bool subDelimiter) +std::string StitchString(const std::string& stringOne, const std::string& stringTwo, const bool subDelimiter) { if (subDelimiter) return stringOne + SubDelimiter + stringTwo; @@ -68,7 +68,7 @@ std::string StitchString(std::string stringOne, std::string stringTwo, bool subD return stringOne + PrimaryDelimiter + stringTwo; } -std::string StitchString(std::string stringOne, std::string stringTwo, std::string stringThree, bool subDelimiter) +std::string StitchString(const std::string& stringOne, const std::string& stringTwo, const std::string& stringThree, const bool subDelimiter) { if (subDelimiter) return stringOne + SubDelimiter + stringTwo + SubDelimiter + stringThree; @@ -76,7 +76,7 @@ std::string StitchString(std::string stringOne, std::string stringTwo, std::stri return stringOne + PrimaryDelimiter + stringTwo + PrimaryDelimiter + stringThree; } -std::string GetRidOfScriptStatement(std::string input, int position) +std::string GetRidOfScriptStatement(const std::string& input, const int& position) { std::vector output; boost::split(output, input, boost::is_any_of(" ")); @@ -111,7 +111,6 @@ bool COperations::VerifyAddressOwnership(const CDynamicAddress& dynamicAddress) #endif //ENABLE_WALLET } - bool COperations::SignTokenMessage(const CDynamicAddress& address, std::string unsignedMessage, std::string& stitchedMessage, bool stitch) { #ifdef ENABLE_WALLET diff --git a/src/fluid/operations.h b/src/fluid/operations.h index 847a2b1449..4f654593dc 100644 --- a/src/fluid/operations.h +++ b/src/fluid/operations.h @@ -57,10 +57,10 @@ class HexFunctions void ScrubString(std::string& input, bool forInteger = false); void SeparateString(const std::string& input, std::vector& output, bool subDelimiter = false); -void SeparateFluidOpString(std::string input, std::vector& output); -std::string StitchString(std::string stringOne, std::string stringTwo, bool subDelimiter = false); -std::string StitchString(std::string stringOne, std::string stringTwo, std::string stringThree, bool subDelimiter = false); -std::string GetRidOfScriptStatement(std::string input, int position = 1); +void SeparateFluidOpString(const std::string& input, std::vector& output); +std::string StitchString(const std::string& stringOne, const std::string& stringTwo, const bool subDelimiter = false); +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; diff --git a/src/validation.cpp b/src/validation.cpp index c7516e4cff..ad9b493346 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -752,7 +752,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // fluid transaction is already in the mempool. Reject tx. return state.DoS(100, false, REJECT_INVALID, strErrorMessage); } - if (!fluid.ExtractCheckTimestamp(ScriptToAsmStr(txout.scriptPubKey), GetTime())) { + std::string strFluidOpScript = ScriptToAsmStr(txout.scriptPubKey); + std::string verificationWithoutOpCode = GetRidOfScriptStatement(strFluidOpScript); + std::string strOperationCode = GetRidOfScriptStatement(strFluidOpScript, 0); + if (strOperationCode == "OP_BDAP_REVOKE" && !sporkManager.IsSporkActive(SPORK_30_ACTIVATE_BDAP)) + return state.Invalid(false, REJECT_INVALID, "bdap-spork-inactive"); + + 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)) { @@ -2505,6 +2511,21 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd } pFluidMintDB->AddFluidMintEntry(fluidMint, OP_MINT); } + } else if (OpCode == OP_BDAP_REVOKE) { + LogPrintf("%s -- Found OP_BDAP_REVOKE transaction.\n", __func__); + if (!CheckSignatureQuorum(FluidScriptToCharVector(scriptFluid), strError)) + return state.DoS(0, error("%s: %s", __func__, strError), REJECT_INVALID, "invalid-fluid-ban-address-signature"); + + if (!sporkManager.IsSporkActive(SPORK_30_ACTIVATE_BDAP)) + return state.DoS(0, error("%s: BDAP spork is inactive.", __func__), REJECT_INVALID, "bdap-spork-inactive"); + + if (!fluid.CheckAccountBanScript(scriptFluid, tx.GetHash(), pindex->nHeight, strError)) + return state.DoS(100, error("%s -- CheckAccountBanScript failed: %s", __func__, strError), REJECT_INVALID, "fluid-ban-script-invalid"); + } + else { + std::string strFluidOpScript = ScriptToAsmStr(scriptFluid); + std::string strOperationCode = GetRidOfScriptStatement(strFluidOpScript, 0); + return state.DoS(100, error("%s -- Invalid fluid operation code %s (%d)", __func__, strOperationCode, OpCode), REJECT_INVALID, "invalid-fluid-operation-code"); } } } From 71ed6b6e40d19d4d50ae3ad8f8b198ce43d3846b Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Wed, 22 May 2019 00:00:29 -0500 Subject: [PATCH 10/36] [Fluid] Cleanup code, remove unused comments and code --- src/bdap/domainentrydb.cpp | 2 +- src/fluid/fluid.cpp | 17 +---------------- src/fluid/fluiddynode.cpp | 4 ---- src/fluid/fluidmining.cpp | 4 ---- src/fluid/fluidmint.cpp | 4 ---- src/fluid/fluidsovereign.cpp | 4 ---- 6 files changed, 2 insertions(+), 33 deletions(-) diff --git a/src/bdap/domainentrydb.cpp b/src/bdap/domainentrydb.cpp index 927ef14f40..54aa14a54c 100644 --- a/src/bdap/domainentrydb.cpp +++ b/src/bdap/domainentrydb.cpp @@ -23,7 +23,7 @@ bool GetDomainEntry(const std::vector& vchObjectPath, CDomainEntr return false; } - if ((unsigned int)chainActive.Tip()->GetMedianTimePast() >= entry.nExpireTime) { + if (chainActive.Tip() && (unsigned int)chainActive.Tip()->GetMedianTimePast() >= entry.nExpireTime) { entry.SetNull(); return false; } diff --git a/src/fluid/fluid.cpp b/src/fluid/fluid.cpp index bee3049a5f..bcc16101d3 100644 --- a/src/fluid/fluid.cpp +++ b/src/fluid/fluid.cpp @@ -601,22 +601,7 @@ bool CFluid::CheckTransactionInRecord(const CScript& fluidInstruction, CBlockInd { if (IsTransactionFluid(fluidInstruction)) { std::string verificationString; - //TODO fluid - /* - CFluidEntry fluidIndex; - if (chainActive.Height() <= fluid.FLUID_ACTIVATE_HEIGHT) { - return false; - } - else if (pindex == nullptr) { - GetLastBlockIndex(chainActive.Tip()); - //TODO fluid - //fluidIndex = chainActive.Tip()->fluidParams; - } else { - //TODO fluid - //fluidIndex = pindex->fluidParams; - } - */ - std::vector transactionRecord; //fluidIndex.fluidHistory; + std::vector transactionRecord; std::string verificationWithoutOpCode = GetRidOfScriptStatement(verificationString); std::string message; if (CheckIfQuorumExists(verificationString, message)) { diff --git a/src/fluid/fluiddynode.cpp b/src/fluid/fluiddynode.cpp index 46a1cb3ba8..24d5e63e08 100644 --- a/src/fluid/fluiddynode.cpp +++ b/src/fluid/fluiddynode.cpp @@ -68,8 +68,6 @@ bool GetFluidDynodeData(const CTransaction& tx, CFluidDynode& entry, int& nOut) bool CFluidDynode::UnserializeFromTx(const CTransaction& tx) { - std::vector vchData; - std::vector vchHash; int nOut; if (!GetFluidDynodeData(tx, *this, nOut)) { SetNull(); @@ -80,8 +78,6 @@ bool CFluidDynode::UnserializeFromTx(const CTransaction& tx) bool CFluidDynode::UnserializeFromScript(const CScript& fluidScript) { - std::vector vchData; - std::vector vchHash; if (!GetFluidDynodeData(fluidScript, *this)) { SetNull(); return false; diff --git a/src/fluid/fluidmining.cpp b/src/fluid/fluidmining.cpp index 6783d38d7a..a37ab665f5 100644 --- a/src/fluid/fluidmining.cpp +++ b/src/fluid/fluidmining.cpp @@ -68,8 +68,6 @@ bool GetFluidMiningData(const CTransaction& tx, CFluidMining& entry, int& nOut) bool CFluidMining::UnserializeFromTx(const CTransaction& tx) { - std::vector vchData; - std::vector vchHash; int nOut; if (!GetFluidMiningData(tx, *this, nOut)) { SetNull(); @@ -80,8 +78,6 @@ bool CFluidMining::UnserializeFromTx(const CTransaction& tx) bool CFluidMining::UnserializeFromScript(const CScript& fluidScript) { - std::vector vchData; - std::vector vchHash; if (!GetFluidMiningData(fluidScript, *this)) { SetNull(); return false; diff --git a/src/fluid/fluidmint.cpp b/src/fluid/fluidmint.cpp index 22ca5346f2..4b08c65a4b 100644 --- a/src/fluid/fluidmint.cpp +++ b/src/fluid/fluidmint.cpp @@ -72,8 +72,6 @@ bool GetFluidMintData(const CTransaction& tx, CFluidMint& entry, int& nOut) bool CFluidMint::UnserializeFromTx(const CTransaction& tx) { - std::vector vchData; - std::vector vchHash; int nOut; if (!GetFluidMintData(tx, *this, nOut)) { SetNull(); @@ -84,8 +82,6 @@ bool CFluidMint::UnserializeFromTx(const CTransaction& tx) bool CFluidMint::UnserializeFromScript(const CScript& fluidScript) { - std::vector vchData; - std::vector vchHash; if (!GetFluidMintData(fluidScript, *this)) { SetNull(); return false; diff --git a/src/fluid/fluidsovereign.cpp b/src/fluid/fluidsovereign.cpp index 38bfb5ac8a..8d50478392 100644 --- a/src/fluid/fluidsovereign.cpp +++ b/src/fluid/fluidsovereign.cpp @@ -60,8 +60,6 @@ bool GetFluidSovereignData(const CTransaction& tx, CFluidSovereign& entry, int& bool CFluidSovereign::UnserializeFromTx(const CTransaction& tx) { - std::vector vchData; - std::vector vchHash; int nOut; if (!GetFluidSovereignData(tx, *this, nOut)) { SetNull(); @@ -72,8 +70,6 @@ bool CFluidSovereign::UnserializeFromTx(const CTransaction& tx) bool CFluidSovereign::UnserializeFromScript(const CScript& fluidScript) { - std::vector vchData; - std::vector vchHash; if (!GetFluidSovereignData(fluidScript, *this)) { SetNull(); return false; From 15db6b9a4cb01f9d8e1b1eee2c1322bcb48db0c6 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Wed, 22 May 2019 00:59:54 -0500 Subject: [PATCH 11/36] [Fluid] Fixes to ban accounts operation script processing (BDAP_REVOKE_TX) --- src/fluid/fluid.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/fluid/fluid.cpp b/src/fluid/fluid.cpp index bcc16101d3..aae180b2c4 100644 --- a/src/fluid/fluid.cpp +++ b/src/fluid/fluid.cpp @@ -206,6 +206,7 @@ bool CFluid::CheckFluidOperationScript(const CScript& fluidScriptPubKey, const i } else { errorMessage = strprintf("%s -- %s is an unknown fluid operation", __func__, strOperationCode); + return false; } } else { errorMessage = "CheckFluidOperationScript fluid token is not hex. " + verificationWithoutOpCode; @@ -249,6 +250,10 @@ bool CFluid::CheckAccountBanScript(const CScript& fluidScript, const uint256& tx std::string strUnHexedFluidOpScript = HexToString(verificationWithoutOpCode); std::vector vecSplitScript; SeparateString(strUnHexedFluidOpScript, vecSplitScript, "$"); + if (vecSplitScript.size() == 0) { + strErrorMessage = "Could not split fluid command script."; + return false; + } for (uint32_t iter = 1; iter != vecSplitScript.size(); iter++) { CDomainEntry entry; std::string strBanAccountFQDN = DecodeBase64(vecSplitScript[iter]); @@ -363,6 +368,9 @@ bool CFluid::ExtractCheckTimestamp(const std::string& strOpCode, const std::stri std::string dehexString = HexToString(consentTokenNoScript); std::vector strs, ptrs; SeparateString(dehexString, strs, false); + if (strs.size() == 0) + return false; + SeparateString(strs.at(0), ptrs, true); if (1 >= (int)strs.size()) return false; @@ -600,7 +608,7 @@ void CFluid::AddFluidTransactionsToRecord(const CBlockIndex* pblockindex, std::v bool CFluid::CheckTransactionInRecord(const CScript& fluidInstruction, CBlockIndex* pindex) { if (IsTransactionFluid(fluidInstruction)) { - std::string verificationString; + std::string verificationString = ScriptToAsmStr(fluidInstruction); std::vector transactionRecord; std::string verificationWithoutOpCode = GetRidOfScriptStatement(verificationString); std::string message; From 7d1bb408dba4ed2148b09e199e391e85124cc2bf Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Wed, 22 May 2019 01:07:21 -0500 Subject: [PATCH 12/36] [Fluid] Remove unused methods in fluid class --- src/fluid/fluid.cpp | 103 +------------------------------------------- src/fluid/fluid.h | 8 +--- 2 files changed, 2 insertions(+), 109 deletions(-) diff --git a/src/fluid/fluid.cpp b/src/fluid/fluid.cpp index aae180b2c4..f43c532198 100644 --- a/src/fluid/fluid.cpp +++ b/src/fluid/fluid.cpp @@ -96,34 +96,6 @@ std::vector InitialiseAddresses() return params.InitialiseAddresses(); } -/** Checks if any given address is a current master key (invoked by RPC) */ -bool CFluid::IsGivenKeyMaster(const CDynamicAddress& inputKey) -{ - if (!inputKey.IsValid()) { - return false; - } - - std::vector fluidSovereigns; - GetLastBlockIndex(chainActive.Tip()); - CBlockIndex* pindex = chainActive.Tip(); - - if (pindex != NULL) { - //TODO fluid - fluidSovereigns = InitialiseAddresses(); //pindex->fluidParams.fluidSovereigns; - } - - else - fluidSovereigns = InitialiseAddresses(); - - for (const std::string& strAddress : fluidSovereigns) { - CDynamicAddress attemptKey(strAddress); - if (attemptKey.IsValid() && inputKey == attemptKey) - return true; - } - - return false; -} - std::vector CFluidParameters::InitialiseAddresses() { std::vector initialSovereignAddresses; @@ -518,7 +490,7 @@ bool CFluid::ParseMintKey(const int64_t& nTime, CDynamicAddress& destination, CA return true; } -static bool GetFluidBlock(const CBlockIndex* pblockindex, CBlock& block) +bool GetFluidBlock(const CBlockIndex* pblockindex, CBlock& block) { if (pblockindex != nullptr) { // Check for invalid block position and file. @@ -554,56 +526,6 @@ bool CFluid::GetMintingInstructions(const CBlockIndex* pblockindex, CDynamicAddr return false; } -bool CFluid::GetProofOverrideRequest(const CBlockIndex* pblockindex, CAmount& coinAmount) -{ - CBlock block; - if (GetFluidBlock(pblockindex, block)) { - for (const CTransactionRef& tx : block.vtx) { - for (const CTxOut& txout : tx->vout) { - if (txout.scriptPubKey.IsProtocolInstruction(MINING_MODIFY_TX)) { - std::string message; - if (CheckIfQuorumExists(ScriptToAsmStr(txout.scriptPubKey), message)) - return GenericParseNumber(ScriptToAsmStr(txout.scriptPubKey), block.nTime, coinAmount); - } - } - } - } - return false; -} - -bool CFluid::GetDynodeOverrideRequest(const CBlockIndex* pblockindex, CAmount& coinAmount) -{ - CBlock block; - if (GetFluidBlock(pblockindex, block)) { - for (const CTransactionRef& tx : block.vtx) { - for (const CTxOut& txout : tx->vout) { - if (txout.scriptPubKey.IsProtocolInstruction(DYNODE_MODFIY_TX)) { - std::string message; - if (CheckIfQuorumExists(ScriptToAsmStr(txout.scriptPubKey), message)) - return GenericParseNumber(ScriptToAsmStr(txout.scriptPubKey), block.nTime, coinAmount); - } - } - } - } - return false; -} - -void CFluid::AddFluidTransactionsToRecord(const CBlockIndex* pblockindex, std::vector& transactionRecord) -{ - CBlock block; - if (GetFluidBlock(pblockindex, block)) { - for (const CTransactionRef& tx : block.vtx) { - for (const CTxOut& txout : tx->vout) { - if (IsTransactionFluid(txout.scriptPubKey)) { - if (!InsertTransactionToRecord(txout.scriptPubKey, transactionRecord)) { - LogPrintf("AddFluidTransactionsToRecord(): Script Database Entry: %s , FAILED!\n", ScriptToAsmStr(txout.scriptPubKey)); - } - } - } - } - } -} - /* Check if transaction exists in record */ bool CFluid::CheckTransactionInRecord(const CScript& fluidInstruction, CBlockIndex* pindex) { @@ -627,29 +549,6 @@ bool CFluid::CheckTransactionInRecord(const CScript& fluidInstruction, CBlockInd return false; } -/* Insertion of transaction script to record */ -bool CFluid::InsertTransactionToRecord(const CScript& fluidInstruction, std::vector& transactionRecord) -{ - std::string verificationString; - - if (IsTransactionFluid(fluidInstruction)) { - verificationString = ScriptToAsmStr(fluidInstruction); - - std::string message; - if (CheckIfQuorumExists(verificationString, message)) { - for (const std::string& existingRecord : transactionRecord) { - if (existingRecord == verificationString) { - return false; - } - } - transactionRecord.push_back(verificationString); - return true; - } - } - - return false; -} - CAmount GetStandardPoWBlockPayment(const int nHeight) { if (nHeight == 1) { diff --git a/src/fluid/fluid.h b/src/fluid/fluid.h index c4235be60d..e6e3939c5c 100644 --- a/src/fluid/fluid.h +++ b/src/fluid/fluid.h @@ -46,11 +46,8 @@ std::vector InitialiseAddresses(); class CFluid : public CFluidParameters, public COperations { public: - void AddFluidTransactionsToRecord(const CBlockIndex* pblockindex, std::vector& transactionRecord); void ReplaceFluidSovereigns(const CBlockHeader& blockHeader, std::vector& fluidSovereigns); - bool IsGivenKeyMaster(const CDynamicAddress& inputKey); - 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 CheckIfQuorumExists(const std::string& consentToken, std::string& message, const bool individual = false); @@ -66,16 +63,12 @@ class CFluid : public CFluidParameters, public COperations bool ProcessFluidToken(const std::string& consentToken, std::vector& ptrs, const int& strVecNo); bool GetMintingInstructions(const CBlockIndex* pblockindex, CDynamicAddress& toMintAddress, CAmount& mintAmount); - bool GetProofOverrideRequest(const CBlockIndex* pblockindex, CAmount& howMuch); - bool GetDynodeOverrideRequest(const CBlockIndex* pblockindex, CAmount& howMuch); - bool ValidationProcesses(CValidationState& state, const CScript& txOut, const CAmount& txValue); bool CheckTransactionToBlock(const CTransaction& transaction, const CBlockHeader& blockHeader); bool CheckTransactionToBlock(const CTransaction& transaction, const uint256 hash); bool ProvisionalCheckTransaction(const CTransaction& transaction); - bool InsertTransactionToRecord(const CScript& fluidInstruction, std::vector& transactionRecord); CDynamicAddress GetAddressFromDigestSignature(const std::string& digestSignature, const std::string& messageTokenKey); bool CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::string& strErrorMessage); @@ -93,6 +86,7 @@ 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); extern CFluid fluid; From 342cdd2831424371350cf40f48162331fc019525 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Wed, 22 May 2019 03:30:06 -0500 Subject: [PATCH 13/36] Fix getblocktemplate when running a fluid mint transaction - Adds fluid mint to superblock payments for block template - Make sure YIIMP and other mining pools support this change --- src/rpcmining.cpp | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index d77c2e1e78..1871d045db 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -14,6 +14,9 @@ #include "consensus/params.h" #include "consensus/validation.h" #include "core_io.h" +#include "fluid/fluid.h" +#include "fluid/fluiddb.h" +#include "fluid/fluidmint.h" #include "init.h" #include "miner/miner.h" #include "net.h" @@ -838,11 +841,12 @@ UniValue getblocktemplate(const JSONRPCRequest& request) // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated aMutable.push_back("version/force"); } - + int64_t nHeight = (int64_t)(pindexPrev->nHeight + 1); + CAmount nCoinbaseValue = pblock->vtx[0]->GetValueOut(); result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); result.push_back(Pair("transactions", transactions)); result.push_back(Pair("coinbaseaux", aux)); - result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->GetValueOut())); + result.push_back(Pair("coinbasevalue", (int64_t)nCoinbaseValue)); result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); result.push_back(Pair("target", hashTarget.GetHex())); result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast() + 1)); @@ -852,7 +856,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE)); result.push_back(Pair("curtime", pblock->GetBlockTime())); result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); - result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight + 1))); + result.push_back(Pair("height", nHeight)); UniValue dynodeObj(UniValue::VOBJ); if (pblocktemplate->txoutDynode != CTxOut()) { @@ -880,9 +884,36 @@ UniValue getblocktemplate(const JSONRPCRequest& request) superblockObjArray.push_back(entry); } } + CFluidMint fluidMint; + bool areWeMinting = GetMintingInstructions(nHeight, fluidMint); + CScript scriptMint; + if (areWeMinting) { + // Add minting output to superblock payments + CAmount fluidIssuance = nCoinbaseValue - GetFluidDynodeReward(nHeight) - GetFluidMiningReward(nHeight); + if (fluidIssuance > 0) { + UniValue entry(UniValue::VOBJ); + CDynamicAddress mintAddress = fluidMint.GetDestinationAddress(); + if (!mintAddress.IsScript()) { + scriptMint = GetScriptForDestination(mintAddress.Get()); + } else { + CScriptID fluidScriptID = boost::get(mintAddress.Get()); + scriptMint = CScript() << OP_HASH160 << ToByteVector(fluidScriptID) << OP_EQUAL; + } + entry.push_back(Pair("payee", mintAddress.ToString().c_str())); + entry.push_back(Pair("script", HexStr(scriptMint.begin(), scriptMint.end()))); + entry.push_back(Pair("amount", (int64_t)fluidIssuance)); + superblockObjArray.push_back(entry); + } + } result.push_back(Pair("superblock", superblockObjArray)); - result.push_back(Pair("superblocks_started", pindexPrev->nHeight + 1 > Params().GetConsensus().nSuperblockStartBlock)); - result.push_back(Pair("superblocks_enabled", sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED))); + if (areWeMinting) { + result.push_back(Pair("superblocks_started", true)); + result.push_back(Pair("superblocks_enabled", true)); + } + else { + result.push_back(Pair("superblocks_started", pindexPrev->nHeight + 1 > Params().GetConsensus().nSuperblockStartBlock)); + result.push_back(Pair("superblocks_enabled", sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED))); + } return result; } From d4e89d8d1079c2907b945431f7f4833bebc32b33 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Thu, 23 May 2019 14:01:22 -0500 Subject: [PATCH 14/36] Bump client version to 2.4.19 --- configure.ac | 2 +- src/clientversion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 3bd3aafaa7..28c14cc1f2 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 4) -define(_CLIENT_VERSION_REVISION, 18) +define(_CLIENT_VERSION_REVISION, 19) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2019) diff --git a/src/clientversion.h b/src/clientversion.h index 308980927f..f705135136 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -19,7 +19,7 @@ //! These need to be macros, as clientversion.cpp's and dynamic*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 4 -#define CLIENT_VERSION_REVISION 18 +#define CLIENT_VERSION_REVISION 19 #define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build From 6739bd1bb121f40188d106948f5f213361dacf9e Mon Sep 17 00:00:00 2001 From: dave-mann <19619811+dave-mann@users.noreply.github.com> Date: Thu, 23 May 2019 12:36:47 -0700 Subject: [PATCH 15/36] [Wallet] Add ability to upgrade older wallet that is locked. Defer upgrade until unlocked. WIP --- src/wallet/wallet.cpp | 104 ++++++++++++++++++++++++++++++------------ src/wallet/wallet.h | 1 + 2 files changed, 76 insertions(+), 29 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 2ac1d160a5..00b994020c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -581,6 +581,13 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) continue; // try another master key if (CCryptoKeyStore::Unlock(vMasterKey, fForMixingOnly)) { + if (fNeedToUpgradeWallet) { + LogPrintf("DEBUGGER WALLET %s - Made it to unlock portion\n", __func__); + if (SyncEdKeyPool()) { + SetMinVersion(FEATURE_HD); + LogPrintf("DEBUGGER WALLET %s - Upgraded wallet\n", __func__); + } + } if (nWalletBackups == -2) { TopUpKeyPoolCombo(); LogPrintf("Keypool replenished, re-initializing automatic backups.\n"); @@ -590,10 +597,25 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl RunProcessStealthQueue(); // Process stealth transactions in queue ProcessLinkQueue(); // Process encrypted links in queue } - return true; + if (!fNeedToUpgradeWallet) return true; } } } + + if (fNeedToUpgradeWallet) { + { + LOCK2(cs_main, pwalletMain->cs_wallet); + fNeedToUpgradeWallet = false; + fNeedToUpdateKeyPools = true; + fNeedToUpdateLinks = true; + LogPrintf("DEBUGGER WALLET %s - Rescanning transasctions\n", __func__); + pwalletMain->UpdateTimeFirstKey(1); + pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true); + LogPrintf("DEBUGGER WALLET %s - Rescanning transasctions DONE\n", __func__); + } + return true; + } + return false; } @@ -4466,7 +4488,11 @@ size_t CWallet::EdKeypoolCountInternalKeys() bool CWallet::SyncEdKeyPool() { + if (pwalletMain->IsLocked()) + return false; + CWalletDB walletdb(strWalletFile); + CKeyPool keypool; CPubKey retrievedPubKey; CKey retrievedKey; @@ -4477,7 +4503,6 @@ bool CWallet::SyncEdKeyPool() LogPrintf("DEBUGGER WALLET %s - made it here!\n", __func__); - for (int64_t nIndex : setInternalKeyPool) { if (!walletdb.ReadPool(nIndex, keypool)) { throw std::runtime_error(std::string(__func__) + ": read failed"); @@ -4485,17 +4510,23 @@ bool CWallet::SyncEdKeyPool() retrievedPubKey = keypool.vchPubKey; GetKey(retrievedPubKey.GetID(), retrievedKey); - // int64_t nEnd = 1; - // if (!setInternalEdKeyPool.empty()) { - // nEnd = *(--setInternalEdKeyPool.end()) + 1; - // } - - if (!walletdb.WriteEdPool(nIndex, CEdKeyPool(GenerateNewEdKey(0, true, retrievedKey), true))) - throw std::runtime_error("SyncEdKeyPool(): writing generated key failed"); + std::array edSeed = ConvertSecureVector32ToArray(retrievedKey.getKeyData()); + CKeyEd25519 childKey(edSeed); + CharString vchDHTPubKey = childKey.GetPubKey(); - setInternalEdKeyPool.insert(nIndex); + CKeyID vchDHTPubKeyID = GetIdFromCharVector(vchDHTPubKey); - LogPrintf("edkeypool added key %d, size=%u, internal=%d\n", nIndex, setInternalEdKeyPool.size() + setExternalEdKeyPool.size(), 1); + //only add if doesn't currently exist + if (!pwalletMain->HaveDHTKey(vchDHTPubKeyID)) { + if (!walletdb.WriteEdPool(nIndex, CEdKeyPool(GenerateNewEdKey(0, true, retrievedKey), true))) + throw std::runtime_error("SyncEdKeyPool(): writing generated key failed"); + else { + setInternalEdKeyPool.insert(nIndex); + LogPrintf("edkeypool added key %d, size=%u, internal=%d\n", nIndex, setInternalEdKeyPool.size() + setExternalEdKeyPool.size(), 1); + } + } + else + LogPrintf("DEBUGGER WALLET %s - internal edkey not added. already exists\n",__func__); } for (int64_t nIndex : setExternalKeyPool) { @@ -4505,17 +4536,24 @@ bool CWallet::SyncEdKeyPool() retrievedPubKey2 = keypool2.vchPubKey; GetKey(retrievedPubKey2.GetID(), retrievedKey2); - // int64_t nEnd = 1; - // if (!setInternalEdKeyPool.empty()) { - // nEnd = *(--setInternalEdKeyPool.end()) + 1; - // } + std::array edSeed2 = ConvertSecureVector32ToArray(retrievedKey2.getKeyData()); + CKeyEd25519 childKey2(edSeed2); + CharString vchDHTPubKey2 = childKey2.GetPubKey(); - if (!walletdb.WriteEdPool(nIndex, CEdKeyPool(GenerateNewEdKey(0, false, retrievedKey2), false))) - throw std::runtime_error("SyncEdKeyPool(): writing generated key failed"); + CKeyID vchDHTPubKeyID2 = GetIdFromCharVector(vchDHTPubKey2); - setExternalEdKeyPool.insert(nIndex); + //only add if doesn't currently exist + if (!pwalletMain->HaveDHTKey(vchDHTPubKeyID2)) { + if (!walletdb.WriteEdPool(nIndex, CEdKeyPool(GenerateNewEdKey(0, false, retrievedKey2), false))) + throw std::runtime_error("SyncEdKeyPool(): writing generated key failed"); + else { + setExternalEdKeyPool.insert(nIndex); + LogPrintf("edkeypool added key %d, size=%u, internal=%d\n", nIndex, setInternalEdKeyPool.size() + setExternalEdKeyPool.size(), 0); + } + } + else + LogPrintf("DEBUGGER WALLET %s - external edkey not added. already exists\n",__func__); - LogPrintf("edkeypool added key %d, size=%u, internal=%d\n", nIndex, setInternalEdKeyPool.size() + setExternalEdKeyPool.size(), 0); } return true; @@ -5689,19 +5727,27 @@ bool CWallet::InitLoadWallet() LogPrintf("DEBUGGER WALLET %s - wallet version [%d]\n", __func__,pwallet->GetVersion()); if (pwallet->GetVersion() < FEATURE_HD) { - if (!pwallet->SyncEdKeyPool()) { - LogPrintf("DEBUGGER WALLET %s - SyncEdKeyPool is false\n", __func__); + if (!pwalletMain->IsLocked()) { + if (!pwallet->SyncEdKeyPool()) { + LogPrintf("DEBUGGER WALLET %s - SyncEdKeyPool is false\n", __func__); + } + else { + LogPrintf("DEBUGGER WALLET %s - SyncEdKeyPool is true\n", __func__); + LogPrintf("DEBUGGER WALLET %s - Upgrading wallet version\n", __func__); + pwallet->SetMinVersion(FEATURE_HD); + pwallet->fNeedToUpgradeWallet = false; + + LogPrintf("setExternalKeyPool.size() = %u\n", pwallet->KeypoolCountExternalKeys()); + LogPrintf("setInternalKeyPool.size() = %u\n", pwallet->KeypoolCountInternalKeys()); + LogPrintf("setExternalEdKeyPool.size() = %u\n", pwallet->EdKeypoolCountExternalKeys()); + LogPrintf("setInternalEdKeyPool.size() = %u\n", pwallet->EdKeypoolCountInternalKeys()); + } } else { - LogPrintf("DEBUGGER WALLET %s - SyncEdKeyPool is true\n", __func__); - LogPrintf("DEBUGGER WALLET %s - Upgrading wallet version\n", __func__); - pwallet->SetMinVersion(FEATURE_HD); - - LogPrintf("setExternalKeyPool.size() = %u\n", pwallet->KeypoolCountExternalKeys()); - LogPrintf("setInternalKeyPool.size() = %u\n", pwallet->KeypoolCountInternalKeys()); - LogPrintf("setExternalEdKeyPool.size() = %u\n", pwallet->EdKeypoolCountExternalKeys()); - LogPrintf("setInternalEdKeyPool.size() = %u\n", pwallet->EdKeypoolCountInternalKeys()); + LogPrintf("DEBUGGER WALLET %s - Upgrade wallet pending unlock\n", __func__); + pwallet->fNeedToUpgradeWallet = true; } + } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 4e4caf4874..05a074b98a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -755,6 +755,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool fNeedToUpdateKeyPools = false; bool fNeedToUpdateLinks = false; + bool fNeedToUpgradeWallet = false; mutable bool fAnonymizableTallyCached; mutable std::vector vecAnonymizableTallyCached; From 3a3709c09182157cba25fb44e39cbcbfdc64cdc2 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Fri, 24 May 2019 00:36:47 -0500 Subject: [PATCH 16/36] [Fluid] Store banned accounts in local leveldb --- src/Makefile.am | 2 + src/fluid/banaccount.cpp | 67 +++++++++++++++++++++++++ src/fluid/banaccount.h | 103 +++++++++++++++++++++++++++++++++++++++ src/fluid/fluid.cpp | 51 +++++++++++++++---- src/fluid/fluid.h | 4 +- src/init.cpp | 4 +- src/validation.cpp | 23 +++++++-- 7 files changed, 238 insertions(+), 16 deletions(-) create mode 100644 src/fluid/banaccount.cpp create mode 100644 src/fluid/banaccount.h diff --git a/src/Makefile.am b/src/Makefile.am index d82e195028..4e3125adc6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -142,6 +142,7 @@ DYNAMIC_CORE_H = \ dynodeman.h \ dynodeconfig.h \ flat-database.h \ + fluid/banaccount.h \ fluid/fluid.h \ fluid/fluiddb.h \ fluid/fluiddynode.h \ @@ -296,6 +297,7 @@ libdynamic_server_a_SOURCES = \ dynode-sync.cpp \ dynodeconfig.cpp \ dynodeman.cpp \ + fluid/banaccount.cpp \ fluid/fluid.cpp \ fluid/fluiddb.cpp \ fluid/fluiddynode.cpp \ diff --git a/src/fluid/banaccount.cpp b/src/fluid/banaccount.cpp new file mode 100644 index 0000000000..5767dc03b7 --- /dev/null +++ b/src/fluid/banaccount.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2019 Duality Blockchain Solutions Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + + +#include "fluid/banaccount.h" + +#include + +CBanAccountDB* pBanAccountDB = NULL; + +bool AddBanAccountEntry(const CBanAccount& entry) +{ + if (!CheckBanAccountDB()) + return false; + + return pBanAccountDB->AddBanAccountEntry(entry); +} + +bool CheckBanAccountDB() +{ + if (!pBanAccountDB) + return false; + + return true; +} + +CBanAccountDB::CBanAccountDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate) : CDBWrapper(GetDataDir() / "blocks" / "banned-accounts", nCacheSize, fMemory, fWipe, obfuscate) +{ +} + +bool CBanAccountDB::AddBanAccountEntry(const CBanAccount& entry) +{ + LOCK(cs_ban_account); + return Write(make_pair(std::string("account"), entry.vchFullObjectPath), entry, true); +} + +bool CBanAccountDB::GetAllBanAccountRecords(std::vector& entries) +{ + LOCK(cs_ban_account); + std::unique_ptr pcursor(NewIterator()); + pcursor->SeekToFirst(); + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + CBanAccount entry; + try { + std::pair> key; + if (pcursor->GetKey(key) && key.first == "account") { + 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 CBanAccountDB::RecordExists(const std::vector& vchFullObjectPath) +{ + LOCK(cs_ban_account); + CBanAccount entry; + return CDBWrapper::Read(make_pair(std::string("account"), vchFullObjectPath), entry); +} \ No newline at end of file diff --git a/src/fluid/banaccount.h b/src/fluid/banaccount.h new file mode 100644 index 0000000000..94a7aa68a9 --- /dev/null +++ b/src/fluid/banaccount.h @@ -0,0 +1,103 @@ +// Copyright (c) 2019 Duality Blockchain Solutions Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef FLUID_BANACCOUNT_H +#define FLUID_BANACCOUNT_H + +#include "dbwrapper.h" +#include "serialize.h" +#include "sync.h" +#include "uint256.h" + +class CBanAccount +{ +public: + static const int CURRENT_VERSION = 1; + int nVersion; + std::vector vchFullObjectPath; + int64_t nTimeStamp; + std::vector > SovereignAddresses; + uint256 txHash; + unsigned int nHeight; + + CBanAccount() + { + SetNull(); + } + + CBanAccount(const std::vector& vchFQDN, const int64_t& timestamp, const std::vector >& addresses, + const uint256& txid, const unsigned int& height) + : vchFullObjectPath(vchFQDN), nTimeStamp(timestamp), SovereignAddresses(addresses), txHash(txid), nHeight(height) + { + nVersion = CBanAccount::CURRENT_VERSION; + } + + inline void SetNull() + { + nVersion = CBanAccount::CURRENT_VERSION; + vchFullObjectPath.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(vchFullObjectPath); + READWRITE(nTimeStamp); + READWRITE(SovereignAddresses); + READWRITE(txHash); + READWRITE(VARINT(nHeight)); + } + + inline friend bool operator==(const CBanAccount& a, const CBanAccount& b) + { + return (a.vchFullObjectPath == b.vchFullObjectPath && a.txHash == b.txHash && a.nTimeStamp == b.nTimeStamp); + } + + inline friend bool operator!=(const CBanAccount& a, const CBanAccount& b) + { + return !(a == b); + } + + inline CBanAccount operator=(const CBanAccount& b) + { + nVersion = b.nVersion; + vchFullObjectPath = b.vchFullObjectPath; + 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); } + +}; + +static CCriticalSection cs_ban_account; + +class CBanAccountDB : public CDBWrapper +{ +public: + CBanAccountDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate); + bool AddBanAccountEntry(const CBanAccount& entry); + bool GetAllBanAccountRecords(std::vector& entries); + bool RecordExists(const std::vector& vchFluidScript); +}; + +bool CheckBanAccountDB(); +bool AddBanAccountEntry(const CBanAccount& entry); + +extern CBanAccountDB* pBanAccountDB; + +#endif // FLUID_BANACCOUNT_H \ No newline at end of file diff --git a/src/fluid/fluid.cpp b/src/fluid/fluid.cpp index f43c532198..92f6eae013 100644 --- a/src/fluid/fluid.cpp +++ b/src/fluid/fluid.cpp @@ -211,7 +211,7 @@ bool CFluid::CheckIfExistsInMemPool(const CTxMemPool& pool, const CScript& fluid return false; } -bool CFluid::CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::string& strErrorMessage) +bool CFluid::CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::vector& vBanAccounts, std::string& strErrorMessage) { std::string strFluidOpScript = ScriptToAsmStr(fluidScript); std::string verificationWithoutOpCode = GetRidOfScriptStatement(strFluidOpScript); @@ -226,19 +226,13 @@ bool CFluid::CheckAccountBanScript(const CScript& fluidScript, const uint256& tx strErrorMessage = "Could not split fluid command script."; return false; } + for (uint32_t iter = 1; iter != vecSplitScript.size(); iter++) { CDomainEntry entry; std::string strBanAccountFQDN = DecodeBase64(vecSplitScript[iter]); std::vector vchBanAccountFQDN = vchFromString(strBanAccountFQDN); if (GetDomainEntry(vchBanAccountFQDN, entry)) { - LogPrintf("%s -- Fluid command banning account %s\n", __func__, strBanAccountFQDN); - if (!DeleteDomainEntry(entry)) - LogPrintf("%s -- Error deleting account %s\n", __func__, strBanAccountFQDN); - - // TODO (Fluid): Keep a local LevelDB database with all banned accounts, txid and block height. - //CFluidBanTx fluidBanTx(fluidScript); - //fluidBanTx.nHeight = nHeight; - //fluidBanTx.txHash = txHashId; + vBanAccounts.push_back(entry); } else { LogPrintf("%s -- Can't ban %s account because it was not found.\n", __func__, strBanAccountFQDN); @@ -660,4 +654,43 @@ std::vector FluidScriptToCharVector(const CScript& fluidScript) { std::string fluidOperationString = ScriptToAsmStr(fluidScript); return vchFromString(fluidOperationString); +} + +bool CFluid::ExtractTimestampWithAddresses(const std::string& strOpCode, const CScript& fluidScript, int64_t& nTimeStamp, std::vector>& vSovereignAddresses) +{ + std::string fluidOperationString = ScriptToAsmStr(fluidScript); + std::string consentTokenNoScript = GetRidOfScriptStatement(fluidOperationString); + std::string strDehexedToken = HexToString(consentTokenNoScript); + std::vector strs, ptrs; + SeparateString(strDehexedToken, strs, false); + if (strs.size() == 0) + return false; + + SeparateString(strs.at(0), ptrs, true); + if (1 >= (int)strs.size()) + 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; + } + + ScrubString(strTimeStamp, true); + ParseInt64(strTimeStamp, &nTimeStamp); + if (strs.size() > 1) { + std::string strToken = strs.at(0); + for (uint32_t iter = 1; iter != strs.size(); iter++) { + std::string strSignature = strs.at(iter); + CDynamicAddress address = GetAddressFromDigestSignature(strSignature, strToken); + vSovereignAddresses.push_back(CharVectorFromString(address.ToString())); + } + } + else { + return false; + } + return true; } \ No newline at end of file diff --git a/src/fluid/fluid.h b/src/fluid/fluid.h index e6e3939c5c..bc2fa388f5 100644 --- a/src/fluid/fluid.h +++ b/src/fluid/fluid.h @@ -19,6 +19,7 @@ #include class CBlock; +class CDomainEntry; class CTxMemPool; struct CBlockTemplate; class CTransaction; @@ -70,7 +71,8 @@ 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::string& strErrorMessage); + bool CheckAccountBanScript(const CScript& fluidScript, const uint256& txHashId, const unsigned int& nHeight, std::vector& vBanAccounts, std::string& strErrorMessage); + bool ExtractTimestampWithAddresses(const std::string& strOpCode, const CScript& fluidScript, int64_t& nTimeStamp, std::vector>& vSovereignAddresses); }; diff --git a/src/init.cpp b/src/init.cpp index bcee68a2c2..004f368b57 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -30,6 +30,7 @@ #include "dynodeconfig.h" #include "dynodeman.h" #include "flat-database.h" +#include "fluid/banaccount.h" #include "fluid/fluiddynode.h" #include "fluid/fluidmining.h" #include "fluid/fluidmint.h" @@ -1696,6 +1697,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) delete pFluidMiningDB; delete pFluidMintDB; delete pFluidSovereignDB; + delete pBanAccountDB; // BDAP Services DB's delete pDomainEntryDB; delete pLinkRequestDB; @@ -1716,7 +1718,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) pFluidMiningDB = new CFluidMiningDB(nTotalCache * 35, false, fReindex, obfuscate); pFluidMintDB = new CFluidMintDB(nTotalCache * 35, false, fReindex, obfuscate); pFluidSovereignDB = new CFluidSovereignDB(nTotalCache * 35, false, fReindex, obfuscate); - + pBanAccountDB = new CBanAccountDB(nTotalCache * 35, false, fReindex, obfuscate); // Init BDAP Services DBs pDomainEntryDB = new CDomainEntryDB(nTotalCache * 35, false, fReindex, obfuscate); pLinkRequestDB = new CLinkRequestDB(nTotalCache * 35, false, fReindex, obfuscate); diff --git a/src/validation.cpp b/src/validation.cpp index ad9b493346..7544effde8 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -24,6 +24,7 @@ #include "dynode-payments.h" #include "dynode-sync.h" #include "dynodeman.h" +#include "fluid/banaccount.h" #include "fluid/fluid.h" #include "fluid/fluiddb.h" #include "fluid/fluiddynode.h" @@ -2512,17 +2513,29 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd pFluidMintDB->AddFluidMintEntry(fluidMint, OP_MINT); } } else if (OpCode == OP_BDAP_REVOKE) { - LogPrintf("%s -- Found OP_BDAP_REVOKE transaction.\n", __func__); if (!CheckSignatureQuorum(FluidScriptToCharVector(scriptFluid), strError)) return state.DoS(0, error("%s: %s", __func__, strError), REJECT_INVALID, "invalid-fluid-ban-address-signature"); if (!sporkManager.IsSporkActive(SPORK_30_ACTIVATE_BDAP)) return state.DoS(0, error("%s: BDAP spork is inactive.", __func__), REJECT_INVALID, "bdap-spork-inactive"); - if (!fluid.CheckAccountBanScript(scriptFluid, tx.GetHash(), pindex->nHeight, strError)) - return state.DoS(100, error("%s -- CheckAccountBanScript failed: %s", __func__, strError), REJECT_INVALID, "fluid-ban-script-invalid"); - } - else { + std::vector vBanAccounts; + if (!fluid.CheckAccountBanScript(scriptFluid, tx.GetHash(), pindex->nHeight, vBanAccounts, strError)) + return state.DoS(0, error("%s -- CheckAccountBanScript failed: %s", __func__, strError), REJECT_INVALID, "fluid-ban-script-invalid"); + + int64_t nTimeStamp; + std::vector> vSovereignAddresses; + if (fluid.ExtractTimestampWithAddresses("OP_BDAP_REVOKE", scriptFluid, nTimeStamp, vSovereignAddresses)) { + for (const CDomainEntry& entry : vBanAccounts) { + LogPrintf("%s -- Fluid command banning account %s\n", __func__, entry.GetFullObjectPath()); + if (!DeleteDomainEntry(entry)) + LogPrintf("%s -- Error deleting account %s\n", __func__, entry.GetFullObjectPath()); + + CBanAccount banAccount(entry.vchFullObjectPath(), nTimeStamp, vSovereignAddresses, tx.GetHash(), pindex->nHeight); + AddBanAccountEntry(banAccount); + } + } + } else { std::string strFluidOpScript = ScriptToAsmStr(scriptFluid); std::string strOperationCode = GetRidOfScriptStatement(strFluidOpScript, 0); return state.DoS(100, error("%s -- Invalid fluid operation code %s (%d)", __func__, strOperationCode, OpCode), REJECT_INVALID, "invalid-fluid-operation-code"); From fcd8e5e414b87a3b56652d77fdbaa2c599bc7cdd Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Fri, 24 May 2019 00:37:54 -0500 Subject: [PATCH 17/36] Add missing pointer cleanup for Fluid, BDAP, and DHT objects in init --- src/init.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 004f368b57..bfec96a65a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -356,6 +356,29 @@ void PrepareShutdown() pcoinsdbview = NULL; delete pblocktree; pblocktree = NULL; + // Fluid transaction DB's + delete pFluidDynodeDB; + pFluidDynodeDB = NULL; + delete pFluidMiningDB; + pFluidMiningDB = NULL; + delete pFluidMintDB; + pFluidMintDB = NULL; + delete pFluidSovereignDB; + pFluidSovereignDB = NULL; + // BDAP Services DB's + delete pDomainEntryDB; + pDomainEntryDB = NULL; + delete pLinkRequestDB; + pLinkRequestDB = NULL; + delete pLinkAcceptDB; + pLinkAcceptDB = NULL; + delete pLinkManager; + pLinkManager = NULL; + // LibTorrent DHT Netowrk Services + delete pHashTableSession; + pHashTableSession = NULL; + delete pMutableDataDB; + pMutableDataDB = NULL; } #ifdef ENABLE_WALLET if (pwalletMain) From 1b3bce76331cc6a22ec195d98554b32a91ba56de Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Fri, 24 May 2019 00:38:30 -0500 Subject: [PATCH 18/36] Add missing pBanAccountDB cleanup code --- src/init.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index bfec96a65a..2e69cd15e9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -365,6 +365,8 @@ void PrepareShutdown() pFluidMintDB = NULL; delete pFluidSovereignDB; pFluidSovereignDB = NULL; + delete pBanAccountDB; + pBanAccountDB = NULL; // BDAP Services DB's delete pDomainEntryDB; pDomainEntryDB = NULL; From b41e94607f39a0f47c89cb1a9b5a34ebe825cfd2 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Fri, 24 May 2019 04:13:27 -0500 Subject: [PATCH 19/36] [Fluid] Support ban accounts in get fluid history and read fluid token RPC --- src/fluid/banaccount.cpp | 26 ++++++- src/fluid/banaccount.h | 37 ++++++---- src/fluid/fluiddynode.h | 10 +++ src/fluid/fluidmining.h | 10 +++ src/fluid/fluidmint.h | 10 +++ src/fluid/rpcfluid.cpp | 144 +++++++++++++++++++++++++++++++-------- src/validation.cpp | 2 +- 7 files changed, 196 insertions(+), 43 deletions(-) diff --git a/src/fluid/banaccount.cpp b/src/fluid/banaccount.cpp index 5767dc03b7..988a007865 100644 --- a/src/fluid/banaccount.cpp +++ b/src/fluid/banaccount.cpp @@ -5,10 +5,22 @@ #include "fluid/banaccount.h" +#include "core_io.h" +#include "fluid/fluid.h" +#include "script/script.h" + #include CBanAccountDB* pBanAccountDB = NULL; +bool CheckBanAccountDB() +{ + if (!pBanAccountDB) + return false; + + return true; +} + bool AddBanAccountEntry(const CBanAccount& entry) { if (!CheckBanAccountDB()) @@ -17,12 +29,20 @@ bool AddBanAccountEntry(const CBanAccount& entry) return pBanAccountDB->AddBanAccountEntry(entry); } -bool CheckBanAccountDB() +bool GetAllBanAccountRecords(std::vector& entries) { - if (!pBanAccountDB) + if (!CheckBanAccountDB()) return false; - return true; + return pBanAccountDB->GetAllBanAccountRecords(entries); +} + +CBanAccount::CBanAccount(const CScript& fluidScript, const std::vector& fqdn, const int64_t& timestamp, + const std::vector>& addresses, const uint256& txid, const unsigned int& height) + : vchFullObjectPath(fqdn), nTimeStamp(timestamp), vSovereignAddresses(addresses), txHash(txid), nHeight(height) +{ + nVersion = CBanAccount::CURRENT_VERSION; + FluidScript = CharVectorFromString(ScriptToAsmStr(fluidScript)); } CBanAccountDB::CBanAccountDB(size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate) : CDBWrapper(GetDataDir() / "blocks" / "banned-accounts", nCacheSize, fMemory, fWipe, obfuscate) diff --git a/src/fluid/banaccount.h b/src/fluid/banaccount.h index 94a7aa68a9..28d42b1794 100644 --- a/src/fluid/banaccount.h +++ b/src/fluid/banaccount.h @@ -10,14 +10,17 @@ #include "sync.h" #include "uint256.h" +class CScript; + class CBanAccount { public: static const int CURRENT_VERSION = 1; int nVersion; + std::vector FluidScript; std::vector vchFullObjectPath; int64_t nTimeStamp; - std::vector > SovereignAddresses; + std::vector> vSovereignAddresses; uint256 txHash; unsigned int nHeight; @@ -26,19 +29,16 @@ class CBanAccount SetNull(); } - CBanAccount(const std::vector& vchFQDN, const int64_t& timestamp, const std::vector >& addresses, - const uint256& txid, const unsigned int& height) - : vchFullObjectPath(vchFQDN), nTimeStamp(timestamp), SovereignAddresses(addresses), txHash(txid), nHeight(height) - { - nVersion = CBanAccount::CURRENT_VERSION; - } + CBanAccount(const CScript& fluidScript, const std::vector& fqdn, const int64_t& timestamp, + const std::vector >& addresses, const uint256& txid, const unsigned int& height); inline void SetNull() { nVersion = CBanAccount::CURRENT_VERSION; + FluidScript.clear(); vchFullObjectPath.clear(); nTimeStamp = 0; - SovereignAddresses.clear(); + vSovereignAddresses.clear(); txHash.SetNull(); nHeight = 0; } @@ -49,9 +49,10 @@ class CBanAccount inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(this->nVersion); + READWRITE(FluidScript); READWRITE(vchFullObjectPath); READWRITE(nTimeStamp); - READWRITE(SovereignAddresses); + READWRITE(vSovereignAddresses); READWRITE(txHash); READWRITE(VARINT(nHeight)); } @@ -66,14 +67,25 @@ class CBanAccount return !(a == b); } + friend bool operator<(const CBanAccount& a, const CBanAccount& b) + { + return (a.nTimeStamp < b.nTimeStamp); + } + + friend bool operator>(const CBanAccount& a, const CBanAccount& b) + { + return (a.nTimeStamp > b.nTimeStamp); + } + inline CBanAccount operator=(const CBanAccount& b) { nVersion = b.nVersion; + FluidScript = b.FluidScript; vchFullObjectPath = b.vchFullObjectPath; nTimeStamp = b.nTimeStamp; - SovereignAddresses.clear(); //clear out previous entries - for (const std::vector& vchAddress : b.SovereignAddresses) { - SovereignAddresses.push_back(vchAddress); + vSovereignAddresses.clear(); //clear out previous entries + for (const std::vector& vchAddress : b.vSovereignAddresses) { + vSovereignAddresses.push_back(vchAddress); } txHash = b.txHash; nHeight = b.nHeight; @@ -97,6 +109,7 @@ class CBanAccountDB : public CDBWrapper bool CheckBanAccountDB(); bool AddBanAccountEntry(const CBanAccount& entry); +bool GetAllBanAccountRecords(std::vector& entries); extern CBanAccountDB* pBanAccountDB; diff --git a/src/fluid/fluiddynode.h b/src/fluid/fluiddynode.h index ba2630e73e..2230df889a 100644 --- a/src/fluid/fluiddynode.h +++ b/src/fluid/fluiddynode.h @@ -77,6 +77,16 @@ class CFluidDynode 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; diff --git a/src/fluid/fluidmining.h b/src/fluid/fluidmining.h index ce4e607519..e61a500cf4 100644 --- a/src/fluid/fluidmining.h +++ b/src/fluid/fluidmining.h @@ -77,6 +77,16 @@ class CFluidMining 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; diff --git a/src/fluid/fluidmint.h b/src/fluid/fluidmint.h index 40bf988e09..1096201afa 100644 --- a/src/fluid/fluidmint.h +++ b/src/fluid/fluidmint.h @@ -81,6 +81,16 @@ class CFluidMint 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; diff --git a/src/fluid/rpcfluid.cpp b/src/fluid/rpcfluid.cpp index 3363432901..327e278798 100644 --- a/src/fluid/rpcfluid.cpp +++ b/src/fluid/rpcfluid.cpp @@ -7,6 +7,7 @@ #include "chain.h" #include "core_io.h" #include "dynode-sync.h" +#include "banaccount.h" #include "fluiddb.h" #include "fluiddynode.h" #include "fluidmining.h" @@ -422,6 +423,24 @@ UniValue getfluidhistoryraw(const JSONRPCRequest& request) } } ret.push_back(Pair("mining_reward_history", oMining)); + // load fluid BDAP account ban transaction history + UniValue oAccountBan(UniValue::VOBJ); + { + std::vector vBanEntries; + if (!GetAllBanAccountRecords(vBanEntries)) { + throw std::runtime_error("GET_FLUID_HISTORY_RPC_ERROR: ERRCODE: 4005 - " + _("Error getting fluid account ban entries")); + } + int x = 1; + for (const CBanAccount& banEntry : vBanEntries) { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("fluid_script", StringFromCharVector(banEntry.FluidScript))); + std::string addLabel = "account_ban_" + std::to_string(x); + oAccountBan.push_back(Pair(addLabel, obj)); + x++; + nTotal++; + } + } + ret.push_back(Pair("account_ban_history", oAccountBan)); // load fluid transaction summary UniValue oSummary(UniValue::VOBJ); { @@ -564,6 +583,36 @@ UniValue getfluidhistory(const JSONRPCRequest& request) } } ret.push_back(Pair("mining_reward_history", oMining)); + // load fluid ban account transaction history + UniValue oBanAccounts(UniValue::VOBJ); + { + std::vector banEntries; + if (!GetAllBanAccountRecords(banEntries)) { + throw std::runtime_error("GET_FLUID_HISTORY_RPC_ERROR: ERRCODE: 4005 - " + _("Error getting fluid ban account entries")); + } + int x = 1; + std::sort(banEntries.begin(), banEntries.end()); //sort entries by TimeStamp + for (const CBanAccount& banEntry : banEntries) { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("operation", "Ban Account")); + obj.push_back(Pair("account_fqdn", StringFromCharVector(banEntry.vchFullObjectPath))); + obj.push_back(Pair("timestamp", banEntry.nTimeStamp)); + obj.push_back(Pair("display_date", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", banEntry.nTimeStamp))); + obj.push_back(Pair("block_height", (int)banEntry.nHeight)); + obj.push_back(Pair("txid", banEntry.txHash.GetHex())); + int index = 1; + for (const std::vector& vchAddress : banEntry.vSovereignAddresses) { + std::string addLabel = "sovereign_address_" + std::to_string(index); + obj.push_back(Pair(addLabel, StringFromCharVector(vchAddress))); + index++; + } + std::string addLabel = "ban_account_" + std::to_string(x); + oBanAccounts.push_back(Pair(addLabel, obj)); + x++; + nTotal++; + } + } + ret.push_back(Pair("ban_account_history", oBanAccounts)); // load fluid transaction summary UniValue oSummary(UniValue::VOBJ); { @@ -639,50 +688,91 @@ UniValue readfluidtoken(const JSONRPCRequest& request) UniValue ret(UniValue::VOBJ); std::string strFluidToken = request.params[0].get_str(); if (IsHex(strFluidToken)) { - std::string strAmount; + bool fBanAccount = false; HexFunctions fluidFunctions; std::string strUnHexedFluidOpScript = fluidFunctions.HexToString(strFluidToken); std::vector vecSplitScript; SeparateString(strUnHexedFluidOpScript, vecSplitScript, true); if (vecSplitScript.size() > 1) { - strAmount = vecSplitScript[0]; - CAmount fluidAmount; - if (ParseFixedPoint(strAmount, 8, &fluidAmount)) { - ret.push_back(Pair("amount", FormatMoney(fluidAmount))); + CAmount nAmount; + if (!ParseFixedPoint(vecSplitScript[0], 8, &nAmount)) { + fBanAccount = true; } - else { - throw std::runtime_error("READ_FLUID_TOKEN_RPC_ERROR: ERRCODE: 4100 - " + _("Fluid token amount too high or invalid.")); + if (!fBanAccount) { + int64_t nTimeStamp; + if (!ParseInt64(vecSplitScript[1], &nTimeStamp)) { + fBanAccount = true; + } + } + } + if (!fBanAccount) { + std::string strAmount; + if (vecSplitScript.size() > 1) { + strAmount = vecSplitScript[0]; + CAmount fluidAmount; + if (ParseFixedPoint(strAmount, 8, &fluidAmount)) { + ret.push_back(Pair("amount", FormatMoney(fluidAmount))); + } + else { + throw std::runtime_error("READ_FLUID_TOKEN_RPC_ERROR: ERRCODE: 4100 - " + _("Fluid token amount too high or invalid.")); + } + ret.push_back(Pair("time_stamp", vecSplitScript[1])); + } else { + throw std::runtime_error("READ_FLUID_TOKEN_RPC_ERROR: ERRCODE: 4101 - " + _("Fluid token does not have enough parameters")); + } + } + else { + ret.push_back(Pair("time_stamp", vecSplitScript[0])); + if (vecSplitScript.size() > 1) { + for (uint32_t iter = 1; iter != vecSplitScript.size(); iter++) { + std::string strFQDN = DecodeBase64(vecSplitScript[iter]); + std::string strLabel = "ban_account_" + std::to_string(iter); + ret.push_back(Pair(strLabel, strFQDN)); + } } - ret.push_back(Pair("time_stamp", vecSplitScript[1])); - } else { - throw std::runtime_error("READ_FLUID_TOKEN_RPC_ERROR: ERRCODE: 4101 - " + _("Fluid token does not have enough parameters")); } if (vecSplitScript.size() > 2) { std::string strPayAddress = vecSplitScript[2]; std::vector vecSplitAddress; SeparateString(strPayAddress, vecSplitAddress, false); - if (vecSplitAddress.size() == 1) { - ret.push_back(Pair("pay_address", vecSplitScript[2])); + if (!fBanAccount) { + if (vecSplitAddress.size() == 1) { + ret.push_back(Pair("pay_address", vecSplitScript[2])); + } + else if (vecSplitAddress.size() == 2) { + ret.push_back(Pair("pay_address", vecSplitAddress[0])); + ret.push_back(Pair("signature_1", vecSplitAddress[1])); + } + else if (vecSplitAddress.size() == 3) { + ret.push_back(Pair("pay_address", vecSplitAddress[0])); + ret.push_back(Pair("signature_1", vecSplitAddress[1])); + ret.push_back(Pair("signature_2", vecSplitAddress[2])); + } + else if (vecSplitAddress.size() == 4) { + ret.push_back(Pair("pay_address", vecSplitAddress[0])); + ret.push_back(Pair("signature_1", vecSplitAddress[1])); + ret.push_back(Pair("signature_2", vecSplitAddress[2])); + ret.push_back(Pair("signature_3", vecSplitAddress[3])); + } } - else if (vecSplitAddress.size() == 2) { - ret.push_back(Pair("pay_address", vecSplitAddress[0])); - ret.push_back(Pair("signature_1", vecSplitAddress[1])); - } - else if (vecSplitAddress.size() == 3) { - ret.push_back(Pair("pay_address", vecSplitAddress[0])); - ret.push_back(Pair("signature_1", vecSplitAddress[1])); - ret.push_back(Pair("signature_2", vecSplitAddress[2])); - } - else if (vecSplitAddress.size() == 4) { - ret.push_back(Pair("pay_address", vecSplitAddress[0])); - ret.push_back(Pair("signature_1", vecSplitAddress[1])); - ret.push_back(Pair("signature_2", vecSplitAddress[2])); - ret.push_back(Pair("signature_3", vecSplitAddress[3])); + else { + if (vecSplitAddress.size() == 2) { + ret.push_back(Pair("signature_1", vecSplitAddress[1])); + } + else if (vecSplitAddress.size() == 3) { + ret.push_back(Pair("signature_1", vecSplitAddress[1])); + ret.push_back(Pair("signature_2", vecSplitAddress[2])); + } + else if (vecSplitAddress.size() == 4) { + ret.push_back(Pair("signature_1", vecSplitAddress[1])); + ret.push_back(Pair("signature_2", vecSplitAddress[2])); + ret.push_back(Pair("signature_3", vecSplitAddress[3])); + } } } } else { - throw std::runtime_error("READ_FLUID_TOKEN_RPC_ERROR: ERRCODE: 4102 - " + _("Fluid token is not hex")); + throw std::runtime_error("READ_FLUID_TOKEN_RPC_ERROR: ERRCODE: 4105 - " + _("Fluid token is not hex")); } return ret; diff --git a/src/validation.cpp b/src/validation.cpp index 7544effde8..abdd90146e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2531,7 +2531,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd if (!DeleteDomainEntry(entry)) LogPrintf("%s -- Error deleting account %s\n", __func__, entry.GetFullObjectPath()); - CBanAccount banAccount(entry.vchFullObjectPath(), nTimeStamp, vSovereignAddresses, tx.GetHash(), pindex->nHeight); + CBanAccount banAccount(scriptFluid, entry.vchFullObjectPath(), nTimeStamp, vSovereignAddresses, tx.GetHash(), pindex->nHeight); AddBanAccountEntry(banAccount); } } From b56987250182559efbce2e46ab4aab1d574ea176 Mon Sep 17 00:00:00 2001 From: dave-mann <19619811+dave-mann@users.noreply.github.com> Date: Fri, 24 May 2019 15:32:42 -0700 Subject: [PATCH 20/36] [Wallet] During unlock, add confirmation popup to GUI that older locked wallet needs to be upgraded and rescan done. Misc cleanup. --- src/qt/askpassphrasedialog.cpp | 12 +++++++++++ src/qt/forms/askpassphrasedialog.ui | 7 +++++++ src/wallet/wallet.cpp | 31 +++++++---------------------- src/wallet/wallet.h | 5 +++++ 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index df84848211..4654f2f991 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -167,6 +167,18 @@ void AskPassphraseDialog::accept() } break; case UnlockMixing: case Unlock: + if (model->getWallet()->WalletNeedsUpgrading()) { + QMessageBox::StandardButton reply; + ui->buttonBox->clear(); + ui->statuslabel->setText(tr("Rescanning... Please wait, this may take several minutes.")); + reply = QMessageBox::question(this, QObject::tr("Confirm Additional Operations"), QObject::tr("The current wallet needs to be upgraded to a newer version. This will require the creation of new keys and a full rescan. This may take several minutes to complete. Continue?"), QMessageBox::Yes|QMessageBox::No); + + if (reply == QMessageBox::No) { + QDialog::reject(); //cancel + break; + } + } + if (!model->setWalletLocked(false, oldpass, mode == UnlockMixing)) { QMessageBox::critical(this, tr("Wallet unlock failed"), tr("The passphrase entered for the wallet decryption was incorrect.")); diff --git a/src/qt/forms/askpassphrasedialog.ui b/src/qt/forms/askpassphrasedialog.ui index a2105ecd0a..3017762670 100644 --- a/src/qt/forms/askpassphrasedialog.ui +++ b/src/qt/forms/askpassphrasedialog.ui @@ -110,6 +110,13 @@ + + + + + + + diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 00b994020c..9df6cc1207 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -582,10 +582,9 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl continue; // try another master key if (CCryptoKeyStore::Unlock(vMasterKey, fForMixingOnly)) { if (fNeedToUpgradeWallet) { - LogPrintf("DEBUGGER WALLET %s - Made it to unlock portion\n", __func__); if (SyncEdKeyPool()) { SetMinVersion(FEATURE_HD); - LogPrintf("DEBUGGER WALLET %s - Upgraded wallet\n", __func__); + LogPrintf("%s - Upgraded wallet\n", __func__); } } if (nWalletBackups == -2) { @@ -608,10 +607,10 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl fNeedToUpgradeWallet = false; fNeedToUpdateKeyPools = true; fNeedToUpdateLinks = true; - LogPrintf("DEBUGGER WALLET %s - Rescanning transasctions\n", __func__); + LogPrintf("%s - Rescanning transasctions\n", __func__); pwalletMain->UpdateTimeFirstKey(1); pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true); - LogPrintf("DEBUGGER WALLET %s - Rescanning transasctions DONE\n", __func__); + LogPrintf("%s - Rescanning transasctions DONE\n", __func__); } return true; } @@ -4501,8 +4500,6 @@ bool CWallet::SyncEdKeyPool() CPubKey retrievedPubKey2; CKey retrievedKey2; - LogPrintf("DEBUGGER WALLET %s - made it here!\n", __func__); - for (int64_t nIndex : setInternalKeyPool) { if (!walletdb.ReadPool(nIndex, keypool)) { throw std::runtime_error(std::string(__func__) + ": read failed"); @@ -4525,8 +4522,6 @@ bool CWallet::SyncEdKeyPool() LogPrintf("edkeypool added key %d, size=%u, internal=%d\n", nIndex, setInternalEdKeyPool.size() + setExternalEdKeyPool.size(), 1); } } - else - LogPrintf("DEBUGGER WALLET %s - internal edkey not added. already exists\n",__func__); } for (int64_t nIndex : setExternalKeyPool) { @@ -4551,9 +4546,6 @@ bool CWallet::SyncEdKeyPool() LogPrintf("edkeypool added key %d, size=%u, internal=%d\n", nIndex, setInternalEdKeyPool.size() + setExternalEdKeyPool.size(), 0); } } - else - LogPrintf("DEBUGGER WALLET %s - external edkey not added. already exists\n",__func__); - } return true; @@ -5724,33 +5716,24 @@ bool CWallet::InitLoadWallet() } pwalletMain = pwallet; - LogPrintf("DEBUGGER WALLET %s - wallet version [%d]\n", __func__,pwallet->GetVersion()); - if (pwallet->GetVersion() < FEATURE_HD) { + LogPrintf("%s - Older wallet version detected. Need to upgrade.\n", __func__); if (!pwalletMain->IsLocked()) { if (!pwallet->SyncEdKeyPool()) { - LogPrintf("DEBUGGER WALLET %s - SyncEdKeyPool is false\n", __func__); + LogPrintf("%s - ERROR: Unable to sync Ed25519 Keypool.\n", __func__); } else { - LogPrintf("DEBUGGER WALLET %s - SyncEdKeyPool is true\n", __func__); - LogPrintf("DEBUGGER WALLET %s - Upgrading wallet version\n", __func__); + LogPrintf("%s - Upgrading wallet version\n", __func__); pwallet->SetMinVersion(FEATURE_HD); pwallet->fNeedToUpgradeWallet = false; - - LogPrintf("setExternalKeyPool.size() = %u\n", pwallet->KeypoolCountExternalKeys()); - LogPrintf("setInternalKeyPool.size() = %u\n", pwallet->KeypoolCountInternalKeys()); - LogPrintf("setExternalEdKeyPool.size() = %u\n", pwallet->EdKeypoolCountExternalKeys()); - LogPrintf("setInternalEdKeyPool.size() = %u\n", pwallet->EdKeypoolCountInternalKeys()); } } else { - LogPrintf("DEBUGGER WALLET %s - Upgrade wallet pending unlock\n", __func__); + LogPrintf("%s - Upgrade wallet pending unlock\n", __func__); pwallet->fNeedToUpgradeWallet = true; } - } - ProcessLinkQueue(); // Process links in queue. return true; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 05a074b98a..3470b9e5ab 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -825,6 +825,11 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface const std::string strWalletFile; + bool WalletNeedsUpgrading() + { + return fNeedToUpgradeWallet; + } + void LoadKeyPool(int nIndex, const CKeyPool& keypool) { if (keypool.fInternal) { From db0f25425cd1060fa1815d95af786dca09c872d6 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Mon, 27 May 2019 17:14:41 -0500 Subject: [PATCH 21/36] Reserve keypool, check std::set entries exist before erasing - reserve key for tx calls erase without checking if it was found --- src/wallet/wallet.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 13d5a39b91..89a0978d11 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4667,11 +4667,9 @@ void CWallet::UpdateKeyPoolsFromTransactions(const std::string& strOpType, const std::vector key1 = vvchOpParameters[1]; if (strOpType == "bdap_new_account") { - //reservedEd25519PubKeys.push_back(key1); ReserveEdKeyForTransactions(key1); } else if (strOpType == "bdap_new_link_request" || strOpType == "bdap_new_link_accept") { - //reservedEd25519PubKeys.push_back(key0); ReserveEdKeyForTransactions(key0); fNeedToUpdateLinks = true; } @@ -4774,10 +4772,11 @@ void CWallet::ReserveEdKeyForTransactions(const std::vector& pubK } if (EraseIndex) { - std::set::iterator eraseIndexEd = setInternalEdKeyPool.find(IndexToErase); - std::set::iterator eraseIndex = setInternalKeyPool.find(IndexToErase); - + std::set::iterator eraseIndexEd = setInternalEdKeyPool.find(IndexToErase); + std::set::iterator eraseIndex = setInternalKeyPool.find(IndexToErase); + if (eraseIndexEd != setInternalEdKeyPool.end()) setInternalEdKeyPool.erase(eraseIndexEd); + if (eraseIndex != setInternalKeyPool.end()) setInternalKeyPool.erase(eraseIndex); } @@ -4790,7 +4789,7 @@ void CWallet::KeepKey(int64_t nIndex) CWalletDB walletdb(strWalletFile); walletdb.ErasePool(nIndex); nKeysLeftSinceAutoBackup = nWalletBackups ? nKeysLeftSinceAutoBackup - 1 : 0; - } + } LogPrintf("keypool keep %d\n", nIndex); } From c198f68c42b34278bd5084f56d5c3673bf525f62 Mon Sep 17 00:00:00 2001 From: dave-mann <19619811+dave-mann@users.noreply.github.com> Date: Thu, 30 May 2019 16:22:31 -0700 Subject: [PATCH 22/36] [BDAP] Fix issue where bdap_link_accept was not being seen by original requestor --- src/bdap/rpclinking.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bdap/rpclinking.cpp b/src/bdap/rpclinking.cpp index 4b57197ee8..cf928bde24 100644 --- a/src/bdap/rpclinking.cpp +++ b/src/bdap/rpclinking.cpp @@ -395,9 +395,9 @@ static UniValue SendLinkAccept(const JSONRPCRequest& request) // Create OP Script with destination address bool fStealthAddress = false; - CTxDestination dest = DecodeDestination(entryAcceptor.GetLinkAddress().ToString()); + CTxDestination dest = DecodeDestination(entryRequestor.GetLinkAddress().ToString()); if (!IsValidDestination(dest)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid destination address %s", entryAcceptor.GetLinkAddress().ToString())); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid destination address %s", entryRequestor.GetLinkAddress().ToString())); CScript scriptDest; std::vector vStealthData; @@ -407,7 +407,7 @@ static UniValue SendLinkAccept(const JSONRPCRequest& request) std::string sError; if (0 != PrepareStealthOutput(sxAddr, scriptDest, vStealthData, sError)) { LogPrintf("%s -- PrepareStealthOutput failed. Error = %s\n", __func__, sError); - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid stealth destination address %s", entryAcceptor.GetLinkAddress().ToString())); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid stealth destination address %s", entryRequestor.GetLinkAddress().ToString())); } fStealthAddress = true; } From 16eb85cb74cecbe25853a7d57787eea451652736 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Fri, 24 May 2019 17:26:26 -0500 Subject: [PATCH 23/36] [BDAP] Draft fee structure and utility credit system --- src/Makefile.am | 2 + src/amount.h | 1 + src/bdap/bdap.h | 4 +- src/bdap/domainentry.h | 7 +-- src/bdap/fees.cpp | 108 +++++++++++++++++++++++++++++++++++++++++ src/bdap/fees.h | 40 +++++++++++++++ src/bdap/utils.cpp | 8 +-- src/bdap/utils.h | 6 ++- 8 files changed, 163 insertions(+), 13 deletions(-) create mode 100644 src/bdap/fees.cpp create mode 100644 src/bdap/fees.h diff --git a/src/Makefile.am b/src/Makefile.am index 4e3125adc6..121cd86ca0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,6 +82,7 @@ DYNAMIC_CORE_H = \ bdap/domainentrydb.h \ bdap/certificate.h \ bdap/entrycheckpoints.h \ + bdap/fees.h \ bdap/identity.h \ bdap/linking.h \ bdap/linkingdb.h \ @@ -269,6 +270,7 @@ libdynamic_server_a_SOURCES = \ bdap/domainentrydb.cpp \ bdap/certificate.cpp \ bdap/entrycheckpoints.cpp \ + bdap/fees.cpp \ bdap/identity.cpp \ bdap/linking.cpp \ bdap/linkingdb.cpp \ diff --git a/src/amount.h b/src/amount.h index e72deb5915..9a4283c7c0 100644 --- a/src/amount.h +++ b/src/amount.h @@ -17,6 +17,7 @@ typedef int64_t CAmount; static const CAmount COIN = 100000000; static const CAmount CENT = 1000000; +static const CAmount BDAP_CREDIT = 100001; //= 0.00100001 DYN. Matches lowest PrivateSend denomination extern const std::string CURRENCY_UNIT; diff --git a/src/bdap/bdap.h b/src/bdap/bdap.h index e9cbf6797d..99fccbc302 100644 --- a/src/bdap/bdap.h +++ b/src/bdap/bdap.h @@ -18,8 +18,8 @@ namespace BDAP { BDAP_ORGANIZATIONAL_UNIT = 5, BDAP_CERTIFICATE = 6, BDAP_AUDIT = 7, - BDAP_CHANNEL = 8, - BDAP_CHECKPOINT = 9, + BDAP_SIDECHAIN = 8, + BDAP_SIDECHAIN_CHECKPOINT = 9, BDAP_LINK_REQUEST = 10, BDAP_LINK_ACCEPT = 11, BDAP_IDENTITY = 12, diff --git a/src/bdap/domainentry.h b/src/bdap/domainentry.h index 7cb3516d53..e3173141e5 100644 --- a/src/bdap/domainentry.h +++ b/src/bdap/domainentry.h @@ -6,6 +6,7 @@ #define DYNAMIC_BDAP_DOMAINENTRY_H #include "bdap.h" +#include "bdap/utils.h" #include "amount.h" #include "consensus/params.h" #include "primitives/transaction.h" @@ -38,12 +39,6 @@ class CTxMemPool; using namespace BDAP; -namespace BDAP { - std::string GetObjectTypeString(unsigned int nObjectType); - unsigned int GetObjectTypeInt(BDAP::ObjectType ObjectType); - BDAP::ObjectType GetObjectTypeEnum(unsigned int nObjectType); -} - class CDomainEntryDefaultParameters { public: void InitialiseAdminOwners(); //DEFAULT_ADMIN_DOMAIN diff --git a/src/bdap/fees.cpp b/src/bdap/fees.cpp new file mode 100644 index 0000000000..ed8414da2e --- /dev/null +++ b/src/bdap/fees.cpp @@ -0,0 +1,108 @@ +// Copyright (c) 2019 Duality Blockchain Solutions Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bdap/fees.h" + +#include "bdap/utils.h" // for GetObjectTypeString +#include "util.h" // for LogPrintf + +// Default BDAP Monthly Fees +std::map mapDefaultMonthlyFees = { + {BDAP_MONTHY_USER_FEE, 50 * BDAP_CREDIT}, + {BDAP_MONTHY_GROUP_FEE, 200 * BDAP_CREDIT}, + {BDAP_MONTHY_CERTIFICATE_FEE, 100 * BDAP_CREDIT}, + {BDAP_MONTHY_SIDECHAIN_FEE, 1000 * BDAP_CREDIT}, +}; + +// Default BDAP One Time Fees +std::map mapOneTimeFees = { + {BDAP_ONE_TIME_REQUEST_LINK_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_ACCEPT_LINK_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_AUDIT_RECORD_FEE, 100 * BDAP_CREDIT}, + {BDAP_ONE_TIME_UPDATE_USER_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_DELETE_USER_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_UPDATE_GROUP_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_DELETE_GROUP_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_UPDATE_LINK_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_DELETE_LINK_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_UPDATE_CERTIFICATE_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_DELETE_CERTIFICATE_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_UPDATE_SIDECHAIN_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_DELETE_SIDECHAIN_FEE, 1 * BDAP_CREDIT}, +}; + +// Default BDAP Non-Refundable Security Deposit Fees +std::map mapNoRefundDeposits = { + {BDAP_NON_REFUNDABLE_USER_DEPOSIT, 1000 * BDAP_CREDIT}, + {BDAP_NON_REFUNDABLE_GROUP_DEPOSIT, 10000 * BDAP_CREDIT}, + {BDAP_NON_REFUNDABLE_CERTIFICATE_DEPOSIT, 5000 * BDAP_CREDIT}, + {BDAP_NON_REFUNDABLE_SIDECHAIN_DEPOSIT, 25000 * BDAP_CREDIT}, +}; + +bool GetBDAPFees(const opcodetype& opCodeAction, const opcodetype& opCodeObject, const BDAP::ObjectType objType, const uint16_t nMonths, CAmount& monthlyFee, CAmount& oneTimeFee, CAmount& depositFee) +{ + std::string strObjectType = BDAP::GetObjectTypeString((unsigned int)objType); + LogPrintf("%s -- strObjectType = %s, OpAction %d, OpObject %d\n", __func__, strObjectType, opCodeAction, opCodeObject); + if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_ACCOUNT_ENTRY && objType == BDAP::ObjectType::BDAP_USER) { + // new BDAP user account + oneTimeFee = 0; + monthlyFee = mapDefaultMonthlyFees[BDAP_MONTHY_USER_FEE] * nMonths; + depositFee = mapNoRefundDeposits[BDAP_NON_REFUNDABLE_USER_DEPOSIT]; + + } else if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_ACCOUNT_ENTRY && objType == BDAP::ObjectType::BDAP_GROUP) { + // new BDAP group account + oneTimeFee = 0; + monthlyFee = mapDefaultMonthlyFees[BDAP_MONTHY_GROUP_FEE] * nMonths; + depositFee = mapNoRefundDeposits[BDAP_NON_REFUNDABLE_GROUP_DEPOSIT]; + + } else if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_CERTIFICATE && objType == BDAP::ObjectType::BDAP_CERTIFICATE) { + // new BDAP certificate + oneTimeFee = 0; + monthlyFee = mapDefaultMonthlyFees[BDAP_MONTHY_CERTIFICATE_FEE] * nMonths; + depositFee = mapNoRefundDeposits[BDAP_NON_REFUNDABLE_CERTIFICATE_DEPOSIT]; + + } else if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_SIDECHAIN && objType == BDAP::ObjectType::BDAP_SIDECHAIN) { + // new BDAP sidechain entry + oneTimeFee = 0; + monthlyFee = mapDefaultMonthlyFees[BDAP_MONTHY_SIDECHAIN_FEE] * nMonths; + depositFee = mapNoRefundDeposits[BDAP_NON_REFUNDABLE_SIDECHAIN_DEPOSIT]; + + } else if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_LINK_REQUEST && objType == BDAP::ObjectType::BDAP_LINK_REQUEST) { + // new BDAP sidechain entry + oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_REQUEST_LINK_FEE]; + monthlyFee = 0; + depositFee = 0; + + } else if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_LINK_ACCEPT && objType == BDAP::ObjectType::BDAP_LINK_ACCEPT) { + // new BDAP sidechain entry + oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_ACCEPT_LINK_FEE]; + monthlyFee = 0; + depositFee = 0; + + } else if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_AUDIT && objType == BDAP::ObjectType::BDAP_AUDIT) { + // new BDAP sidechain entry + oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_AUDIT_RECORD_FEE]; + monthlyFee = 0; + depositFee = 0; + + } else if (opCodeAction == OP_BDAP_MODIFY && opCodeObject == OP_BDAP_ACCOUNT_ENTRY && objType == BDAP::ObjectType::BDAP_USER) { + // new BDAP sidechain entry + oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_UPDATE_USER_FEE]; + monthlyFee = 0; + depositFee = 0; + + } else if (opCodeAction == OP_BDAP_MODIFY && opCodeObject == OP_BDAP_ACCOUNT_ENTRY && objType == BDAP::ObjectType::BDAP_GROUP) { + // new BDAP sidechain entry + oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_UPDATE_GROUP_FEE]; + monthlyFee = 0; + depositFee = 0; + + } + else { + LogPrintf("%s -- BDAP operation code pair (%d and %d) for %s not found or unsupported.\n", __func__, opCodeAction, opCodeObject, strObjectType); + return false; + } + + return true; +} \ No newline at end of file diff --git a/src/bdap/fees.h b/src/bdap/fees.h new file mode 100644 index 0000000000..2d255bff03 --- /dev/null +++ b/src/bdap/fees.h @@ -0,0 +1,40 @@ +// Copyright (c) 2019 Duality Blockchain Solutions Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef DYNAMIC_BDAP_FEES_H +#define DYNAMIC_BDAP_FEES_H + +#include "amount.h" +#include "bdap/bdap.h" +#include "script/script.h" + +#include + +static const int32_t BDAP_MONTHY_USER_FEE = 5001; +static const int32_t BDAP_MONTHY_GROUP_FEE = 5002; +static const int32_t BDAP_MONTHY_CERTIFICATE_FEE = 5003; +static const int32_t BDAP_MONTHY_SIDECHAIN_FEE = 5004; + +static const int32_t BDAP_ONE_TIME_REQUEST_LINK_FEE = 6001; +static const int32_t BDAP_ONE_TIME_ACCEPT_LINK_FEE = 6002; +static const int32_t BDAP_ONE_TIME_AUDIT_RECORD_FEE = 6003; +static const int32_t BDAP_ONE_TIME_UPDATE_USER_FEE = 6004; +static const int32_t BDAP_ONE_TIME_DELETE_USER_FEE = 6005; +static const int32_t BDAP_ONE_TIME_UPDATE_GROUP_FEE = 6006; +static const int32_t BDAP_ONE_TIME_DELETE_GROUP_FEE = 6007; +static const int32_t BDAP_ONE_TIME_UPDATE_LINK_FEE = 6008; +static const int32_t BDAP_ONE_TIME_DELETE_LINK_FEE = 6009; +static const int32_t BDAP_ONE_TIME_UPDATE_CERTIFICATE_FEE = 6010; +static const int32_t BDAP_ONE_TIME_DELETE_CERTIFICATE_FEE = 6011; +static const int32_t BDAP_ONE_TIME_UPDATE_SIDECHAIN_FEE = 6012; +static const int32_t BDAP_ONE_TIME_DELETE_SIDECHAIN_FEE = 6013; + +static const int32_t BDAP_NON_REFUNDABLE_USER_DEPOSIT = 7001; +static const int32_t BDAP_NON_REFUNDABLE_GROUP_DEPOSIT = 7002; +static const int32_t BDAP_NON_REFUNDABLE_CERTIFICATE_DEPOSIT = 7003; +static const int32_t BDAP_NON_REFUNDABLE_SIDECHAIN_DEPOSIT = 7004; + +bool GetBDAPFees(const opcodetype& opCodeAction, const opcodetype& opCodeObject, const BDAP::ObjectType objType, const uint16_t nMonths, CAmount& monthlyFee, CAmount& oneTimeFee, CAmount& depositFee); + +#endif // DYNAMIC_BDAP_FEES_H \ No newline at end of file diff --git a/src/bdap/utils.cpp b/src/bdap/utils.cpp index 2e7997d15f..3db0cda4fb 100644 --- a/src/bdap/utils.cpp +++ b/src/bdap/utils.cpp @@ -36,10 +36,10 @@ namespace BDAP { return "Certificate Entry"; case BDAP::ObjectType::BDAP_AUDIT: return "Audit Entry"; - case BDAP::ObjectType::BDAP_CHANNEL: - return "Channel Entry"; - case BDAP::ObjectType::BDAP_CHECKPOINT: - return "Channel Checkpoint Entry"; + case BDAP::ObjectType::BDAP_SIDECHAIN: + return "Sidechain Entry"; + case BDAP::ObjectType::BDAP_SIDECHAIN_CHECKPOINT: + return "Sidechain Checkpoint Entry"; case BDAP::ObjectType::BDAP_LINK_REQUEST: return "Link Request Entry"; case BDAP::ObjectType::BDAP_LINK_ACCEPT: diff --git a/src/bdap/utils.h b/src/bdap/utils.h index 10c5b70f4f..15535837b8 100644 --- a/src/bdap/utils.h +++ b/src/bdap/utils.h @@ -24,7 +24,11 @@ namespace Consensus { struct Params; } - +namespace BDAP { + std::string GetObjectTypeString(unsigned int nObjectType); + unsigned int GetObjectTypeInt(BDAP::ObjectType ObjectType); + BDAP::ObjectType GetObjectTypeEnum(unsigned int nObjectType); +} std::string BDAPFromOp(const int op); bool IsBDAPDataOutput(const CTxOut& out); From 79edaee9fea7483b7eee75fee54ca807b58c772d Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Mon, 27 May 2019 02:07:08 -0500 Subject: [PATCH 24/36] [BDAP] Use in account and link RPC commands --- src/bdap/bdap.h | 3 ++- src/bdap/fees.cpp | 14 ++++++++++ src/bdap/fees.h | 1 + src/bdap/rpcdomainentry.cpp | 50 ++++++++++++++++------------------ src/bdap/rpclinking.cpp | 54 +++++++++++++++++-------------------- src/bdap/rpcrawbdap.cpp | 29 +++++++++----------- src/rpcprotocol.h | 3 ++- 7 files changed, 79 insertions(+), 75 deletions(-) diff --git a/src/bdap/bdap.h b/src/bdap/bdap.h index 99fccbc302..d35b1a984d 100644 --- a/src/bdap/bdap.h +++ b/src/bdap/bdap.h @@ -53,7 +53,8 @@ static constexpr unsigned int DHT_HEX_PUBLIC_KEY_LENGTH = 64; // Ed25519 pubke static constexpr unsigned int MAX_BDAP_LINK_MESSAGE = 256; static constexpr unsigned int MAX_BDAP_SIGNATURE_PROOF = 90; // TODO (bdap): Update to 65 or use MAX_SIGNATURE_LENGTH when you start a new chain. static constexpr unsigned int MAX_BDAP_LINK_DATA_SIZE = 1592; -static constexpr unsigned int DEFAULT_REGISTRATION_DAYS = 731; // 2 years +static constexpr uint64_t DEFAULT_LINK_EXPIRE_TIME = 4102444800; +static constexpr int32_t DEFAULT_REGISTRATION_MONTHS = 12; // 1 year static const std::string DEFAULT_PUBLIC_DOMAIN = "bdap.io"; static const std::string DEFAULT_PUBLIC_OU = "public"; static const std::string DEFAULT_ADMIN_OU = "admin"; diff --git a/src/bdap/fees.cpp b/src/bdap/fees.cpp index ed8414da2e..fa30fd98f4 100644 --- a/src/bdap/fees.cpp +++ b/src/bdap/fees.cpp @@ -4,9 +4,12 @@ #include "bdap/fees.h" +#include "bdap/bdap.h" // for SECONDS_PER_DAY #include "bdap/utils.h" // for GetObjectTypeString #include "util.h" // for LogPrintf +#include + // Default BDAP Monthly Fees std::map mapDefaultMonthlyFees = { {BDAP_MONTHY_USER_FEE, 50 * BDAP_CREDIT}, @@ -105,4 +108,15 @@ bool GetBDAPFees(const opcodetype& opCodeAction, const opcodetype& opCodeObject, } return true; +} + +int64_t AddMonthsToCurrentEpoch(const short nMonths) +{ + boost::gregorian::date dt = boost::gregorian::day_clock::local_day(); + short nYear = dt.year() + ((dt.month() + nMonths)/12); + short nMonth = (dt.month() + nMonths) % 12; + short nDay = dt.day(); + boost::posix_time::time_duration dur = boost::posix_time::ptime(boost::gregorian::date(nYear, nMonth, nDay)) - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1)); + //LogPrintf("%s -- nYear %d, nMonth %d, nDay %d\n", __func__, nYear, nMonth, nDay); + return dur.total_seconds() + SECONDS_PER_DAY; } \ No newline at end of file diff --git a/src/bdap/fees.h b/src/bdap/fees.h index 2d255bff03..340173a511 100644 --- a/src/bdap/fees.h +++ b/src/bdap/fees.h @@ -36,5 +36,6 @@ static const int32_t BDAP_NON_REFUNDABLE_CERTIFICATE_DEPOSIT = 7003; static const int32_t BDAP_NON_REFUNDABLE_SIDECHAIN_DEPOSIT = 7004; bool GetBDAPFees(const opcodetype& opCodeAction, const opcodetype& opCodeObject, const BDAP::ObjectType objType, const uint16_t nMonths, CAmount& monthlyFee, CAmount& oneTimeFee, CAmount& depositFee); +int64_t AddMonthsToCurrentEpoch(const short nMonths); #endif // DYNAMIC_BDAP_FEES_H \ No newline at end of file diff --git a/src/bdap/rpcdomainentry.cpp b/src/bdap/rpcdomainentry.cpp index 7b0a1fbda2..543b693432 100644 --- a/src/bdap/rpcdomainentry.cpp +++ b/src/bdap/rpcdomainentry.cpp @@ -4,8 +4,8 @@ #include "bdap/domainentry.h" #include "bdap/domainentrydb.h" +#include "bdap/fees.h" #include "bdap/utils.h" -#include "dht/ed25519.h" #include "core_io.h" // needed for ScriptToAsmStr #include "dynodeman.h" #include "rpcprotocol.h" @@ -69,13 +69,12 @@ static UniValue AddDomainEntry(const JSONRPCRequest& request, BDAP::ObjectType b txDomainEntry.LinkAddress = vchFromString(sxAddr.ToString()); - int64_t nDays = DEFAULT_REGISTRATION_DAYS; // default to 2 years. + int32_t nMonths = DEFAULT_REGISTRATION_MONTHS; // default to 2 years. if (request.params.size() >= 3) { - if (!ParseInt64(request.params[2].get_str(), &nDays)) + if (!ParseInt32(request.params[2].get_str(), &nMonths)) throw std::runtime_error("BDAP_ADD_PUBLIC_ENTRY_RPC_ERROR: ERRCODE: 3505 - " + _("Error converting registration days to int")); } - int64_t nSeconds = nDays * SECONDS_PER_DAY; - txDomainEntry.nExpireTime = chainActive.Tip()->GetMedianTimePast() + nSeconds; + txDomainEntry.nExpireTime = AddMonthsToCurrentEpoch((short)nMonths); CharString data; txDomainEntry.Serialize(data); @@ -94,12 +93,11 @@ static UniValue AddDomainEntry(const JSONRPCRequest& request, BDAP::ObjectType b CScript scriptData; scriptData << OP_RETURN << data; - // Send the transaction - CWalletTx wtx; - float fYears = ((float)nDays/365.25); - CAmount nOperationFee = GetBDAPFee(scriptPubKey) * powf(3.1, fYears); - CAmount nDataFee = GetBDAPFee(scriptData) * powf(3.1, fYears); - + // Get BDAP fees + CAmount monthlyFee, oneTimeFee, depositFee; + if (!GetBDAPFees(OP_BDAP_NEW, OP_BDAP_ACCOUNT_ENTRY, bdapType, nMonths, monthlyFee, oneTimeFee, depositFee)) + throw JSONRPCError(RPC_BDAP_FEE_UNKNOWN, strprintf("Error calculating BDAP fees.")); + LogPrintf("%s -- monthlyFee %d, oneTimeFee %d, depositFee %d\n", __func__, monthlyFee, oneTimeFee, depositFee); // check BDAP values std::string strMessage; if (!txDomainEntry.ValidateValues(strMessage)) @@ -107,11 +105,11 @@ static UniValue AddDomainEntry(const JSONRPCRequest& request, BDAP::ObjectType b bool fUseInstantSend = false; if (dnodeman.EnoughActiveForInstandSend() && sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED)) { - // TODO (bdap): calculate cost for instant send. - nOperationFee = nOperationFee * 2; fUseInstantSend = true; } - SendBDAPTransaction(scriptData, scriptPubKey, wtx, nOperationFee, nDataFee, fUseInstantSend); + // Send the transaction + CWalletTx wtx; + SendBDAPTransaction(scriptData, scriptPubKey, wtx, monthlyFee, depositFee, fUseInstantSend); txDomainEntry.txHash = wtx.GetHash(); UniValue oName(UniValue::VOBJ); @@ -401,13 +399,12 @@ static UniValue UpdateDomainEntry(const JSONRPCRequest& request, BDAP::ObjectTyp txUpdatedEntry.CommonName = vchCommonName; txUpdatedEntry.nObjectType = GetObjectTypeInt(bdapType); - int64_t nDays = DEFAULT_REGISTRATION_DAYS; // default to 2 years. + int32_t nMonths = DEFAULT_REGISTRATION_MONTHS; // default to 1 year. if (request.params.size() >= 3) { - if (!ParseInt64(request.params[2].get_str(), &nDays)) + if (!ParseInt32(request.params[2].get_str(), &nMonths)) throw std::runtime_error("BDAP_UPDATE_PUBLIC_ENTRY_RPC_ERROR: ERRCODE: 3702 - " + _("Error converting registration days to int")); } - int64_t nSeconds = nDays * SECONDS_PER_DAY; - txUpdatedEntry.nExpireTime = chainActive.Tip()->GetMedianTimePast() + nSeconds; + txUpdatedEntry.nExpireTime = AddMonthsToCurrentEpoch((short)nMonths); CharString data; txUpdatedEntry.Serialize(data); @@ -427,12 +424,11 @@ static UniValue UpdateDomainEntry(const JSONRPCRequest& request, BDAP::ObjectTyp CScript scriptData; scriptData << OP_RETURN << data; - // Send the transaction - CWalletTx wtx; - float fYears = ((float)nDays/365.25); - CAmount nOperationFee = GetBDAPFee(scriptPubKey) * powf(3.1, fYears); - CAmount nDataFee = GetBDAPFee(scriptData) * powf(3.1, fYears); - + // Get BDAP fees + CAmount monthlyFee, oneTimeFee, depositFee; + if (!GetBDAPFees(OP_BDAP_MODIFY, OP_BDAP_ACCOUNT_ENTRY, bdapType, nMonths, monthlyFee, oneTimeFee, depositFee)) + throw JSONRPCError(RPC_BDAP_FEE_UNKNOWN, strprintf("Error calculating BDAP fees.")); + LogPrintf("%s -- monthlyFee %d, oneTimeFee %d, depositFee %d\n", __func__, monthlyFee, oneTimeFee, depositFee); // check BDAP values std::string strMessage; if (!txUpdatedEntry.ValidateValues(strMessage)) @@ -440,11 +436,11 @@ static UniValue UpdateDomainEntry(const JSONRPCRequest& request, BDAP::ObjectTyp bool fUseInstantSend = false; if (dnodeman.EnoughActiveForInstandSend() && sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED)) { - // TODO (bdap): calculate cost for instant send. - nOperationFee = nOperationFee * 2; fUseInstantSend = true; } - SendBDAPTransaction(scriptData, scriptPubKey, wtx, nOperationFee, nDataFee, fUseInstantSend); + // Send the transaction + CWalletTx wtx; + SendBDAPTransaction(scriptData, scriptPubKey, wtx, monthlyFee, depositFee, fUseInstantSend); txUpdatedEntry.txHash = wtx.GetHash(); UniValue oName(UniValue::VOBJ); diff --git a/src/bdap/rpclinking.cpp b/src/bdap/rpclinking.cpp index cf928bde24..6770e21ab2 100644 --- a/src/bdap/rpclinking.cpp +++ b/src/bdap/rpclinking.cpp @@ -5,6 +5,7 @@ #include "bdap/bdap.h" #include "bdap/domainentry.h" #include "bdap/domainentrydb.h" +#include "bdap/fees.h" #include "bdap/vgp/include/encryption.h" // for VGP E2E encryption #include "bdap/linking.h" #include "bdap/linkingdb.h" @@ -102,7 +103,7 @@ static bool BuildJsonLinkAcceptInfo(const CLinkAccept& link, const CDomainEntry& static UniValue SendLinkRequest(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 4 || request.params.size() > 5) + if (request.fHelp || request.params.size() != 4) throw std::runtime_error( "link request userid-from userid-to message\n" "Creates a link request transaction on the blockchain." @@ -111,7 +112,6 @@ static UniValue SendLinkRequest(const JSONRPCRequest& request) "1. requestor (string) BDAP account requesting the link\n" "2. recipient (string) Link recipient's BDAP account.\n" "3. invite message (string) Message from requestor to recipient.\n" - "4. registration days (int, optional) Number of days to keep the link request on the blockchain before pruning.\n" "\nResult:\n" "{(json object)\n" " \"Requestor FQDN\" (string) Requestor's BDAP full path\n" @@ -196,14 +196,7 @@ static UniValue SendLinkRequest(const JSONRPCRequest& request) if (!CreateSignatureProof(key, strRecipientFQDN, txLink.SignatureProof)) throw std::runtime_error("BDAP_SEND_LINK_RPC_ERROR: ERRCODE: 4008 - Error signing " + strRequestorFQDN + _("'s signature proof.")); - int64_t nDays = DEFAULT_REGISTRATION_DAYS; //default to 4 years. - if (request.params.size() > 4) { - if (!ParseInt64(request.params[4].get_str(), &nDays)) - throw std::runtime_error("BDAP_SEND_LINK_RPC_ERROR: ERRCODE: 4009 - Error parsing registration days parameter = " + request.params[4].get_str()); - } - - int64_t nSeconds = nDays * SECONDS_PER_DAY; - txLink.nExpireTime = chainActive.Tip()->GetMedianTimePast() + nSeconds; + txLink.nExpireTime = DEFAULT_LINK_EXPIRE_TIME; CKeyEd25519 dhtKey; std::vector vchSharedPubKey = GetLinkSharedPubKey(privReqDHTKey, entryRecipient.DHTPublicKey); txLink.SharedPubKey = vchSharedPubKey; @@ -265,14 +258,18 @@ static UniValue SendLinkRequest(const JSONRPCRequest& request) CScript scriptData; scriptData << OP_RETURN << dataEncrypted; + // Get BDAP fees + BDAP::ObjectType bdapType = ObjectType::BDAP_LINK_REQUEST; + int32_t nMonths = 0; // Links do not expire + CAmount monthlyFee, oneTimeFee, depositFee; + if (!GetBDAPFees(OP_BDAP_NEW, OP_BDAP_LINK_REQUEST, bdapType, nMonths, monthlyFee, oneTimeFee, depositFee)) + throw JSONRPCError(RPC_BDAP_FEE_UNKNOWN, strprintf("Error calculating BDAP fees.")); + LogPrintf("%s -- monthlyFee %d, oneTimeFee %d, depositFee %d\n", __func__, monthlyFee, oneTimeFee, depositFee); // Send the transaction CWalletTx wtx; - float fYears = ((float)nDays/365.25); - CAmount nOperationFee = GetBDAPFee(scriptPubKey) * powf(3.1, fYears); - CAmount nDataFee = (GetBDAPFee(scriptData) * powf(3.1, fYears)) + (GetBDAPFee(stealthScript) * powf(3.1, fYears)); - bool fUseInstantSend = false; - SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, nOperationFee, nDataFee, fUseInstantSend); + SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, oneTimeFee, depositFee, fUseInstantSend); + txLink.txHash = wtx.GetHash(); UniValue oLink(UniValue::VOBJ); @@ -284,7 +281,7 @@ static UniValue SendLinkRequest(const JSONRPCRequest& request) static UniValue SendLinkAccept(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 3 || request.params.size() > 4) + if (request.fHelp || request.params.size() != 3) throw std::runtime_error( "link accept userid-from userid-to\n" "Creates a link accept transaction on the blockchain." @@ -292,7 +289,6 @@ static UniValue SendLinkAccept(const JSONRPCRequest& request) "\nLink Send Arguments:\n" "1. accept account (string) BDAP account accepting the link\n" "2. requestor account (string) Link requestor's BDAP account.\n" - "3. registration days (int, optional) Number of days to keep the link accept on the blockchain before pruning.\n" "\nResult:\n" "{(json object)\n" " \"Requestor FQDN\" (string) Requestor's BDAP full path\n" @@ -377,13 +373,7 @@ static UniValue SendLinkAccept(const JSONRPCRequest& request) if (!CreateSignatureProof(key, strRequestorFQDN, txLinkAccept.SignatureProof)) throw std::runtime_error("BDAP_ACCEPT_LINK_RPC_ERROR: ERRCODE: 4110 - Error signing " + strRequestorFQDN + _("'s signature proof.")); - int64_t nDays = DEFAULT_REGISTRATION_DAYS; //default to 4 years. - if (request.params.size() > 3) { - if (!ParseInt64(request.params[3].get_str(), &nDays)) - throw std::runtime_error("BDAP_SEND_LINK_RPC_ERROR: ERRCODE: 4111 - Error parsing registration days parameter = " + request.params[3].get_str()); - } - int64_t nSeconds = nDays * SECONDS_PER_DAY; - txLinkAccept.nExpireTime = chainActive.Tip()->GetMedianTimePast() + nSeconds; + txLinkAccept.nExpireTime = DEFAULT_LINK_EXPIRE_TIME; CKeyEd25519 dhtKey; std::vector vchSharedPubKey = GetLinkSharedPubKey(privAcceptDHTKey, entryRequestor.DHTPublicKey); txLinkAccept.SharedPubKey = vchSharedPubKey; @@ -443,13 +433,17 @@ static UniValue SendLinkAccept(const JSONRPCRequest& request) CScript scriptData; scriptData << OP_RETURN << dataEncrypted; + // Get BDAP fees + BDAP::ObjectType bdapType = ObjectType::BDAP_LINK_ACCEPT; + int32_t nMonths = 0; // Links do not expire + CAmount monthlyFee, oneTimeFee, depositFee; + if (!GetBDAPFees(OP_BDAP_NEW, OP_BDAP_LINK_ACCEPT, bdapType, nMonths, monthlyFee, oneTimeFee, depositFee)) + throw JSONRPCError(RPC_BDAP_FEE_UNKNOWN, strprintf("Error calculating BDAP fees.")); + // Send the transaction CWalletTx wtx; - float fYears = ((float)nDays/365.25); - CAmount nOperationFee = GetBDAPFee(scriptPubKey) * powf(3.1, fYears); - CAmount nDataFee = (GetBDAPFee(scriptData) * powf(3.1, fYears)) + (GetBDAPFee(stealthScript) * powf(3.1, fYears)); bool fUseInstantSend = false; - SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, nOperationFee, nDataFee, fUseInstantSend); + SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, oneTimeFee, depositFee, fUseInstantSend); txLinkAccept.txHash = wtx.GetHash(); UniValue oLink(UniValue::VOBJ); @@ -912,10 +906,10 @@ static UniValue DenyLink(const JSONRPCRequest& request) oLink.push_back(Pair("list_data_size", (int)vchSerializedList.size())); oLink.push_back(Pair("list_records", nRecords)); uint16_t nVersion = 1; // VGP encryption version 1 - uint32_t nExpire = 0; // Does not expire. + uint64_t nExpire = DEFAULT_LINK_EXPIRE_TIME; // Does not expire. std::vector> vvchPubKeys; vvchPubKeys.push_back(getKey.GetPubKeyBytes()); - CDataRecord newRecord(strOperationType, nTotalSlots, vvchPubKeys, vchSerializedList, nVersion, nExpire, DHT::DataFormat::BinaryBlob); + CDataRecord newRecord(strOperationType, nTotalSlots, vvchPubKeys, vchSerializedList, nVersion, (uint32_t)nExpire, DHT::DataFormat::BinaryBlob); if (newRecord.HasError()) throw std::runtime_error("BDAP_DENY_LINK_RPC_ERROR: ERRCODE: 4245 - Error creating DHT data entry. " + newRecord.ErrorMessage() + _("\n")); diff --git a/src/bdap/rpcrawbdap.cpp b/src/bdap/rpcrawbdap.cpp index 9a05d1f4b2..0639df97b7 100644 --- a/src/bdap/rpcrawbdap.cpp +++ b/src/bdap/rpcrawbdap.cpp @@ -4,9 +4,9 @@ #include "bdap/domainentry.h" #include "bdap/domainentrydb.h" +#include "bdap/fees.h" #include "bdap/utils.h" #include "core_io.h" // for EncodeHexTx -#include "dht/ed25519.h" #include "rpcprotocol.h" #include "rpcserver.h" #include "policy/policy.h" @@ -57,12 +57,11 @@ UniValue createrawbdapaccount(const JSONRPCRequest& request) CharString vchObjectID = vchFromString(strObjectID); CharString vchCommonName = vchFromValue(request.params[1]); - int64_t nDays = DEFAULT_REGISTRATION_DAYS; //default to 2 years. + int32_t nMonths = DEFAULT_REGISTRATION_MONTHS; // default to 1 year. if (request.params.size() >= 3) { - if (!ParseInt64(request.params[2].get_str(), &nDays)) + if (!ParseInt32(request.params[2].get_str(), &nMonths)) throw std::runtime_error("BDAP_CREATE_RAW_TX_RPC_ERROR: ERRCODE: 4500 - " + _("Error converting registration days to int")); } - int64_t nSeconds = nDays * SECONDS_PER_DAY; BDAP::ObjectType bdapType = ObjectType::BDAP_USER; if (request.params.size() >= 4) { int32_t nObjectType; @@ -89,8 +88,8 @@ UniValue createrawbdapaccount(const JSONRPCRequest& request) txDomainEntry.fPublicObject = 1; // make entry public txDomainEntry.nObjectType = GetObjectTypeInt(bdapType); // Add an extra 8 hours or 28,800 seconds to expire time. - txDomainEntry.nExpireTime = chainActive.Tip()->GetMedianTimePast() + nSeconds + 28800; - + txDomainEntry.nExpireTime = AddMonthsToCurrentEpoch((short)nMonths); + // Check if name already exists if (GetDomainEntry(txDomainEntry.vchFullObjectPath(), txDomainEntry)) throw std::runtime_error("BDAP_CREATE_RAW_TX_RPC_ERROR: ERRCODE: 4503 - " + txDomainEntry.GetFullObjectPath() + _(" entry already exists. Can not add duplicate.")); @@ -121,8 +120,11 @@ UniValue createrawbdapaccount(const JSONRPCRequest& request) CharString data; txDomainEntry.Serialize(data); - // TODO (bdap): calculate real BDAP deposit once fee structure is implemented. - CAmount nBDAPDeposit(2 * COIN); + // Get BDAP fees + CAmount monthlyFee, oneTimeFee, depositFee; + if (!GetBDAPFees(OP_BDAP_NEW, OP_BDAP_ACCOUNT_ENTRY, bdapType, nMonths, monthlyFee, oneTimeFee, depositFee)) + throw JSONRPCError(RPC_BDAP_FEE_UNKNOWN, strprintf("Error calculating BDAP fees.")); + LogPrintf("%s -- monthlyFee %d, oneTimeFee %d, depositFee %d\n", __func__, monthlyFee, oneTimeFee, depositFee); // Create BDAP operation script CScript scriptPubKey; std::vector vchFullObjectPath = txDomainEntry.vchFullObjectPath(); @@ -133,9 +135,6 @@ UniValue createrawbdapaccount(const JSONRPCRequest& request) scriptDestination = GetScriptForDestination(walletAddress.Get()); scriptPubKey += scriptDestination; - // TODO (bdap): calculate BDAP registration fee once fee structure is implemented. - CAmount nBDAPRegistrationFee(3 * COIN); - // Create BDAP OP_RETURN script CScript scriptData; scriptData << OP_RETURN << data; @@ -151,19 +150,17 @@ UniValue createrawbdapaccount(const JSONRPCRequest& request) CScript stealthScript; stealthScript << OP_RETURN << vStealthData; - // TODO (bdap): decrease this amount after BDAP fee structure is implemented. - CAmount nLinkAmount(30 * COIN); - // Add the Stealth OP return data CTxOut outStealthData(0, stealthScript); rawTx.vout.push_back(outStealthData); // Add the BDAP data output - CTxOut outData(nBDAPRegistrationFee, scriptData); + CTxOut outData(monthlyFee, scriptData); rawTx.vout.push_back(outData); // Add the BDAP operation output - CTxOut outOP(nBDAPDeposit, scriptPubKey); + CTxOut outOP(depositFee, scriptPubKey); rawTx.vout.push_back(outOP); // Add the BDAP link funds output + CAmount nLinkAmount(0.0400004 * COIN); // enough for 4 links CTxOut outLinkFunds(nLinkAmount, scriptDest); rawTx.vout.push_back(outLinkFunds); diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index fd9c83a139..0d029b0925 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -82,7 +82,8 @@ enum RPCErrorCode { RPC_BDAP_SPORK_INACTIVE = -301, //! BDAP spork is not active RPC_BDAP_DB_ERROR = -302, //! BDAP database error RPC_BDAP_LINK_MNGR_ERROR = -303, //! BDAP link manager error - RPC_BDAP_ACCOUNT_NOT_FOUND = -304, //! BDAP link manager error + RPC_BDAP_ACCOUNT_NOT_FOUND = -304, //! BDAP account not found + RPC_BDAP_FEE_UNKNOWN = -305, //! BDAP fee can not be calculated //! DHT errors RPC_DHT_ERROR = -400, //! Unspecified problem with the DHT RPC_DHT_NOT_STARTED = -401, //! DHT session not started From 3c6f1fcdd323dd21d94483b806cdf28097f75764 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Tue, 28 May 2019 02:22:51 -0500 Subject: [PATCH 25/36] [BDAP] Fix issues with using fees when sending account and links --- src/bdap/bdap.h | 2 +- src/bdap/fees.cpp | 40 +++++++++++++---------------------- src/bdap/rpcdomainentry.cpp | 42 ++++++++++++++++++++----------------- src/bdap/rpclinking.cpp | 8 ++++--- src/wallet/rpcwallet.cpp | 25 +++++++++++----------- src/wallet/wallet.cpp | 4 ++-- 6 files changed, 59 insertions(+), 62 deletions(-) diff --git a/src/bdap/bdap.h b/src/bdap/bdap.h index d35b1a984d..6bdd683a6b 100644 --- a/src/bdap/bdap.h +++ b/src/bdap/bdap.h @@ -53,7 +53,7 @@ static constexpr unsigned int DHT_HEX_PUBLIC_KEY_LENGTH = 64; // Ed25519 pubke static constexpr unsigned int MAX_BDAP_LINK_MESSAGE = 256; static constexpr unsigned int MAX_BDAP_SIGNATURE_PROOF = 90; // TODO (bdap): Update to 65 or use MAX_SIGNATURE_LENGTH when you start a new chain. static constexpr unsigned int MAX_BDAP_LINK_DATA_SIZE = 1592; -static constexpr uint64_t DEFAULT_LINK_EXPIRE_TIME = 4102444800; +static constexpr uint64_t DEFAULT_LINK_EXPIRE_TIME = 1861920000; static constexpr int32_t DEFAULT_REGISTRATION_MONTHS = 12; // 1 year static const std::string DEFAULT_PUBLIC_DOMAIN = "bdap.io"; static const std::string DEFAULT_PUBLIC_OU = "public"; diff --git a/src/bdap/fees.cpp b/src/bdap/fees.cpp index fa30fd98f4..2d41f68d14 100644 --- a/src/bdap/fees.cpp +++ b/src/bdap/fees.cpp @@ -20,19 +20,9 @@ std::map mapDefaultMonthlyFees = { // Default BDAP One Time Fees std::map mapOneTimeFees = { - {BDAP_ONE_TIME_REQUEST_LINK_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_ACCEPT_LINK_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_AUDIT_RECORD_FEE, 100 * BDAP_CREDIT}, - {BDAP_ONE_TIME_UPDATE_USER_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_DELETE_USER_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_UPDATE_GROUP_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_DELETE_GROUP_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_UPDATE_LINK_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_DELETE_LINK_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_UPDATE_CERTIFICATE_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_DELETE_CERTIFICATE_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_UPDATE_SIDECHAIN_FEE, 1 * BDAP_CREDIT}, - {BDAP_ONE_TIME_DELETE_SIDECHAIN_FEE, 1 * BDAP_CREDIT}, + {BDAP_ONE_TIME_REQUEST_LINK_FEE, 99 * BDAP_CREDIT}, + {BDAP_ONE_TIME_ACCEPT_LINK_FEE, 99 * BDAP_CREDIT}, + {BDAP_ONE_TIME_AUDIT_RECORD_FEE, 99 * BDAP_CREDIT}, }; // Default BDAP Non-Refundable Security Deposit Fees @@ -72,34 +62,34 @@ bool GetBDAPFees(const opcodetype& opCodeAction, const opcodetype& opCodeObject, depositFee = mapNoRefundDeposits[BDAP_NON_REFUNDABLE_SIDECHAIN_DEPOSIT]; } else if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_LINK_REQUEST && objType == BDAP::ObjectType::BDAP_LINK_REQUEST) { - // new BDAP sidechain entry + // new BDAP link request oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_REQUEST_LINK_FEE]; monthlyFee = 0; - depositFee = 0; + depositFee = BDAP_CREDIT; } else if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_LINK_ACCEPT && objType == BDAP::ObjectType::BDAP_LINK_ACCEPT) { - // new BDAP sidechain entry + // new BDAP link accept oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_ACCEPT_LINK_FEE]; monthlyFee = 0; - depositFee = 0; + depositFee = BDAP_CREDIT; } else if (opCodeAction == OP_BDAP_NEW && opCodeObject == OP_BDAP_AUDIT && objType == BDAP::ObjectType::BDAP_AUDIT) { - // new BDAP sidechain entry + // new BDAP audit record oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_AUDIT_RECORD_FEE]; monthlyFee = 0; - depositFee = 0; + depositFee = BDAP_CREDIT; } else if (opCodeAction == OP_BDAP_MODIFY && opCodeObject == OP_BDAP_ACCOUNT_ENTRY && objType == BDAP::ObjectType::BDAP_USER) { - // new BDAP sidechain entry - oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_UPDATE_USER_FEE]; + // update BDAP user account entry + oneTimeFee = 0; monthlyFee = 0; - depositFee = 0; + depositFee = BDAP_CREDIT; } else if (opCodeAction == OP_BDAP_MODIFY && opCodeObject == OP_BDAP_ACCOUNT_ENTRY && objType == BDAP::ObjectType::BDAP_GROUP) { - // new BDAP sidechain entry - oneTimeFee = mapOneTimeFees[BDAP_ONE_TIME_UPDATE_GROUP_FEE]; + // update BDAP group account entry + oneTimeFee = 0; monthlyFee = 0; - depositFee = 0; + depositFee = BDAP_CREDIT; } else { diff --git a/src/bdap/rpcdomainentry.cpp b/src/bdap/rpcdomainentry.cpp index 543b693432..fb020ab350 100644 --- a/src/bdap/rpcdomainentry.cpp +++ b/src/bdap/rpcdomainentry.cpp @@ -18,7 +18,7 @@ #include -extern void SendBDAPTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, CWalletTx& wtxNew, const CAmount& nOPValue, const CAmount& nDataValue, const bool fUseInstantSend); +extern void SendBDAPTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, CWalletTx& wtxNew, const CAmount& nRegFee, const CAmount& nDepositFee, const bool fUseInstantSend); static constexpr bool fPrintDebug = true; @@ -109,7 +109,7 @@ static UniValue AddDomainEntry(const JSONRPCRequest& request, BDAP::ObjectType b } // Send the transaction CWalletTx wtx; - SendBDAPTransaction(scriptData, scriptPubKey, wtx, monthlyFee, depositFee, fUseInstantSend); + SendBDAPTransaction(scriptData, scriptPubKey, wtx, monthlyFee + oneTimeFee, depositFee, fUseInstantSend); txDomainEntry.txHash = wtx.GetHash(); UniValue oName(UniValue::VOBJ); @@ -141,9 +141,9 @@ UniValue adduser(const JSONRPCRequest& request) throw std::runtime_error( "adduser \"account id\" \"common name\" \"registration days\"\n" "\nArguments:\n" - "1. account id (string) The account userid\n" - "2. common name (string) The account common name used for searching\n" - "3. registration days (int, optional) Number of days to register account\n" + "1. account id (string) The account userid\n" + "2. common name (string) The account common name used for searching\n" + "3. registration months (int, optional) Number of months to register account\n" "\nAdds a new bdap.io public name account entry to the blockchain directory.\n" "\nResult:\n" "{(json object)\n" @@ -440,7 +440,7 @@ static UniValue UpdateDomainEntry(const JSONRPCRequest& request, BDAP::ObjectTyp } // Send the transaction CWalletTx wtx; - SendBDAPTransaction(scriptData, scriptPubKey, wtx, monthlyFee, depositFee, fUseInstantSend); + SendBDAPTransaction(scriptData, scriptPubKey, wtx, monthlyFee + oneTimeFee, depositFee, fUseInstantSend); txUpdatedEntry.txHash = wtx.GetHash(); UniValue oName(UniValue::VOBJ); @@ -468,9 +468,9 @@ UniValue updateuser(const JSONRPCRequest& request) throw std::runtime_error( "updateuser \"account id\" \"common name\" \"registration days\"\n" "\nArguments:\n" - "1. account id (string) The account objectid within public.bdap.io\n" - "2. common name (string) The account common name used for searching\n" - "3. registration days (int, optional) Number of additional days to register account\n" + "1. account id (string) The account objectid within public.bdap.io\n" + "2. common name (string) The account common name used for searching\n" + "3. registration months (int, optional) Number of additional months to register the account\n" "\nUpdates an existing bdap.io public name account entry in the blockchain directory.\n" "\nResult:\n" "{(json object)\n" @@ -515,9 +515,9 @@ UniValue updategroup(const JSONRPCRequest& request) throw std::runtime_error( "updategroup \"account id\" \"common name\" \"registration days\"\n" "\nArguments:\n" - "1. groupid (string) The account objectid within public.bdap.io\n" - "2. common name (string) The account common name used for searching\n" - "3. registration days (int, optional) Number of additional days to register account\n" + "1. groupid (string) The account objectid within public.bdap.io\n" + "2. common name (string) The account common name used for searching\n" + "3. registration months (int, optional) Number of additional months to register the account\n" "\nUpdates an existing bdap.io public group account entry in the blockchain directory.\n" "\nResult:\n" "{(json object)\n" @@ -598,13 +598,17 @@ static UniValue DeleteDomainEntry(const JSONRPCRequest& request, BDAP::ObjectTyp // Create empty BDAP OP_RETURN script CScript scriptData; + // Get BDAP fees + uint16_t nMonths = 0; + CAmount monthlyFee, oneTimeFee, depositFee; + if (!GetBDAPFees(OP_BDAP_DELETE, OP_BDAP_ACCOUNT_ENTRY, bdapType, nMonths, monthlyFee, oneTimeFee, depositFee)) + throw JSONRPCError(RPC_BDAP_FEE_UNKNOWN, strprintf("Error calculating BDAP fees.")); + LogPrintf("%s -- monthlyFee %d, oneTimeFee %d, depositFee %d\n", __func__, monthlyFee, oneTimeFee, depositFee); + // Send the transaction CWalletTx wtx; - CAmount nOperationFee = (GetBDAPFee(scriptPubKey) * powf(3.1, 1)) + GetDataFee(scriptPubKey); - CAmount nDataFee = 0; // No OP_RETURN data needed for deleted account transactions - bool fUseInstantSend = false; - SendBDAPTransaction(scriptData, scriptPubKey, wtx, nOperationFee, nDataFee, fUseInstantSend); + SendBDAPTransaction(scriptData, scriptPubKey, wtx, monthlyFee + oneTimeFee, depositFee, fUseInstantSend); txDeletedEntry.txHash = wtx.GetHash(); UniValue oName(UniValue::VOBJ); @@ -784,9 +788,9 @@ UniValue addgroup(const JSONRPCRequest& request) throw std::runtime_error( "addgroup \"account id\" \"common name\" \"registration days\"\n" "\nArguments:\n" - "1. account id (string) The new group account id\n" - "2. common name (string) The group account common name used for searching\n" - "3. registration days (int, optional) Number of days to register the account\n" + "1. account id (string) The new group account id\n" + "2. common name (string) The group account common name used for searching\n" + "3. registration months (int, optional) Number of months to register the account\n" "\nAdds a new bdap.io public group account entry to the blockchain directory.\n" "\nResult:\n" "{(json object)\n" diff --git a/src/bdap/rpclinking.cpp b/src/bdap/rpclinking.cpp index 6770e21ab2..fef46ba635 100644 --- a/src/bdap/rpclinking.cpp +++ b/src/bdap/rpclinking.cpp @@ -32,7 +32,8 @@ #ifdef ENABLE_WALLET extern void SendLinkingTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, const CScript& stealthScript, - CWalletTx& wtxNew, const CAmount& nOPValue, const CAmount& nDataValue, const bool fUseInstantSend); + CWalletTx& wtxNew, const CAmount& nOneTimeFee, const CAmount& nDepositFee, const bool fUseInstantSend); + static bool BuildJsonLinkRequestInfo(const CLinkRequest& link, const CDomainEntry& requestor, const CDomainEntry& recipient, UniValue& oLink) { @@ -268,7 +269,7 @@ static UniValue SendLinkRequest(const JSONRPCRequest& request) // Send the transaction CWalletTx wtx; bool fUseInstantSend = false; - SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, oneTimeFee, depositFee, fUseInstantSend); + SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, monthlyFee + oneTimeFee, depositFee, fUseInstantSend); txLink.txHash = wtx.GetHash(); @@ -443,7 +444,8 @@ static UniValue SendLinkAccept(const JSONRPCRequest& request) // Send the transaction CWalletTx wtx; bool fUseInstantSend = false; - SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, oneTimeFee, depositFee, fUseInstantSend); + SendLinkingTransaction(scriptData, scriptPubKey, stealthScript, wtx, monthlyFee + oneTimeFee, depositFee, fUseInstantSend); + txLinkAccept.txHash = wtx.GetHash(); UniValue oLink(UniValue::VOBJ); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 1bf3e63ccb..db0fd37d70 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -459,15 +459,15 @@ static void SendMoney(const CTxDestination& address, CAmount nValue, bool fSubtr } } -void SendBDAPTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, CWalletTx& wtxNew, const CAmount& nOPValue, const CAmount& nDataValue, const bool fUseInstantSend) +void SendBDAPTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, CWalletTx& wtxNew, const CAmount& nRegFee, const CAmount& nDepositFee, const bool fUseInstantSend) { CAmount curBalance = pwalletMain->GetBalance(); // Check amount - if (nOPValue <= 0) + if (nRegFee <= 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "SendBDAPTransaction invalid amount"); - if (nOPValue + nDataValue > curBalance) + if (nRegFee + nDepositFee > curBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "SendBDAPTransaction insufficient funds"); // Create and send the transaction @@ -480,11 +480,11 @@ void SendBDAPTransaction(const CScript& bdapDataScript, const CScript& bdapOPScr LogPrintf("Sending BDAP Data Script: %s\n", ScriptToAsmStr(bdapDataScript)); LogPrintf("Sending BDAP OP Script: %s\n", ScriptToAsmStr(bdapOPScript)); - if (nDataValue > 0) { - CRecipient recDataScript = {bdapDataScript, 0, false}; + if (nRegFee > 0) { + CRecipient recDataScript = {bdapDataScript, nRegFee, false}; vecSend.push_back(recDataScript); } - CRecipient recOPScript = {bdapOPScript, DEFAULT_MIN_RELAY_TX_FEE, false}; + CRecipient recOPScript = {bdapOPScript, nDepositFee, false}; vecSend.push_back(recOPScript); if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosInOut, @@ -501,15 +501,15 @@ void SendBDAPTransaction(const CScript& bdapDataScript, const CScript& bdapOPScr } void SendLinkingTransaction(const CScript& bdapDataScript, const CScript& bdapOPScript, const CScript& stealthScript, - CWalletTx& wtxNew, const CAmount& nOPValue, const CAmount& nDataValue, const bool fUseInstantSend) + CWalletTx& wtxNew, const CAmount& nOneTimeFee, const CAmount& nDepositFee, const bool fUseInstantSend) { CAmount curBalance = pwalletMain->GetBalance(); // Check amount - if (nOPValue <= 0) + if (nOneTimeFee <= 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "SendLinkingTransaction invalid amount"); - if (nOPValue + nDataValue > curBalance) + if (nOneTimeFee + nDepositFee > curBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "SendLinkingTransaction insufficient funds"); // Create and send the transaction @@ -522,8 +522,8 @@ void SendLinkingTransaction(const CScript& bdapDataScript, const CScript& bdapOP LogPrintf("Sending BDAP Linking Data Script: %s\n", ScriptToAsmStr(bdapDataScript)); LogPrintf("Sending BDAP Linking OP Script: %s\n", ScriptToAsmStr(bdapOPScript)); - if (nDataValue > 0) { - CRecipient recDataScript = {bdapDataScript, 0, false}; + if (nOneTimeFee > 0) { + CRecipient recDataScript = {bdapDataScript, nOneTimeFee, false}; vecSend.push_back(recDataScript); if (stealthScript.size() > 0) { CRecipient sendStealthData = {stealthScript, 0, false}; @@ -531,7 +531,8 @@ void SendLinkingTransaction(const CScript& bdapDataScript, const CScript& bdapOP LogPrintf("Sending Stealth Script: %s\n", ScriptToAsmStr(stealthScript)); } } - CRecipient recOPScript = {bdapOPScript, DEFAULT_MIN_RELAY_TX_FEE, false}; + CRecipient recOPScript = {bdapOPScript, nDepositFee, false}; + vecSend.push_back(recOPScript); // TODO (BDAP) Make sure it uses privatesend funds if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosInOut, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4e61bb95a9..4948f61009 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1388,8 +1388,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex UpdateKeyPoolsFromTransactions(strOpType,vvchOpParameters); if (GetOpCodeType(strOpType) == "link" && vvchOpParameters.size() > 1) { uint64_t nExpireTime = 0; - if (vvchOpParameters.size() > 2) { - nExpireTime = (uint64_t)CScriptNum(vvchOpParameters[2], false).getint(); + if (vvchOpParameters.size() > 2 && vvchOpParameters[2].size() <= 10) { + nExpireTime = (uint64_t)CScriptNum(vvchOpParameters[2], false, 10).getint(); } uint64_t nHeight = pIndex ? (uint64_t)pIndex->nHeight : (uint64_t)chainActive.Height(); std::vector vchLinkPubKey = vvchOpParameters[0]; From b2b64061d17c566f86e269e87cde3499184e249e Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Tue, 28 May 2019 03:14:33 -0500 Subject: [PATCH 26/36] [BDAP] Use UTC instead of local day for add months to current epoch --- src/bdap/fees.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bdap/fees.cpp b/src/bdap/fees.cpp index 2d41f68d14..da3b5a1e0e 100644 --- a/src/bdap/fees.cpp +++ b/src/bdap/fees.cpp @@ -102,7 +102,7 @@ bool GetBDAPFees(const opcodetype& opCodeAction, const opcodetype& opCodeObject, int64_t AddMonthsToCurrentEpoch(const short nMonths) { - boost::gregorian::date dt = boost::gregorian::day_clock::local_day(); + boost::gregorian::date dt = boost::gregorian::day_clock::universal_day(); short nYear = dt.year() + ((dt.month() + nMonths)/12); short nMonth = (dt.month() + nMonths) % 12; short nDay = dt.day(); From 37e0d97f1194f8960f69ba6738395bee48616486 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Tue, 28 May 2019 17:11:54 -0500 Subject: [PATCH 27/36] [BDAP] Add fee enforcement checking --- src/bdap/bdap.h | 1 + src/bdap/domainentrydb.cpp | 181 +++++++++++++++++++++++++++--------- src/bdap/domainentrydb.h | 16 +--- src/bdap/fees.cpp | 43 ++++++++- src/bdap/fees.h | 4 + src/bdap/linkingdb.cpp | 17 +++- src/bdap/linkingdb.h | 2 +- src/bdap/rpcdomainentry.cpp | 8 +- src/validation.cpp | 6 +- src/wallet/wallet.cpp | 4 +- 10 files changed, 211 insertions(+), 71 deletions(-) diff --git a/src/bdap/bdap.h b/src/bdap/bdap.h index 6bdd683a6b..4fffa5e3fe 100644 --- a/src/bdap/bdap.h +++ b/src/bdap/bdap.h @@ -55,6 +55,7 @@ static constexpr unsigned int MAX_BDAP_SIGNATURE_PROOF = 90; // TODO (bdap): static constexpr unsigned int MAX_BDAP_LINK_DATA_SIZE = 1592; static constexpr uint64_t DEFAULT_LINK_EXPIRE_TIME = 1861920000; static constexpr int32_t DEFAULT_REGISTRATION_MONTHS = 12; // 1 year +static constexpr bool ENFORCE_BDAP_FEES = false; // ********** TODO (BDAP): Update to true after a new testnet. static const std::string DEFAULT_PUBLIC_DOMAIN = "bdap.io"; static const std::string DEFAULT_PUBLIC_OU = "public"; static const std::string DEFAULT_ADMIN_OU = "admin"; diff --git a/src/bdap/domainentrydb.cpp b/src/bdap/domainentrydb.cpp index 54aa14a54c..0d69e2d345 100644 --- a/src/bdap/domainentrydb.cpp +++ b/src/bdap/domainentrydb.cpp @@ -4,7 +4,9 @@ #include "bdap/domainentrydb.h" +#include "amount.h" #include "base58.h" +#include "bdap/fees.h" #include "coins.h" #include "bdap/utils.h" #include "validation.h" @@ -351,12 +353,30 @@ static bool CommonDataCheck(const CDomainEntry& entry, const vchCharString& vvch return false; } + if (vvchOpParameters.size() != 3) + { + errorMessage = "CommonDataCheck failed! Not enough parameters."; + return false; + } + if (entry.GetFullObjectPath() != stringFromVch(vvchOpParameters[0])) { errorMessage = "CommonDataCheck failed! Script operation parameter does not match entry entry object."; return false; } + if (entry.DHTPublicKey != vvchOpParameters[1]) + { + errorMessage = "CommonDataCheck failed! DHT public key mismatch."; + return false; + } + + if (vvchOpParameters[2].size() > 10) + { + errorMessage = "CommonDataCheck failed! Expire date or expire months invalid."; + return false; + } + if (entry.DomainComponent != vchDefaultDomainName) { errorMessage = "CommonDataCheck failed! Must use default domain."; @@ -378,7 +398,7 @@ static bool CommonDataCheck(const CDomainEntry& entry, const vchCharString& vvch return true; } -bool CheckNewDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, const uint256& txHash, +static bool CheckNewDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, const uint256& txHash, std::string& errorMessage, bool fJustCheck) { if (!CommonDataCheck(entry, vvchOpParameters, errorMessage)) @@ -415,7 +435,7 @@ bool CheckNewDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scrip return FlushLevelDB(); } -bool CheckDeleteDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, +static bool CheckDeleteDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, std::string& errorMessage, bool fJustCheck) { if (vvchOpParameters.size() == 0) { @@ -473,7 +493,7 @@ bool CheckDeleteDomainEntryTxInputs(const CDomainEntry& entry, const CScript& sc return FlushLevelDB(); } -bool CheckUpdateDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, const uint256& txHash, +static bool CheckUpdateDomainEntryTxInputs(CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, const uint256& txHash, const int& nMonths, const uint32_t& nBlockTime, std::string& errorMessage, bool fJustCheck) { //if exists, check for owner's signature @@ -523,7 +543,12 @@ bool CheckUpdateDomainEntryTxInputs(const CDomainEntry& entry, const CScript& sc return error(errorMessage.c_str()); } } - + if (nMonths < 10000) { + entry.nExpireTime = prevDomainEntry.nExpireTime + AddMonthsToBlockTime(nBlockTime, nMonths); + } + else { + entry.nExpireTime = nMonths; + } if (!pDomainEntryDB->UpdateDomainEntry(entry.vchFullObjectPath(), entry)) { errorMessage = "CheckUpdateDomainEntryTxInputs: - Error updating entry in LevelDB; this update operation failed!"; @@ -533,7 +558,7 @@ bool CheckUpdateDomainEntryTxInputs(const CDomainEntry& entry, const CScript& sc return FlushLevelDB(); } -bool CheckMoveDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, +static bool CheckMoveDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, std::string& errorMessage, bool fJustCheck) { //check name in operation matches entry data in leveldb @@ -542,36 +567,8 @@ bool CheckMoveDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scri return false; } -bool CheckExecuteDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, - std::string& errorMessage, bool fJustCheck) -{ - //check name in operation matches entry data in leveldb - //check if exists already - //if exists, check for owner's signature - return false; -} - -bool CheckBindDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, - std::string& errorMessage, bool fJustCheck) -{ - //check names in operation matches entry data in leveldb - //check if request or accept response - //check if names exists already - //if exists, check for owner's signature - return false; -} - -bool CheckRevokeDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, - std::string& errorMessage, bool fJustCheck) -{ - //check name in operation matches entry data in leveldb - //check if names exists already - //if exists, check for fluid signature - return false; -} - bool CheckDomainEntryTx(const CTransactionRef& tx, const CScript& scriptOp, const int& op1, const int& op2, const std::vector >& vvchArgs, - bool fJustCheck, int nHeight, std::string& errorMessage, bool bSanityCheck) + const bool fJustCheck, const int& nHeight, const uint32_t& nBlockTime, const bool bSanityCheck, std::string& errorMessage) { if (tx->IsCoinBase() && !fJustCheck && !bSanityCheck) { @@ -579,8 +576,8 @@ bool CheckDomainEntryTx(const CTransactionRef& tx, const CScript& scriptOp, cons return true; } - LogPrint("bdap", "%s -- *** BDAP nHeight=%d, chainActive.Tip()=%d, op1=%s, op2=%s, hash=%s justcheck=%s\n", __func__, nHeight, chainActive.Tip()->nHeight, BDAPFromOp(op1).c_str(), BDAPFromOp(op2).c_str(), tx->GetHash().ToString().c_str(), fJustCheck ? "JUSTCHECK" : "BLOCK"); - + LogPrintf("%s -- *** BDAP nHeight=%d, chainActive.Tip()=%d, op1=%s, op2=%s, hash=%s justcheck=%s\n", __func__, nHeight, chainActive.Tip()->nHeight, BDAPFromOp(op1).c_str(), BDAPFromOp(op2).c_str(), tx->GetHash().ToString().c_str(), fJustCheck ? "JUSTCHECK" : "BLOCK"); + // unserialize BDAP from txn, check if the entry is valid and does not conflict with a previous entry CDomainEntry entry; std::vector vchData; @@ -606,16 +603,114 @@ bool CheckDomainEntryTx(const CTransactionRef& tx, const CScript& scriptOp, cons entry.txHash = tx->GetHash(); entry.nHeight = nHeight; } - if (strOperationType == "bdap_new_account") + + CAmount monthlyFee, oneTimeFee, depositFee; + if (strOperationType == "bdap_new_account") { + if (vvchArgs.size() != 3) { + errorMessage = "Failed to get fees to add a new BDAP account"; + return false; + } + int nMonths = CScriptNum(vvchArgs[2], false, 10).getint(); + if (nMonths >= 10000) + nMonths = 24; + if (nMonths < 10000 && !GetBDAPFees(OP_BDAP_NEW, OP_BDAP_ACCOUNT_ENTRY, entry.ObjectType(), nMonths, monthlyFee, oneTimeFee, depositFee)) { + errorMessage = "Failed to get fees to add a new BDAP account"; + return false; + } + // extract amounts from tx. + CAmount dataAmount, opAmount; + if (!ExtractAmountsFromTx(tx, dataAmount, opAmount)) { + errorMessage = "Unable to extract BDAP amounts from transaction"; + return false; + } + // check if fees equal or exceed tx amounts. Use ENFORCE_BDAP_FEES for now. If ENFORCE_BDAP_FEES = false, just print the error. + if (monthlyFee > dataAmount) { + if (ENFORCE_BDAP_FEES) { + errorMessage = "Invalid BDAP monthly registration fee amount for new BDAP account"; + return false; + } + else { + LogPrintf("%s -- Invalid BDAP monthly registration fee amount for new BDAP account. Monthly paid %d but should be %d. Fees not enforced.\n", __func__, dataAmount, monthlyFee); + } + } + else { + LogPrintf("%s -- *** Valid BDAP monthly registration fee amount for new BDAP account. Monthly paid %d, should be %d.\n", __func__, dataAmount, monthlyFee); + } + if (depositFee > opAmount) { + if (ENFORCE_BDAP_FEES) { + errorMessage = "Invalid BDAP deposit fee amount for new BDAP account"; + return false; + } + else { + LogPrintf("%s -- Invalid BDAP deposit fee amount for new BDAP account. Deposit paid %d but should be %d. Fees not enforced.\n", __func__, opAmount, depositFee); + } + } + else { + LogPrintf("%s -- *** Valid BDAP deposit fee amount for new BDAP account. Deposit paid %d, should be %d\n", __func__, opAmount, depositFee); + } + if (nMonths < 10000) { + entry.nExpireTime = AddMonthsToBlockTime(nBlockTime, nMonths); + } + else { + entry.nExpireTime = nMonths; + } + return CheckNewDomainEntryTxInputs(entry, scriptOp, vvchArgs, tx->GetHash(), errorMessage, fJustCheck); - else if (strOperationType == "bdap_delete_account") + } + else if (strOperationType == "bdap_delete_account") { + uint16_t nMonths = 0; + if (!GetBDAPFees(OP_BDAP_DELETE, OP_BDAP_ACCOUNT_ENTRY, entry.ObjectType(), nMonths, monthlyFee, oneTimeFee, depositFee)) { + errorMessage = "Failed to get fees to delete a BDAP account"; + return false; + } + return CheckDeleteDomainEntryTxInputs(entry, scriptOp, vvchArgs, errorMessage, fJustCheck); - else if (strOperationType == "bdap_update_account") - return CheckUpdateDomainEntryTxInputs(entry, scriptOp, vvchArgs, tx->GetHash(), errorMessage, fJustCheck); - else if (strOperationType == "bdap_move_account") + } + else if (strOperationType == "bdap_update_account") { + if (vvchArgs.size() != 3) { + errorMessage = "Failed to get fees to add a new BDAP account"; + return false; + } + int nMonths = CScriptNum(vvchArgs[2], false, 10).getint(); + if (nMonths >= 10000) + nMonths = 24; + if (!GetBDAPFees(OP_BDAP_MODIFY, OP_BDAP_ACCOUNT_ENTRY, entry.ObjectType(), nMonths, monthlyFee, oneTimeFee, depositFee)) { + errorMessage = "Failed to get fees to add a new BDAP account"; + return false; + } + // extract amounts from tx. + CAmount dataAmount, opAmount; + if (!ExtractAmountsFromTx(tx, dataAmount, opAmount)) { + errorMessage = "Unable to extract BDAP amounts from transaction"; + return false; + } + // check if fees equal or exceed tx amounts. Use ENFORCE_BDAP_FEES for now. If ENFORCE_BDAP_FEES = false, just print the error. + if (monthlyFee + oneTimeFee + depositFee > dataAmount + opAmount) { + if (ENFORCE_BDAP_FEES) { + errorMessage = "Invalid BDAP deposit fee amount for updated BDAP account"; + return false; + } + else { + LogPrintf("%s -- Invalid BDAP deposit fee amount for updated BDAP account. Total paid %d but should be %d. Fees not enforced.\n", __func__, + (dataAmount + opAmount), (monthlyFee + oneTimeFee + depositFee)); + } + } + else { + LogPrintf("%s -- *** Valid BDAP deposit fee amount for updated BDAP account. Total paid %d, should be %d\n", __func__, + (dataAmount + opAmount), (monthlyFee + oneTimeFee + depositFee)); + } + // Add previous expire date plus additional months + return CheckUpdateDomainEntryTxInputs(entry, scriptOp, vvchArgs, tx->GetHash(), nMonths, nBlockTime, errorMessage, fJustCheck); + } + else if (strOperationType == "bdap_move_account") { + uint16_t nMonths = 0; + if (!GetBDAPFees(OP_BDAP_MODIFY_RDN, OP_BDAP_ACCOUNT_ENTRY, entry.ObjectType(), nMonths, monthlyFee, oneTimeFee, depositFee)) { + errorMessage = "Failed to get fees to move a BDAP account to another domain"; + return false; + } + return CheckMoveDomainEntryTxInputs(entry, scriptOp, vvchArgs, errorMessage, fJustCheck); - else if (strOperationType == "bdap_revoke_account") - return CheckRevokeDomainEntryTxInputs(entry, scriptOp, vvchArgs, errorMessage, fJustCheck); + } return false; } diff --git a/src/bdap/domainentrydb.h b/src/bdap/domainentrydb.h index 574b7c9675..6e2688f395 100644 --- a/src/bdap/domainentrydb.h +++ b/src/bdap/domainentrydb.h @@ -46,22 +46,8 @@ bool DeleteDomainEntry(const CDomainEntry& entry); bool CheckDomainEntryDB(); bool FlushLevelDB(); void CleanupLevelDB(int& nRemoved); -bool CheckNewDomainEntryTxInputs(const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, const uint256& txHash, - std::string& errorMessage, bool fJustCheck); -bool CheckDeleteDomainEntryTxInputs(const CTransaction& tx, const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, - std::string& errorMessage, bool fJustCheck); -bool CheckUpdateDomainEntryTxInputs(const CTransaction& tx, const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, const uint256& txHash, - std::string& errorMessage, bool fJustCheck); -bool CheckMoveDomainEntryTxInputs(const CTransaction& tx, const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, - std::string& errorMessage, bool fJustCheck); -bool CheckExecuteDomainEntryTxInputs(const CTransaction& tx, const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, - std::string& errorMessage, bool fJustCheck); -bool CheckBindDomainEntryTxInputs(const CTransaction& tx, const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, - std::string& errorMessage, bool fJustCheck); -bool CheckRevokeDomainEntryTxInputs(const CTransaction& tx, const CDomainEntry& entry, const CScript& scriptOp, const vchCharString& vvchOpParameters, - std::string& errorMessage, bool fJustCheck); bool CheckDomainEntryTx(const CTransactionRef& tx, const CScript& scriptOp, const int& op1, const int& op2, const std::vector >& vvchArgs, - bool fJustCheck, int nHeight, std::string& errorMessage, bool bSanityCheck); + const bool fJustCheck, const int& nHeight, const uint32_t& nBlockTime, const bool bSanityCheck, std::string& errorMessage); extern CDomainEntryDB *pDomainEntryDB; diff --git a/src/bdap/fees.cpp b/src/bdap/fees.cpp index da3b5a1e0e..e538b32246 100644 --- a/src/bdap/fees.cpp +++ b/src/bdap/fees.cpp @@ -90,7 +90,11 @@ bool GetBDAPFees(const opcodetype& opCodeAction, const opcodetype& opCodeObject, oneTimeFee = 0; monthlyFee = 0; depositFee = BDAP_CREDIT; - + } else if (objType == BDAP::ObjectType::BDAP_DEFAULT_TYPE) { + // ********** TODO (BDAP): Remove this + oneTimeFee = 0; + monthlyFee = 0; + depositFee = BDAP_CREDIT; } else { LogPrintf("%s -- BDAP operation code pair (%d and %d) for %s not found or unsupported.\n", __func__, opCodeAction, opCodeObject, strObjectType); @@ -109,4 +113,41 @@ int64_t AddMonthsToCurrentEpoch(const short nMonths) boost::posix_time::time_duration dur = boost::posix_time::ptime(boost::gregorian::date(nYear, nMonth, nDay)) - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1)); //LogPrintf("%s -- nYear %d, nMonth %d, nDay %d\n", __func__, nYear, nMonth, nDay); return dur.total_seconds() + SECONDS_PER_DAY; +} + +int64_t AddMonthsToBlockTime(const uint32_t& nBlockTime, const short nMonths) +{ + boost::gregorian::date dt = boost::posix_time::from_time_t(nBlockTime).date(); + short nYear = dt.year() + ((dt.month() + nMonths)/12); + short nMonth = (dt.month() + nMonths) % 12; + short nDay = dt.day(); + boost::posix_time::time_duration dur = boost::posix_time::ptime(boost::gregorian::date(nYear, nMonth, nDay)) - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1)); + //LogPrintf("%s -- nYear %d, nMonth %d, nDay %d\n", __func__, nYear, nMonth, nDay); + return dur.total_seconds() + SECONDS_PER_DAY; +} + +uint16_t MonthsFromBlockToExpire(const uint32_t& nBlockTime, const uint64_t& nExpireTime) +{ + boost::gregorian::date dtBlock = boost::posix_time::from_time_t(nBlockTime).date(); + boost::gregorian::date dtExpire = boost::posix_time::from_time_t(nExpireTime).date(); + return (uint16_t)((dtExpire.year() - dtBlock.year())*12 + dtExpire.month() - dtBlock.month()); +} + +bool ExtractAmountsFromTx(const CTransactionRef& ptx, CAmount& dataAmount, CAmount& opAmount) +{ + bool fDataFound = false, fOpFound = false; + for (const CTxOut& out : ptx->vout) { + if (out.scriptPubKey.IsUnspendable() && out.scriptPubKey.size() > 40) + { + dataAmount = out.nValue; + fDataFound = true; + } + int op1, op2; + std::vector> vOpArgs; + if (DecodeBDAPScript(out.scriptPubKey, op1, op2, vOpArgs)) { + opAmount = out.nValue; + fOpFound = true; + } + } + return (fDataFound && fOpFound); } \ No newline at end of file diff --git a/src/bdap/fees.h b/src/bdap/fees.h index 340173a511..143d0da401 100644 --- a/src/bdap/fees.h +++ b/src/bdap/fees.h @@ -7,6 +7,7 @@ #include "amount.h" #include "bdap/bdap.h" +#include "primitives/transaction.h" #include "script/script.h" #include @@ -37,5 +38,8 @@ static const int32_t BDAP_NON_REFUNDABLE_SIDECHAIN_DEPOSIT = 7004; bool GetBDAPFees(const opcodetype& opCodeAction, const opcodetype& opCodeObject, const BDAP::ObjectType objType, const uint16_t nMonths, CAmount& monthlyFee, CAmount& oneTimeFee, CAmount& depositFee); int64_t AddMonthsToCurrentEpoch(const short nMonths); +int64_t AddMonthsToBlockTime(const uint32_t& nBlockTime, const short nMonths); +uint16_t MonthsFromBlockToExpire(const uint32_t& nBlockTime, const uint64_t& nExpireTime); +bool ExtractAmountsFromTx(const CTransactionRef& ptx, CAmount& dataAmount, CAmount& opAmount); #endif // DYNAMIC_BDAP_FEES_H \ No newline at end of file diff --git a/src/bdap/linkingdb.cpp b/src/bdap/linkingdb.cpp index d3a913920a..5676f0bdd0 100644 --- a/src/bdap/linkingdb.cpp +++ b/src/bdap/linkingdb.cpp @@ -4,6 +4,8 @@ #include "bdap/linkingdb.h" +#include "amount.h" +#include "bdap/fees.h" #include "bdap/utils.h" #include "base58.h" #include "validation.h" @@ -276,7 +278,7 @@ static bool CheckNewLinkAcceptTx(const CScript& scriptData, const vchCharString& } bool CheckLinkTx(const CTransactionRef& tx, const int& op1, const int& op2, const std::vector >& vvchArgs, - bool fJustCheck, int nHeight, std::string& errorMessage, bool bSanityCheck) + const bool fJustCheck, const int& nHeight, const uint32_t& nBlockTime, const bool bSanityCheck, std::string& errorMessage) { if (tx->IsCoinBase() && !fJustCheck && !bSanityCheck) { LogPrintf("%s -- Trying to add BDAP link in coinbase transaction, skipping...\n", __func__); @@ -292,10 +294,23 @@ bool CheckLinkTx(const CTransactionRef& tx, const int& op1, const int& op2, cons const std::string strOperationType = GetBDAPOpTypeString(op1, op2); + CAmount monthlyFee, oneTimeFee, depositFee; if (strOperationType == "bdap_new_link_request") { + uint16_t nMonths = 0; + if (!GetBDAPFees(OP_BDAP_NEW, OP_BDAP_LINK_REQUEST, BDAP::ObjectType::BDAP_LINK_REQUEST, nMonths, monthlyFee, oneTimeFee, depositFee)) { + errorMessage = "Failed to get BDAP fees for new link request"; + return false; + } + return CheckNewLinkRequestTx(scriptData, vvchArgs, tx->GetHash(), errorMessage, fJustCheck); } else if (strOperationType == "bdap_new_link_accept") { + uint16_t nMonths = 0; + if (!GetBDAPFees(OP_BDAP_NEW, OP_BDAP_LINK_ACCEPT, BDAP::ObjectType::BDAP_LINK_ACCEPT, nMonths, monthlyFee, oneTimeFee, depositFee)) { + errorMessage = "Failed to get BDAP fees for new link accept"; + return false; + } + return CheckNewLinkAcceptTx(scriptData, vvchArgs, tx->GetHash(), errorMessage, fJustCheck); } diff --git a/src/bdap/linkingdb.h b/src/bdap/linkingdb.h index 4b67ae1ea0..a6f7f5d2aa 100644 --- a/src/bdap/linkingdb.h +++ b/src/bdap/linkingdb.h @@ -46,7 +46,7 @@ bool CheckLinkDBs(); bool FlushLinkRequestDB(); bool FlushLinkAcceptDB(); bool CheckLinkTx(const CTransactionRef& tx, const int& op1, const int& op2, const std::vector >& vvchArgs, - bool fJustCheck, int nHeight, std::string& errorMessage, bool bSanityCheck); + const bool fJustCheck, const int& nHeight, const uint32_t& nBlockTime, const bool bSanityCheck, std::string& errorMessage); bool CheckPreviousLinkInputs(const std::string& strOpType, const CScript& scriptOp, const std::vector>& vvchOpParameters, std::string& errorMessage, bool fJustCheck); diff --git a/src/bdap/rpcdomainentry.cpp b/src/bdap/rpcdomainentry.cpp index fb020ab350..c00c2e8a0a 100644 --- a/src/bdap/rpcdomainentry.cpp +++ b/src/bdap/rpcdomainentry.cpp @@ -74,7 +74,7 @@ static UniValue AddDomainEntry(const JSONRPCRequest& request, BDAP::ObjectType b if (!ParseInt32(request.params[2].get_str(), &nMonths)) throw std::runtime_error("BDAP_ADD_PUBLIC_ENTRY_RPC_ERROR: ERRCODE: 3505 - " + _("Error converting registration days to int")); } - txDomainEntry.nExpireTime = AddMonthsToCurrentEpoch((short)nMonths); + //txDomainEntry.nExpireTime = AddMonthsToCurrentEpoch((short)nMonths); CharString data; txDomainEntry.Serialize(data); @@ -83,7 +83,7 @@ static UniValue AddDomainEntry(const JSONRPCRequest& request, BDAP::ObjectType b CScript scriptPubKey; std::vector vchFullObjectPath = txDomainEntry.vchFullObjectPath(); scriptPubKey << CScript::EncodeOP_N(OP_BDAP_NEW) << CScript::EncodeOP_N(OP_BDAP_ACCOUNT_ENTRY) - << vchFullObjectPath << txDomainEntry.DHTPublicKey << txDomainEntry.nExpireTime << OP_2DROP << OP_2DROP << OP_DROP; + << vchFullObjectPath << txDomainEntry.DHTPublicKey << nMonths << OP_2DROP << OP_2DROP << OP_DROP; CScript scriptDestination; scriptDestination = GetScriptForDestination(walletAddress.Get()); @@ -404,7 +404,7 @@ static UniValue UpdateDomainEntry(const JSONRPCRequest& request, BDAP::ObjectTyp if (!ParseInt32(request.params[2].get_str(), &nMonths)) throw std::runtime_error("BDAP_UPDATE_PUBLIC_ENTRY_RPC_ERROR: ERRCODE: 3702 - " + _("Error converting registration days to int")); } - txUpdatedEntry.nExpireTime = AddMonthsToCurrentEpoch((short)nMonths); + //txUpdatedEntry.nExpireTime = AddMonthsToCurrentEpoch((short)nMonths); CharString data; txUpdatedEntry.Serialize(data); @@ -413,7 +413,7 @@ static UniValue UpdateDomainEntry(const JSONRPCRequest& request, BDAP::ObjectTyp CScript scriptPubKey; std::vector vchFullObjectPath = txUpdatedEntry.vchFullObjectPath(); scriptPubKey << CScript::EncodeOP_N(OP_BDAP_MODIFY) << CScript::EncodeOP_N(OP_BDAP_ACCOUNT_ENTRY) - << vchFullObjectPath << txUpdatedEntry.DHTPublicKey << txUpdatedEntry.nExpireTime << OP_2DROP << OP_2DROP << OP_DROP; + << vchFullObjectPath << txUpdatedEntry.DHTPublicKey << nMonths << OP_2DROP << OP_2DROP << OP_DROP; CDynamicAddress walletAddress(stringFromVch(txUpdatedEntry.WalletAddress)); CScript scriptDestination; diff --git a/src/validation.cpp b/src/validation.cpp index abdd90146e..7b370e4b84 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -657,7 +657,7 @@ bool ValidateBDAPInputs(const CTransactionRef& tx, CValidationState& state, cons std::string strOpType = GetBDAPOpTypeString(op1, op2); if (strOpType == "bdap_new_account" || strOpType == "bdap_update_account" || strOpType == "bdap_delete_account") { - bValid = CheckDomainEntryTx(tx, scriptOp, op1, op2, vvchBDAPArgs, fJustCheck, nHeight, errorMessage, bSanity); + bValid = CheckDomainEntryTx(tx, scriptOp, op1, op2, vvchBDAPArgs, fJustCheck, nHeight, block.nTime, bSanity, errorMessage); if (!bValid) { errorMessage = "ValidateBDAPInputs: " + errorMessage; return state.DoS(100, false, REJECT_INVALID, errorMessage); @@ -668,7 +668,7 @@ bool ValidateBDAPInputs(const CTransactionRef& tx, CValidationState& state, cons else if (strOpType == "bdap_new_link_request") { std::vector vchPubKey = vvchBDAPArgs[0]; LogPrint("bdap", "%s -- New Link Request vchPubKey = %s\n", __func__, stringFromVch(vchPubKey)); - bValid = CheckLinkTx(tx, op1, op2, vvchBDAPArgs, fJustCheck, nHeight, errorMessage, bSanity); + bValid = CheckLinkTx(tx, op1, op2, vvchBDAPArgs, fJustCheck, nHeight, block.nTime, bSanity, errorMessage); if (!bValid) { errorMessage = "ValidateBDAPInputs: CheckLinkTx failed: " + errorMessage; return state.DoS(100, false, REJECT_INVALID, errorMessage); @@ -686,7 +686,7 @@ bool ValidateBDAPInputs(const CTransactionRef& tx, CValidationState& state, cons else if (strOpType == "bdap_new_link_accept") { std::vector vchPubKey = vvchBDAPArgs[0]; LogPrint("bdap", "%s -- New Link Accept vchPubKey = %s\n", __func__, stringFromVch(vchPubKey)); - bValid = CheckLinkTx(tx, op1, op2, vvchBDAPArgs, fJustCheck, nHeight, errorMessage, bSanity); + bValid = CheckLinkTx(tx, op1, op2, vvchBDAPArgs, fJustCheck, nHeight, block.nTime, bSanity, errorMessage); if (!bValid) { errorMessage = "ValidateBDAPInputs: CheckLinkTx failed: " + errorMessage; return state.DoS(100, false, REJECT_INVALID, errorMessage); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4948f61009..1faa8bd3f7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1388,10 +1388,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex UpdateKeyPoolsFromTransactions(strOpType,vvchOpParameters); if (GetOpCodeType(strOpType) == "link" && vvchOpParameters.size() > 1) { uint64_t nExpireTime = 0; - if (vvchOpParameters.size() > 2 && vvchOpParameters[2].size() <= 10) { - nExpireTime = (uint64_t)CScriptNum(vvchOpParameters[2], false, 10).getint(); - } uint64_t nHeight = pIndex ? (uint64_t)pIndex->nHeight : (uint64_t)chainActive.Height(); + // get block time from height. std::vector vchLinkPubKey = vvchOpParameters[0]; std::vector vchSharedPubKey = vvchOpParameters[1]; CWalletDB walletdb(strWalletFile); From e01181f6b6c50574003c44f417f94fcb9d681ab9 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Tue, 28 May 2019 17:16:12 -0500 Subject: [PATCH 28/36] [BDAP] Remove unused functions and methods --- src/bdap/utils.cpp | 22 ---------------------- src/bdap/utils.h | 3 --- src/script/script.h | 1 - 3 files changed, 26 deletions(-) diff --git a/src/bdap/utils.cpp b/src/bdap/utils.cpp index 3db0cda4fb..88cfc21de6 100644 --- a/src/bdap/utils.cpp +++ b/src/bdap/utils.cpp @@ -215,17 +215,6 @@ void CreateFeeRecipient(CScript& scriptPubKey, const std::vector& recipient = recp; } -CAmount GetDataFee(const CScript& scriptPubKey) -{ - CAmount nFee = 0; - CRecipient recp = {scriptPubKey, 0, false}; - CTxOut txout(0, scriptPubKey); - size_t nSize = GetSerializeSize(txout, SER_DISK,0)+148u; - nFee = CWallet::GetMinimumFee(nSize, nTxConfirmTarget, mempool); - recp.nAmount = nFee; - return recp.nAmount; -} - void ToLowerCase(CharString& vchValue) { std::string strValue; CharString::const_iterator vi = vchValue.begin(); @@ -245,17 +234,6 @@ void ToLowerCase(std::string& strValue) { } } -CAmount GetBDAPFee(const CScript& scriptPubKey) -{ - CAmount nFee = 0; - CRecipient recp = {scriptPubKey, 0, false}; - CTxOut txout(0, scriptPubKey); - size_t nSize = GetSerializeSize(txout, SER_DISK,0)+148u; - nFee = CWallet::GetMinimumFee(nSize, nTxConfirmTarget, mempool); - recp.nAmount = nFee; - return recp.nAmount; -} - bool DecodeBDAPTx(const CTransactionRef& tx, int& op1, int& op2, std::vector >& vvch) { bool found = false; diff --git a/src/bdap/utils.h b/src/bdap/utils.h index 15535837b8..1ebc1d7f29 100644 --- a/src/bdap/utils.h +++ b/src/bdap/utils.h @@ -6,7 +6,6 @@ #define DYNAMIC_BDAP_UTILS_H #include "bdap/bdap.h" -#include "amount.h" #include "primitives/transaction.h" #include @@ -42,8 +41,6 @@ std::vector vchFromString(const std::string& str); void CreateRecipient(const CScript& scriptPubKey, CRecipient& recipient); void ToLowerCase(CharString& vchValue); void ToLowerCase(std::string& strValue); -CAmount GetDataFee(const CScript& scriptPubKey); -CAmount GetBDAPFee(const CScript& scriptPubKey); bool DecodeBDAPTx(const CTransactionRef& tx, int& op1, int& op2, std::vector >& vvch); bool FindBDAPInTx(const CCoinsViewCache &inputs, const CTransaction& tx, std::vector >& vvch); int GetBDAPOpType(const CScript& script); diff --git a/src/script/script.h b/src/script/script.h index 5750737e65..f5097f8b27 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -756,7 +756,6 @@ class CReserveScript }; // TODO: Use a seperate code file for these BDAP functions -bool IsDirectoryOp(int op); bool DecodeBDAPScript(const CScript& script, int& op, int& op2, std::vector >& vvch, CScript::const_iterator& pc); bool DecodeBDAPScript(const CScript& script, int& op1, int& op2, std::vector >& vvch); bool RemoveBDAPScript(const CScript& scriptIn, CScript& scriptOut); From 0c1e5a684af86bc0a58cd53fb95cd2c049e7a331 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Wed, 29 May 2019 00:26:43 -0500 Subject: [PATCH 29/36] [BDAP] Check link fee amounts --- src/bdap/linkingdb.cpp | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/bdap/linkingdb.cpp b/src/bdap/linkingdb.cpp index 5676f0bdd0..79edda969b 100644 --- a/src/bdap/linkingdb.cpp +++ b/src/bdap/linkingdb.cpp @@ -292,6 +292,13 @@ bool CheckLinkTx(const CTransactionRef& tx, const int& op1, const int& op2, cons if (!GetBDAPDataScript(tx, scriptData)) return false; + // extract amounts from tx. + CAmount dataAmount, opAmount; + if (!ExtractAmountsFromTx(tx, dataAmount, opAmount)) { + errorMessage = "Unable to extract BDAP amounts from transaction"; + return false; + } + const std::string strOperationType = GetBDAPOpTypeString(op1, op2); CAmount monthlyFee, oneTimeFee, depositFee; @@ -301,7 +308,21 @@ bool CheckLinkTx(const CTransactionRef& tx, const int& op1, const int& op2, cons errorMessage = "Failed to get BDAP fees for new link request"; return false; } - + // check if fees equal or exceed tx amounts. Use ENFORCE_BDAP_FEES for now. If ENFORCE_BDAP_FEES = false, just print the error. + if (monthlyFee + oneTimeFee + depositFee > dataAmount + opAmount) { + if (ENFORCE_BDAP_FEES) { + errorMessage = "Invalid BDAP fee amount for a new BDAP link request"; + return false; + } + else { + LogPrintf("%s -- Invalid BDAP fee amount for a new BDAP link request. Total paid %d but should be %d. Fees not enforced.\n", __func__, + (dataAmount + opAmount), (monthlyFee + oneTimeFee + depositFee)); + } + } + else { + LogPrintf("%s -- *** Valid BDAP fee amount for a new BDAP link request. Total paid %d, should be %d\n", __func__, + (dataAmount + opAmount), (monthlyFee + oneTimeFee + depositFee)); + } return CheckNewLinkRequestTx(scriptData, vvchArgs, tx->GetHash(), errorMessage, fJustCheck); } else if (strOperationType == "bdap_new_link_accept") { @@ -310,7 +331,21 @@ bool CheckLinkTx(const CTransactionRef& tx, const int& op1, const int& op2, cons errorMessage = "Failed to get BDAP fees for new link accept"; return false; } - + // check if fees equal or exceed tx amounts. Use ENFORCE_BDAP_FEES for now. If ENFORCE_BDAP_FEES = false, just print the error. + if (monthlyFee + oneTimeFee + depositFee > dataAmount + opAmount) { + if (ENFORCE_BDAP_FEES) { + errorMessage = "Invalid BDAP fee amount for a new BDAP link accept"; + return false; + } + else { + LogPrintf("%s -- Invalid BDAP fee amount for a new BDAP link accept. Total paid %d but should be %d. Fees not enforced.\n", __func__, + (dataAmount + opAmount), (monthlyFee + oneTimeFee + depositFee)); + } + } + else { + LogPrintf("%s -- *** Valid BDAP fee amount for a new BDAP link accept. Total paid %d, should be %d\n", __func__, + (dataAmount + opAmount), (monthlyFee + oneTimeFee + depositFee)); + } return CheckNewLinkAcceptTx(scriptData, vvchArgs, tx->GetHash(), errorMessage, fJustCheck); } From d7eb2bd164ce34d5a4e8199a2fcfdcabc790a20d Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Sat, 1 Jun 2019 18:22:42 -0500 Subject: [PATCH 30/36] [BDAP] Change "Registration days" to "Registration months" in UI - default account registration to 2 years or 24 months. --- src/bdap/bdap.h | 2 +- src/bdap/rpcdomainentry.cpp | 5 ++--- src/qt/forms/bdapadduserdialog.ui | 2 +- src/qt/locale/dynamic_de.ts | 2 +- src/qt/locale/dynamic_es.ts | 2 +- src/qt/locale/dynamic_ko.ts | 2 +- src/qt/locale/dynamic_nl.ts | 2 +- src/qt/locale/dynamic_pl.ts | 2 +- src/qt/locale/dynamic_ru.ts | 2 +- 9 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/bdap/bdap.h b/src/bdap/bdap.h index 4fffa5e3fe..debb677e71 100644 --- a/src/bdap/bdap.h +++ b/src/bdap/bdap.h @@ -54,7 +54,7 @@ static constexpr unsigned int MAX_BDAP_LINK_MESSAGE = 256; static constexpr unsigned int MAX_BDAP_SIGNATURE_PROOF = 90; // TODO (bdap): Update to 65 or use MAX_SIGNATURE_LENGTH when you start a new chain. static constexpr unsigned int MAX_BDAP_LINK_DATA_SIZE = 1592; static constexpr uint64_t DEFAULT_LINK_EXPIRE_TIME = 1861920000; -static constexpr int32_t DEFAULT_REGISTRATION_MONTHS = 12; // 1 year +static constexpr int32_t DEFAULT_REGISTRATION_MONTHS = 24; // 2 years static constexpr bool ENFORCE_BDAP_FEES = false; // ********** TODO (BDAP): Update to true after a new testnet. static const std::string DEFAULT_PUBLIC_DOMAIN = "bdap.io"; static const std::string DEFAULT_PUBLIC_OU = "public"; diff --git a/src/bdap/rpcdomainentry.cpp b/src/bdap/rpcdomainentry.cpp index c00c2e8a0a..18262d606b 100644 --- a/src/bdap/rpcdomainentry.cpp +++ b/src/bdap/rpcdomainentry.cpp @@ -69,12 +69,11 @@ static UniValue AddDomainEntry(const JSONRPCRequest& request, BDAP::ObjectType b txDomainEntry.LinkAddress = vchFromString(sxAddr.ToString()); - int32_t nMonths = DEFAULT_REGISTRATION_MONTHS; // default to 2 years. + int32_t nMonths = DEFAULT_REGISTRATION_MONTHS; // default to 2 years. if (request.params.size() >= 3) { if (!ParseInt32(request.params[2].get_str(), &nMonths)) throw std::runtime_error("BDAP_ADD_PUBLIC_ENTRY_RPC_ERROR: ERRCODE: 3505 - " + _("Error converting registration days to int")); } - //txDomainEntry.nExpireTime = AddMonthsToCurrentEpoch((short)nMonths); CharString data; txDomainEntry.Serialize(data); @@ -399,7 +398,7 @@ static UniValue UpdateDomainEntry(const JSONRPCRequest& request, BDAP::ObjectTyp txUpdatedEntry.CommonName = vchCommonName; txUpdatedEntry.nObjectType = GetObjectTypeInt(bdapType); - int32_t nMonths = DEFAULT_REGISTRATION_MONTHS; // default to 1 year. + int32_t nMonths = DEFAULT_REGISTRATION_MONTHS; // default to 2 years. if (request.params.size() >= 3) { if (!ParseInt32(request.params[2].get_str(), &nMonths)) throw std::runtime_error("BDAP_UPDATE_PUBLIC_ENTRY_RPC_ERROR: ERRCODE: 3702 - " + _("Error converting registration days to int")); diff --git a/src/qt/forms/bdapadduserdialog.ui b/src/qt/forms/bdapadduserdialog.ui index 2d0261e917..00172ca8c7 100644 --- a/src/qt/forms/bdapadduserdialog.ui +++ b/src/qt/forms/bdapadduserdialog.ui @@ -37,7 +37,7 @@ - Registration days: + Registration months: diff --git a/src/qt/locale/dynamic_de.ts b/src/qt/locale/dynamic_de.ts index c543e55c75..bea823c270 100644 --- a/src/qt/locale/dynamic_de.ts +++ b/src/qt/locale/dynamic_de.ts @@ -5478,7 +5478,7 @@ zum Beispiel: alertnotify=echo %%s | mail -s "Dynamic Alarm" admin@foo Needs Translating - Registration days: + Registration months: Needs Translating diff --git a/src/qt/locale/dynamic_es.ts b/src/qt/locale/dynamic_es.ts index c703dd6eac..69502f303e 100644 --- a/src/qt/locale/dynamic_es.ts +++ b/src/qt/locale/dynamic_es.ts @@ -5466,7 +5466,7 @@ por ejemplo: alertnotify=echo %%s | mail -s "Alerta Dynamic" admin@foo Needs Translating - Registration days: + Registration months: Needs Translating diff --git a/src/qt/locale/dynamic_ko.ts b/src/qt/locale/dynamic_ko.ts index 88be00ddbe..ae306a4c31 100644 --- a/src/qt/locale/dynamic_ko.ts +++ b/src/qt/locale/dynamic_ko.ts @@ -5417,7 +5417,7 @@ rpcpassword=%s Needs Translating - Registration days: + Registration months: Needs Translating diff --git a/src/qt/locale/dynamic_nl.ts b/src/qt/locale/dynamic_nl.ts index 631ced57bc..80463d9d5a 100644 --- a/src/qt/locale/dynamic_nl.ts +++ b/src/qt/locale/dynamic_nl.ts @@ -5475,7 +5475,7 @@ Bijvoorbeeld: alertnotify=echo %%s | mail -s "Dynamic Alert" admin@foo Needs Translating - Registration days: + Registration months: Needs Translating diff --git a/src/qt/locale/dynamic_pl.ts b/src/qt/locale/dynamic_pl.ts index 4578634711..70088d4b13 100644 --- a/src/qt/locale/dynamic_pl.ts +++ b/src/qt/locale/dynamic_pl.ts @@ -5487,7 +5487,7 @@ Na przykład: alertnotify=echo %%s | mail -s "Dynamic Alert" admin@foo Needs Translating - Registration days: + Registration months: Needs Translating diff --git a/src/qt/locale/dynamic_ru.ts b/src/qt/locale/dynamic_ru.ts index 10baf91276..503dbc170e 100644 --- a/src/qt/locale/dynamic_ru.ts +++ b/src/qt/locale/dynamic_ru.ts @@ -5464,7 +5464,7 @@ rpcpassword =%s Needs Translating - Registration days: + Registration months: Needs Translating From 1bd4fa61e59b50ed841ded25b3e7b8eeef0c26f1 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Sat, 1 Jun 2019 20:34:10 -0500 Subject: [PATCH 31/36] [Docs] Remove dead Waffle.io links from main Readme file - Waffle.io shutdown services in May 2019 --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index e513721797..2dcf27332b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,6 @@ [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) [![Build Status](https://travis-ci.org/duality-solutions/Dynamic.png?branch=master)](https://travis-ci.org/duality-solutions/Dynamic) -[![Stories in Ready](https://badge.waffle.io/duality-solutions/Dynamic.png?label=ready&title=Ready)](https://waffle.io/duality-solutions/Dynamic) - -Graph on Pull Request History -==================================== - -[![Throughput Graph](https://graphs.waffle.io/duality-solutions/Dynamic/throughput.svg)](https://waffle.io/duality-solutions/Dynamic/metrics/throughput) # **Dynamic (DYN) v2.4.0.0** From 879094a0554dd344e3c90e0191cb4ac3bc394aca Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Sun, 2 Jun 2019 02:45:12 -0500 Subject: [PATCH 32/36] [BDAP] Remove link registration days from UI --- src/qt/bdapaddlinkdialog.cpp | 47 ++++++------------------------- src/qt/forms/bdapaddlinkdialog.ui | 14 --------- 2 files changed, 9 insertions(+), 52 deletions(-) diff --git a/src/qt/bdapaddlinkdialog.cpp b/src/qt/bdapaddlinkdialog.cpp index 052295b777..11503e7e7a 100644 --- a/src/qt/bdapaddlinkdialog.cpp +++ b/src/qt/bdapaddlinkdialog.cpp @@ -16,11 +16,9 @@ #include #include - BdapAddLinkDialog::BdapAddLinkDialog(QWidget *parent) : QDialog(parent), ui(new Ui::BdapAddLinkDialog) { - ui->setupUi(this); connect(ui->pushButtonCancel, SIGNAL(clicked()), this, SLOT(goCancel())); @@ -53,8 +51,6 @@ BdapAddLinkDialog::BdapAddLinkDialog(QWidget *parent) : QDialog(parent), autoCompleterTo = new QCompleter(toList, this); ui->lineEditRecipient->setCompleter(autoCompleterTo); autoCompleterTo->popup()->installEventFilter(this); - - } BdapAddLinkDialog::~BdapAddLinkDialog() @@ -104,7 +100,6 @@ void BdapAddLinkDialog::populateList(std::vector &inputList, LinkUs return; } - for (size_t i {0} ; i < result.size() ; ++i) { getaccountID = ""; @@ -116,17 +111,13 @@ void BdapAddLinkDialog::populateList(std::vector &inputList, LinkUs inputList.push_back(getaccountID); }; //for loop i - - } //populateList - void BdapAddLinkDialog::addLink() { std::string requestor = ""; std::string recipient = ""; std::string linkMessage = ""; - std::string registrationDays = ""; std::string outputmessage = ""; JSONRPCRequest jreq; @@ -135,7 +126,6 @@ void BdapAddLinkDialog::addLink() requestor = ui->lineEditRequestor->text().toStdString(); recipient = ui->lineEditRecipient->text().toStdString(); linkMessage = ui->lineEditLinkMessage->text().toStdString(); - registrationDays = ui->lineEditRegistrationDays->text().toStdString(); if ((requestor == "") || (recipient == "") || (linkMessage == "")) { QMessageBox::critical(this, "BDAP Add Link Error", QObject::tr("Requestor, Recipient and Link Message are required fields")); @@ -146,7 +136,6 @@ void BdapAddLinkDialog::addLink() params.push_back(requestor); params.push_back(recipient); params.push_back(linkMessage); - if (registrationDays.length() >> 0) params.push_back(registrationDays); jreq.params = RPCConvertValues("link", params); jreq.strMethod = "link"; @@ -169,17 +158,13 @@ void BdapAddLinkDialog::addLink() QMessageBox::critical(this, "BDAP Add Link Error", QObject::tr(outputmessage.c_str())); return; } - } //addLink - - void BdapAddLinkDialog::goCancel() { QDialog::reject(); //cancelled } //goCancel - void BdapAddLinkDialog::goClose() { QDialog::accept(); //accepted @@ -187,8 +172,7 @@ void BdapAddLinkDialog::goClose() std::string BdapAddLinkDialog::ignoreErrorCode(const std::string input) { - //assuming error code is in the following format: ERROR CODE - ERROR MESSAGE - + //assuming error code is in the following format: ERROR CODE - ERROR MESSAGE std::vector results; std::string returnvalue = input; @@ -202,28 +186,15 @@ std::string BdapAddLinkDialog::ignoreErrorCode(const std::string input) } //ignoreErrorCode std::string BdapAddLinkDialog::getIdFromPath(std::string inputstring) { - std::string returnvalue = inputstring; - std::vector results; - - boost::split(results, inputstring, [](char c){return c == '@';}); - - if (results.size() > 0) { - returnvalue = results[0]; - } - - return returnvalue; - - } //getIdFromPath - - - - - - - - - + std::string returnvalue = inputstring; + std::vector results; + boost::split(results, inputstring, [](char c){return c == '@';}); + if (results.size() > 0) { + returnvalue = results[0]; + } + return returnvalue; +} //getIdFromPath \ No newline at end of file diff --git a/src/qt/forms/bdapaddlinkdialog.ui b/src/qt/forms/bdapaddlinkdialog.ui index 9f57223dc1..678f3ddf8c 100644 --- a/src/qt/forms/bdapaddlinkdialog.ui +++ b/src/qt/forms/bdapaddlinkdialog.ui @@ -39,13 +39,6 @@ - - - - Registration Days: - - - @@ -67,13 +60,6 @@ - - - - (optional) - - - From 72d5aadd13e93e902d0bb951e17cdea42cc0389f Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Sun, 2 Jun 2019 02:47:22 -0500 Subject: [PATCH 33/36] [BDAP] Change account update from add days to add months --- src/qt/bdapupdateaccountdialog.cpp | 31 ++++--------------------- src/qt/forms/bdapupdateaccountdialog.ui | 4 ++-- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/src/qt/bdapupdateaccountdialog.cpp b/src/qt/bdapupdateaccountdialog.cpp index bb4574991d..47b549cfe2 100644 --- a/src/qt/bdapupdateaccountdialog.cpp +++ b/src/qt/bdapupdateaccountdialog.cpp @@ -21,7 +21,6 @@ BdapUpdateAccountDialog::BdapUpdateAccountDialog(QWidget *parent, BDAP::ObjectTy ui(new Ui::BdapUpdateAccountDialog) { //By default, accountType is USER. so only change stuff if different - ui->setupUi(this); inputAccountType = accountType; @@ -50,7 +49,6 @@ BdapUpdateAccountDialog::BdapUpdateAccountDialog(QWidget *parent, BDAP::ObjectTy ui->labelErrorMsg->setVisible(false); ui->pushButtonOK->setVisible(false); - } BdapUpdateAccountDialog::~BdapUpdateAccountDialog() @@ -70,17 +68,17 @@ void BdapUpdateAccountDialog::updateAccount() accountID = ui->lineEditID->text().toStdString(); commonName = ui->lineEditCommonName->text().toStdString(); - registrationDays = ui->lineEditRegistrationDays->text().toStdString(); + registrationDays = ui->lineEditRegistrationMonths->text().toStdString(); ui->lineEditID->setReadOnly(true); ui->lineEditCommonName->setReadOnly(true); - ui->lineEditRegistrationDays->setReadOnly(true); + ui->lineEditRegistrationMonths->setReadOnly(true); QPalette *palette = new QPalette(); palette->setColor(QPalette::Text,Qt::darkGray); ui->lineEditID->setPalette(*palette); ui->lineEditCommonName->setPalette(*palette); - ui->lineEditRegistrationDays->setPalette(*palette); + ui->lineEditRegistrationMonths->setPalette(*palette); ui->labelErrorMsg->setVisible(true); @@ -105,8 +103,7 @@ void BdapUpdateAccountDialog::updateAccount() jreq.params = RPCConvertValues("updategroup", params); jreq.strMethod = "updategroup"; - }; //end inputAccountType if - + } //end inputAccountType if try { UniValue result = tableRPC.execute(jreq); @@ -133,15 +130,11 @@ void BdapUpdateAccountDialog::updateAccount() ui->labelErrorMsg->setText(QObject::tr(outputmessage.c_str())); } //updateAccount - - - void BdapUpdateAccountDialog::goCancel() { QDialog::reject(); //cancelled } //goCancel - void BdapUpdateAccountDialog::goClose() { QDialog::accept(); //accepted @@ -163,18 +156,4 @@ std::string BdapUpdateAccountDialog::ignoreErrorCode(const std::string input) return returnvalue; -} //ignoreErrorCode - - - - - - - - - - - - - - +} //ignoreErrorCode \ No newline at end of file diff --git a/src/qt/forms/bdapupdateaccountdialog.ui b/src/qt/forms/bdapupdateaccountdialog.ui index b6efd2b887..6b99710caa 100644 --- a/src/qt/forms/bdapupdateaccountdialog.ui +++ b/src/qt/forms/bdapupdateaccountdialog.ui @@ -45,12 +45,12 @@ - Additional Days: + Additional Months: - + From 4cd296c00194f7323b5d7d0482d602efac6515ed Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Sun, 2 Jun 2019 02:48:01 -0500 Subject: [PATCH 34/36] [BDAP] Cleanup UI code formatting --- src/qt/bantablemodel.h | 4 +- src/qt/bdapaccounttablemodel.cpp | 2 +- src/qt/bdapaddlinkdialog.h | 8 +- src/qt/bdapadduserdialog.cpp | 32 +------- src/qt/bdapadduserdialog.h | 7 +- src/qt/bdaplinkdetaildialog.cpp | 27 +------ src/qt/bdaplinkdetaildialog.h | 11 +-- src/qt/bdaplinktablemodel.cpp | 12 +-- src/qt/bdappage.cpp | 134 ++++++++++--------------------- src/qt/bdappage.h | 8 +- src/qt/bdapupdateaccountdialog.h | 7 +- src/qt/bdapuserdetaildialog.cpp | 27 +------ src/qt/bdapuserdetaildialog.h | 8 +- 13 files changed, 56 insertions(+), 231 deletions(-) diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h index 688176d55e..bd0e8578f0 100644 --- a/src/qt/bantablemodel.h +++ b/src/qt/bantablemodel.h @@ -51,8 +51,7 @@ class BanTableModel : public QAbstractTableModel Bantime = 1 }; - /** @name Methods overridden from QAbstractTableModel - @{*/ + /** @name Methods overridden from QAbstractTableModel*/ int rowCount(const QModelIndex& parent) const; int columnCount(const QModelIndex& parent) const; QVariant data(const QModelIndex& index, int role) const; @@ -61,7 +60,6 @@ class BanTableModel : public QAbstractTableModel Qt::ItemFlags flags(const QModelIndex& index) const; void sort(int column, Qt::SortOrder order); bool shouldShow(); - /*@}*/ public Q_SLOTS: void refresh(); diff --git a/src/qt/bdapaccounttablemodel.cpp b/src/qt/bdapaccounttablemodel.cpp index f395999377..ada98b5d54 100644 --- a/src/qt/bdapaccounttablemodel.cpp +++ b/src/qt/bdapaccounttablemodel.cpp @@ -299,4 +299,4 @@ void BdapAccountTableModel::sort(int column, Qt::SortOrder order) priv->sortColumn = column; priv->sortOrder = order; refresh(); -} +} \ No newline at end of file diff --git a/src/qt/bdapaddlinkdialog.h b/src/qt/bdapaddlinkdialog.h index 5e105bbeb4..65413e179e 100644 --- a/src/qt/bdapaddlinkdialog.h +++ b/src/qt/bdapaddlinkdialog.h @@ -14,13 +14,11 @@ #include - enum LinkUserType { LINK_REQUESTOR = 0, LINK_RECIPIENT = 1 }; - namespace Ui { class BdapAddLinkDialog; @@ -34,8 +32,6 @@ class BdapAddLinkDialog : public QDialog explicit BdapAddLinkDialog(QWidget *parent = 0); ~BdapAddLinkDialog(); - - private: Ui::BdapAddLinkDialog* ui; std::string ignoreErrorCode(const std::string input); @@ -46,8 +42,6 @@ class BdapAddLinkDialog : public QDialog std::string getIdFromPath(std::string inputstring); void populateList(std::vector &inputList, LinkUserType userType); - - private Q_SLOTS: void goClose(); @@ -56,4 +50,4 @@ private Q_SLOTS: }; -#endif // BDAPADDLINKDIALOG_H +#endif // BDAPADDLINKDIALOG_H \ No newline at end of file diff --git a/src/qt/bdapadduserdialog.cpp b/src/qt/bdapadduserdialog.cpp index 22d80a4107..c23ebd2631 100644 --- a/src/qt/bdapadduserdialog.cpp +++ b/src/qt/bdapadduserdialog.cpp @@ -20,7 +20,6 @@ BdapAddUserDialog::BdapAddUserDialog(QWidget *parent, BDAP::ObjectType accountTy ui(new Ui::BdapAddUserDialog) { //By default, accountType is USER. so only change stuff if different - ui->setupUi(this); inputAccountType = accountType; @@ -45,7 +44,6 @@ BdapAddUserDialog::~BdapAddUserDialog() delete ui; } - void BdapAddUserDialog::goAddUser() { std::string accountID = ""; @@ -91,10 +89,6 @@ void BdapAddUserDialog::goAddUser() }; //end inputAccountType if - - - //UniValue rpc_result(UniValue::VOBJ); - try { UniValue result = tableRPC.execute(jreq); @@ -111,20 +105,14 @@ void BdapAddUserDialog::goAddUser() dlg.exec(); goClose(); } catch (const UniValue& objError) { - //rpc_result = JSONRPCReplyObj(NullUniValue, objError, jreq.id); std::string message = find_value(objError, "message").get_str(); outputmessage = ignoreErrorCode(message); } catch (const std::exception& e) { - //rpc_result = JSONRPCReplyObj(NullUniValue, - //JSONRPCError(RPC_PARSE_ERROR, e.what()), jreq.id); outputmessage = e.what(); } - ui->labelErrorMsg->setText(QObject::tr(outputmessage.c_str())); - - } //goAddUser void BdapAddUserDialog::goCancel() @@ -132,7 +120,6 @@ void BdapAddUserDialog::goCancel() QDialog::reject(); //cancelled } //goCancel - void BdapAddUserDialog::goClose() { QDialog::accept(); //accepted @@ -141,7 +128,6 @@ void BdapAddUserDialog::goClose() std::string BdapAddUserDialog::ignoreErrorCode(const std::string input) { //assuming error code is in the following format: ERROR CODE - ERROR MESSAGE - std::vector results; std::string returnvalue = input; @@ -152,20 +138,4 @@ std::string BdapAddUserDialog::ignoreErrorCode(const std::string input) } return returnvalue; - - -} //ignoreErrorCode - - - - - - - - - - - - - - +} //ignoreErrorCode \ No newline at end of file diff --git a/src/qt/bdapadduserdialog.h b/src/qt/bdapadduserdialog.h index f4b4a9876f..1085b2c27b 100644 --- a/src/qt/bdapadduserdialog.h +++ b/src/qt/bdapadduserdialog.h @@ -26,16 +26,11 @@ class BdapAddUserDialog : public QDialog explicit BdapAddUserDialog(QWidget *parent = 0, BDAP::ObjectType accountType = BDAP::ObjectType::BDAP_USER); ~BdapAddUserDialog(); - - private: Ui::BdapAddUserDialog* ui; std::string ignoreErrorCode(const std::string input); BDAP::ObjectType inputAccountType; - - - private Q_SLOTS: void goAddUser(); @@ -44,4 +39,4 @@ private Q_SLOTS: }; -#endif // BDAPADDUSERDIALOG_H +#endif // BDAPADDUSERDIALOG_H \ No newline at end of file diff --git a/src/qt/bdaplinkdetaildialog.cpp b/src/qt/bdaplinkdetaildialog.cpp index 8123773ee4..6d975042b3 100644 --- a/src/qt/bdaplinkdetaildialog.cpp +++ b/src/qt/bdaplinkdetaildialog.cpp @@ -16,7 +16,6 @@ #include - BdapLinkDetailDialog::BdapLinkDetailDialog(QWidget *parent, LinkActions actionType, const std::string& requestor, const std::string& recipient, const UniValue& resultinput, bool displayInfo) : QDialog(parent), ui(new Ui::BdapLinkDetailDialog) { @@ -37,7 +36,6 @@ BdapLinkDetailDialog::~BdapLinkDetailDialog() delete ui; } - void BdapLinkDetailDialog::populateValues(LinkActions accountType, const std::string& requestor, const std::string& recipient, const UniValue& resultinput) { std::vector results; @@ -72,8 +70,6 @@ void BdapLinkDetailDialog::populateValues(LinkActions accountType, const std::st result = resultinput; } - - for (size_t i {0} ; i < result.size() ; ++i) { keyName = ""; keyName = result.getKeys()[i]; @@ -196,28 +192,7 @@ void BdapLinkDetailDialog::populateValues(LinkActions accountType, const std::st } //populateValues - void BdapLinkDetailDialog::goClose() { QDialog::accept(); //accepted -} //goClose - - - - - - - - - - - - - - - - - - - - +} //goClose \ No newline at end of file diff --git a/src/qt/bdaplinkdetaildialog.h b/src/qt/bdaplinkdetaildialog.h index ae28a9dfdc..507528f8a9 100644 --- a/src/qt/bdaplinkdetaildialog.h +++ b/src/qt/bdaplinkdetaildialog.h @@ -16,10 +16,8 @@ #include - const std::string LINK_TRANSACTION_MESSAGE = "Please note that your transaction will not be reflected until the next block.";; - namespace Ui { class BdapLinkDetailDialog; @@ -29,25 +27,18 @@ class BdapLinkDetailDialog : public QDialog { Q_OBJECT - public: explicit BdapLinkDetailDialog(QWidget *parent = 0, LinkActions actionType = LinkActions::LINK_DEFAULT, const std::string& requestor = "", const std::string& recipient = "", const UniValue& resultinput = UniValue(UniValue::VOBJ), bool displayInfo = false); ~BdapLinkDetailDialog(); - - private: Ui::BdapLinkDetailDialog* ui; void populateValues(LinkActions accountType, const std::string& requestor, const std::string& recipient, const UniValue& resultinput); - - - private Q_SLOTS: void goClose(); - }; -#endif // BDAPLINKDETAILDIALOG_H +#endif // BDAPLINKDETAILDIALOG_H \ No newline at end of file diff --git a/src/qt/bdaplinktablemodel.cpp b/src/qt/bdaplinktablemodel.cpp index 16bf66afde..ccd9df3214 100644 --- a/src/qt/bdaplinktablemodel.cpp +++ b/src/qt/bdaplinktablemodel.cpp @@ -64,7 +64,6 @@ class BdapLinkTablePriv } //if rowcount } //if not isempty - //Execute proper RPC call if (tableWidgetName == "tableWidgetComplete") { params.push_back("complete"); @@ -150,7 +149,7 @@ class BdapLinkTablePriv } //if searchRequestor... - }; //for loop + } //for loop //if we saved the previous state, apply to current results if (hasValues) { @@ -193,8 +192,6 @@ class BdapLinkTablePriv }; //BdapLinkTablePriv - - BdapLinkTableModel::BdapLinkTableModel(BdapPage* parent) : QAbstractTableModel(parent), bdapPage(parent), timer(0) @@ -237,7 +234,6 @@ void BdapLinkTableModel::stopAutoRefresh() timer->stop(); } - int BdapLinkTableModel::rowCount(const QModelIndex& parent) const { Q_UNUSED(parent); @@ -287,7 +283,6 @@ QModelIndex BdapLinkTableModel::index(int row, int column, const QModelIndex& pa return QModelIndex(); } - void BdapLinkTableModel::sort(int column, Qt::SortOrder order) { priv->sortColumn = column; @@ -309,7 +304,6 @@ void BdapLinkTableModel::refreshAll() } //refreshAll - void BdapLinkTableModel::refreshComplete() { searchCompleteRequestor = bdapPage->getCompleteRequestorSearch(); @@ -320,7 +314,6 @@ void BdapLinkTableModel::refreshComplete() Q_EMIT layoutChanged(); } - void BdapLinkTableModel::refreshPendingAccept() { searchPARequestor = bdapPage->getPARequestorSearch(); @@ -331,7 +324,6 @@ void BdapLinkTableModel::refreshPendingAccept() Q_EMIT layoutChanged(); } - void BdapLinkTableModel::refreshPendingRequest() { searchPRRequestor = bdapPage->getPRRequestorSearch(); @@ -340,4 +332,4 @@ void BdapLinkTableModel::refreshPendingRequest() Q_EMIT layoutAboutToBeChanged(); priv->refreshLinks(pendingRequestTable,pendingRequestStatus,searchPRRequestor,searchPRRecipient); Q_EMIT layoutChanged(); -} +} \ No newline at end of file diff --git a/src/qt/bdappage.cpp b/src/qt/bdappage.cpp index 756ad92ab7..cdcd62c242 100644 --- a/src/qt/bdappage.cpp +++ b/src/qt/bdappage.cpp @@ -90,9 +90,6 @@ BdapPage::BdapPage(const PlatformStyle* platformStyle, QWidget* parent) : QWidge connect(ui->tableWidgetComplete, SIGNAL(cellDoubleClicked(int,int)), this, SLOT(getLinkDetails(int,int))); connect(ui->pushButtonAddLink, SIGNAL(clicked()), this, SLOT(addLink())); - - - } BdapPage::~BdapPage() @@ -122,11 +119,8 @@ void BdapPage::evaluateTransactionButtons() break; }; //end switch - - } //evaluateTransactionButtons - //Links tab ========================================================================= void BdapPage::listLinksComplete() { @@ -151,7 +145,6 @@ void BdapPage::listAllGroups() bdapAccountTableModel->refreshGroups(); } //listAllGroups - void BdapPage::addGroup() { if (!dynodeSync.IsBlockchainSynced()) { @@ -163,12 +156,10 @@ void BdapPage::addGroup() dlg.setWindowTitle(QObject::tr("Add BDAP Group")); dlg.exec(); if (dlg.result() == 1) { - //QMessageBox::critical(this, "TEST", QObject::tr("Refreshing...")); bdapAccountTableModel->refreshGroups(); } } //addGroup - void BdapPage::deleteGroup() { if (!dynodeSync.IsBlockchainSynced()) { @@ -223,13 +214,11 @@ void BdapPage::updateGroup() dlg.exec(); if (dlg.result() == 1) { - //QMessageBox::critical(this, "TEST", QObject::tr("Refreshing...")); bdapAccountTableModel->refreshGroups(); } } //updateGroup - void BdapPage::getGroupDetails(int row, int column) { BdapUserDetailDialog dlg(this,BDAP::ObjectType::BDAP_GROUP,ui->tableWidget_Groups->item(row,1)->text().toStdString()); @@ -237,8 +226,6 @@ void BdapPage::getGroupDetails(int row, int column) dlg.exec(); } //getGroupDetails - - //Users tab ========================================================================= void BdapPage::listAllUsers() { @@ -248,7 +235,6 @@ void BdapPage::listAllUsers() } //listAllUsers - void BdapPage::addUser() { if (!dynodeSync.IsBlockchainSynced()) { @@ -257,16 +243,12 @@ void BdapPage::addUser() } BdapAddUserDialog dlg(this); - //connect(&dlg, SIGNAL(cmdToConsole(QString)),rpcConsole, SIGNAL(cmdRequest(QString))); dlg.exec(); if (dlg.result() == 1) { - //QMessageBox::critical(this, "TEST", QObject::tr("Refreshing...")); bdapAccountTableModel->refreshUsers(); } } //addUser - - void BdapPage::getUserDetails(int row, int column) { BdapUserDetailDialog dlg(this,BDAP::ObjectType::BDAP_USER,ui->tableWidget_Users->item(row,1)->text().toStdString()); @@ -282,7 +264,6 @@ void BdapPage::addLink() } BdapAddLinkDialog dlg(this); - //connect(&dlg, SIGNAL(cmdToConsole(QString)),rpcConsole, SIGNAL(cmdRequest(QString))); dlg.exec(); if (dlg.result() == 1) { @@ -316,15 +297,11 @@ void BdapPage::acceptLink() reply = QMessageBox::question(this, QObject::tr("Confirm Accept Link"), QObject::tr(displayedMessage.c_str()), QMessageBox::Yes|QMessageBox::No); if (reply == QMessageBox::Yes) { - //excuteAcceptLink executeLinkTransaction(LinkActions::LINK_ACCEPT, requestor, recipient); - }; - - + } } //acceptLink - void BdapPage::getLinkDetails(int row, int column) { std::string requestor = ""; @@ -342,13 +319,10 @@ void BdapPage::getLinkDetails(int row, int column) else if (tableSource == ui->tableWidgetPendingRequest) actionType = LinkActions::LINK_PENDING_REQUEST_DETAIL; else if (tableSource == ui->tableWidgetComplete) actionType = LinkActions::LINK_COMPLETE_DETAIL; - //excuteAcceptLink executeLinkTransaction(actionType, requestor, recipient); - } //linkDetails - void BdapPage::deleteUser() { if (!dynodeSync.IsBlockchainSynced()) { @@ -373,13 +347,10 @@ void BdapPage::deleteUser() if (reply == QMessageBox::Yes) { executeDeleteAccount(account, BDAP::ObjectType::BDAP_USER); - - }; + } } //deleteUser - - void BdapPage::updateUser() { if (!dynodeSync.IsBlockchainSynced()) { @@ -406,12 +377,10 @@ void BdapPage::updateUser() dlg.exec(); if (dlg.result() == 1) { - //QMessageBox::critical(this, "TEST", QObject::tr("Refreshing...")); bdapAccountTableModel->refreshUsers(); } } //updateUser - void BdapPage::executeDeleteAccount(std::string account, BDAP::ObjectType accountType) { std::string objectID = ""; @@ -429,46 +398,46 @@ void BdapPage::executeDeleteAccount(std::string account, BDAP::ObjectType accoun params.push_back(objectID); - switch (accountType) { - case (BDAP::ObjectType::BDAP_USER): - jreq.params = RPCConvertValues("deleteuser", params); - jreq.strMethod = "deleteuser"; - break; - case (BDAP::ObjectType::BDAP_GROUP): - jreq.params = RPCConvertValues("deletegroup", params); - jreq.strMethod = "deletegroup"; - break; - default: - jreq.params = RPCConvertValues("deleteuser", params); - jreq.strMethod = "deleteuser"; - break; - } //end switch - - try { - UniValue result = tableRPC.execute(jreq); - - outputmessage = result.getValues()[0].get_str(); - BdapUserDetailDialog dlg(this,accountType,"",result,true); - - if (accountType == BDAP::ObjectType::BDAP_USER) { - dlg.setWindowTitle(QObject::tr("Successfully deleted user")); - } else { //only other option for now is group - dlg.setWindowTitle(QObject::tr("Successfully deleted group")); - }; //end accountType if - - dlg.exec(); - if (accountType == BDAP::ObjectType::BDAP_USER) bdapAccountTableModel->refreshUsers(); - else if (accountType == BDAP::ObjectType::BDAP_GROUP) bdapAccountTableModel->refreshGroups(); - - return; - } catch (const UniValue& objError) { - std::string message = find_value(objError, "message").get_str(); - outputmessage = message; - } catch (const std::exception& e) { - outputmessage = e.what(); - } + switch (accountType) { + case (BDAP::ObjectType::BDAP_USER): + jreq.params = RPCConvertValues("deleteuser", params); + jreq.strMethod = "deleteuser"; + break; + case (BDAP::ObjectType::BDAP_GROUP): + jreq.params = RPCConvertValues("deletegroup", params); + jreq.strMethod = "deletegroup"; + break; + default: + jreq.params = RPCConvertValues("deleteuser", params); + jreq.strMethod = "deleteuser"; + break; + } //end switch - QMessageBox::critical(this, "BDAP Error", QObject::tr(outputmessage.c_str())); + try { + UniValue result = tableRPC.execute(jreq); + + outputmessage = result.getValues()[0].get_str(); + BdapUserDetailDialog dlg(this,accountType,"",result,true); + + if (accountType == BDAP::ObjectType::BDAP_USER) { + dlg.setWindowTitle(QObject::tr("Successfully deleted user")); + } else { //only other option for now is group + dlg.setWindowTitle(QObject::tr("Successfully deleted group")); + }; //end accountType if + + dlg.exec(); + if (accountType == BDAP::ObjectType::BDAP_USER) bdapAccountTableModel->refreshUsers(); + else if (accountType == BDAP::ObjectType::BDAP_GROUP) bdapAccountTableModel->refreshGroups(); + + return; + } catch (const UniValue& objError) { + std::string message = find_value(objError, "message").get_str(); + outputmessage = message; + } catch (const std::exception& e) { + outputmessage = e.what(); + } + + QMessageBox::critical(this, "BDAP Error", QObject::tr(outputmessage.c_str())); } //executeDeleteAccount @@ -540,9 +509,7 @@ void BdapPage::executeLinkTransaction(LinkActions actionType, std::string reques dlg.setWindowTitle(QObject::tr("BDAP Pending Request Link Detail")); } else if (actionType == LinkActions::LINK_COMPLETE_DETAIL) { dlg.setWindowTitle(QObject::tr("BDAP Complete Link Detail")); - }; //end actionType if - - //dlg.layout()->setSizeConstraint(QLayout::SetFixedSize); + } //end actionType if dlg.exec(); @@ -558,12 +525,8 @@ void BdapPage::executeLinkTransaction(LinkActions actionType, std::string reques QMessageBox::critical(this, "BDAP Error", QObject::tr(outputmessage.c_str())); } - - } //executeLinkTransaction - - BdapAccountTableModel* BdapPage::getBdapAccountTableModel() { return bdapAccountTableModel; @@ -574,13 +537,11 @@ BdapLinkTableModel* BdapPage::getBdapLinkTableModel() return bdapLinkTableModel; } - QTableWidget* BdapPage::getCompleteTable() { return ui->tableWidgetComplete; } - QTableWidget* BdapPage::getPendingAcceptTable() { return ui->tableWidgetPendingAccept; @@ -593,13 +554,11 @@ QTableWidget* BdapPage::getPendingRequestTable() } - QTableWidget* BdapPage::getUserTable() { return ui->tableWidget_Users; } - QTableWidget* BdapPage::getGroupTable() { return ui->tableWidget_Groups; @@ -625,19 +584,16 @@ QLabel* BdapPage::getPendingRequestRecords() return ui->labelPRRecords; } - QLabel* BdapPage::getGroupStatus() { return ui->labelGroupStatus; } - int BdapPage::getCurrentIndex() { return ui->tabWidget->currentIndex(); } - bool BdapPage::getMyUserCheckBoxChecked() { return ui->checkBoxMyUsers->isChecked(); @@ -696,8 +652,4 @@ std::string BdapPage::getPRRequestorSearch() std::string BdapPage::getPRRecipientSearch() { return ui->lineEditPRRecipientSearch->text().toStdString(); -} - - - - +} \ No newline at end of file diff --git a/src/qt/bdappage.h b/src/qt/bdappage.h index 1fa218b6f8..f6f3a3c591 100644 --- a/src/qt/bdappage.h +++ b/src/qt/bdappage.h @@ -32,7 +32,6 @@ enum LinkActions { LINK_COMPLETE_DETAIL = 5 }; - namespace Ui { class BdapPage; @@ -76,9 +75,6 @@ class BdapPage : public QWidget std::string getPRRequestorSearch(); std::string getPRRecipientSearch(); - - - private: Ui::BdapPage* ui; WalletModel* model; @@ -88,8 +84,6 @@ class BdapPage : public QWidget void executeDeleteAccount(std::string account, BDAP::ObjectType accountType); void executeLinkTransaction(LinkActions actionType, std::string requestor, std::string recipient); - - private Q_SLOTS: void listAllUsers(); @@ -113,4 +107,4 @@ private Q_SLOTS: }; -#endif // BDAPPAGE_H +#endif // BDAPPAGE_H \ No newline at end of file diff --git a/src/qt/bdapupdateaccountdialog.h b/src/qt/bdapupdateaccountdialog.h index b0e328da9e..09684241fe 100644 --- a/src/qt/bdapupdateaccountdialog.h +++ b/src/qt/bdapupdateaccountdialog.h @@ -26,16 +26,11 @@ class BdapUpdateAccountDialog : public QDialog explicit BdapUpdateAccountDialog(QWidget *parent = 0, BDAP::ObjectType accountType = BDAP::ObjectType::BDAP_USER, std::string account = "", std::string commonName = "", std::string expirationDate = ""); ~BdapUpdateAccountDialog(); - - private: Ui::BdapUpdateAccountDialog* ui; std::string ignoreErrorCode(const std::string input); BDAP::ObjectType inputAccountType; - - - private Q_SLOTS: void goCancel(); @@ -44,4 +39,4 @@ private Q_SLOTS: }; -#endif // BDAPUPDATEACCOUNTDIALOG_H +#endif // BDAPUPDATEACCOUNTDIALOG_H \ No newline at end of file diff --git a/src/qt/bdapuserdetaildialog.cpp b/src/qt/bdapuserdetaildialog.cpp index 01598ad50e..96a251ca48 100644 --- a/src/qt/bdapuserdetaildialog.cpp +++ b/src/qt/bdapuserdetaildialog.cpp @@ -27,7 +27,6 @@ BdapUserDetailDialog::BdapUserDetailDialog(QWidget *parent, BDAP::ObjectType acc connect(ui->pushButtonOK, SIGNAL(clicked()), this, SLOT(goCancel())); populateValues(accountType,accountID,resultinput); - } BdapUserDetailDialog::~BdapUserDetailDialog() @@ -35,7 +34,6 @@ BdapUserDetailDialog::~BdapUserDetailDialog() delete ui; } - void BdapUserDetailDialog::populateValues(BDAP::ObjectType accountType, const std::string& accountID, const UniValue& resultinput) { std::vector results; @@ -102,8 +100,6 @@ void BdapUserDetailDialog::populateValues(BDAP::ObjectType accountType, const st result = resultinput; } - - for (size_t i {0} ; i < result.size() ; ++i) { keyName = ""; keyName = result.getKeys()[i]; @@ -132,28 +128,7 @@ void BdapUserDetailDialog::populateValues(BDAP::ObjectType accountType, const st } //populateValues - void BdapUserDetailDialog::goCancel() { QDialog::reject(); //cancelled -} //goCancel - - - - - - - - - - - - - - - - - - - - +} //goCancel \ No newline at end of file diff --git a/src/qt/bdapuserdetaildialog.h b/src/qt/bdapuserdetaildialog.h index 80ec5e421c..9d4c8df306 100644 --- a/src/qt/bdapuserdetaildialog.h +++ b/src/qt/bdapuserdetaildialog.h @@ -30,20 +30,14 @@ class BdapUserDetailDialog : public QDialog explicit BdapUserDetailDialog(QWidget *parent = 0, BDAP::ObjectType accountType = BDAP::ObjectType::BDAP_USER, const std::string& accountID = "", const UniValue& resultinput = UniValue(UniValue::VOBJ), bool displayInfo = false); ~BdapUserDetailDialog(); - - private: Ui::BdapUserDetailDialog* ui; void populateValues(BDAP::ObjectType accountType, const std::string& accountID, const UniValue& resultinput); - - - private Q_SLOTS: void goCancel(); - }; -#endif // BDAPUSERDETAILDIALOG_H +#endif // BDAPUSERDETAILDIALOG_H \ No newline at end of file From b9e9e0f39e9fecbd952f8f47df1d27d2337509bb Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Tue, 4 Jun 2019 13:37:22 -0500 Subject: [PATCH 35/36] [BDAP] Remove debug code from RPC command --- src/wallet/rpcdump.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 69214ab0b3..562eb6f813 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -874,10 +874,7 @@ UniValue importmnemonic(const JSONRPCRequest& request) "\nImports mnemonic\n" + HelpExampleCli("importmnemonic", "\"inflict-witness-off-property-target-faint-gather-match-outdoor-weapon-wide-mix\"") ); - - - LogPrintf("DEBUGGER %s - NUMBER OF PARAMS %s\n", __func__, std::to_string(request.params.size())); - + if (fPruneMode) throw std::runtime_error(std::string(__func__) + ": Importing wallets is disabled in pruned mode"); From 0344c0a5178c9d9fed80e5616e779815f9ad10ed Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Tue, 4 Jun 2019 13:38:35 -0500 Subject: [PATCH 36/36] [Dynode] Format money debug print output for Dynode reward amount --- src/dynode-payments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dynode-payments.cpp b/src/dynode-payments.cpp index 53b4fd96e8..983fac7252 100644 --- a/src/dynode-payments.cpp +++ b/src/dynode-payments.cpp @@ -285,7 +285,7 @@ void CDynodePayments::FillBlockPayee(CMutableTransaction& txNew, int nBlockHeigh ExtractDestination(payee, address1); CDynamicAddress address2(address1); - LogPrintf("CDynodePayments::FillBlockPayee -- Dynode payment %lld to %s\n", dynodePayment, address2.ToString()); + LogPrintf("CDynodePayments::FillBlockPayee -- Dynode payment %ld to %s\n", FormatMoney(dynodePayment), address2.ToString()); } int CDynodePayments::GetMinDynodePaymentsProto() const