From 033b11aecfb9f4ee68fe5d92cf0825055e1f8221 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 18 Oct 2017 14:24:21 -0400 Subject: [PATCH 01/62] travis: move back to the minimal image The most recent update replaced the minimal image with a large one for the 'generic' image. Switching back to 'minimal' should reduce dependencies and maybe speed us up some. It should also eliminiate the need for aa2e0f09e. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index caa14339fcc82..b5afc6cd1ce93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ addons: hostname: bitcoin-tester os: linux -language: generic +language: minimal cache: directories: - depends/built From cacfd7092f9c76c117b4a5b2c69486ae4c8070c7 Mon Sep 17 00:00:00 2001 From: Zathras Date: Sun, 10 Dec 2017 11:19:53 +1100 Subject: [PATCH 02/62] Add foundation 3 of 5 multisig to authorized senders --- src/omnicore/notifications.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/omnicore/notifications.cpp b/src/omnicore/notifications.cpp index 9f2c7989d255d..756043f887e6f 100644 --- a/src/omnicore/notifications.cpp +++ b/src/omnicore/notifications.cpp @@ -94,6 +94,7 @@ bool CheckAlertAuthorization(const std::string& sender) whitelisted.insert("16oDZYCspsczfgKXVj3xyvsxH21NpEj94F"); // Adam whitelisted.insert("1883ZMsRJfzKNozUBJBTCxQ7EaiNioNDWz"); // Zathras whitelisted.insert("1HHv91gRxqBzQ3gydMob3LU8hqXcWoLfvd"); // dexX7 + whitelisted.insert("34kwkVRSvFVEoUwcQSgpQ4ZUasuZ54DJLD"); // multisig (signatories are Craig, Adam, Zathras, dexX7, JR) // Testnet / Regtest // use -omnialertallowsender for testing From b8ceef1268243f89aa0f4d078d29b2973dc2dc94 Mon Sep 17 00:00:00 2001 From: Zathras Date: Sun, 10 Dec 2017 11:20:24 +1100 Subject: [PATCH 03/62] Add back in forced (manual) client upgrade --- src/omnicore/tx.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index a76d3b6cc3eb2..2920ff3c01ba4 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -13,6 +13,8 @@ #include "omnicore/rules.h" #include "omnicore/sp.h" #include "omnicore/sto.h" +#include "omnicore/utilsbitcoin.h" +#include "omnicore/version.h" #include "amount.h" #include "main.h" @@ -2049,6 +2051,18 @@ int CMPTransaction::logicMath_Alert() return (PKT_ERROR -51); } + if (alert_type == ALERT_CLIENT_VERSION_EXPIRY && OMNICORE_VERSION < alert_expiry) { + // regular alert keys CANNOT be used to force a client upgrade on mainnet - at least 3 signatures from board/devs are required + if (sender == "34kwkVRSvFVEoUwcQSgpQ4ZUasuZ54DJLD" || isNonMainNet()) { + std::string msgText = "Client upgrade is required! Shutting down due to unsupported consensus state!"; + PrintToLog(msgText); + PrintToConsole(msgText); + if (!GetBoolArg("-overrideforcedshutdown", false)) { + AbortNode(msgText, msgText); + } + } + } + if (alert_type == 65535) { // set alert type to FFFF to clear previously sent alerts DeleteAlerts(sender); } else { From d630b68030e64a5866b6198af51f6530471bd3ef Mon Sep 17 00:00:00 2001 From: Zathras Date: Sun, 10 Dec 2017 11:21:15 +1100 Subject: [PATCH 04/62] Add test for client expiry --- src/omnicore/test/test_clientexpiry.sh | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 src/omnicore/test/test_clientexpiry.sh diff --git a/src/omnicore/test/test_clientexpiry.sh b/src/omnicore/test/test_clientexpiry.sh new file mode 100755 index 0000000000000..ef2c0e638d49e --- /dev/null +++ b/src/omnicore/test/test_clientexpiry.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +SRCDIR=./src/ +NUL=/dev/null +PASS=0 +FAIL=0 +clear +printf "Preparing a test environment...\n" +printf " * Starting a fresh regtest daemon\n" +rm -r ~/.bitcoin/regtest +$SRCDIR/omnicored --regtest --server --daemon --omnialertallowsender=any >$NUL +sleep 10 +printf " * Preparing some mature testnet BTC\n" +$SRCDIR/omnicore-cli --regtest generate 102 >$NUL +printf " * Obtaining a master address to work with\n" +ADDR=$($SRCDIR/omnicore-cli --regtest getnewaddress OMNIAccount) +printf " * Funding the address with some testnet BTC for fees\n" +$SRCDIR/omnicore-cli --regtest sendtoaddress $ADDR 20 >$NUL +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " * Sending an alert with client expiry version of 999999999\n" +$SRCDIR/omnicore-cli --regtest omni_sendalert $ADDR 3 999999999 "Client version out of date test." >$NUL +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " * The client should now be shutting down, sleeping 5 seconds and then attempting to get block height - this should FAIL.\n" +sleep 5 +printf "\nWe should have shut down now, if we can still query the block height, something is wrong.\n" +BLOCKFINAL=$($SRCDIR/omnicore-cli --regtest getblockcount) +printf " * The current block height is %d\n" $BLOCKFINAL From 563d491640f181b4a93266a8d94d6c7270eab90e Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:30:17 +1100 Subject: [PATCH 05/62] Add HashToAddress() helper to determine Bitcoin address from hash160 & version --- src/omnicore/utils.cpp | 19 +++++++++++++++++++ src/omnicore/utils.h | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/src/omnicore/utils.cpp b/src/omnicore/utils.cpp index a1a8c87b779a0..0bba9ed2e0518 100644 --- a/src/omnicore/utils.cpp +++ b/src/omnicore/utils.cpp @@ -7,11 +7,14 @@ #include "omnicore/utils.h" +#include "base58.h" #include "utilstrencodings.h" // TODO: use crypto/sha256 instead of openssl #include "openssl/sha.h" +#include "omnicore/script.h" + #include #include @@ -55,3 +58,19 @@ void PrepareObfuscatedHashes(const std::string& strSeed, int hashCount, std::str strcpy((char *)sha_input, vstrHashes[j].c_str()); } } + +std::string HashToAddress(unsigned char version, uint160 hash) +{ + CBitcoinAddress address; + if (version == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)[0]) { + CKeyID keyId = hash; + address.Set(keyId); + return address.ToString(); + } else if (version == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)[0]) { + CScriptID scriptId = hash; + address.Set(scriptId); + return address.ToString(); + } + + return ""; +} diff --git a/src/omnicore/utils.h b/src/omnicore/utils.h index e84e17988c93d..90c682f2d4c63 100644 --- a/src/omnicore/utils.h +++ b/src/omnicore/utils.h @@ -3,10 +3,14 @@ #include +#include "uint256.h" + #define MAX_SHA256_OBFUSCATION_TIMES 255 /** Generates hashes used for obfuscation via ToUpper(HexStr(SHA256(x))). */ void PrepareObfuscatedHashes(const std::string& strSeed, int hashCount, std::string(&vstrHashes)[1+MAX_SHA256_OBFUSCATION_TIMES]); +/** Determines the Bitcoin address associated with a given hash and version. */ +std::string HashToAddress(unsigned char version, uint160 hash); #endif // OMNICORE_UTILS_H From fd3e69e20ea62ea63376117025544bfeaa925cde Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:32:14 +1100 Subject: [PATCH 06/62] Add AddressToHash() helper to determine hash160 & version from Bitcoin address --- src/omnicore/utils.cpp | 23 +++++++++++++++++++++++ src/omnicore/utils.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/src/omnicore/utils.cpp b/src/omnicore/utils.cpp index 0bba9ed2e0518..92623d216cc52 100644 --- a/src/omnicore/utils.cpp +++ b/src/omnicore/utils.cpp @@ -74,3 +74,26 @@ std::string HashToAddress(unsigned char version, uint160 hash) return ""; } + +std::vector AddressToBytes(const std::string& address) +{ + std::vector addressBytes; + + txnouttype whichType; + CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(address).Get()); + if (!GetOutputType(scriptPubKey, whichType)) { + return addressBytes; + } + + if (scriptPubKey.size() > 23) { + if (whichType == TX_PUBKEYHASH) { + addressBytes.assign(scriptPubKey.begin()+3, scriptPubKey.begin()+23); //uggh - todo - get hash160 bytes in a cleaner way + addressBytes.insert(addressBytes.begin(), Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)[0]); // insert version byte at the beginning + } else if (whichType == TX_SCRIPTHASH) { + addressBytes.assign(scriptPubKey.begin()+2, scriptPubKey.begin()+22); + addressBytes.insert(addressBytes.begin(), Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)[0]); + } + } + + return addressBytes; +} diff --git a/src/omnicore/utils.h b/src/omnicore/utils.h index 90c682f2d4c63..f876fbe18d5fc 100644 --- a/src/omnicore/utils.h +++ b/src/omnicore/utils.h @@ -13,4 +13,7 @@ void PrepareObfuscatedHashes(const std::string& strSeed, int hashCount, std::str /** Determines the Bitcoin address associated with a given hash and version. */ std::string HashToAddress(unsigned char version, uint160 hash); +/** Returns a vector of bytes containing the version and hash160 for an address.*/ +std::vector AddressToBytes(const std::string& address); + #endif // OMNICORE_UTILS_H From e57a9d6fa14aa9d32fd7c45204299c294a2eb3e9 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:34:28 +1100 Subject: [PATCH 07/62] Add type ints for new 'freeze', 'unfreeze' & 'change freeze setting' transactions --- src/omnicore/omnicore.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index e4020d8e61b1d..d9177d5f3b609 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -86,6 +86,9 @@ enum TransactionType { MSC_TYPE_GRANT_PROPERTY_TOKENS = 55, MSC_TYPE_REVOKE_PROPERTY_TOKENS = 56, MSC_TYPE_CHANGE_ISSUER_ADDRESS = 70, + MSC_TYPE_CHANGE_FREEZE_SETTING = 71, + MSC_TYPE_FREEZE_PROPERTY_TOKENS = 185, + MSC_TYPE_UNFREEZE_PROPERTY_TOKENS = 186, OMNICORE_MESSAGE_TYPE_DEACTIVATION = 65533, OMNICORE_MESSAGE_TYPE_ACTIVATION = 65534, OMNICORE_MESSAGE_TYPE_ALERT = 65535 From 6ee92bd437cd7a0ed32cb37ddfee6c575d023c4b Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:37:17 +1100 Subject: [PATCH 08/62] Add payload creation for 'change freeze setting' transaction --- src/omnicore/createpayload.cpp | 19 +++++++++++++++++++ src/omnicore/createpayload.h | 1 + 2 files changed, 20 insertions(+) diff --git a/src/omnicore/createpayload.cpp b/src/omnicore/createpayload.cpp index b4847f31acdc4..51d64dea9d485 100644 --- a/src/omnicore/createpayload.cpp +++ b/src/omnicore/createpayload.cpp @@ -3,6 +3,7 @@ #include "omnicore/createpayload.h" #include "omnicore/convert.h" +#include "omnicore/utils.h" #include "tinyformat.h" @@ -316,6 +317,24 @@ std::vector CreatePayload_ChangeIssuer(uint32_t propertyId) return payload; } +std::vector CreatePayload_ChangeFreezeSetting(uint32_t propertyId, bool state) +{ + std::vector payload; + uint16_t messageType = 71; + uint16_t messageVer = 0; + mastercore::swapByteOrder16(messageType); + mastercore::swapByteOrder16(messageVer); + mastercore::swapByteOrder32(propertyId); + unsigned char freezeState = (state) ? 1 : 0; + + PUSH_BACK_BYTES(payload, messageVer); + PUSH_BACK_BYTES(payload, messageType); + PUSH_BACK_BYTES(payload, propertyId); + PUSH_BACK_BYTES(payload, freezeState); + + return payload; +} + std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired) { std::vector payload; diff --git a/src/omnicore/createpayload.h b/src/omnicore/createpayload.h index 4392383575fa8..35d7e23f90c06 100644 --- a/src/omnicore/createpayload.h +++ b/src/omnicore/createpayload.h @@ -21,6 +21,7 @@ std::vector CreatePayload_CloseCrowdsale(uint32_t propertyId); std::vector CreatePayload_Grant(uint32_t propertyId, uint64_t amount, std::string memo); std::vector CreatePayload_Revoke(uint32_t propertyId, uint64_t amount, std::string memo); std::vector CreatePayload_ChangeIssuer(uint32_t propertyId); +std::vector CreatePayload_ChangeFreezeSetting(uint32_t propertyId, bool state); std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired); std::vector CreatePayload_MetaDExCancelPrice(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired); std::vector CreatePayload_MetaDExCancelPair(uint32_t propertyIdForSale, uint32_t propertyIdDesired); From 05d2999bb9f5f58e76176152365ac108decbe406 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:38:50 +1100 Subject: [PATCH 09/62] Add payload creation for 'freeze' transaction --- src/omnicore/createpayload.cpp | 20 ++++++++++++++++++++ src/omnicore/createpayload.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/omnicore/createpayload.cpp b/src/omnicore/createpayload.cpp index 51d64dea9d485..61eba59b4f223 100644 --- a/src/omnicore/createpayload.cpp +++ b/src/omnicore/createpayload.cpp @@ -335,6 +335,26 @@ std::vector CreatePayload_ChangeFreezeSetting(uint32_t propertyId return payload; } +std::vector CreatePayload_FreezeTokens(uint32_t propertyId, uint64_t amount, const std::string& address) +{ + std::vector payload; + uint16_t messageType = 185; + uint16_t messageVer = 0; + mastercore::swapByteOrder16(messageType); + mastercore::swapByteOrder16(messageVer); + mastercore::swapByteOrder32(propertyId); + mastercore::swapByteOrder64(amount); + std::vector addressBytes = AddressToBytes(address); + + PUSH_BACK_BYTES(payload, messageVer); + PUSH_BACK_BYTES(payload, messageType); + PUSH_BACK_BYTES(payload, propertyId); + PUSH_BACK_BYTES(payload, amount); + payload.insert(payload.end(), addressBytes.begin(), addressBytes.end()); + + return payload; +} + std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired) { std::vector payload; diff --git a/src/omnicore/createpayload.h b/src/omnicore/createpayload.h index 35d7e23f90c06..f77fea6de45e1 100644 --- a/src/omnicore/createpayload.h +++ b/src/omnicore/createpayload.h @@ -22,6 +22,7 @@ std::vector CreatePayload_Grant(uint32_t propertyId, uint64_t amo std::vector CreatePayload_Revoke(uint32_t propertyId, uint64_t amount, std::string memo); std::vector CreatePayload_ChangeIssuer(uint32_t propertyId); std::vector CreatePayload_ChangeFreezeSetting(uint32_t propertyId, bool state); +std::vector CreatePayload_FreezeTokens(uint32_t propertyId, uint64_t amount, const std::string& address); std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired); std::vector CreatePayload_MetaDExCancelPrice(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired); std::vector CreatePayload_MetaDExCancelPair(uint32_t propertyIdForSale, uint32_t propertyIdDesired); From 147000fabddeaa8405d8c275c1b733739746ee67 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:40:06 +1100 Subject: [PATCH 10/62] Add payload creation for 'unfreeze' transaction --- src/omnicore/createpayload.cpp | 20 ++++++++++++++++++++ src/omnicore/createpayload.h | 1 + 2 files changed, 21 insertions(+) diff --git a/src/omnicore/createpayload.cpp b/src/omnicore/createpayload.cpp index 61eba59b4f223..da748a3ad4b54 100644 --- a/src/omnicore/createpayload.cpp +++ b/src/omnicore/createpayload.cpp @@ -355,6 +355,26 @@ std::vector CreatePayload_FreezeTokens(uint32_t propertyId, uint6 return payload; } +std::vector CreatePayload_UnfreezeTokens(uint32_t propertyId, uint64_t amount, const std::string& address) +{ + std::vector payload; + uint16_t messageType = 186; + uint16_t messageVer = 0; + mastercore::swapByteOrder16(messageType); + mastercore::swapByteOrder16(messageVer); + mastercore::swapByteOrder32(propertyId); + mastercore::swapByteOrder64(amount); + std::vector addressBytes = AddressToBytes(address); + + PUSH_BACK_BYTES(payload, messageVer); + PUSH_BACK_BYTES(payload, messageType); + PUSH_BACK_BYTES(payload, propertyId); + PUSH_BACK_BYTES(payload, amount); + payload.insert(payload.end(), addressBytes.begin(), addressBytes.end()); + + return payload; +} + std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired) { std::vector payload; diff --git a/src/omnicore/createpayload.h b/src/omnicore/createpayload.h index f77fea6de45e1..99a032c2cf908 100644 --- a/src/omnicore/createpayload.h +++ b/src/omnicore/createpayload.h @@ -23,6 +23,7 @@ std::vector CreatePayload_Revoke(uint32_t propertyId, uint64_t am std::vector CreatePayload_ChangeIssuer(uint32_t propertyId); std::vector CreatePayload_ChangeFreezeSetting(uint32_t propertyId, bool state); std::vector CreatePayload_FreezeTokens(uint32_t propertyId, uint64_t amount, const std::string& address); +std::vector CreatePayload_UnfreezeTokens(uint32_t propertyId, uint64_t amount, const std::string& address); std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired); std::vector CreatePayload_MetaDExCancelPrice(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired); std::vector CreatePayload_MetaDExCancelPair(uint32_t propertyIdForSale, uint32_t propertyIdDesired); From 34ba0586c3290da88f749aa0f7aea7cd3326c22f Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:41:59 +1100 Subject: [PATCH 11/62] Add sets to hold which properties allow freezing and which addresses are frozen --- src/omnicore/omnicore.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 00fe460e3c49c..14a890f66904c 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -110,6 +110,11 @@ std::map global_balance_reserved; //! Vector containing a list of properties relative to the wallet std::set global_wallet_property_list; +//! Set containing properties that have freezing enabled +std::set > setFreezingEnabledProperties; +//! Set containing properties waiting to have freezing enabled after their waiting period +std::set > setFrozenAddresses; + /** * Used to indicate, whether to automatically commit created transactions. * From 265608f965ee42df4d0a05248fa019e19851e061 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:45:32 +1100 Subject: [PATCH 12/62] Add freezeAddress() & unfreezeAddress() helpers --- src/omnicore/omnicore.cpp | 12 ++++++++++++ src/omnicore/omnicore.h | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 14a890f66904c..e1b9f9eaf12ce 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -304,6 +304,18 @@ bool mastercore::isMainEcosystemProperty(uint32_t propertyId) return false; } +void mastercore::freezeAddress(const std::string& address, uint32_t propertyId) +{ + setFrozenAddresses.insert(std::make_pair(address, propertyId)); + PrintToLog("Address %s has been frozen for property %d.\n", address, propertyId); +} + +void mastercore::unfreezeAddress(const std::string& address, uint32_t propertyId) +{ + setFrozenAddresses.erase(std::make_pair(address, propertyId)); + PrintToLog("Address %s has been unfrozen for property %d.\n", address, propertyId); +} + std::string mastercore::getTokenLabel(uint32_t propertyId) { std::string tokenStr; diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index d9177d5f3b609..c4e385961fe82 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -361,6 +361,15 @@ bool getValidMPTX(const uint256 &txid, int *block = NULL, unsigned int *type = N bool update_tally_map(const std::string& who, uint32_t propertyId, int64_t amount, TallyType ttype); std::string getTokenLabel(uint32_t propertyId); + +/** + NOTE: The following functions are only permitted for properties + managed by a central issuer that have enabled freezing. + **/ +/** Adds an address and property to the frozenMap **/ +void freezeAddress(const std::string& address, uint32_t propertyId); +/** Removes an address and property from the frozenMap **/ +void unfreezeAddress(const std::string& address, uint32_t propertyId); } From 756773478173b8ad9b002547ca1154193457ef85 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:47:34 +1100 Subject: [PATCH 13/62] Add isAddressFrozen() check --- src/omnicore/omnicore.cpp | 12 ++++++++++++ src/omnicore/omnicore.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index e1b9f9eaf12ce..3562a4886e155 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -316,6 +316,18 @@ void mastercore::unfreezeAddress(const std::string& address, uint32_t propertyId PrintToLog("Address %s has been unfrozen for property %d.\n", address, propertyId); } +bool mastercore::isAddressFrozen(const std::string& address, uint32_t propertyId) +{ + for (std::set >::iterator it = setFrozenAddresses.begin(); it != setFrozenAddresses.end(); it++) { + std::string itemAddress = (*it).first; + uint32_t itemPropertyId = (*it).second; + if (address == itemAddress && propertyId == itemPropertyId) { + return true; + } + } + return false; +} + std::string mastercore::getTokenLabel(uint32_t propertyId) { std::string tokenStr; diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index c4e385961fe82..c6e7072983c5e 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -370,6 +370,8 @@ std::string getTokenLabel(uint32_t propertyId); void freezeAddress(const std::string& address, uint32_t propertyId); /** Removes an address and property from the frozenMap **/ void unfreezeAddress(const std::string& address, uint32_t propertyId); +/** Checks whether an address and property are frozen **/ +bool isAddressFrozen(const std::string& address, uint32_t propertyId); } From 56ec86d4a0674b8c912c0e86ffa1e9cfab5577e2 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:49:31 +1100 Subject: [PATCH 14/62] Add descriptions for new transactions --- src/omnicore/tx.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index a76d3b6cc3eb2..bb6e313b613ef 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -59,6 +59,9 @@ std::string mastercore::strTransactionType(uint16_t txType) case MSC_TYPE_GRANT_PROPERTY_TOKENS: return "Grant Property Tokens"; case MSC_TYPE_REVOKE_PROPERTY_TOKENS: return "Revoke Property Tokens"; case MSC_TYPE_CHANGE_ISSUER_ADDRESS: return "Change Issuer Address"; + case MSC_TYPE_CHANGE_FREEZE_SETTING: return "Change Freeze Setting"; + case MSC_TYPE_FREEZE_PROPERTY_TOKENS: return "Freeze Property Tokens"; + case MSC_TYPE_UNFREEZE_PROPERTY_TOKENS: return "Unfreeze Property Tokens"; case MSC_TYPE_NOTIFICATION: return "Notification"; case OMNICORE_MESSAGE_TYPE_ALERT: return "ALERT"; case OMNICORE_MESSAGE_TYPE_DEACTIVATION: return "Feature Deactivation"; From 04560977375276a521a875d03de90d18ceb0e189 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 07:51:05 +1100 Subject: [PATCH 15/62] Update consensus rules to allow freezing for managed properties --- src/omnicore/rules.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/omnicore/rules.cpp b/src/omnicore/rules.cpp index bc54a05e634b8..ec7333cc71521 100644 --- a/src/omnicore/rules.cpp +++ b/src/omnicore/rules.cpp @@ -56,6 +56,9 @@ std::vector CConsensusParams::GetRestrictions() const { MSC_TYPE_GRANT_PROPERTY_TOKENS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, { MSC_TYPE_REVOKE_PROPERTY_TOKENS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, { MSC_TYPE_CHANGE_ISSUER_ADDRESS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, + { MSC_TYPE_CHANGE_FREEZE_SETTING, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, + { MSC_TYPE_FREEZE_PROPERTY_TOKENS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, + { MSC_TYPE_UNFREEZE_PROPERTY_TOKENS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, { MSC_TYPE_SEND_TO_OWNERS, MP_TX_PKT_V0, false, MSC_STO_BLOCK }, { MSC_TYPE_SEND_TO_OWNERS, MP_TX_PKT_V1, false, MSC_STOV1_BLOCK }, From 651b3c20e0ab8deb5e8285da8ca3a29e0cdc1586 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:20:43 +1100 Subject: [PATCH 16/62] Update consensus rules to enforce a waiting period for enabling freezing Note: waiting period activated by feature 14 --- src/omnicore/rules.cpp | 19 +++++++++++++++++++ src/omnicore/rules.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/src/omnicore/rules.cpp b/src/omnicore/rules.cpp index ec7333cc71521..6f4e8c7b2c03b 100644 --- a/src/omnicore/rules.cpp +++ b/src/omnicore/rules.cpp @@ -166,6 +166,8 @@ CMainConsensusParams::CMainConsensusParams() // Notice range for feature activations: MIN_ACTIVATION_BLOCKS = 2048; // ~2 weeks MAX_ACTIVATION_BLOCKS = 12288; // ~12 weeks + // Waiting period for enabling freezing + OMNI_FREEZE_WAIT_PERIOD = 4096; // ~4 weeks // Script related: PUBKEYHASH_BLOCK = 0; SCRIPTHASH_BLOCK = 322000; @@ -188,6 +190,7 @@ CMainConsensusParams::CMainConsensusParams() SPCROWDCROSSOVER_FEATURE_BLOCK = 395000; TRADEALLPAIRS_FEATURE_BLOCK = 438500; FEES_FEATURE_BLOCK = 999999; + FREEZENOTICE_FEATURE_BLOCK = 999999; } /** @@ -204,6 +207,8 @@ CTestNetConsensusParams::CTestNetConsensusParams() // Notice range for feature activations: MIN_ACTIVATION_BLOCKS = 0; MAX_ACTIVATION_BLOCKS = 999999; + // Waiting period for enabling freezing + OMNI_FREEZE_WAIT_PERIOD = 0; // Script related: PUBKEYHASH_BLOCK = 0; SCRIPTHASH_BLOCK = 0; @@ -226,6 +231,7 @@ CTestNetConsensusParams::CTestNetConsensusParams() SPCROWDCROSSOVER_FEATURE_BLOCK = 0; TRADEALLPAIRS_FEATURE_BLOCK = 0; FEES_FEATURE_BLOCK = 0; + FREEZENOTICE_FEATURE_BLOCK = 0; } /** @@ -242,6 +248,8 @@ CRegTestConsensusParams::CRegTestConsensusParams() // Notice range for feature activations: MIN_ACTIVATION_BLOCKS = 5; MAX_ACTIVATION_BLOCKS = 10; + // Waiting period for enabling freezing + OMNI_FREEZE_WAIT_PERIOD = 10; // Script related: PUBKEYHASH_BLOCK = 0; SCRIPTHASH_BLOCK = 0; @@ -264,6 +272,7 @@ CRegTestConsensusParams::CRegTestConsensusParams() SPCROWDCROSSOVER_FEATURE_BLOCK = 999999; TRADEALLPAIRS_FEATURE_BLOCK = 999999; FEES_FEATURE_BLOCK = 999999; + FREEZENOTICE_FEATURE_BLOCK = 999999; } //! Consensus parameters for mainnet @@ -426,6 +435,9 @@ bool ActivateFeature(uint16_t featureId, int activationBlock, uint32_t minClient case FEATURE_STOV1: MutableConsensusParams().MSC_STOV1_BLOCK = activationBlock; break; + case FEATURE_FREEZENOTICE: + MutableConsensusParams().FREEZENOTICE_FEATURE_BLOCK = activationBlock; + break; default: supported = false; break; @@ -494,6 +506,9 @@ bool DeactivateFeature(uint16_t featureId, int transactionBlock) case FEATURE_STOV1: MutableConsensusParams().MSC_STOV1_BLOCK = 999999; break; + case FEATURE_FREEZENOTICE: + MutableConsensusParams().FREEZENOTICE_FEATURE_BLOCK = 999999; + break; default: return false; break; @@ -524,6 +539,7 @@ std::string GetFeatureName(uint16_t featureId) case FEATURE_TRADEALLPAIRS: return "Allow trading all pairs on the Distributed Exchange"; case FEATURE_FEES: return "Fee system (inc 0.05% fee from trades of non-Omni pairs)"; case FEATURE_STOV1: return "Cross-property Send To Owners"; + case FEATURE_FREEZENOTICE: return "Activate the waiting period for enabling freezing"; default: return "Unknown feature"; } @@ -568,6 +584,9 @@ bool IsFeatureActivated(uint16_t featureId, int transactionBlock) case FEATURE_STOV1: activationBlock = params.MSC_STOV1_BLOCK; break; + case FEATURE_FREEZENOTICE: + activationBlock = params.FREEZENOTICE_FEATURE_BLOCK; + break; default: return false; } diff --git a/src/omnicore/rules.h b/src/omnicore/rules.h index a974dd40cab3b..b2e5d62c888b9 100644 --- a/src/omnicore/rules.h +++ b/src/omnicore/rules.h @@ -34,6 +34,8 @@ const uint16_t FEATURE_TRADEALLPAIRS = 8; const uint16_t FEATURE_FEES = 9; //! Feature identifier to enable cross property (v1) Send To Owners const uint16_t FEATURE_STOV1 = 10; +//! Feature identifier to activate the waiting period for enabling managed property address freezing +const uint16_t FEATURE_FREEZENOTICE = 14; //! When (propertyTotalTokens / OMNI_FEE_THRESHOLD) is reached fee distribution will occur const int64_t OMNI_FEE_THRESHOLD = 100000; // 0.001% @@ -86,6 +88,9 @@ class CConsensusParams //! Maximum number of blocks to use for notice rules on activation int MAX_ACTIVATION_BLOCKS; + //! Waiting period after enabling freezing before addresses may be frozen + int OMNI_FREEZE_WAIT_PERIOD; + //! Block to enable pay-to-pubkey-hash support int PUBKEYHASH_BLOCK; //! Block to enable pay-to-script-hash support @@ -126,6 +131,8 @@ class CConsensusParams int TRADEALLPAIRS_FEATURE_BLOCK; //! Block to enable the fee system & 0.05% fee for trading non-Omni pairs int FEES_FEATURE_BLOCK; + //! Block to activate the waiting period for enabling managed property address freezing + int FREEZENOTICE_FEATURE_BLOCK; /** Returns a mapping of transaction types, and the blocks at which they are enabled. */ virtual std::vector GetRestrictions() const; From 9c03cdcdb085275e54d01aa29e7e64b35de42106 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:23:10 +1100 Subject: [PATCH 17/62] Add enableFreezing() function --- src/omnicore/omnicore.cpp | 13 +++++++++++++ src/omnicore/omnicore.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 3562a4886e155..e733e899464ce 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -304,6 +304,19 @@ bool mastercore::isMainEcosystemProperty(uint32_t propertyId) return false; } +void mastercore::enableFreezing(uint32_t propertyId, int block) +{ + if (!IsFeatureActivated(FEATURE_FREEZENOTICE, block)) { + setFreezingEnabledProperties.insert(std::make_pair(propertyId, block)); + PrintToLog("Freezing for property %d has been enabled.\n", propertyId); + } else { + const CConsensusParams& params = ConsensusParams(); + int liveBlock = params.OMNI_FREEZE_WAIT_PERIOD + block; + setFreezingEnabledProperties.insert(std::make_pair(propertyId, liveBlock)); + PrintToLog("Freezing for property %d will be enabled at block %d.\n", propertyId, liveBlock); + } +} + void mastercore::freezeAddress(const std::string& address, uint32_t propertyId) { setFrozenAddresses.insert(std::make_pair(address, propertyId)); diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index c6e7072983c5e..17eb6a2d3049e 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -372,6 +372,9 @@ void freezeAddress(const std::string& address, uint32_t propertyId); void unfreezeAddress(const std::string& address, uint32_t propertyId); /** Checks whether an address and property are frozen **/ bool isAddressFrozen(const std::string& address, uint32_t propertyId); +/** Adds a property to the freezingEnabledMap **/ +void enableFreezing(uint32_t propertyId, int block); + } From 7af2e6ab369f0fcf9e6bfb742ad6f5a78297a82b Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:24:47 +1100 Subject: [PATCH 18/62] Add disableFreezing() function --- src/omnicore/omnicore.cpp | 26 ++++++++++++++++++++++++++ src/omnicore/omnicore.h | 3 ++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index e733e899464ce..8e5bcfebd8e43 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -317,6 +317,32 @@ void mastercore::enableFreezing(uint32_t propertyId, int block) } } +void mastercore::disableFreezing(uint32_t propertyId) +{ + int liveBlock = 0; + for (std::set >::iterator it = setFreezingEnabledProperties.begin(); it != setFreezingEnabledProperties.end(); it++) { + if (propertyId == (*it).first) { + liveBlock = (*it).second; + } + } + if (liveBlock == 0) { + PrintToLog("ERROR: Failed to determine live block to disable freezing for property %d!\n", propertyId); + } else { + setFreezingEnabledProperties.erase(std::make_pair(propertyId, liveBlock)); + PrintToLog("Freezing for property %d has been disabled.\n", propertyId); + } + + // When disabling freezing for a property, all frozen addresses for that property will be unfrozen! + for (std::set >::iterator it = setFrozenAddresses.begin(); it != setFrozenAddresses.end(); ) { + if ((*it).second == propertyId) { + PrintToLog("Address %s has been unfrozen for property %d.\n", (*it).first, propertyId); + it = setFrozenAddresses.erase(it); + } else { + it++; + } + } +} + void mastercore::freezeAddress(const std::string& address, uint32_t propertyId) { setFrozenAddresses.insert(std::make_pair(address, propertyId)); diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 17eb6a2d3049e..476e39f4de3bb 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -374,8 +374,9 @@ void unfreezeAddress(const std::string& address, uint32_t propertyId); bool isAddressFrozen(const std::string& address, uint32_t propertyId); /** Adds a property to the freezingEnabledMap **/ void enableFreezing(uint32_t propertyId, int block); +/** Removes a property from the freezingEnabledMap **/ +void disableFreezing(uint32_t propertyId); } - #endif // OMNICORE_OMNICORE_H From 25d975f2eda43c7c671774e352fcc937520c2f8d Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:26:01 +1100 Subject: [PATCH 19/62] Add isFreezingEnabled() helper --- src/omnicore/omnicore.cpp | 12 ++++++++++++ src/omnicore/omnicore.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 8e5bcfebd8e43..5999da891b487 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -343,6 +343,18 @@ void mastercore::disableFreezing(uint32_t propertyId) } } +bool mastercore::isFreezingEnabled(uint32_t propertyId, int block) +{ + for (std::set >::iterator it = setFreezingEnabledProperties.begin(); it != setFreezingEnabledProperties.end(); it++) { + uint32_t itemPropertyId = (*it).first; + int itemBlock = (*it).second; + if (propertyId == itemPropertyId && block >= itemBlock) { + return true; + } + } + return false; +} + void mastercore::freezeAddress(const std::string& address, uint32_t propertyId) { setFrozenAddresses.insert(std::make_pair(address, propertyId)); diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 476e39f4de3bb..2631ca5924503 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -376,6 +376,8 @@ bool isAddressFrozen(const std::string& address, uint32_t propertyId); void enableFreezing(uint32_t propertyId, int block); /** Removes a property from the freezingEnabledMap **/ void disableFreezing(uint32_t propertyId); +/** Checks whether a property has freezing enabled **/ +bool isFreezingEnabled(uint32_t propertyId, int block); } From 92fe11deab857e56fd412d5b43a9bf4de152a93f Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:31:54 +1100 Subject: [PATCH 20/62] Add processing for 'change freeze setting' transaction --- src/omnicore/tx.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++ src/omnicore/tx.h | 2 ++ 2 files changed, 81 insertions(+) diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index bb6e313b613ef..776ad1ddee18e 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -152,6 +152,9 @@ bool CMPTransaction::interpret_Transaction() case MSC_TYPE_CHANGE_ISSUER_ADDRESS: return interpret_ChangeIssuer(); + case MSC_TYPE_CHANGE_FREEZE_SETTING: + return interpret_ChangeFreezeSetting(); + case OMNICORE_MESSAGE_TYPE_DEACTIVATION: return interpret_Deactivation(); @@ -634,6 +637,24 @@ bool CMPTransaction::interpret_ChangeIssuer() return true; } +/** Tx 71 */ +bool CMPTransaction::interpret_ChangeFreezeSetting() +{ + if (pkt_size < 9) { + return false; + } + memcpy(&property, &pkt[4], 4); + swapByteOrder32(property); + memcpy(&action, &pkt[8], 1); + + if ((!rpcOnly && msc_debug_packets) || msc_debug_packets_readonly) { + PrintToLog("\t property: %d (%s)\n", property, strMPProperty(property)); + PrintToLog("\t state: %d\n", action); + } + + return true; +} + /** Tx 65533 */ bool CMPTransaction::interpret_Deactivation() { @@ -772,6 +793,9 @@ int CMPTransaction::interpretPacket() case MSC_TYPE_CHANGE_ISSUER_ADDRESS: return logicMath_ChangeIssuer(); + case MSC_TYPE_CHANGE_FREEZE_SETTING: + return logicMath_ChangeFreezeSetting(); + case OMNICORE_MESSAGE_TYPE_DEACTIVATION: return logicMath_Deactivation(); @@ -1950,6 +1974,61 @@ int CMPTransaction::logicMath_ChangeIssuer() return 0; } +/** Tx 71 */ +int CMPTransaction::logicMath_ChangeFreezeSetting() +{ + uint256 blockHash; + { + LOCK(cs_main); + + CBlockIndex* pindex = chainActive[block]; + if (pindex == NULL) { + PrintToLog("%s(): ERROR: block %d not in the active chain\n", __func__, block); + return (PKT_ERROR_TOKENS -20); + } + blockHash = pindex->GetBlockHash(); + } + + if (!IsTransactionTypeAllowed(block, property, type, version)) { + PrintToLog("%s(): rejected: type %d or version %d not permitted for property %d at block %d\n", + __func__, + type, + version, + property, + block); + return (PKT_ERROR_TOKENS -22); + } + + if (!IsPropertyIdValid(property)) { + PrintToLog("%s(): rejected: property %d does not exist\n", __func__, property); + return (PKT_ERROR_TOKENS -24); + } + + CMPSPInfo::Entry sp; + assert(_my_sps->getSP(property, sp)); + + if (!sp.manual) { + PrintToLog("%s(): rejected: property %d is not managed\n", __func__, property); + return (PKT_ERROR_TOKENS -42); + } + + if (sender != sp.issuer) { + PrintToLog("%s(): rejected: sender %s is not issuer of property %d [issuer=%s]\n", __func__, sender, property, sp.issuer); + return (PKT_ERROR_TOKENS -43); + } + + if (action == 0) { + disableFreezing(property); + } else if (action == 1) { + enableFreezing(property, block); + } else { + PrintToLog("%s(): rejected: state value %d is not 0 or 1\n", __func__, action); + return (PKT_ERROR_TOKENS -49); + } + + return 0; +} + /** Tx 65533 */ int CMPTransaction::logicMath_Deactivation() { diff --git a/src/omnicore/tx.h b/src/omnicore/tx.h index 6a09806219c55..e9d7f3db29c32 100644 --- a/src/omnicore/tx.h +++ b/src/omnicore/tx.h @@ -119,6 +119,7 @@ class CMPTransaction bool interpret_GrantTokens(); bool interpret_RevokeTokens(); bool interpret_ChangeIssuer(); + bool interpret_ChangeFreezeSetting(); bool interpret_Activation(); bool interpret_Deactivation(); bool interpret_Alert(); @@ -142,6 +143,7 @@ class CMPTransaction int logicMath_GrantTokens(); int logicMath_RevokeTokens(); int logicMath_ChangeIssuer(); + int logicMath_ChangeFreezeSetting(); int logicMath_Activation(); int logicMath_Deactivation(); int logicMath_Alert(); From 1e67c396e50ca9efcca798abd486860fd8937230 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:36:24 +1100 Subject: [PATCH 21/62] Add processing for 'freeze' transaction --- src/omnicore/tx.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++ src/omnicore/tx.h | 2 + 2 files changed, 101 insertions(+) diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index 776ad1ddee18e..b41692e7b754d 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -155,6 +155,9 @@ bool CMPTransaction::interpret_Transaction() case MSC_TYPE_CHANGE_FREEZE_SETTING: return interpret_ChangeFreezeSetting(); + case MSC_TYPE_FREEZE_PROPERTY_TOKENS: + return interpret_FreezeTokens(); + case OMNICORE_MESSAGE_TYPE_DEACTIVATION: return interpret_Deactivation(); @@ -655,6 +658,41 @@ bool CMPTransaction::interpret_ChangeFreezeSetting() return true; } +/** Tx 185 */ +bool CMPTransaction::interpret_FreezeTokens() +{ + if (pkt_size < 37) { + return false; + } + memcpy(&property, &pkt[4], 4); + swapByteOrder32(property); + memcpy(&nValue, &pkt[8], 8); + swapByteOrder64(nValue); + nNewValue = nValue; + + /** + Note, TX185 is a virtual reference transaction type. + With virtual reference transactions a hash160 in the payload sets the receiver. + Reference outputs are ignored. + **/ + unsigned char address_version; + uint160 address_hash160; + memcpy(&address_version, &pkt[16], 1); + memcpy(&address_hash160, &pkt[17], 20); + receiver = HashToAddress(address_version, address_hash160); + if (receiver.empty()) { + return false; + } + + if ((!rpcOnly && msc_debug_packets) || msc_debug_packets_readonly) { + PrintToLog("\t property: %d (%s)\n", property, strMPProperty(property)); + PrintToLog("\t value (unused): %s\n", FormatMP(property, nValue)); + PrintToLog("\t address: %s\n", receiver); + } + + return true; +} + /** Tx 65533 */ bool CMPTransaction::interpret_Deactivation() { @@ -796,6 +834,9 @@ int CMPTransaction::interpretPacket() case MSC_TYPE_CHANGE_FREEZE_SETTING: return logicMath_ChangeFreezeSetting(); + case MSC_TYPE_FREEZE_PROPERTY_TOKENS: + return logicMath_FreezeTokens(); + case OMNICORE_MESSAGE_TYPE_DEACTIVATION: return logicMath_Deactivation(); @@ -2029,6 +2070,64 @@ int CMPTransaction::logicMath_ChangeFreezeSetting() return 0; } +/** Tx 185 */ +int CMPTransaction::logicMath_FreezeTokens() +{ + uint256 blockHash; + { + LOCK(cs_main); + + CBlockIndex* pindex = chainActive[block]; + if (pindex == NULL) { + PrintToLog("%s(): ERROR: block %d not in the active chain\n", __func__, block); + return (PKT_ERROR_TOKENS -20); + } + blockHash = pindex->GetBlockHash(); + } + + if (!IsTransactionTypeAllowed(block, property, type, version)) { + PrintToLog("%s(): rejected: type %d or version %d not permitted for property %d at block %d\n", + __func__, + type, + version, + property, + block); + return (PKT_ERROR_TOKENS -22); + } + + if (!IsPropertyIdValid(property)) { + PrintToLog("%s(): rejected: property %d does not exist\n", __func__, property); + return (PKT_ERROR_TOKENS -24); + } + + CMPSPInfo::Entry sp; + assert(_my_sps->getSP(property, sp)); + + if (!sp.manual) { + PrintToLog("%s(): rejected: property %d is not managed\n", __func__, property); + return (PKT_ERROR_TOKENS -42); + } + + if (sender != sp.issuer) { + PrintToLog("%s(): rejected: sender %s is not issuer of property %d [issuer=%s]\n", __func__, sender, property, sp.issuer); + return (PKT_ERROR_TOKENS -43); + } + + if (!isFreezingEnabled(property, block)) { + PrintToLog("%s(): rejected: freezing is not enabled for property %d\n", __func__, property); + return (PKT_ERROR_TOKENS -47); + } + + if (isAddressFrozen(receiver, property)) { + PrintToLog("%s(): rejected: address %s is already frozen for property %d\n", __func__, receiver, property); + return (PKT_ERROR_TOKENS -50); + } + + freezeAddress(receiver, property); + + return 0; +} + /** Tx 65533 */ int CMPTransaction::logicMath_Deactivation() { diff --git a/src/omnicore/tx.h b/src/omnicore/tx.h index e9d7f3db29c32..e1442fd0ba44b 100644 --- a/src/omnicore/tx.h +++ b/src/omnicore/tx.h @@ -120,6 +120,7 @@ class CMPTransaction bool interpret_RevokeTokens(); bool interpret_ChangeIssuer(); bool interpret_ChangeFreezeSetting(); + bool interpret_FreezeTokens(); bool interpret_Activation(); bool interpret_Deactivation(); bool interpret_Alert(); @@ -144,6 +145,7 @@ class CMPTransaction int logicMath_RevokeTokens(); int logicMath_ChangeIssuer(); int logicMath_ChangeFreezeSetting(); + int logicMath_FreezeTokens(); int logicMath_Activation(); int logicMath_Deactivation(); int logicMath_Alert(); From 4d0e3ed7332d257d1d3795bc46b7db3841bd60c6 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:41:03 +1100 Subject: [PATCH 22/62] Add processing for 'unfreeze' transaction --- src/omnicore/tx.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++ src/omnicore/tx.h | 2 + 2 files changed, 101 insertions(+) diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index b41692e7b754d..147fadd227603 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -158,6 +158,9 @@ bool CMPTransaction::interpret_Transaction() case MSC_TYPE_FREEZE_PROPERTY_TOKENS: return interpret_FreezeTokens(); + case MSC_TYPE_UNFREEZE_PROPERTY_TOKENS: + return interpret_UnfreezeTokens(); + case OMNICORE_MESSAGE_TYPE_DEACTIVATION: return interpret_Deactivation(); @@ -693,6 +696,41 @@ bool CMPTransaction::interpret_FreezeTokens() return true; } +/** Tx 186 */ +bool CMPTransaction::interpret_UnfreezeTokens() +{ + if (pkt_size < 37) { + return false; + } + memcpy(&property, &pkt[4], 4); + swapByteOrder32(property); + memcpy(&nValue, &pkt[8], 8); + swapByteOrder64(nValue); + nNewValue = nValue; + + /** + Note, TX186 virtual reference transaction type. + With virtual reference transactions a hash160 in the payload sets the receiver. + Reference outputs are ignored. + **/ + unsigned char address_version; + uint160 address_hash160; + memcpy(&address_version, &pkt[16], 1); + memcpy(&address_hash160, &pkt[17], 20); + receiver = HashToAddress(address_version, address_hash160); + if (receiver.empty()) { + return false; + } + + if ((!rpcOnly && msc_debug_packets) || msc_debug_packets_readonly) { + PrintToLog("\t property: %d (%s)\n", property, strMPProperty(property)); + PrintToLog("\t value (unused): %s\n", FormatMP(property, nValue)); + PrintToLog("\t address: %s\n", receiver); + } + + return true; +} + /** Tx 65533 */ bool CMPTransaction::interpret_Deactivation() { @@ -837,6 +875,9 @@ int CMPTransaction::interpretPacket() case MSC_TYPE_FREEZE_PROPERTY_TOKENS: return logicMath_FreezeTokens(); + case MSC_TYPE_UNFREEZE_PROPERTY_TOKENS: + return logicMath_UnfreezeTokens(); + case OMNICORE_MESSAGE_TYPE_DEACTIVATION: return logicMath_Deactivation(); @@ -2128,6 +2169,64 @@ int CMPTransaction::logicMath_FreezeTokens() return 0; } +/** Tx 186 */ +int CMPTransaction::logicMath_UnfreezeTokens() +{ + uint256 blockHash; + { + LOCK(cs_main); + + CBlockIndex* pindex = chainActive[block]; + if (pindex == NULL) { + PrintToLog("%s(): ERROR: block %d not in the active chain\n", __func__, block); + return (PKT_ERROR_TOKENS -20); + } + blockHash = pindex->GetBlockHash(); + } + + if (!IsTransactionTypeAllowed(block, property, type, version)) { + PrintToLog("%s(): rejected: type %d or version %d not permitted for property %d at block %d\n", + __func__, + type, + version, + property, + block); + return (PKT_ERROR_TOKENS -22); + } + + if (!IsPropertyIdValid(property)) { + PrintToLog("%s(): rejected: property %d does not exist\n", __func__, property); + return (PKT_ERROR_TOKENS -24); + } + + CMPSPInfo::Entry sp; + assert(_my_sps->getSP(property, sp)); + + if (!sp.manual) { + PrintToLog("%s(): rejected: property %d is not managed\n", __func__, property); + return (PKT_ERROR_TOKENS -42); + } + + if (sender != sp.issuer) { + PrintToLog("%s(): rejected: sender %s is not issuer of property %d [issuer=%s]\n", __func__, sender, property, sp.issuer); + return (PKT_ERROR_TOKENS -43); + } + + if (!isFreezingEnabled(property, block)) { + PrintToLog("%s(): rejected: freezing is not enabled for property %d\n", __func__, property); + return (PKT_ERROR_TOKENS -47); + } + + if (!isAddressFrozen(receiver, property)) { + PrintToLog("%s(): rejected: address %s is not frozen for property %d\n", __func__, receiver, property); + return (PKT_ERROR_TOKENS -48); + } + + unfreezeAddress(receiver, property); + + return 0; +} + /** Tx 65533 */ int CMPTransaction::logicMath_Deactivation() { diff --git a/src/omnicore/tx.h b/src/omnicore/tx.h index e1442fd0ba44b..bba0dbc87c431 100644 --- a/src/omnicore/tx.h +++ b/src/omnicore/tx.h @@ -121,6 +121,7 @@ class CMPTransaction bool interpret_ChangeIssuer(); bool interpret_ChangeFreezeSetting(); bool interpret_FreezeTokens(); + bool interpret_UnfreezeTokens(); bool interpret_Activation(); bool interpret_Deactivation(); bool interpret_Alert(); @@ -146,6 +147,7 @@ class CMPTransaction int logicMath_ChangeIssuer(); int logicMath_ChangeFreezeSetting(); int logicMath_FreezeTokens(); + int logicMath_UnfreezeTokens(); int logicMath_Activation(); int logicMath_Deactivation(); int logicMath_Alert(); From f2e1b428703fca66ebbd09da701eba824c5595c8 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:42:43 +1100 Subject: [PATCH 23/62] Reject transactions from frozen addresses prior to logic processing Note: rejected after interpretation so the transactions can still be viewed --- src/omnicore/tx.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index 147fadd227603..dcf553917c855 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -13,6 +13,7 @@ #include "omnicore/rules.h" #include "omnicore/sp.h" #include "omnicore/sto.h" +#include "omnicore/utils.h" #include "amount.h" #include "main.h" @@ -818,6 +819,11 @@ int CMPTransaction::interpretPacket() return (PKT_ERROR -2); } + if (isAddressFrozen(sender, property)) { + PrintToLog("%s(): REJECTED: address %s is frozen for property %d\n", __func__, sender, property); + return (PKT_ERROR -3); + } + LOCK(cs_tally); switch (type) { From ca91249ccd9877eadcc71afadc62726b170aca70 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:44:46 +1100 Subject: [PATCH 24/62] Add freeze error descriptions to errors.h --- src/omnicore/errors.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/omnicore/errors.h b/src/omnicore/errors.h index 5f085bb6c92d8..2f5775127f43c 100644 --- a/src/omnicore/errors.h +++ b/src/omnicore/errors.h @@ -85,6 +85,9 @@ inline std::string error_str(int ec) { case PKT_ERROR -2: ec_str = "Failed to interpret transaction"; break; + case PKT_ERROR -3: + ec_str = "Sender is frozen for the property"; + break; case PKT_ERROR -22: ec_str = "Transaction type or version not permitted"; break; @@ -321,6 +324,18 @@ inline std::string error_str(int ec) { case PKT_ERROR_TOKENS -46: ec_str = "Receiver has an active crowdsale"; break; + case PKT_ERROR_TOKENS -47: + ec_str = "Freezing is not enabled for the property"; + break; + case PKT_ERROR_TOKENS -48: + ec_str = "Address is not frozen"; + break; + case PKT_ERROR_TOKENS -49: + ec_str = "State value is not 0 or 1"; + break; + case PKT_ERROR_TOKENS -50: + ec_str = "Address is already frozen"; + break; default: ec_str = "Unknown error"; From 8736b51dfe83e541e7f50d61fcfc3a905bc08a44 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:49:05 +1100 Subject: [PATCH 25/62] Load the freeze state at startup --- src/omnicore/omnicore.cpp | 75 +++++++++++++++++++++++++++++++++++++++ src/omnicore/omnicore.h | 1 + 2 files changed, 76 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 5999da891b487..c84bc317f79d3 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -2304,6 +2304,15 @@ int mastercore_init() // load all alerts from levelDB (and immediately expire old ones) p_txlistdb->LoadAlerts(nWaterlineBlock); + // load the state of any freeable properties and frozen addresses from levelDB + if (!p_txlistdb->LoadFreezeState(nWaterlineBlock)) { + std::string strShutdownReason = "Failed to load freeze state from levelDB. It is unsafe to continue.\n"; + PrintToLog(strShutdownReason); + if (!GetBoolArg("-overrideforcedshutdown", false)) { + AbortNode(strShutdownReason, strShutdownReason); + } + } + // initial scan msc_initial_scan(nWaterlineBlock); @@ -2618,6 +2627,72 @@ std::set CMPTxList::GetSeedBlocks(int startHeight, int endHeight) return setSeedBlocks; } +bool CMPTxList::LoadFreezeState(int blockHeight) +{ + assert(pdb); + std::vector > loadOrder; + Iterator* it = NewIterator(); + PrintToLog("Loading freeze state from levelDB\n"); + + for (it->SeekToFirst(); it->Valid(); it->Next()) { + std::string itData = it->value().ToString(); + std::vector vstr; + boost::split(vstr, itData, boost::is_any_of(":"), token_compress_on); + if (4 != vstr.size()) continue; + if (atoi(vstr[2]) != MSC_TYPE_FREEZE_PROPERTY_TOKENS && atoi(vstr[2]) != MSC_TYPE_CHANGE_FREEZE_SETTING) continue; + if (atoi(vstr[0]) != 1) continue; + uint256 txid = uint256S(it->key().ToString());; + loadOrder.push_back(std::make_pair(atoi(vstr[1]), txid)); + } + + std::sort (loadOrder.begin(), loadOrder.end()); + + for (std::vector >::iterator it = loadOrder.begin(); it != loadOrder.end(); ++it) { + uint256 hash = (*it).second; + uint256 blockHash; + CTransaction wtx; + CMPTransaction mp_obj; + if (!GetTransaction(hash, wtx, Params().GetConsensus(), blockHash, true)) { + PrintToLog("ERROR: While loading freeze transaction %s: tx in levelDB but does not exist.\n", hash.GetHex()); + return false; + } + if (blockHash.IsNull() || (NULL == GetBlockIndex(blockHash))) { + PrintToLog("ERROR: While loading freeze transaction %s: failed to retrieve block hash.\n", hash.GetHex()); + return false; + } + CBlockIndex* pBlockIndex = GetBlockIndex(blockHash); + if (NULL == pBlockIndex) { + PrintToLog("ERROR: While loading freeze transaction %s: failed to retrieve block index.\n", hash.GetHex()); + return false; + } + int txBlockHeight = pBlockIndex->nHeight; + if (txBlockHeight > blockHeight) { + PrintToLog("ERROR: While loading freeze transaction %s: transaction is in the future.\n", hash.GetHex()); + return false; + } + if (0 != ParseTransaction(wtx, txBlockHeight, 0, mp_obj)) { + PrintToLog("ERROR: While loading freeze transaction %s: failed ParseTransaction.\n", hash.GetHex()); + return false; + } + if (!mp_obj.interpret_Transaction()) { + PrintToLog("ERROR: While loading freeze transaction %s: failed interpret_Transaction.\n", hash.GetHex()); + return false; + } + if (MSC_TYPE_FREEZE_PROPERTY_TOKENS != mp_obj.getType() && MSC_TYPE_CHANGE_FREEZE_SETTING != mp_obj.getType()) { + PrintToLog("ERROR: While loading freeze transaction %s: levelDB type mismatch, not a freeze transaction.\n", hash.GetHex()); + return false; + } + mp_obj.unlockLogic(); + if (0 != mp_obj.interpretPacket()) { + PrintToLog("ERROR: While loading freeze transaction %s: non-zero return from interpretPacket\n", hash.GetHex()); + return false; + } + } + delete it; + + return true; +} + void CMPTxList::LoadActivations(int blockHeight) { if (!pdb) return; diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 2631ca5924503..99d019e1e6e78 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -281,6 +281,7 @@ class CMPTxList : public CDBBase std::set GetSeedBlocks(int startHeight, int endHeight); void LoadAlerts(int blockHeight); void LoadActivations(int blockHeight); + bool LoadFreezeState(int blockHeight); void printStats(); void printAll(); From fc38b800eb068232ed7c1c95cc81a15512b83386 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:50:15 +1100 Subject: [PATCH 26/62] Add managedissuance attribute to omni_getproperty RPC response --- src/omnicore/rpc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/omnicore/rpc.cpp b/src/omnicore/rpc.cpp index 34c981a08fe78..7cbc2dafa6b35 100644 --- a/src/omnicore/rpc.cpp +++ b/src/omnicore/rpc.cpp @@ -899,6 +899,7 @@ UniValue omni_getproperty(const UniValue& params, bool fHelp) " \"issuer\" : \"address\", (string) the Bitcoin address of the issuer on record\n" " \"creationtxid\" : \"hash\", (string) the hex-encoded creation transaction hash\n" " \"fixedissuance\" : true|false, (boolean) whether the token supply is fixed\n" + " \"managedissuance\" : true|false, (boolean) whether the token supply is managed\n" " \"totaltokens\" : \"n.nnnnnnnn\" (string) the total number of tokens in existence\n" "}\n" "\nExamples:\n" @@ -927,6 +928,7 @@ UniValue omni_getproperty(const UniValue& params, bool fHelp) response.push_back(Pair("issuer", sp.issuer)); response.push_back(Pair("creationtxid", strCreationHash)); response.push_back(Pair("fixedissuance", sp.fixed)); + response.push_back(Pair("managedissuance", sp.manual)); response.push_back(Pair("totaltokens", strTotalTokens)); return response; From 0247861f053c4608c806e0258ea32b7bf0d8538f Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 09:55:28 +1100 Subject: [PATCH 27/62] Add 'freezingenabled' attribute to omni_getproperty RPC response if property is managed --- src/omnicore/rpc.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/omnicore/rpc.cpp b/src/omnicore/rpc.cpp index 7cbc2dafa6b35..df9d476df0f39 100644 --- a/src/omnicore/rpc.cpp +++ b/src/omnicore/rpc.cpp @@ -929,6 +929,11 @@ UniValue omni_getproperty(const UniValue& params, bool fHelp) response.push_back(Pair("creationtxid", strCreationHash)); response.push_back(Pair("fixedissuance", sp.fixed)); response.push_back(Pair("managedissuance", sp.manual)); + if (sp.manual) { + LOCK(cs_tally); + int currentBlock = GetHeight(); + response.push_back(Pair("freezingenabled", isFreezingEnabled(propertyId, currentBlock))); + } response.push_back(Pair("totaltokens", strTotalTokens)); return response; From 338fa73544f0a26bdd81a16b362ec6cd0024284e Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 10:01:44 +1100 Subject: [PATCH 28/62] Add 'omni_changefreezesetting' RPC --- src/omnicore/rpctx.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++ src/rpc/client.cpp | 2 ++ 2 files changed, 54 insertions(+) diff --git a/src/omnicore/rpctx.cpp b/src/omnicore/rpctx.cpp index e1e46feabe35a..f17feddb795d3 100644 --- a/src/omnicore/rpctx.cpp +++ b/src/omnicore/rpctx.cpp @@ -1098,6 +1098,57 @@ UniValue omni_sendchangeissuer(const UniValue& params, bool fHelp) } } +UniValue omni_sendchangefreezesetting(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "omni_sendchangefreezesetting \"fromaddress\" propertyid state\n" + + "\nEnables or disables address freezing for a centrally managed property.\n" + "\nIMPORTANT NOTE: Disabling freezing for a property will UNFREEZE all frozen addresses for that property!" + + "\nArguments:\n" + "1. fromaddress (string, required) the issuer of the tokens\n" + "2. propertyid (number, required) the identifier of the tokens\n" + "3. state (boolean, required) the state of address freezing\n" + + "\nResult:\n" + "\"hash\" (string) the hex-encoded transaction hash\n" + + "\nExamples:\n" + + HelpExampleCli("omni_sendchangefreezesetting", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\" 3 false") + + HelpExampleRpc("omni_sendchangefreezesetting", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\", 3, false") + ); + + // obtain parameters & info + std::string fromAddress = ParseAddress(params[0]); + uint32_t propertyId = ParsePropertyId(params[1]); + bool state = params[2].get_bool(); + + // perform checks + RequireExistingProperty(propertyId); + RequireTokenIssuer(fromAddress, propertyId); + + // create a payload for the transaction + std::vector payload = CreatePayload_ChangeFreezeSetting(propertyId, state); + + // request the wallet build the transaction (and if needed commit it) + uint256 txid; + std::string rawHex; + int result = WalletTxBuilder(fromAddress, "", "", 0, payload, txid, rawHex, autoCommit); + + // check error and return the txid (or raw hex depending on autocommit) + if (result != 0) { + throw JSONRPCError(result, error_str(result)); + } else { + if (!autoCommit) { + return rawHex; + } else { + return txid.GetHex(); + } + } +} + UniValue omni_sendactivation(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 4) @@ -1258,6 +1309,7 @@ static const CRPCCommand commands[] = { "omni layer (transaction creation)", "omni_sendclosecrowdsale", &omni_sendclosecrowdsale, false }, { "omni layer (transaction creation)", "omni_sendchangeissuer", &omni_sendchangeissuer, false }, { "omni layer (transaction creation)", "omni_sendall", &omni_sendall, false }, + { "omni layer (transaction creation)", "omni_sendchangefreezesetting", &omni_sendchangefreezesetting, false }, { "hidden", "omni_senddeactivation", &omni_senddeactivation, true }, { "hidden", "omni_sendactivation", &omni_sendactivation, false }, { "hidden", "omni_sendalert", &omni_sendalert, true }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 60b65277fc503..5b061d25bc063 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -171,6 +171,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "omni_sendgrant", 2 }, { "omni_sendrevoke", 1 }, { "omni_sendchangeissuer", 2 }, + { "omni_sendchangefreezesetting", 1 }, + { "omni_sendchangefreezesetting", 2 }, { "omni_senddeactivation", 1 }, { "omni_sendactivation", 1 }, { "omni_sendactivation", 2 }, From 55ae04a75313a24c36c49aadf68067fe1c152c2e Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 10:03:19 +1100 Subject: [PATCH 29/62] Add 'omni_sendfreeze' RPC --- src/omnicore/rpctx.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++ src/rpc/client.cpp | 1 + 2 files changed, 52 insertions(+) diff --git a/src/omnicore/rpctx.cpp b/src/omnicore/rpctx.cpp index f17feddb795d3..17bd413a65038 100644 --- a/src/omnicore/rpctx.cpp +++ b/src/omnicore/rpctx.cpp @@ -1149,6 +1149,56 @@ UniValue omni_sendchangefreezesetting(const UniValue& params, bool fHelp) } } +UniValue omni_sendfreeze(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 4) + throw runtime_error( + "omni_sendfreeze \"fromaddress\" \"toaddress\" propertyid amount \n" + "\nFreeze an address for a centrally managed token.\n" + "\nNote: Only the issuer may freeze tokens, and only if the token is of the managed type with the freezing option enabled.\n" + "\nArguments:\n" + "1. fromaddress (string, required) the address to send from (must be the issuer of the property)\n" + "2. toaddress (string, required) the address to freeze tokens for\n" + "3. propertyid (number, required) the property to freeze tokens for (must be managed type and have freezing option enabled)\n" + "4. amount (number, required) the amount of tokens to freeze (note: this is unused - once frozen an address cannot send any transactions for the property)\n" + "\nResult:\n" + "\"hash\" (string) the hex-encoded transaction hash\n" + "\nExamples:\n" + + HelpExampleCli("omni_sendfreeze", "\"1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P\" \"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\" 1 0") + + HelpExampleRpc("omni_sendfreeze", "\"1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P\", \"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\", 1, 0") + ); + + // obtain parameters & info + std::string fromAddress = ParseAddress(params[0]); + std::string refAddress = ParseAddress(params[1]); + uint32_t propertyId = ParsePropertyId(params[2]); + int64_t amount = ParseAmount(params[3], isPropertyDivisible(propertyId)); + + // perform checks + RequireExistingProperty(propertyId); + RequireTokenIssuer(fromAddress, propertyId); + + // create a payload for the transaction + std::vector payload = CreatePayload_FreezeTokens(propertyId, amount, refAddress); + + // request the wallet build the transaction (and if needed commit it) + // Note: no ref address is sent to WalletTxBuilder as the ref address is contained within the payload + uint256 txid; + std::string rawHex; + int result = WalletTxBuilder(fromAddress, "", "", 0, payload, txid, rawHex, autoCommit); + + // check error and return the txid (or raw hex depending on autocommit) + if (result != 0) { + throw JSONRPCError(result, error_str(result)); + } else { + if (!autoCommit) { + return rawHex; + } else { + return txid.GetHex(); + } + } +} + UniValue omni_sendactivation(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 4) @@ -1310,6 +1360,7 @@ static const CRPCCommand commands[] = { "omni layer (transaction creation)", "omni_sendchangeissuer", &omni_sendchangeissuer, false }, { "omni layer (transaction creation)", "omni_sendall", &omni_sendall, false }, { "omni layer (transaction creation)", "omni_sendchangefreezesetting", &omni_sendchangefreezesetting, false }, + { "omni layer (transaction creation)", "omni_sendfreeze", &omni_sendfreeze, false }, { "hidden", "omni_senddeactivation", &omni_senddeactivation, true }, { "hidden", "omni_sendactivation", &omni_sendactivation, false }, { "hidden", "omni_sendalert", &omni_sendalert, true }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 5b061d25bc063..a1bd6f58cffd8 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -173,6 +173,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "omni_sendchangeissuer", 2 }, { "omni_sendchangefreezesetting", 1 }, { "omni_sendchangefreezesetting", 2 }, + { "omni_sendfreeze", 2 }, { "omni_senddeactivation", 1 }, { "omni_sendactivation", 1 }, { "omni_sendactivation", 2 }, From 3889c08419bbda4cb6d1a2264be2780ce85e8cb0 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 10:04:40 +1100 Subject: [PATCH 30/62] Add 'omni_sendunfreeze' RPC --- src/omnicore/rpctx.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++ src/rpc/client.cpp | 1 + 2 files changed, 52 insertions(+) diff --git a/src/omnicore/rpctx.cpp b/src/omnicore/rpctx.cpp index 17bd413a65038..88a2f760738ee 100644 --- a/src/omnicore/rpctx.cpp +++ b/src/omnicore/rpctx.cpp @@ -1199,6 +1199,56 @@ UniValue omni_sendfreeze(const UniValue& params, bool fHelp) } } +UniValue omni_sendunfreeze(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 4) + throw runtime_error( + "omni_sendunfreeze \"fromaddress\" \"toaddress\" propertyid amount \n" + "\nUnfreezes an address for a centrally managed token.\n" + "\nNote: Only the issuer may unfreeze tokens.\n" + "\nArguments:\n" + "1. fromaddress (string, required) the address to send from (must be the issuer of the property)\n" + "2. toaddress (string, required) the address to unfreeze tokens for\n" + "3. propertyid (number, required) the property to unfreeze tokens for (must be managed type and have freezing option enabled)\n" + "4. amount (number, required) the amount of tokens to unfreeze (note: this is unused - once frozen an address cannot send any transactions for the property)\n" + "\nResult:\n" + "\"hash\" (string) the hex-encoded transaction hash\n" + "\nExamples:\n" + + HelpExampleCli("omni_sendunfreeze", "\"1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P\" \"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\" 1 0") + + HelpExampleRpc("omni_sendunfreeze", "\"1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P\", \"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\", 1, 0") + ); + + // obtain parameters & info + std::string fromAddress = ParseAddress(params[0]); + std::string refAddress = ParseAddress(params[1]); + uint32_t propertyId = ParsePropertyId(params[2]); + int64_t amount = ParseAmount(params[3], isPropertyDivisible(propertyId)); + + // perform checks + RequireExistingProperty(propertyId); + RequireTokenIssuer(fromAddress, propertyId); + + // create a payload for the transaction + std::vector payload = CreatePayload_UnfreezeTokens(propertyId, amount, refAddress); + + // request the wallet build the transaction (and if needed commit it) + // Note: no ref address is sent to WalletTxBuilder as the ref address is contained within the payload + uint256 txid; + std::string rawHex; + int result = WalletTxBuilder(fromAddress, "", "", 0, payload, txid, rawHex, autoCommit); + + // check error and return the txid (or raw hex depending on autocommit) + if (result != 0) { + throw JSONRPCError(result, error_str(result)); + } else { + if (!autoCommit) { + return rawHex; + } else { + return txid.GetHex(); + } + } +} + UniValue omni_sendactivation(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 4) @@ -1361,6 +1411,7 @@ static const CRPCCommand commands[] = { "omni layer (transaction creation)", "omni_sendall", &omni_sendall, false }, { "omni layer (transaction creation)", "omni_sendchangefreezesetting", &omni_sendchangefreezesetting, false }, { "omni layer (transaction creation)", "omni_sendfreeze", &omni_sendfreeze, false }, + { "omni layer (transaction creation)", "omni_sendunfreeze", &omni_sendunfreeze, false }, { "hidden", "omni_senddeactivation", &omni_senddeactivation, true }, { "hidden", "omni_sendactivation", &omni_sendactivation, false }, { "hidden", "omni_sendalert", &omni_sendalert, true }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index a1bd6f58cffd8..2bf05868dfdf0 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -174,6 +174,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "omni_sendchangefreezesetting", 1 }, { "omni_sendchangefreezesetting", 2 }, { "omni_sendfreeze", 2 }, + { "omni_sendunfreeze", 2 }, { "omni_senddeactivation", 1 }, { "omni_sendactivation", 1 }, { "omni_sendactivation", 2 }, From 4540747e3d639c8cbea93b1edec6b36347353b57 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 11:27:53 +1100 Subject: [PATCH 31/62] Commit bash script for freeze regtest scenario --- src/omnicore/test/test_freeze.sh | 317 +++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100755 src/omnicore/test/test_freeze.sh diff --git a/src/omnicore/test/test_freeze.sh b/src/omnicore/test/test_freeze.sh new file mode 100755 index 0000000000000..a9bff2279064d --- /dev/null +++ b/src/omnicore/test/test_freeze.sh @@ -0,0 +1,317 @@ +#!/bin/bash + +SRCDIR=./src/ +NUL=/dev/null +PASS=0 +FAIL=0 +clear +printf "Preparing a test environment...\n" +printf " * Starting a fresh regtest daemon\n" +rm -r ~/.bitcoin/regtest +$SRCDIR/omnicored --regtest --server --daemon --omniactivationallowsender=any >$NUL +sleep 10 +printf " * Preparing some mature testnet BTC\n" +$SRCDIR/omnicore-cli --regtest generate 102 >$NUL +printf " * Obtaining addresses to work with\n" +ADDR=$($SRCDIR/omnicore-cli --regtest getnewaddress OMNIAccount) +FADDR=$($SRCDIR/omnicore-cli --regtest getnewaddress) +printf " * Funding the addresses with some testnet BTC for fees\n" +JSON="{\""$ADDR"\":4,\""$FADDR"\":4}" +$SRCDIR/omnicore-cli --regtest sendmany "" $JSON >$NUL +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " * Creating a test (managed) property and granting 1000 tokens to the test address\n" +$SRCDIR/omnicore-cli --regtest omni_sendissuancemanaged $ADDR 1 1 0 "TestCat" "TestSubCat" "TestProperty" "TestURL" "TestData" >$NUL +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +$SRCDIR/omnicore-cli --regtest omni_sendgrant $ADDR $FADDR 3 1000 >$NUL +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL + +printf "\nRunning the test scenario...\n" +printf " * Sending a 'freeze' tranasction for the test address prior to enabling freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'freeze' transaction was INVALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking that freezing is currently disabled... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending a 'change freeze setting' transaction to ENABLE freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendchangefreezesetting $ADDR 3 true) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'change freeze setting' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking that freezing is now enabled... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending another 'freeze' tranasction for the test address\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'freeze' transaction was now VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Testing a send from the test address (should now be frozen)\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_send $FADDR $ADDR 3 50) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'send' transaction was INVALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking the test address balance has not changed... " +BALANCE=$($SRCDIR/omnicore-cli --regtest omni_getbalance $FADDR 3 | grep balance | cut -d '"' -f4) +if [ $BALANCE == "1000" ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $BALANCE + FAIL=$((FAIL+1)) +fi +printf " * Sending an 'unfreeze' tranasction for the test address\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendunfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'unfreeze' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Testing a send from the test address (should now be unfrozen)\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_send $FADDR $ADDR 3 50) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'send' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking the test address balance has reduced by the amount of the send... " +BALANCE=$($SRCDIR/omnicore-cli --regtest omni_getbalance $FADDR 3 | grep balance | cut -d '"' -f4) +if [ $BALANCE == "950" ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $BALANCE + FAIL=$((FAIL+1)) +fi +printf " * Sending another 'freeze' tranasction for the test address\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'freeze' transaction was now VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending a 'change freeze setting' transaction to DISABLE freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendchangefreezesetting $ADDR 3 false) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'change freeze setting' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking that freezing is now disabled... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Testing a send from the test address (unfrozen when freezing was disabled)\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_send $FADDR $ADDR 3 30) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'send' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking the test address balance has reduced by the amount of the send... " +BALANCE=$($SRCDIR/omnicore-cli --regtest omni_getbalance $FADDR 3 | grep balance | cut -d '"' -f4) +if [ $BALANCE == "920" ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $BALANCE + FAIL=$((FAIL+1)) +fi +printf " * Sending a 'freeze' tranasction for the test address to test that freezing is now disabled\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'freeze' transaction was INVALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending a feature 14 activation to activate the notice period\n" +BLOCKS=$($SRCDIR/omnicore-cli --regtest getblockcount) +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendactivation $ADDR 14 $(($BLOCKS + 8)) 999) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the activation transaction was valid... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Mining 10 blocks to forward past the activation block\n" +$SRCDIR/omnicore-cli --regtest generate 10 >$NUL +printf " - Checking the activation went live as expected... " +FEATUREID=$($SRCDIR/omnicore-cli --regtest omni_getactivations | grep -A 10 completed | grep featureid | cut -c20-21) +if [ $FEATUREID == "14" ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $FEATUREID + FAIL=$((FAIL+1)) +fi +printf " * Sending a 'change freeze setting' transaction to ENABLE freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendchangefreezesetting $ADDR 3 true) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'change freeze setting' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking that freezing is still disabled (due to wait period)... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending a 'freeze' tranasction for the test address before waiting period expiry\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'freeze' transaction was INVALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Mining 30 blocks to forward past the waiting period\n" +$SRCDIR/omnicore-cli --regtest generate 10 >$NUL +printf " - Checking that freezing is now enabled... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending a 'freeze' tranasction for the test address after waiting period expiry\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'freeze' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi + + +printf "\n" +printf "####################\n" +printf "# Summary: #\n" +printf "# Passed = %d #\n" $PASS +printf "# Failed = %d #\n" $FAIL +printf "####################\n" +printf "\n" +$SRCDIR/omnicore-cli --regtest stop + + From 5f3ff4aac8953c100d7d4766378143817e5b6651 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 29 Nov 2017 11:28:39 +1100 Subject: [PATCH 32/62] Increment DB_VERSION to force a reparse (consensus changes) Note: includes minor comment correction --- src/omnicore/omnicore.cpp | 2 +- src/omnicore/omnicore.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index c84bc317f79d3..90f09f9e59646 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -112,7 +112,7 @@ std::set global_wallet_property_list; //! Set containing properties that have freezing enabled std::set > setFreezingEnabledProperties; -//! Set containing properties waiting to have freezing enabled after their waiting period +//! Set containing addresses that have been frozen std::set > setFrozenAddresses; /** diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 99d019e1e6e78..2ebb5d3ee303d 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -36,7 +36,7 @@ int const MAX_STATE_HISTORY = 50; #define TEST_ECO_PROPERTY_1 (0x80000003UL) // increment this value to force a refresh of the state (similar to --startclean) -#define DB_VERSION 5 +#define DB_VERSION 6 // could probably also use: int64_t maxInt64 = std::numeric_limits::max(); // maximum numeric values from the spec: From f0255f126977d847b77bcc7e8cd3cee09f57bd76 Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 10:49:36 +1100 Subject: [PATCH 33/62] Use DecodeBase58() in AddressToBytes() function - thanks @dexx7 --- src/omnicore/utils.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/omnicore/utils.cpp b/src/omnicore/utils.cpp index 92623d216cc52..5719199f49d4b 100644 --- a/src/omnicore/utils.cpp +++ b/src/omnicore/utils.cpp @@ -13,6 +13,7 @@ // TODO: use crypto/sha256 instead of openssl #include "openssl/sha.h" +#include "omnicore/log.h" #include "omnicore/script.h" #include @@ -78,21 +79,14 @@ std::string HashToAddress(unsigned char version, uint160 hash) std::vector AddressToBytes(const std::string& address) { std::vector addressBytes; - - txnouttype whichType; - CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(address).Get()); - if (!GetOutputType(scriptPubKey, whichType)) { - return addressBytes; + bool success = DecodeBase58(address, addressBytes); + if (!success) { + PrintToLog("ERROR: failed to decode address %s.\n", address); } - - if (scriptPubKey.size() > 23) { - if (whichType == TX_PUBKEYHASH) { - addressBytes.assign(scriptPubKey.begin()+3, scriptPubKey.begin()+23); //uggh - todo - get hash160 bytes in a cleaner way - addressBytes.insert(addressBytes.begin(), Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)[0]); // insert version byte at the beginning - } else if (whichType == TX_SCRIPTHASH) { - addressBytes.assign(scriptPubKey.begin()+2, scriptPubKey.begin()+22); - addressBytes.insert(addressBytes.begin(), Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)[0]); - } + if (addressBytes.size() == 24) { + addressBytes.resize(20); // truncate checksum + } else { + PrintToLog("ERROR: unexpected size from DecodeBase58 when decoding address %s.\n", address); } return addressBytes; From 74362793b7e689fde065945c505d58810e8d7555 Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 10:56:38 +1100 Subject: [PATCH 34/62] Add const to HashToAddress() to avoid copying object - thanks @dexx7 --- src/omnicore/utils.cpp | 2 +- src/omnicore/utils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/omnicore/utils.cpp b/src/omnicore/utils.cpp index 5719199f49d4b..cd12155227ad6 100644 --- a/src/omnicore/utils.cpp +++ b/src/omnicore/utils.cpp @@ -60,7 +60,7 @@ void PrepareObfuscatedHashes(const std::string& strSeed, int hashCount, std::str } } -std::string HashToAddress(unsigned char version, uint160 hash) +std::string HashToAddress(unsigned char version, const uint160& hash) { CBitcoinAddress address; if (version == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)[0]) { diff --git a/src/omnicore/utils.h b/src/omnicore/utils.h index f876fbe18d5fc..9204fd9400032 100644 --- a/src/omnicore/utils.h +++ b/src/omnicore/utils.h @@ -11,7 +11,7 @@ void PrepareObfuscatedHashes(const std::string& strSeed, int hashCount, std::string(&vstrHashes)[1+MAX_SHA256_OBFUSCATION_TIMES]); /** Determines the Bitcoin address associated with a given hash and version. */ -std::string HashToAddress(unsigned char version, uint160 hash); +std::string HashToAddress(unsigned char version, const uint160& hash); /** Returns a vector of bytes containing the version and hash160 for an address.*/ std::vector AddressToBytes(const std::string& address); From 243c930336a1de74146a7fd2b65f55a646daeace Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 11:02:36 +1100 Subject: [PATCH 35/62] Optimize isAddressFrozen() - thanks @dexx7 --- src/omnicore/omnicore.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 90f09f9e59646..89a492e8124a4 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -369,12 +369,8 @@ void mastercore::unfreezeAddress(const std::string& address, uint32_t propertyId bool mastercore::isAddressFrozen(const std::string& address, uint32_t propertyId) { - for (std::set >::iterator it = setFrozenAddresses.begin(); it != setFrozenAddresses.end(); it++) { - std::string itemAddress = (*it).first; - uint32_t itemPropertyId = (*it).second; - if (address == itemAddress && propertyId == itemPropertyId) { - return true; - } + if (setFrozenAddresses.find(std::make_pair(address, propertyId)) != setFrozenAddresses.end()) { + return true; } return false; } From aadafce548da9c15acfb43618c9592dc09da2bdc Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 11:05:30 +1100 Subject: [PATCH 36/62] Return early from disableFreezing() if failure - thanks @dexx7 --- src/omnicore/omnicore.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 89a492e8124a4..608c4cca1bdf7 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -327,6 +327,7 @@ void mastercore::disableFreezing(uint32_t propertyId) } if (liveBlock == 0) { PrintToLog("ERROR: Failed to determine live block to disable freezing for property %d!\n", propertyId); + return; } else { setFreezingEnabledProperties.erase(std::make_pair(propertyId, liveBlock)); PrintToLog("Freezing for property %d has been disabled.\n", propertyId); From 75c7f1a9ff3c5279354d342a045f8d295b1fef4e Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 11:07:22 +1100 Subject: [PATCH 37/62] Move isAddressFrozen() check inside cs_tally LOCK - thanks @dexx7 --- src/omnicore/tx.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index dcf553917c855..4f9d1f171f6fa 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -819,13 +819,13 @@ int CMPTransaction::interpretPacket() return (PKT_ERROR -2); } + LOCK(cs_tally); + if (isAddressFrozen(sender, property)) { PrintToLog("%s(): REJECTED: address %s is frozen for property %d\n", __func__, sender, property); return (PKT_ERROR -3); } - LOCK(cs_tally); - switch (type) { case MSC_TYPE_SIMPLE_SEND: return logicMath_SimpleSend(); From 118e0454cd0320413f42815d46e8201012521a63 Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 11:22:59 +1100 Subject: [PATCH 38/62] Move deletion of iterator in LoadFreezeState() - thanks @dexx7 --- src/omnicore/omnicore.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 608c4cca1bdf7..c954b4067ddb8 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -2642,6 +2642,8 @@ bool CMPTxList::LoadFreezeState(int blockHeight) loadOrder.push_back(std::make_pair(atoi(vstr[1]), txid)); } + delete it; + std::sort (loadOrder.begin(), loadOrder.end()); for (std::vector >::iterator it = loadOrder.begin(); it != loadOrder.end(); ++it) { @@ -2685,7 +2687,6 @@ bool CMPTxList::LoadFreezeState(int blockHeight) return false; } } - delete it; return true; } From d0107fc01018d79be043e837ef25b79d4b686617 Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 11:25:33 +1100 Subject: [PATCH 39/62] Add RequireManagedProperty() check to RPC tx creation - thanks @dexx7 --- src/omnicore/rpctx.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/omnicore/rpctx.cpp b/src/omnicore/rpctx.cpp index 88a2f760738ee..32b72993de12e 100644 --- a/src/omnicore/rpctx.cpp +++ b/src/omnicore/rpctx.cpp @@ -1127,6 +1127,7 @@ UniValue omni_sendchangefreezesetting(const UniValue& params, bool fHelp) // perform checks RequireExistingProperty(propertyId); + RequireManagedProperty(propertyId); RequireTokenIssuer(fromAddress, propertyId); // create a payload for the transaction @@ -1176,6 +1177,7 @@ UniValue omni_sendfreeze(const UniValue& params, bool fHelp) // perform checks RequireExistingProperty(propertyId); + RequireManagedProperty(propertyId); RequireTokenIssuer(fromAddress, propertyId); // create a payload for the transaction @@ -1226,6 +1228,7 @@ UniValue omni_sendunfreeze(const UniValue& params, bool fHelp) // perform checks RequireExistingProperty(propertyId); + RequireManagedProperty(propertyId); RequireTokenIssuer(fromAddress, propertyId); // create a payload for the transaction From 16d6cb9b8960b24d3ba19fc91361fc17b5bf756d Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 11:27:24 +1100 Subject: [PATCH 40/62] Move lock after GetHeight() check in omni_getproperty RPC - thanks @dexx7 --- src/omnicore/rpc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/omnicore/rpc.cpp b/src/omnicore/rpc.cpp index df9d476df0f39..9e4394fc1a78b 100644 --- a/src/omnicore/rpc.cpp +++ b/src/omnicore/rpc.cpp @@ -930,8 +930,8 @@ UniValue omni_getproperty(const UniValue& params, bool fHelp) response.push_back(Pair("fixedissuance", sp.fixed)); response.push_back(Pair("managedissuance", sp.manual)); if (sp.manual) { - LOCK(cs_tally); int currentBlock = GetHeight(); + LOCK(cs_tally); response.push_back(Pair("freezingenabled", isFreezingEnabled(propertyId, currentBlock))); } response.push_back(Pair("totaltokens", strTotalTokens)); From 2257e39e5f4296e0cfd03b1c41b1a58bda639af3 Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 11:41:35 +1100 Subject: [PATCH 41/62] Add safety net to ensure update_tally_map() cannot take tokens from a frozen address/property --- src/omnicore/omnicore.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index c954b4067ddb8..f3a9ed59d694a 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -451,6 +451,10 @@ bool mastercore::update_tally_map(const std::string& who, uint32_t propertyId, i LOCK(cs_tally); + if (ttype != PENDING && amount < 0) { + assert(!isAddressFrozen(who, propertyId)); // for safety, this should never fail if everything else is working properly. + } + before = getMPbalance(who, propertyId, ttype); std::unordered_map::iterator my_it = mp_tally_map.find(who); From 01c343634b08035912f6f94389ed1be55348a1dd Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 1 Dec 2017 11:50:47 +1100 Subject: [PATCH 42/62] Restrict Send All from trying to transfer frozen properties --- src/omnicore/test/test_freeze.sh | 23 +++++++++++++++++++++++ src/omnicore/tx.cpp | 6 ++++++ 2 files changed, 29 insertions(+) diff --git a/src/omnicore/test/test_freeze.sh b/src/omnicore/test/test_freeze.sh index a9bff2279064d..4eefe85f311aa 100755 --- a/src/omnicore/test/test_freeze.sh +++ b/src/omnicore/test/test_freeze.sh @@ -303,6 +303,29 @@ if [ $RESULT == "true," ] printf " FAIL (result:%s)\n" $RESULT FAIL=$((FAIL+1)) fi +printf " * Testing a Send All from the test address (now frozen))\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendall $FADDR $ADDR 1) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'Send All' transaction was INVALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking the test address balance has not changed... " +BALANCE=$($SRCDIR/omnicore-cli --regtest omni_getbalance $FADDR 3 | grep balance | cut -d '"' -f4) +if [ $BALANCE == "920" ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $BALANCE + FAIL=$((FAIL+1)) +fi printf "\n" diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index 4f9d1f171f6fa..ca1bdb75861bf 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -1192,6 +1192,12 @@ int CMPTransaction::logicMath_SendAll() continue; } + // do not transfer tokens from a frozen property + if (isAddressFrozen(sender, propertyId)) { + PrintToLog("%s(): sender %s is frozen for property %d - the property will not be included in processing.\n", __func__, sender, propertyId); + continue; + } + int64_t moneyAvailable = ptally->getMoney(propertyId, BALANCE); if (moneyAvailable > 0) { ++numberOfPropertiesSent; From e8e657a17f1602f494690a9e0d576e3412826544 Mon Sep 17 00:00:00 2001 From: Zathras Date: Tue, 5 Dec 2017 10:53:40 +1100 Subject: [PATCH 43/62] Add 'frozen' attribute to balance RPC responses if address is frozen for a property --- src/omnicore/omnicore.cpp | 11 +++++++++++ src/omnicore/omnicore.h | 1 + src/omnicore/rpc.cpp | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index f3a9ed59d694a..46616bd0b366f 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -290,6 +290,17 @@ int64_t getUserAvailableMPbalance(const std::string& address, uint32_t propertyI return money; } +int64_t getUserFrozenMPbalance(const std::string& address, uint32_t propertyId) +{ + int64_t frozen = 0; + + if (isAddressFrozen(address, propertyId)) { + frozen = getMPbalance(address, propertyId, BALANCE); + } + + return frozen; +} + bool mastercore::isTestEcosystemProperty(uint32_t propertyId) { if ((OMNI_PROPERTY_TMSC == propertyId) || (TEST_ECO_PROPERTY_1 <= propertyId)) return true; diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 2ebb5d3ee303d..64f5c77eee18d 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -298,6 +298,7 @@ extern std::set global_wallet_property_list; int64_t getMPbalance(const std::string& address, uint32_t propertyId, TallyType ttype); int64_t getUserAvailableMPbalance(const std::string& address, uint32_t propertyId); +int64_t getUserFrozenMPbalance(const std::string& address, uint32_t propertyId); /** Global handler to initialize Omni Core. */ int mastercore_init(); diff --git a/src/omnicore/rpc.cpp b/src/omnicore/rpc.cpp index 9e4394fc1a78b..d34d3d74a3938 100644 --- a/src/omnicore/rpc.cpp +++ b/src/omnicore/rpc.cpp @@ -134,12 +134,16 @@ bool BalanceToJSON(const std::string& address, uint32_t property, UniValue& bala nReserved += getMPbalance(address, property, METADEX_RESERVE); nReserved += getMPbalance(address, property, SELLOFFER_RESERVE); + int64_t nFrozen = getUserFrozenMPbalance(address, property); + if (divisible) { balance_obj.push_back(Pair("balance", FormatDivisibleMP(nAvailable))); balance_obj.push_back(Pair("reserved", FormatDivisibleMP(nReserved))); + if (nFrozen != 0) balance_obj.push_back(Pair("frozen", FormatDivisibleMP(nFrozen))); } else { balance_obj.push_back(Pair("balance", FormatIndivisibleMP(nAvailable))); balance_obj.push_back(Pair("reserved", FormatIndivisibleMP(nReserved))); + if (nFrozen != 0) balance_obj.push_back(Pair("frozen", FormatIndivisibleMP(nFrozen))); } if (nAvailable == 0 && nReserved == 0) { From 98741934ab4d47dba779f379df72c7be277103ed Mon Sep 17 00:00:00 2001 From: Zathras Date: Tue, 5 Dec 2017 12:59:19 +1100 Subject: [PATCH 44/62] Swap 'Change Freeze Setting' for 'Enable Freezing' & 'Disable Freezing' transactions Note: TX71 no longer has a state. TX71 enables & TX72 disables. --- src/omnicore/createpayload.cpp | 20 ++++++- src/omnicore/createpayload.h | 3 +- src/omnicore/errors.h | 2 +- src/omnicore/omnicore.cpp | 5 +- src/omnicore/omnicore.h | 3 +- src/omnicore/rpctx.cpp | 68 +++++++++++++++++---- src/omnicore/rules.cpp | 3 +- src/omnicore/tx.cpp | 104 ++++++++++++++++++++++++++++----- src/omnicore/tx.h | 6 +- src/rpc/client.cpp | 4 +- 10 files changed, 179 insertions(+), 39 deletions(-) diff --git a/src/omnicore/createpayload.cpp b/src/omnicore/createpayload.cpp index da748a3ad4b54..b9d5f9d910392 100644 --- a/src/omnicore/createpayload.cpp +++ b/src/omnicore/createpayload.cpp @@ -317,7 +317,7 @@ std::vector CreatePayload_ChangeIssuer(uint32_t propertyId) return payload; } -std::vector CreatePayload_ChangeFreezeSetting(uint32_t propertyId, bool state) +std::vector CreatePayload_EnableFreezing(uint32_t propertyId) { std::vector payload; uint16_t messageType = 71; @@ -325,12 +325,26 @@ std::vector CreatePayload_ChangeFreezeSetting(uint32_t propertyId mastercore::swapByteOrder16(messageType); mastercore::swapByteOrder16(messageVer); mastercore::swapByteOrder32(propertyId); - unsigned char freezeState = (state) ? 1 : 0; PUSH_BACK_BYTES(payload, messageVer); PUSH_BACK_BYTES(payload, messageType); PUSH_BACK_BYTES(payload, propertyId); - PUSH_BACK_BYTES(payload, freezeState); + + return payload; +} + +std::vector CreatePayload_DisableFreezing(uint32_t propertyId) +{ + std::vector payload; + uint16_t messageType = 72; + uint16_t messageVer = 0; + mastercore::swapByteOrder16(messageType); + mastercore::swapByteOrder16(messageVer); + mastercore::swapByteOrder32(propertyId); + + PUSH_BACK_BYTES(payload, messageVer); + PUSH_BACK_BYTES(payload, messageType); + PUSH_BACK_BYTES(payload, propertyId); return payload; } diff --git a/src/omnicore/createpayload.h b/src/omnicore/createpayload.h index 99a032c2cf908..2f1334a68b2f1 100644 --- a/src/omnicore/createpayload.h +++ b/src/omnicore/createpayload.h @@ -21,7 +21,8 @@ std::vector CreatePayload_CloseCrowdsale(uint32_t propertyId); std::vector CreatePayload_Grant(uint32_t propertyId, uint64_t amount, std::string memo); std::vector CreatePayload_Revoke(uint32_t propertyId, uint64_t amount, std::string memo); std::vector CreatePayload_ChangeIssuer(uint32_t propertyId); -std::vector CreatePayload_ChangeFreezeSetting(uint32_t propertyId, bool state); +std::vector CreatePayload_EnableFreezing(uint32_t propertyId); +std::vector CreatePayload_DisableFreezing(uint32_t propertyId); std::vector CreatePayload_FreezeTokens(uint32_t propertyId, uint64_t amount, const std::string& address); std::vector CreatePayload_UnfreezeTokens(uint32_t propertyId, uint64_t amount, const std::string& address); std::vector CreatePayload_MetaDExTrade(uint32_t propertyIdForSale, uint64_t amountForSale, uint32_t propertyIdDesired, uint64_t amountDesired); diff --git a/src/omnicore/errors.h b/src/omnicore/errors.h index 2f5775127f43c..b564a5d066251 100644 --- a/src/omnicore/errors.h +++ b/src/omnicore/errors.h @@ -331,7 +331,7 @@ inline std::string error_str(int ec) { ec_str = "Address is not frozen"; break; case PKT_ERROR_TOKENS -49: - ec_str = "State value is not 0 or 1"; + ec_str = "Freezing is already enabled for the property"; break; case PKT_ERROR_TOKENS -50: ec_str = "Address is already frozen"; diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 46616bd0b366f..c9f15727dbc02 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -2651,7 +2651,8 @@ bool CMPTxList::LoadFreezeState(int blockHeight) std::vector vstr; boost::split(vstr, itData, boost::is_any_of(":"), token_compress_on); if (4 != vstr.size()) continue; - if (atoi(vstr[2]) != MSC_TYPE_FREEZE_PROPERTY_TOKENS && atoi(vstr[2]) != MSC_TYPE_CHANGE_FREEZE_SETTING) continue; + uint16_t txtype = atoi(vstr[2]); + if (txtype != MSC_TYPE_FREEZE_PROPERTY_TOKENS && txtype != MSC_TYPE_ENABLE_FREEZING && txtype != MSC_TYPE_DISABLE_FREEZING) continue; if (atoi(vstr[0]) != 1) continue; uint256 txid = uint256S(it->key().ToString());; loadOrder.push_back(std::make_pair(atoi(vstr[1]), txid)); @@ -2692,7 +2693,7 @@ bool CMPTxList::LoadFreezeState(int blockHeight) PrintToLog("ERROR: While loading freeze transaction %s: failed interpret_Transaction.\n", hash.GetHex()); return false; } - if (MSC_TYPE_FREEZE_PROPERTY_TOKENS != mp_obj.getType() && MSC_TYPE_CHANGE_FREEZE_SETTING != mp_obj.getType()) { + if (MSC_TYPE_FREEZE_PROPERTY_TOKENS != mp_obj.getType() && MSC_TYPE_ENABLE_FREEZING != mp_obj.getType() && MSC_TYPE_DISABLE_FREEZING != mp_obj.getType()) { PrintToLog("ERROR: While loading freeze transaction %s: levelDB type mismatch, not a freeze transaction.\n", hash.GetHex()); return false; } diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 64f5c77eee18d..2e39a741c51d3 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -86,7 +86,8 @@ enum TransactionType { MSC_TYPE_GRANT_PROPERTY_TOKENS = 55, MSC_TYPE_REVOKE_PROPERTY_TOKENS = 56, MSC_TYPE_CHANGE_ISSUER_ADDRESS = 70, - MSC_TYPE_CHANGE_FREEZE_SETTING = 71, + MSC_TYPE_ENABLE_FREEZING = 71, + MSC_TYPE_DISABLE_FREEZING = 72, MSC_TYPE_FREEZE_PROPERTY_TOKENS = 185, MSC_TYPE_UNFREEZE_PROPERTY_TOKENS = 186, OMNICORE_MESSAGE_TYPE_DEACTIVATION = 65533, diff --git a/src/omnicore/rpctx.cpp b/src/omnicore/rpctx.cpp index 32b72993de12e..5d5b804f50d6d 100644 --- a/src/omnicore/rpctx.cpp +++ b/src/omnicore/rpctx.cpp @@ -1098,32 +1098,79 @@ UniValue omni_sendchangeissuer(const UniValue& params, bool fHelp) } } -UniValue omni_sendchangefreezesetting(const UniValue& params, bool fHelp) +UniValue omni_sendenablefreezing(const UniValue& params, bool fHelp) { - if (fHelp || params.size() != 3) + if (fHelp || params.size() != 2) + throw runtime_error( + "omni_sendenablefreezing \"fromaddress\" propertyid\n" + + "\nEnables address freezing for a centrally managed property.\n" + + "\nArguments:\n" + "1. fromaddress (string, required) the issuer of the tokens\n" + "2. propertyid (number, required) the identifier of the tokens\n" + + "\nResult:\n" + "\"hash\" (string) the hex-encoded transaction hash\n" + + "\nExamples:\n" + + HelpExampleCli("omni_sendenablefreezing", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\" 3") + + HelpExampleRpc("omni_sendenablefreezing", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\", 3") + ); + + // obtain parameters & info + std::string fromAddress = ParseAddress(params[0]); + uint32_t propertyId = ParsePropertyId(params[1]); + + // perform checks + RequireExistingProperty(propertyId); + RequireManagedProperty(propertyId); + RequireTokenIssuer(fromAddress, propertyId); + + // create a payload for the transaction + std::vector payload = CreatePayload_EnableFreezing(propertyId); + + // request the wallet build the transaction (and if needed commit it) + uint256 txid; + std::string rawHex; + int result = WalletTxBuilder(fromAddress, "", "", 0, payload, txid, rawHex, autoCommit); + + // check error and return the txid (or raw hex depending on autocommit) + if (result != 0) { + throw JSONRPCError(result, error_str(result)); + } else { + if (!autoCommit) { + return rawHex; + } else { + return txid.GetHex(); + } + } +} + +UniValue omni_senddisablefreezing(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 2) throw runtime_error( - "omni_sendchangefreezesetting \"fromaddress\" propertyid state\n" + "omni_senddisablefreezing \"fromaddress\" propertyid\n" - "\nEnables or disables address freezing for a centrally managed property.\n" + "\nDisables address freezing for a centrally managed property.\n" "\nIMPORTANT NOTE: Disabling freezing for a property will UNFREEZE all frozen addresses for that property!" "\nArguments:\n" "1. fromaddress (string, required) the issuer of the tokens\n" "2. propertyid (number, required) the identifier of the tokens\n" - "3. state (boolean, required) the state of address freezing\n" "\nResult:\n" "\"hash\" (string) the hex-encoded transaction hash\n" "\nExamples:\n" - + HelpExampleCli("omni_sendchangefreezesetting", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\" 3 false") - + HelpExampleRpc("omni_sendchangefreezesetting", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\", 3, false") + + HelpExampleCli("omni_senddisablefreezing", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\" 3") + + HelpExampleRpc("omni_senddisablefreezing", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\", 3") ); // obtain parameters & info std::string fromAddress = ParseAddress(params[0]); uint32_t propertyId = ParsePropertyId(params[1]); - bool state = params[2].get_bool(); // perform checks RequireExistingProperty(propertyId); @@ -1131,7 +1178,7 @@ UniValue omni_sendchangefreezesetting(const UniValue& params, bool fHelp) RequireTokenIssuer(fromAddress, propertyId); // create a payload for the transaction - std::vector payload = CreatePayload_ChangeFreezeSetting(propertyId, state); + std::vector payload = CreatePayload_DisableFreezing(propertyId); // request the wallet build the transaction (and if needed commit it) uint256 txid; @@ -1412,7 +1459,8 @@ static const CRPCCommand commands[] = { "omni layer (transaction creation)", "omni_sendclosecrowdsale", &omni_sendclosecrowdsale, false }, { "omni layer (transaction creation)", "omni_sendchangeissuer", &omni_sendchangeissuer, false }, { "omni layer (transaction creation)", "omni_sendall", &omni_sendall, false }, - { "omni layer (transaction creation)", "omni_sendchangefreezesetting", &omni_sendchangefreezesetting, false }, + { "omni layer (transaction creation)", "omni_sendenablefreezing", &omni_sendenablefreezing, false }, + { "omni layer (transaction creation)", "omni_senddisablefreezing", &omni_senddisablefreezing, false }, { "omni layer (transaction creation)", "omni_sendfreeze", &omni_sendfreeze, false }, { "omni layer (transaction creation)", "omni_sendunfreeze", &omni_sendunfreeze, false }, { "hidden", "omni_senddeactivation", &omni_senddeactivation, true }, diff --git a/src/omnicore/rules.cpp b/src/omnicore/rules.cpp index 6f4e8c7b2c03b..7f9bf2545d7a3 100644 --- a/src/omnicore/rules.cpp +++ b/src/omnicore/rules.cpp @@ -56,7 +56,8 @@ std::vector CConsensusParams::GetRestrictions() const { MSC_TYPE_GRANT_PROPERTY_TOKENS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, { MSC_TYPE_REVOKE_PROPERTY_TOKENS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, { MSC_TYPE_CHANGE_ISSUER_ADDRESS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, - { MSC_TYPE_CHANGE_FREEZE_SETTING, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, + { MSC_TYPE_ENABLE_FREEZING, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, + { MSC_TYPE_DISABLE_FREEZING, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, { MSC_TYPE_FREEZE_PROPERTY_TOKENS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, { MSC_TYPE_UNFREEZE_PROPERTY_TOKENS, MP_TX_PKT_V0, false, MSC_MANUALSP_BLOCK }, diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index ca1bdb75861bf..ebec82a3501a3 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -60,7 +60,8 @@ std::string mastercore::strTransactionType(uint16_t txType) case MSC_TYPE_GRANT_PROPERTY_TOKENS: return "Grant Property Tokens"; case MSC_TYPE_REVOKE_PROPERTY_TOKENS: return "Revoke Property Tokens"; case MSC_TYPE_CHANGE_ISSUER_ADDRESS: return "Change Issuer Address"; - case MSC_TYPE_CHANGE_FREEZE_SETTING: return "Change Freeze Setting"; + case MSC_TYPE_ENABLE_FREEZING: return "Enable Freezing"; + case MSC_TYPE_DISABLE_FREEZING: return "Disable Freezing"; case MSC_TYPE_FREEZE_PROPERTY_TOKENS: return "Freeze Property Tokens"; case MSC_TYPE_UNFREEZE_PROPERTY_TOKENS: return "Unfreeze Property Tokens"; case MSC_TYPE_NOTIFICATION: return "Notification"; @@ -153,8 +154,11 @@ bool CMPTransaction::interpret_Transaction() case MSC_TYPE_CHANGE_ISSUER_ADDRESS: return interpret_ChangeIssuer(); - case MSC_TYPE_CHANGE_FREEZE_SETTING: - return interpret_ChangeFreezeSetting(); + case MSC_TYPE_ENABLE_FREEZING: + return interpret_EnableFreezing(); + + case MSC_TYPE_DISABLE_FREEZING: + return interpret_DisableFreezing(); case MSC_TYPE_FREEZE_PROPERTY_TOKENS: return interpret_FreezeTokens(); @@ -645,18 +649,32 @@ bool CMPTransaction::interpret_ChangeIssuer() } /** Tx 71 */ -bool CMPTransaction::interpret_ChangeFreezeSetting() +bool CMPTransaction::interpret_EnableFreezing() +{ + if (pkt_size < 8) { + return false; + } + memcpy(&property, &pkt[4], 4); + swapByteOrder32(property); + + if ((!rpcOnly && msc_debug_packets) || msc_debug_packets_readonly) { + PrintToLog("\t property: %d (%s)\n", property, strMPProperty(property)); + } + + return true; +} + +/** Tx 72 */ +bool CMPTransaction::interpret_DisableFreezing() { - if (pkt_size < 9) { + if (pkt_size < 8) { return false; } memcpy(&property, &pkt[4], 4); swapByteOrder32(property); - memcpy(&action, &pkt[8], 1); if ((!rpcOnly && msc_debug_packets) || msc_debug_packets_readonly) { PrintToLog("\t property: %d (%s)\n", property, strMPProperty(property)); - PrintToLog("\t state: %d\n", action); } return true; @@ -875,8 +893,11 @@ int CMPTransaction::interpretPacket() case MSC_TYPE_CHANGE_ISSUER_ADDRESS: return logicMath_ChangeIssuer(); - case MSC_TYPE_CHANGE_FREEZE_SETTING: - return logicMath_ChangeFreezeSetting(); + case MSC_TYPE_ENABLE_FREEZING: + return logicMath_EnableFreezing(); + + case MSC_TYPE_DISABLE_FREEZING: + return logicMath_DisableFreezing(); case MSC_TYPE_FREEZE_PROPERTY_TOKENS: return logicMath_FreezeTokens(); @@ -2069,7 +2090,7 @@ int CMPTransaction::logicMath_ChangeIssuer() } /** Tx 71 */ -int CMPTransaction::logicMath_ChangeFreezeSetting() +int CMPTransaction::logicMath_EnableFreezing() { uint256 blockHash; { @@ -2111,15 +2132,66 @@ int CMPTransaction::logicMath_ChangeFreezeSetting() return (PKT_ERROR_TOKENS -43); } - if (action == 0) { - disableFreezing(property); - } else if (action == 1) { - enableFreezing(property, block); - } else { - PrintToLog("%s(): rejected: state value %d is not 0 or 1\n", __func__, action); + if (isFreezingEnabled(property, block)) { + PrintToLog("%s(): rejected: freezing is already enabled for property %d\n", __func__, property); return (PKT_ERROR_TOKENS -49); } + enableFreezing(property, block); + + return 0; +} + +/** Tx 72 */ +int CMPTransaction::logicMath_DisableFreezing() +{ + uint256 blockHash; + { + LOCK(cs_main); + + CBlockIndex* pindex = chainActive[block]; + if (pindex == NULL) { + PrintToLog("%s(): ERROR: block %d not in the active chain\n", __func__, block); + return (PKT_ERROR_TOKENS -20); + } + blockHash = pindex->GetBlockHash(); + } + + if (!IsTransactionTypeAllowed(block, property, type, version)) { + PrintToLog("%s(): rejected: type %d or version %d not permitted for property %d at block %d\n", + __func__, + type, + version, + property, + block); + return (PKT_ERROR_TOKENS -22); + } + + if (!IsPropertyIdValid(property)) { + PrintToLog("%s(): rejected: property %d does not exist\n", __func__, property); + return (PKT_ERROR_TOKENS -24); + } + + CMPSPInfo::Entry sp; + assert(_my_sps->getSP(property, sp)); + + if (!sp.manual) { + PrintToLog("%s(): rejected: property %d is not managed\n", __func__, property); + return (PKT_ERROR_TOKENS -42); + } + + if (sender != sp.issuer) { + PrintToLog("%s(): rejected: sender %s is not issuer of property %d [issuer=%s]\n", __func__, sender, property, sp.issuer); + return (PKT_ERROR_TOKENS -43); + } + + if (!isFreezingEnabled(property, block)) { + PrintToLog("%s(): rejected: freezing is not enabled for property %d\n", __func__, property); + return (PKT_ERROR_TOKENS -47); + } + + disableFreezing(property); + return 0; } diff --git a/src/omnicore/tx.h b/src/omnicore/tx.h index bba0dbc87c431..92cc5c3547dde 100644 --- a/src/omnicore/tx.h +++ b/src/omnicore/tx.h @@ -119,7 +119,8 @@ class CMPTransaction bool interpret_GrantTokens(); bool interpret_RevokeTokens(); bool interpret_ChangeIssuer(); - bool interpret_ChangeFreezeSetting(); + bool interpret_EnableFreezing(); + bool interpret_DisableFreezing(); bool interpret_FreezeTokens(); bool interpret_UnfreezeTokens(); bool interpret_Activation(); @@ -145,7 +146,8 @@ class CMPTransaction int logicMath_GrantTokens(); int logicMath_RevokeTokens(); int logicMath_ChangeIssuer(); - int logicMath_ChangeFreezeSetting(); + int logicMath_EnableFreezing(); + int logicMath_DisableFreezing(); int logicMath_FreezeTokens(); int logicMath_UnfreezeTokens(); int logicMath_Activation(); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 2bf05868dfdf0..ac14da3754556 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -171,8 +171,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "omni_sendgrant", 2 }, { "omni_sendrevoke", 1 }, { "omni_sendchangeissuer", 2 }, - { "omni_sendchangefreezesetting", 1 }, - { "omni_sendchangefreezesetting", 2 }, + { "omni_sendenablefreezing", 1 }, + { "omni_senddisablefreezing", 1 }, { "omni_sendfreeze", 2 }, { "omni_sendunfreeze", 2 }, { "omni_senddeactivation", 1 }, From fe1265ccea248bfebc192fc21684ea73ffe2fcf0 Mon Sep 17 00:00:00 2001 From: Zathras Date: Tue, 5 Dec 2017 13:13:51 +1100 Subject: [PATCH 45/62] Update testing scenario to use new explicit tx71 & tx72 --- src/omnicore/test/test_freeze.sh | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/omnicore/test/test_freeze.sh b/src/omnicore/test/test_freeze.sh index 4eefe85f311aa..331d08af25b7c 100755 --- a/src/omnicore/test/test_freeze.sh +++ b/src/omnicore/test/test_freeze.sh @@ -49,17 +49,17 @@ if [ $RESULT == "false," ] printf " FAIL (result:%s)\n" $RESULT FAIL=$((FAIL+1)) fi -printf " * Sending a 'change freeze setting' transaction to ENABLE freezing\n" -TXID=$($SRCDIR/omnicore-cli --regtest omni_sendchangefreezesetting $ADDR 3 true) +printf " * Sending a 'enable freezing' transaction to ENABLE freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendenablefreezing $ADDR 3) $SRCDIR/omnicore-cli --regtest generate 1 >$NUL -printf " - Checking the 'change freeze setting' transaction was VALID... " +printf " - Checking the 'enable freezing' transaction was VALID... " RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) if [ $RESULT == "true," ] then - printf " PASS\n" + printf " PASS\n" PASS=$((PASS+1)) else - printf " FAIL (result:%s)\n" $RESULT + printf " FAIL (result:%s)\n" $RESULT FAIL=$((FAIL+1)) fi printf " - Checking that freezing is now enabled... " @@ -157,17 +157,17 @@ if [ $RESULT == "true," ] printf " FAIL (result:%s)\n" $RESULT FAIL=$((FAIL+1)) fi -printf " * Sending a 'change freeze setting' transaction to DISABLE freezing\n" -TXID=$($SRCDIR/omnicore-cli --regtest omni_sendchangefreezesetting $ADDR 3 false) +printf " * Sending a 'disable freezing' transaction to DISABLE freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_senddisablefreezing $ADDR 3) $SRCDIR/omnicore-cli --regtest generate 1 >$NUL -printf " - Checking the 'change freeze setting' transaction was VALID... " +printf " - Checking the 'disable freezing' transaction was VALID... " RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) if [ $RESULT == "true," ] then - printf " PASS\n" + printf " PASS\n" PASS=$((PASS+1)) else - printf " FAIL (result:%s)\n" $RESULT + printf " FAIL (result:%s)\n" $RESULT FAIL=$((FAIL+1)) fi printf " - Checking that freezing is now disabled... " @@ -242,17 +242,17 @@ if [ $FEATUREID == "14" ] printf " FAIL (result:%s)\n" $FEATUREID FAIL=$((FAIL+1)) fi -printf " * Sending a 'change freeze setting' transaction to ENABLE freezing\n" -TXID=$($SRCDIR/omnicore-cli --regtest omni_sendchangefreezesetting $ADDR 3 true) +printf " * Sending a 'enable freezing' transaction to ENABLE freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendenablefreezing $ADDR 3) $SRCDIR/omnicore-cli --regtest generate 1 >$NUL -printf " - Checking the 'change freeze setting' transaction was VALID... " +printf " - Checking the 'enable freezing' transaction was VALID... " RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) if [ $RESULT == "true," ] then - printf " PASS\n" + printf " PASS\n" PASS=$((PASS+1)) else - printf " FAIL (result:%s)\n" $RESULT + printf " FAIL (result:%s)\n" $RESULT FAIL=$((FAIL+1)) fi printf " - Checking that freezing is still disabled (due to wait period)... " From 22cd4e006779bf2591ba051680513b717a03a03f Mon Sep 17 00:00:00 2001 From: Zathras Date: Tue, 5 Dec 2017 18:06:21 +1100 Subject: [PATCH 46/62] Add freeze support to RPC payload creation --- src/omnicore/rpcpayload.cpp | 127 ++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/src/omnicore/rpcpayload.cpp b/src/omnicore/rpcpayload.cpp index 357317aa1e256..dbf48a1120cf6 100644 --- a/src/omnicore/rpcpayload.cpp +++ b/src/omnicore/rpcpayload.cpp @@ -564,6 +564,129 @@ UniValue omni_createpayload_cancelalltrades(const UniValue& params, bool fHelp) return HexStr(payload.begin(), payload.end()); } +UniValue omni_createpayload_enablefreezing(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "omni_createpayload_enablefreezing propertyid\n" + + "\nCreates the payload to enable address freezing for a centrally managed property.\n" + + "\nArguments:\n" + "1. propertyid (number, required) the identifier of the tokens\n" + + "\nResult:\n" + "\"payload\" (string) the hex-encoded payload\n" + + "\nExamples:\n" + + HelpExampleCli("omni_createpayload_enablefreezing", "3") + + HelpExampleRpc("omni_createpayload_enablefreezing", "3") + ); + + uint32_t propertyId = ParsePropertyId(params[0]); + RequireExistingProperty(propertyId); + RequireManagedProperty(propertyId); + + std::vector payload = CreatePayload_EnableFreezing(propertyId); + + return HexStr(payload.begin(), payload.end()); +} + +UniValue omni_createpayload_disablefreezing(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "omni_createpayload_disablefreezing propertyid\n" + + "\nCreates the payload to disable address freezing for a centrally managed property.\n" + "\nIMPORTANT NOTE: Disabling freezing for a property will UNFREEZE all frozen addresses for that property!" + + "\nArguments:\n" + "1. propertyid (number, required) the identifier of the tokens\n" + + "\nResult:\n" + "\"payload\" (string) the hex-encoded payload\n" + + "\nExamples:\n" + + HelpExampleCli("omni_createpayload_disablefreezing", "3") + + HelpExampleRpc("omni_createpayload_disablefreezing", "3") + ); + + uint32_t propertyId = ParsePropertyId(params[0]); + RequireExistingProperty(propertyId); + RequireManagedProperty(propertyId); + + std::vector payload = CreatePayload_DisableFreezing(propertyId); + + return HexStr(payload.begin(), payload.end()); +} + +UniValue omni_createpayload_freeze(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "omni_createpayload_freeze \"toaddress\" propertyid amount \n" + + "\nCreates the payload to freeze an address for a centrally managed token.\n" + + "\nArguments:\n" + "1. toaddress (string, required) the address to freeze tokens for\n" + "2. propertyid (number, required) the property to freeze tokens for (must be managed type and have freezing option enabled)\n" + "3. amount (number, required) the amount of tokens to freeze (note: this is unused - once frozen an address cannot send any transactions)\n" + + "\nResult:\n" + "\"payload\" (string) the hex-encoded payload\n" + + "\nExamples:\n" + + HelpExampleCli("omni_createpayload_freeze", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\" 1 0") + + HelpExampleRpc("omni_createpayload_freeze", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\", 1, 0") + ); + + std::string refAddress = ParseAddress(params[0]); + uint32_t propertyId = ParsePropertyId(params[1]); + int64_t amount = ParseAmount(params[2], isPropertyDivisible(propertyId)); + + RequireExistingProperty(propertyId); + RequireManagedProperty(propertyId); + + std::vector payload = CreatePayload_FreezeTokens(propertyId, amount, refAddress); + + return HexStr(payload.begin(), payload.end()); +} + +UniValue omni_createpayload_unfreeze(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "omni_createpayload_unfreeze \"toaddress\" propertyid amount \n" + + "\nCreates the payload to unfreeze an address for a centrally managed token.\n" + + "\nArguments:\n" + "1. toaddress (string, required) the address to unfreeze tokens for\n" + "2. propertyid (number, required) the property to unfreeze tokens for (must be managed type and have freezing option enabled)\n" + "3. amount (number, required) the amount of tokens to unfreeze (note: this is unused)\n" + + "\nResult:\n" + "\"payload\" (string) the hex-encoded payload\n" + + "\nExamples:\n" + + HelpExampleCli("omni_createpayload_unfreeze", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\" 1 0") + + HelpExampleRpc("omni_createpayload_unfreeze", "\"3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs\", 1, 0") + ); + + std::string refAddress = ParseAddress(params[0]); + uint32_t propertyId = ParsePropertyId(params[1]); + int64_t amount = ParseAmount(params[2], isPropertyDivisible(propertyId)); + + RequireExistingProperty(propertyId); + RequireManagedProperty(propertyId); + + std::vector payload = CreatePayload_UnfreezeTokens(propertyId, amount, refAddress); + + return HexStr(payload.begin(), payload.end()); +} + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // -------------------------------- ----------------------------------------- ---------------------------------------- ---------- @@ -583,6 +706,10 @@ static const CRPCCommand commands[] = { "omni layer (payload creation)", "omni_createpayload_canceltradesbyprice", &omni_createpayload_canceltradesbyprice, true }, { "omni layer (payload creation)", "omni_createpayload_canceltradesbypair", &omni_createpayload_canceltradesbypair, true }, { "omni layer (payload creation)", "omni_createpayload_cancelalltrades", &omni_createpayload_cancelalltrades, true }, + { "omni layer (payload creation)", "omni_createpayload_enablefreezing", &omni_createpayload_enablefreezing, true }, + { "omni layer (payload creation)", "omni_createpayload_disablefreezing", &omni_createpayload_disablefreezing, true }, + { "omni layer (payload creation)", "omni_createpayload_freeze", &omni_createpayload_freeze, true }, + { "omni layer (payload creation)", "omni_createpayload_unfreeze", &omni_createpayload_unfreeze, true }, }; void RegisterOmniPayloadCreationRPCCommands(CRPCTable &tableRPC) From d6f1a84109d89476ae0942f56039778e0a517248 Mon Sep 17 00:00:00 2001 From: Zathras Date: Wed, 6 Dec 2017 19:05:31 +1100 Subject: [PATCH 47/62] Make sure LoadFreeze() uses actual position in blockchain Note: during some testing I picked up that while loading the freeze state at startup if there are multiple freeze/unfreeze transactions in the same block they may not be loaded in the correct order. Unlikely scanerio but we need to cover it just the same. This change just adds the tx position within the block to the sort order. --- src/omnicore/omnicore.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index c9f15727dbc02..fab12c4be2561 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -2642,7 +2642,7 @@ std::set CMPTxList::GetSeedBlocks(int startHeight, int endHeight) bool CMPTxList::LoadFreezeState(int blockHeight) { assert(pdb); - std::vector > loadOrder; + std::vector > loadOrder; Iterator* it = NewIterator(); PrintToLog("Loading freeze state from levelDB\n"); @@ -2654,15 +2654,17 @@ bool CMPTxList::LoadFreezeState(int blockHeight) uint16_t txtype = atoi(vstr[2]); if (txtype != MSC_TYPE_FREEZE_PROPERTY_TOKENS && txtype != MSC_TYPE_ENABLE_FREEZING && txtype != MSC_TYPE_DISABLE_FREEZING) continue; if (atoi(vstr[0]) != 1) continue; - uint256 txid = uint256S(it->key().ToString());; - loadOrder.push_back(std::make_pair(atoi(vstr[1]), txid)); + uint256 txid = uint256S(it->key().ToString()); + int txPosition = p_OmniTXDB->FetchTransactionPosition(txid); + std::string sortKey = strprintf("%06d%010d", atoi(vstr[1]), txPosition); + loadOrder.push_back(std::make_pair(sortKey, txid)); } delete it; std::sort (loadOrder.begin(), loadOrder.end()); - for (std::vector >::iterator it = loadOrder.begin(); it != loadOrder.end(); ++it) { + for (std::vector >::iterator it = loadOrder.begin(); it != loadOrder.end(); ++it) { uint256 hash = (*it).second; uint256 blockHash; CTransaction wtx; From c02e63f9c25661790340f6d4e2532c39e6ad9af6 Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 8 Dec 2017 16:24:39 +1100 Subject: [PATCH 48/62] Bugfix: remove checksum from being included in the payload Note: addressBytes size check failed (didn't include version) so was never truncated to remove checksum. Note: also removes "unexpected size from DecodeBase58 when decoding address" erros from log. --- src/omnicore/utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/omnicore/utils.cpp b/src/omnicore/utils.cpp index cd12155227ad6..dfe755f6979f8 100644 --- a/src/omnicore/utils.cpp +++ b/src/omnicore/utils.cpp @@ -83,8 +83,8 @@ std::vector AddressToBytes(const std::string& address) if (!success) { PrintToLog("ERROR: failed to decode address %s.\n", address); } - if (addressBytes.size() == 24) { - addressBytes.resize(20); // truncate checksum + if (addressBytes.size() == 25) { + addressBytes.resize(21); // truncate checksum } else { PrintToLog("ERROR: unexpected size from DecodeBase58 when decoding address %s.\n", address); } From 8f367c954bdba84e4fdca65bad61198e20923abf Mon Sep 17 00:00:00 2001 From: Zathras Date: Fri, 8 Dec 2017 16:30:06 +1100 Subject: [PATCH 49/62] Clear the freeze state when `clear_all_state()` is called --- src/omnicore/omnicore.cpp | 8 ++++++++ src/omnicore/omnicore.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index fab12c4be2561..11de9a9596983 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -315,6 +315,13 @@ bool mastercore::isMainEcosystemProperty(uint32_t propertyId) return false; } +void mastercore::ClearFreezeState() +{ + // Should only ever be called in the event of a reorg + setFreezingEnabledProperties.clear(); + setFrozenAddresses.clear(); +} + void mastercore::enableFreezing(uint32_t propertyId, int block) { if (!IsFeatureActivated(FEATURE_FREEZENOTICE, block)) { @@ -2178,6 +2185,7 @@ void clear_all_state() ResetConsensusParams(); ClearActivations(); ClearAlerts(); + ClearFreezeState(); // LevelDB based storage _my_sps->Clear(); diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 2e39a741c51d3..95f751448e5bc 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -381,6 +381,8 @@ void enableFreezing(uint32_t propertyId, int block); void disableFreezing(uint32_t propertyId); /** Checks whether a property has freezing enabled **/ bool isFreezingEnabled(uint32_t propertyId, int block); +/** Clears the freeze state in the event of a reorg **/ +void ClearFreezeState(); } From 0328d4b37933d043f89c9eb93da611353526500f Mon Sep 17 00:00:00 2001 From: Zathras Date: Sat, 9 Dec 2017 16:49:22 +1100 Subject: [PATCH 50/62] Add PrintFreezeState() function --- src/omnicore/omnicore.cpp | 12 ++++++++++++ src/omnicore/omnicore.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 11de9a9596983..2e02472c71e88 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -322,6 +322,18 @@ void mastercore::ClearFreezeState() setFrozenAddresses.clear(); } +void mastercore::PrintFreezeState() +{ + PrintToLog("setFrozenAddresses state:\n"); + for (std::set >::iterator it = setFrozenAddresses.begin(); it != setFrozenAddresses.end(); it++) { + PrintToLog(" %s:%d\n", (*it).first, (*it).second); + } + PrintToLog("setFreezingEnabledProperties state:\n"); + for (std::set >::iterator it = setFreezingEnabledProperties.begin(); it != setFreezingEnabledProperties.end(); it++) { + PrintToLog(" %d:%d\n", (*it).first, (*it).second); + } +} + void mastercore::enableFreezing(uint32_t propertyId, int block) { if (!IsFeatureActivated(FEATURE_FREEZENOTICE, block)) { diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 95f751448e5bc..879d144e93b3c 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -383,6 +383,8 @@ void disableFreezing(uint32_t propertyId); bool isFreezingEnabled(uint32_t propertyId, int block); /** Clears the freeze state in the event of a reorg **/ void ClearFreezeState(); +/** Prints the freeze state **/ +void PrintFreezeState(); } From 45ad203f7071ee29b8c5665d675da3e3a617d8a9 Mon Sep 17 00:00:00 2001 From: Zathras Date: Sat, 9 Dec 2017 16:56:00 +1100 Subject: [PATCH 51/62] Move wait period for freezing to tx.cpp --- src/omnicore/omnicore.cpp | 13 +++---------- src/omnicore/omnicore.h | 2 +- src/omnicore/tx.cpp | 10 +++++++++- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 2e02472c71e88..d83706f28aa96 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -334,17 +334,10 @@ void mastercore::PrintFreezeState() } } -void mastercore::enableFreezing(uint32_t propertyId, int block) +void mastercore::enableFreezing(uint32_t propertyId, int liveBlock) { - if (!IsFeatureActivated(FEATURE_FREEZENOTICE, block)) { - setFreezingEnabledProperties.insert(std::make_pair(propertyId, block)); - PrintToLog("Freezing for property %d has been enabled.\n", propertyId); - } else { - const CConsensusParams& params = ConsensusParams(); - int liveBlock = params.OMNI_FREEZE_WAIT_PERIOD + block; - setFreezingEnabledProperties.insert(std::make_pair(propertyId, liveBlock)); - PrintToLog("Freezing for property %d will be enabled at block %d.\n", propertyId, liveBlock); - } + setFreezingEnabledProperties.insert(std::make_pair(propertyId, liveBlock)); + PrintToLog("Freezing for property %d will be enabled at block %d.\n", propertyId, liveBlock); } void mastercore::disableFreezing(uint32_t propertyId) diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 879d144e93b3c..88f77485f50d8 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -376,7 +376,7 @@ void unfreezeAddress(const std::string& address, uint32_t propertyId); /** Checks whether an address and property are frozen **/ bool isAddressFrozen(const std::string& address, uint32_t propertyId); /** Adds a property to the freezingEnabledMap **/ -void enableFreezing(uint32_t propertyId, int block); +void enableFreezing(uint32_t propertyId, int liveBlock); /** Removes a property from the freezingEnabledMap **/ void disableFreezing(uint32_t propertyId); /** Checks whether a property has freezing enabled **/ diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index ebec82a3501a3..5d3d0ab313aea 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -2137,7 +2137,15 @@ int CMPTransaction::logicMath_EnableFreezing() return (PKT_ERROR_TOKENS -49); } - enableFreezing(property, block); + int liveBlock = 0; + if (!IsFeatureActivated(FEATURE_FREEZENOTICE, block)) { + liveBlock = block; + } else { + const CConsensusParams& params = ConsensusParams(); + liveBlock = params.OMNI_FREEZE_WAIT_PERIOD + block; + } + + enableFreezing(property, liveBlock); return 0; } From d86b251650f6f1efdbd408fe28287431b7960a67 Mon Sep 17 00:00:00 2001 From: Zathras Date: Sat, 9 Dec 2017 17:24:57 +1100 Subject: [PATCH 52/62] Update freeze regtests to include reorg tests --- src/omnicore/test/test_freeze.sh | 293 ++++++++++++++++++++++++++++++- 1 file changed, 288 insertions(+), 5 deletions(-) diff --git a/src/omnicore/test/test_freeze.sh b/src/omnicore/test/test_freeze.sh index 331d08af25b7c..e332a48ff7795 100755 --- a/src/omnicore/test/test_freeze.sh +++ b/src/omnicore/test/test_freeze.sh @@ -8,23 +8,28 @@ clear printf "Preparing a test environment...\n" printf " * Starting a fresh regtest daemon\n" rm -r ~/.bitcoin/regtest -$SRCDIR/omnicored --regtest --server --daemon --omniactivationallowsender=any >$NUL +$SRCDIR/omnicored --regtest --server --daemon --omniactivationallowsender=any --omnidebug=verbose >$NUL +printf "NOTE: verbose is on, log in datadir/regtest/ should show before and after states for any changes via stateDB\n" sleep 10 printf " * Preparing some mature testnet BTC\n" -$SRCDIR/omnicore-cli --regtest generate 102 >$NUL +$SRCDIR/omnicore-cli --regtest generate 105 >$NUL printf " * Obtaining addresses to work with\n" ADDR=$($SRCDIR/omnicore-cli --regtest getnewaddress OMNIAccount) FADDR=$($SRCDIR/omnicore-cli --regtest getnewaddress) +printf " * Master address is %s\n" $ADDR printf " * Funding the addresses with some testnet BTC for fees\n" -JSON="{\""$ADDR"\":4,\""$FADDR"\":4}" +JSON="{\""$ADDR"\":5,\""$FADDR"\":4}" $SRCDIR/omnicore-cli --regtest sendmany "" $JSON >$NUL +$SRCDIR/omnicore-cli --regtest sendtoaddress $ADDR 6 >$NUL +$SRCDIR/omnicore-cli --regtest sendtoaddress $ADDR 7 >$NUL +$SRCDIR/omnicore-cli --regtest sendtoaddress $ADDR 8 >$NUL +$SRCDIR/omnicore-cli --regtest sendtoaddress $ADDR 9 >$NUL $SRCDIR/omnicore-cli --regtest generate 1 >$NUL printf " * Creating a test (managed) property and granting 1000 tokens to the test address\n" $SRCDIR/omnicore-cli --regtest omni_sendissuancemanaged $ADDR 1 1 0 "TestCat" "TestSubCat" "TestProperty" "TestURL" "TestData" >$NUL $SRCDIR/omnicore-cli --regtest generate 1 >$NUL $SRCDIR/omnicore-cli --regtest omni_sendgrant $ADDR $FADDR 3 1000 >$NUL $SRCDIR/omnicore-cli --regtest generate 1 >$NUL - printf "\nRunning the test scenario...\n" printf " * Sending a 'freeze' tranasction for the test address prior to enabling freezing\n" TXID=$($SRCDIR/omnicore-cli --regtest omni_sendfreeze $ADDR $FADDR 3 1234) @@ -326,7 +331,285 @@ if [ $BALANCE == "920" ] printf " FAIL (result:%s)\n" $BALANCE FAIL=$((FAIL+1)) fi - +printf " * Sending an 'unfreeze' tranasction for the test address\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendunfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'unfreeze' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf "\nRunning reorg test scenarios\n" +printf " * Rolling back the chain to test reversing the last UNFREEZE tx\n" +BLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +BLOCKHASH=$($SRCDIR/omnicore-cli --regtest getblockhash $(($BLOCK))) +$SRCDIR/omnicore-cli --regtest invalidateblock $BLOCKHASH >$NUL +PREVBLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +$SRCDIR/omnicore-cli --regtest clearmempool >$NUL +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +NEWBLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +NEWBLOCKHASH=$($SRCDIR/omnicore-cli --regtest getblockhash $(($BLOCK))) +printf " - Checking the block count is the same as before the rollback... " +if [ $BLOCK == $NEWBLOCK ] + then + printf "PASS\n" + PASS=$((PASS+1)) + else + printf "FAIL (result:%s)\n" $NEWBLOCK + FAIL=$((FAIL+1)) +fi +printf " - Checking the block hash is different from before the rollback... " +if [ $BLOCKHASH == $NEWBLOCKHASH ] + then + printf "FAIL (result:%s)\n" $NEWBLOCKHASH + FAIL=$((FAIL+1)) + else + printf "PASS\n" + PASS=$((PASS+1)) +fi +printf " * Testing a send from the test address (should now be frozen again as the block that unfroze the address was dc'd)\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_send $FADDR $ADDR 3 30) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'send' transaction was INVALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending an 'unfreeze' tranasction for the test address\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendunfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'unfreeze' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +$SRCDIR/omnicore-cli --regtest generate 3 >$NUL +printf " * Sending an 'freeze' tranasction for the test address\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'freeze' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Rolling back the chain to test reversing the last FREEZE tx\n" +BLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +BLOCKHASH=$($SRCDIR/omnicore-cli --regtest getblockhash $(($BLOCK))) +$SRCDIR/omnicore-cli --regtest invalidateblock $BLOCKHASH >$NUL +PREVBLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +$SRCDIR/omnicore-cli --regtest clearmempool >$NUL +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +NEWBLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +NEWBLOCKHASH=$($SRCDIR/omnicore-cli --regtest getblockhash $(($BLOCK))) +printf " - Checking the block count is the same as before the rollback... " +if [ $BLOCK == $NEWBLOCK ] + then + printf "PASS\n" + PASS=$((PASS+1)) + else + printf "FAIL (result:%s)\n" $NEWBLOCK + FAIL=$((FAIL+1)) +fi +printf " - Checking the block hash is different from before the rollback... " +if [ $BLOCKHASH == $NEWBLOCKHASH ] + then + printf "FAIL (result:%s)\n" $NEWBLOCKHASH + FAIL=$((FAIL+1)) + else + printf "PASS\n" + PASS=$((PASS+1)) +fi +printf " * Testing a send from the test address (should now be unfrozen again as the block that froze the address was dc'd)\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_send $FADDR $ADDR 3 30) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'send' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending a 'freeze' tranasction for the test address\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendfreeze $ADDR $FADDR 3 1234) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'freeze' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending a 'disable freezing' transaction to DISABLE freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_senddisablefreezing $ADDR 3) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'disable freezing' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking that freezing is now disabled... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Rolling back the chain to test reversing the last DISABLE FREEZEING tx\n" +BLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +BLOCKHASH=$($SRCDIR/omnicore-cli --regtest getblockhash $(($BLOCK))) +$SRCDIR/omnicore-cli --regtest invalidateblock $BLOCKHASH >$NUL +PREVBLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +$SRCDIR/omnicore-cli --regtest clearmempool >$NUL +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +NEWBLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +NEWBLOCKHASH=$($SRCDIR/omnicore-cli --regtest getblockhash $(($BLOCK))) +printf " - Checking the block count is the same as before the rollback... " +if [ $BLOCK == $NEWBLOCK ] + then + printf "PASS\n" + PASS=$((PASS+1)) + else + printf "FAIL (result:%s)\n" $NEWBLOCK + FAIL=$((FAIL+1)) +fi +printf " - Checking the block hash is different from before the rollback... " +if [ $BLOCKHASH == $NEWBLOCKHASH ] + then + printf "FAIL (result:%s)\n" $NEWBLOCKHASH + FAIL=$((FAIL+1)) + else + printf "PASS\n" + PASS=$((PASS+1)) +fi +printf " - Checking that freezing is now enabled (as the block that disabled it was dc'd)... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Sending a 'disable freezing' transaction to DISABLE freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_senddisablefreezing $ADDR 3) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'disable freezing' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking that freezing is now disabled... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +$SRCDIR/omnicore-cli --regtest generate 3 >$NUL +printf " * Sending a 'enable freezing' transaction to ENABLE freezing\n" +TXID=$($SRCDIR/omnicore-cli --regtest omni_sendenablefreezing $ADDR 3) +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +printf " - Checking the 'enable freezing' transaction was VALID... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_gettransaction $TXID | grep "valid" | grep -v "invalid" | cut -c12-) +if [ $RESULT == "true," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " - Checking that freezing is still disabled (due to waiting period)... " +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "false," ] + then + printf " PASS\n" + PASS=$((PASS+1)) + else + printf " FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi +printf " * Rolling back the chain to test reversing the last ENABLE FREEZEING tx\n" +BLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +BLOCKHASH=$($SRCDIR/omnicore-cli --regtest getblockhash $(($BLOCK))) +$SRCDIR/omnicore-cli --regtest invalidateblock $BLOCKHASH >$NUL +PREVBLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +$SRCDIR/omnicore-cli --regtest clearmempool >$NUL +$SRCDIR/omnicore-cli --regtest generate 1 >$NUL +NEWBLOCK=$($SRCDIR/omnicore-cli --regtest getblockcount) +NEWBLOCKHASH=$($SRCDIR/omnicore-cli --regtest getblockhash $(($BLOCK))) +printf " - Checking the block count is the same as before the rollback... " +if [ $BLOCK == $NEWBLOCK ] + then + printf "PASS\n" + PASS=$((PASS+1)) + else + printf "FAIL (result:%s)\n" $NEWBLOCK + FAIL=$((FAIL+1)) +fi +printf " - Checking the block hash is different from before the rollback... " +if [ $BLOCKHASH == $NEWBLOCKHASH ] + then + printf "FAIL (result:%s)\n" $NEWBLOCKHASH + FAIL=$((FAIL+1)) + else + printf "PASS\n" + PASS=$((PASS+1)) +fi +printf " - Mining past prior activation period and checking that freezing is still disabled... " +$SRCDIR/omnicore-cli --regtest generate 20 >$NUL +RESULT=$($SRCDIR/omnicore-cli --regtest omni_getproperty 3 | grep "freezingenabled" | cut -c21-) +if [ $RESULT == "false," ] + then + printf "PASS\n" + PASS=$((PASS+1)) + else + printf "FAIL (result:%s)\n" $RESULT + FAIL=$((FAIL+1)) +fi printf "\n" printf "####################\n" From 82fe38ecef4143cd9c0da1ab9e78c21082394793 Mon Sep 17 00:00:00 2001 From: Zathras Date: Sat, 9 Dec 2017 17:35:28 +1100 Subject: [PATCH 53/62] Fix LoadFreezeState() failure due to not loading unfreeze txs --- src/omnicore/omnicore.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index d83706f28aa96..ff2085618cf81 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -2665,8 +2665,9 @@ bool CMPTxList::LoadFreezeState(int blockHeight) boost::split(vstr, itData, boost::is_any_of(":"), token_compress_on); if (4 != vstr.size()) continue; uint16_t txtype = atoi(vstr[2]); - if (txtype != MSC_TYPE_FREEZE_PROPERTY_TOKENS && txtype != MSC_TYPE_ENABLE_FREEZING && txtype != MSC_TYPE_DISABLE_FREEZING) continue; - if (atoi(vstr[0]) != 1) continue; + if (txtype != MSC_TYPE_FREEZE_PROPERTY_TOKENS && txtype != MSC_TYPE_UNFREEZE_PROPERTY_TOKENS && + txtype != MSC_TYPE_ENABLE_FREEZING && txtype != MSC_TYPE_DISABLE_FREEZING) continue; + if (atoi(vstr[0]) != 1) continue; // invalid, ignore uint256 txid = uint256S(it->key().ToString()); int txPosition = p_OmniTXDB->FetchTransactionPosition(txid); std::string sortKey = strprintf("%06d%010d", atoi(vstr[1]), txPosition); @@ -2708,7 +2709,8 @@ bool CMPTxList::LoadFreezeState(int blockHeight) PrintToLog("ERROR: While loading freeze transaction %s: failed interpret_Transaction.\n", hash.GetHex()); return false; } - if (MSC_TYPE_FREEZE_PROPERTY_TOKENS != mp_obj.getType() && MSC_TYPE_ENABLE_FREEZING != mp_obj.getType() && MSC_TYPE_DISABLE_FREEZING != mp_obj.getType()) { + if (MSC_TYPE_FREEZE_PROPERTY_TOKENS != mp_obj.getType() && MSC_TYPE_UNFREEZE_PROPERTY_TOKENS != mp_obj.getType() && + MSC_TYPE_ENABLE_FREEZING != mp_obj.getType() && MSC_TYPE_DISABLE_FREEZING != mp_obj.getType()) { PrintToLog("ERROR: While loading freeze transaction %s: levelDB type mismatch, not a freeze transaction.\n", hash.GetHex()); return false; } From 1ba6f9acc83d60165480ff0e8141743c316c63be Mon Sep 17 00:00:00 2001 From: Zathras Date: Sun, 10 Dec 2017 15:25:01 +1100 Subject: [PATCH 54/62] Fix: only trigger assert on bad attempts to change BALANCE tally Note, freezing should only affect the available balance, not prior actions The following steps could be done by anyone and would have tripped the assert: 1) List a trade from address A for prop N 2) Freeze address A for prop N 3) List a matching trade from address B --- src/omnicore/omnicore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index ff2085618cf81..84fcd5b9b3620 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -474,7 +474,7 @@ bool mastercore::update_tally_map(const std::string& who, uint32_t propertyId, i LOCK(cs_tally); - if (ttype != PENDING && amount < 0) { + if (ttype == BALANCE && amount < 0) { assert(!isAddressFrozen(who, propertyId)); // for safety, this should never fail if everything else is working properly. } From 5dd7bce75732ca49437de3b2c78d2c29d9adf468 Mon Sep 17 00:00:00 2001 From: Zathras Date: Sun, 10 Dec 2017 15:41:26 +1100 Subject: [PATCH 55/62] Verify the Bitcoin address extracted from the payload is valid --- src/omnicore/tx.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index 5d3d0ab313aea..8671f0ea52c58 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -16,6 +16,7 @@ #include "omnicore/utils.h" #include "amount.h" +#include "base58.h" #include "main.h" #include "sync.h" #include "utiltime.h" @@ -705,6 +706,10 @@ bool CMPTransaction::interpret_FreezeTokens() if (receiver.empty()) { return false; } + CBitcoinAddress recAddress(receiver); + if (!recAddress.IsValid()) { + return false; + } if ((!rpcOnly && msc_debug_packets) || msc_debug_packets_readonly) { PrintToLog("\t property: %d (%s)\n", property, strMPProperty(property)); @@ -740,6 +745,10 @@ bool CMPTransaction::interpret_UnfreezeTokens() if (receiver.empty()) { return false; } + CBitcoinAddress recAddress(receiver); + if (!recAddress.IsValid()) { + return false; + } if ((!rpcOnly && msc_debug_packets) || msc_debug_packets_readonly) { PrintToLog("\t property: %d (%s)\n", property, strMPProperty(property)); From cda8ffe4f1e555b2017d9e2efdd42cf6357f6f56 Mon Sep 17 00:00:00 2001 From: Zathras Date: Sun, 10 Dec 2017 16:27:37 +1100 Subject: [PATCH 56/62] Add freeze related payload unit tests --- src/omnicore/test/create_payload_tests.cpp | 42 ++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/omnicore/test/create_payload_tests.cpp b/src/omnicore/test/create_payload_tests.cpp index 2496949bf9253..f131bb1f15617 100644 --- a/src/omnicore/test/create_payload_tests.cpp +++ b/src/omnicore/test/create_payload_tests.cpp @@ -383,6 +383,48 @@ BOOST_AUTO_TEST_CASE(payload_change_property_manager) BOOST_CHECK_EQUAL(HexStr(vch), "000000460000000d"); } +BOOST_AUTO_TEST_CASE(payload_enable_freezing) +{ + // Enable freezing [type 71, version 0] + std::vector vch = CreatePayload_EnableFreezing( + static_cast(4)); // property: SP #4 + + BOOST_CHECK_EQUAL(HexStr(vch), "0000004700000004"); +} + +BOOST_AUTO_TEST_CASE(payload_disable_freezing) +{ + // Disable freezing [type 72, version 0] + std::vector vch = CreatePayload_DisableFreezing( + static_cast(4)); // property: SP #4 + + BOOST_CHECK_EQUAL(HexStr(vch), "0000004800000004"); +} + +BOOST_AUTO_TEST_CASE(payload_freeze_tokens) +{ + // Freeze tokens [type 185, version 0] + std::vector vch = CreatePayload_FreezeTokens( + static_cast(4), // property: SP #4 + static_cast(1000), // amount to freeze (unused) + std::string("1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P")); // reference address + + BOOST_CHECK_EQUAL(HexStr(vch), + "000000b90000000400000000000003e800946cb2e08075bcbaf157e47bcb67eb2b2339d242"); +} + +BOOST_AUTO_TEST_CASE(payload_unfreeze_tokens) +{ + // Freeze tokens [type 186, version 0] + std::vector vch = CreatePayload_UnfreezeTokens( + static_cast(4), // property: SP #4 + static_cast(1000), // amount to freeze (unused) + std::string("1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P")); // reference address + + BOOST_CHECK_EQUAL(HexStr(vch), + "000000ba0000000400000000000003e800946cb2e08075bcbaf157e47bcb67eb2b2339d242"); +} + BOOST_AUTO_TEST_CASE(payload_feature_deactivation) { // Omni Core feature activation [type 65533, version 65535] From 531292e4b3769e8fc2d73fad3bc396db6439caa9 Mon Sep 17 00:00:00 2001 From: Zathras Date: Sun, 10 Dec 2017 18:31:03 +1100 Subject: [PATCH 57/62] Reparse if reorging the freeze state --- src/omnicore/omnicore.cpp | 42 ++++++++++++++++++++++++++++---- src/omnicore/omnicore.h | 1 + src/omnicore/test/test_freeze.sh | 1 - 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 84fcd5b9b3620..4dcf1d81459eb 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -2652,6 +2652,30 @@ std::set CMPTxList::GetSeedBlocks(int startHeight, int endHeight) return setSeedBlocks; } +bool CMPTxList::CheckForFreezeTxs(int blockHeight) +{ + assert(pdb); + Iterator* it = NewIterator(); + + for (it->SeekToFirst(); it->Valid(); it->Next()) { + std::string itData = it->value().ToString(); + std::vector vstr; + boost::split(vstr, itData, boost::is_any_of(":"), token_compress_on); + if (4 != vstr.size()) continue; + int block = atoi(vstr[1]); + if (block < blockHeight) continue; + uint16_t txtype = atoi(vstr[2]); + if (txtype == MSC_TYPE_FREEZE_PROPERTY_TOKENS || txtype == MSC_TYPE_UNFREEZE_PROPERTY_TOKENS || + txtype == MSC_TYPE_ENABLE_FREEZING || txtype == MSC_TYPE_DISABLE_FREEZING) { + delete it; + return true; + } + } + + delete it; + return false; +} + bool CMPTxList::LoadFreezeState(int blockHeight) { assert(pdb); @@ -3902,6 +3926,9 @@ int mastercore_handler_block_begin(int nBlockPrev, CBlockIndex const * pBlockInd if (reorgRecoveryMode > 0) { reorgRecoveryMode = 0; // clear reorgRecovery here as this is likely re-entrant + // Check if any freeze related transactions would be rolled back - if so wipe the state and startclean + bool reorgContainsFreeze = p_txlistdb->CheckForFreezeTxs(pBlockIndex->nHeight); + // NOTE: The blockNum parameter is inclusive, so deleteAboveBlock(1000) will delete records in block 1000 and above. p_txlistdb->isMPinBlockRange(pBlockIndex->nHeight, reorgRecoveryMaxHeight, true); t_tradelistdb->deleteAboveBlock(pBlockIndex->nHeight); @@ -3912,12 +3939,17 @@ int mastercore_handler_block_begin(int nBlockPrev, CBlockIndex const * pBlockInd nWaterlineBlock = ConsensusParams().GENESIS_BLOCK - 1; - int best_state_block = load_most_relevant_state(); - if (best_state_block < 0) { - // unable to recover easily, remove stale stale state bits and reparse from the beginning. - clear_all_state(); + if (reorgContainsFreeze) { + PrintToLog("Reorganization containing freeze related transactions detected, forcing a reparse...\n"); + clear_all_state(); // unable to reorg freezes safely, clear state and reparse } else { - nWaterlineBlock = best_state_block; + int best_state_block = load_most_relevant_state(); + if (best_state_block < 0) { + // unable to recover easily, remove stale stale state bits and reparse from the beginning. + clear_all_state(); + } else { + nWaterlineBlock = best_state_block; + } } // clear the global wallet property list, perform a forced wallet update and tell the UI that state is no longer valid, and UI views need to be reinit diff --git a/src/omnicore/omnicore.h b/src/omnicore/omnicore.h index 88f77485f50d8..e3d459f970352 100644 --- a/src/omnicore/omnicore.h +++ b/src/omnicore/omnicore.h @@ -283,6 +283,7 @@ class CMPTxList : public CDBBase void LoadAlerts(int blockHeight); void LoadActivations(int blockHeight); bool LoadFreezeState(int blockHeight); + bool CheckForFreezeTxs(int blockHeight); void printStats(); void printAll(); diff --git a/src/omnicore/test/test_freeze.sh b/src/omnicore/test/test_freeze.sh index e332a48ff7795..76df78d936df1 100755 --- a/src/omnicore/test/test_freeze.sh +++ b/src/omnicore/test/test_freeze.sh @@ -9,7 +9,6 @@ printf "Preparing a test environment...\n" printf " * Starting a fresh regtest daemon\n" rm -r ~/.bitcoin/regtest $SRCDIR/omnicored --regtest --server --daemon --omniactivationallowsender=any --omnidebug=verbose >$NUL -printf "NOTE: verbose is on, log in datadir/regtest/ should show before and after states for any changes via stateDB\n" sleep 10 printf " * Preparing some mature testnet BTC\n" $SRCDIR/omnicore-cli --regtest generate 105 >$NUL From a6ce9aafbf5d89c1ee386c09e9a16945f0cd33ad Mon Sep 17 00:00:00 2001 From: Zathras Date: Mon, 11 Dec 2017 12:12:41 +1100 Subject: [PATCH 58/62] Update RPC-API documentation --- src/omnicore/doc/rpc-api.md | 111 +++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/src/omnicore/doc/rpc-api.md b/src/omnicore/doc/rpc-api.md index b61447fd06c42..9acc8b19fbcf1 100644 --- a/src/omnicore/doc/rpc-api.md +++ b/src/omnicore/doc/rpc-api.md @@ -470,6 +470,112 @@ $ omnicore-cli "omni_sendall" "3M9qvHKtgARhqcMtM5cRT9VaiDJ5PSfQGY" "37FaKponF7zq --- +### omni_sendenablefreezing + +Enables address freezing for a centrally managed property. + +**Arguments:** + +| Name | Type | Presence | Description | +|---------------------|---------|----------|----------------------------------------------------------------------------------------------| +| `fromaddress` | string | required | the address to send from (must be issuer of a managed property) | +| `propertyid` | number | required | the identifier of the tokens | + +**Result:** +```js +"hash" // (string) the hex-encoded transaction hash +``` + +**Example:** + +```bash +$ omnicore-cli "omni_sendenablefreezing" "3M9qvHKtgARhqcMtM5cRT9VaiDJ5PSfQGY" 2 +``` + +--- + +### omni_senddisablefreezing + +Disables address freezing for a centrally managed property. + +IMPORTANT NOTE: Disabling freezing for a property will UNFREEZE all frozen addresses for that property! + +**Arguments:** + +| Name | Type | Presence | Description | +|---------------------|---------|----------|----------------------------------------------------------------------------------------------| +| `fromaddress` | string | required | the address to send from (must be issuer of a managed property) | +| `propertyid` | number | required | the identifier of the tokens | + +**Result:** +```js +"hash" // (string) the hex-encoded transaction hash +``` + +**Example:** + +```bash +$ omnicore-cli "omni_senddisablefreezing" "3M9qvHKtgARhqcMtM5cRT9VaiDJ5PSfQGY" 2 +``` + +--- + +### omni_sendfreeze + +Freeze an address for a centrally managed token. + +Note: Only the issuer may freeze tokens, and only if the token is of the managed type with the freezing option enabled. + +**Arguments:** + +| Name | Type | Presence | Description | +|---------------------|---------|----------|----------------------------------------------------------------------------------------------| +| `fromaddress` | string | required | the address to send from (must be issuer of a managed property with freezing enabled | +| `toaddress` | string | required | the address to freeze | +| `propertyid` | number | required | the identifier of the tokens to freeze | +| `amount` | string | required | the amount to freeze (note: currently unused, frozen addresses cannot transact the property) | + +**Result:** +```js +"hash" // (string) the hex-encoded transaction hash +``` + +**Example:** + +```bash +$ omnicore-cli "omni_sendfreeze" "3M9qvHKtgARhqcMtM5cRT9VaiDJ5PSfQGY" "3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs" 2 1000 +``` + +--- + +### omni_sendunfreeze + +Unfreeze an address for a centrally managed token. + +Note: Only the issuer may unfreeze tokens + +**Arguments:** + +| Name | Type | Presence | Description | +|---------------------|---------|----------|----------------------------------------------------------------------------------------------| +| `fromaddress` | string | required | the address to send from (must be issuer of a managed property with freezing enabled | +| `toaddress` | string | required | the address to unfreeze | +| `propertyid` | number | required | the identifier of the tokens to unfreeze | +| `amount` | string | required | the amount to unfreeze (note: currently unused | + +**Result:** +```js +"hash" // (string) the hex-encoded transaction hash +``` + +**Example:** + +```bash +$ omnicore-cli "omni_sendunfreeze" "3M9qvHKtgARhqcMtM5cRT9VaiDJ5PSfQGY" "3HTHRxu3aSDV4deakjC7VmsiUp7c6dfbvs" 2 1000 +``` + +--- + ### omni_sendrawtx Broadcasts a raw Omni Layer transaction. @@ -560,7 +666,8 @@ Returns the token balance for a given address and property. ```js { "balance" : "n.nnnnnnnn", // (string) the available balance of the address - "reserved" : "n.nnnnnnnn" // (string) the amount reserved by sell offers and accepts + "reserved" : "n.nnnnnnnn", // (string) the amount reserved by sell offers and accepts + "frozen" : "n.nnnnnnnn" // (string) the amount frozen by the issuer (applies to managed properties only) } ``` @@ -878,6 +985,8 @@ Returns details for about the tokens or smart property to lookup. "issuer" : "address", // (string) the Bitcoin address of the issuer on record "creationtxid" : "hash", // (string) the hex-encoded creation transaction hash "fixedissuance" : true|false, // (boolean) whether the token supply is fixed + "managedissuance" : true|false, // (boolean) whether the token supply is managed by the issuer + "freezingenabled" : true|false, // (boolean) whether freezing is enabled for the property (managed properties only) "totaltokens" : "n.nnnnnnnn" // (string) the total number of tokens in existence } ``` From a6dd8a4e721d6a42abe38eba364d836045df54ab Mon Sep 17 00:00:00 2001 From: Zathras Date: Mon, 11 Dec 2017 12:44:15 +1100 Subject: [PATCH 59/62] Force a reparse if a shutdown is forced Note: Behaviour of AbortNode() can be inconsistent and we cannot be sure of the state the client will be left in. During testing it was possible in some circumstances to simply restart the node and continue on after a forced shutdown. This change destroys the persistence state to force a reparse in this case. --- src/omnicore/activation.cpp | 4 ++++ src/omnicore/fees.cpp | 6 +++++- src/omnicore/omnicore.cpp | 6 +++++- src/omnicore/tx.cpp | 2 ++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/omnicore/activation.cpp b/src/omnicore/activation.cpp index f739f50465c3e..f615dd5c6a53f 100644 --- a/src/omnicore/activation.cpp +++ b/src/omnicore/activation.cpp @@ -14,6 +14,8 @@ #include "main.h" #include "ui_interface.h" +#include + #include #include #include @@ -89,6 +91,8 @@ void CheckLiveActivations(int blockHeight) PrintToLog(msgText); PrintToConsole(msgText); if (!GetBoolArg("-overrideforcedshutdown", false)) { + boost::filesystem::path persistPath = GetDataDir() / "MP_persist"; + if (boost::filesystem::exists(persistPath)) boost::filesystem::remove_all(persistPath); // prevent the node being restarted without a reparse after forced shutdown AbortNode(msgText, msgText); } } diff --git a/src/omnicore/fees.cpp b/src/omnicore/fees.cpp index fd76d63b27d28..af428aaa1efb5 100644 --- a/src/omnicore/fees.cpp +++ b/src/omnicore/fees.cpp @@ -102,7 +102,11 @@ void COmniFeeCache::AddFee(const uint32_t &propertyId, int block, const int64_t // overflow - there is no way the fee cache should exceed the maximum possible number of tokens, not safe to continue const std::string& msg = strprintf("Shutting down due to fee cache overflow (block %d property %d current %d amount %d)\n", block, propertyId, currentCachedAmount, amount); PrintToLog(msg); - if (!GetBoolArg("-overrideforcedshutdown", false)) AbortNode(msg, msg); + if (!GetBoolArg("-overrideforcedshutdown", false)) { + boost::filesystem::path persistPath = GetDataDir() / "MP_persist"; + if (boost::filesystem::exists(persistPath)) boost::filesystem::remove_all(persistPath); // prevent the node being restarted without a reparse after forced shutdown + AbortNode(msg, msg); + } } int64_t newCachedAmount = currentCachedAmount + amount; diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 00fe460e3c49c..0481fcb593d3e 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -3807,7 +3807,11 @@ int mastercore_handler_block_end(int nBlockNow, CBlockIndex const * pBlockIndex, // failed checkpoint, can't be trusted to provide valid data - shutdown client const std::string& msg = strprintf("Shutting down due to failed checkpoint for block %d (hash %s)\n", nBlockNow, pBlockIndex->GetBlockHash().GetHex()); PrintToLog(msg); - if (!GetBoolArg("-overrideforcedshutdown", false)) AbortNode(msg, msg); + if (!GetBoolArg("-overrideforcedshutdown", false)) { + boost::filesystem::path persistPath = GetDataDir() / "MP_persist"; + if (boost::filesystem::exists(persistPath)) boost::filesystem::remove_all(persistPath); // prevent the node being restarted without a reparse after forced shutdown + AbortNode(msg, msg); + } } else { // save out the state after this block if (writePersistence(nBlockNow)) { diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index 2920ff3c01ba4..0569463c3f767 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -2058,6 +2058,8 @@ int CMPTransaction::logicMath_Alert() PrintToLog(msgText); PrintToConsole(msgText); if (!GetBoolArg("-overrideforcedshutdown", false)) { + boost::filesystem::path persistPath = GetDataDir() / "MP_persist"; + if (boost::filesystem::exists(persistPath)) boost::filesystem::remove_all(persistPath); // prevent the node being restarted without a reparse after forced shutdown AbortNode(msgText, msgText); } } From cfd2adb0094e7cd7b26ecc46a04fc8ba3b57587b Mon Sep 17 00:00:00 2001 From: Zathras Date: Mon, 11 Dec 2017 17:36:47 +1100 Subject: [PATCH 60/62] Add asserts to confirm freeze actions --- src/omnicore/omnicore.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 4dcf1d81459eb..52d132c32f99e 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -337,6 +337,7 @@ void mastercore::PrintFreezeState() void mastercore::enableFreezing(uint32_t propertyId, int liveBlock) { setFreezingEnabledProperties.insert(std::make_pair(propertyId, liveBlock)); + assert(isFreezingEnabled(propertyId, liveBlock)); PrintToLog("Freezing for property %d will be enabled at block %d.\n", propertyId, liveBlock); } @@ -348,23 +349,23 @@ void mastercore::disableFreezing(uint32_t propertyId) liveBlock = (*it).second; } } - if (liveBlock == 0) { - PrintToLog("ERROR: Failed to determine live block to disable freezing for property %d!\n", propertyId); - return; - } else { - setFreezingEnabledProperties.erase(std::make_pair(propertyId, liveBlock)); - PrintToLog("Freezing for property %d has been disabled.\n", propertyId); - } + assert(liveBlock > 0); + + setFreezingEnabledProperties.erase(std::make_pair(propertyId, liveBlock)); + PrintToLog("Freezing for property %d has been disabled.\n", propertyId); // When disabling freezing for a property, all frozen addresses for that property will be unfrozen! for (std::set >::iterator it = setFrozenAddresses.begin(); it != setFrozenAddresses.end(); ) { if ((*it).second == propertyId) { PrintToLog("Address %s has been unfrozen for property %d.\n", (*it).first, propertyId); it = setFrozenAddresses.erase(it); + assert(!isAddressFrozen((*it).first, (*it).second)); } else { it++; } } + + assert(!isFreezingEnabled(propertyId, liveBlock)); } bool mastercore::isFreezingEnabled(uint32_t propertyId, int block) @@ -382,12 +383,14 @@ bool mastercore::isFreezingEnabled(uint32_t propertyId, int block) void mastercore::freezeAddress(const std::string& address, uint32_t propertyId) { setFrozenAddresses.insert(std::make_pair(address, propertyId)); + assert(isAddressFrozen(address, propertyId)); PrintToLog("Address %s has been frozen for property %d.\n", address, propertyId); } void mastercore::unfreezeAddress(const std::string& address, uint32_t propertyId) { setFrozenAddresses.erase(std::make_pair(address, propertyId)); + assert(!isAddressFrozen(address, propertyId)); PrintToLog("Address %s has been unfrozen for property %d.\n", address, propertyId); } From 2c43859699756955584082bff168adbbee97b1c6 Mon Sep 17 00:00:00 2001 From: Zathras Date: Mon, 11 Dec 2017 18:12:47 +1100 Subject: [PATCH 61/62] Add sanity check to LoadFreezeState() --- src/omnicore/omnicore.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/omnicore/omnicore.cpp b/src/omnicore/omnicore.cpp index 52d132c32f99e..5558b83f007b8 100644 --- a/src/omnicore/omnicore.cpp +++ b/src/omnicore/omnicore.cpp @@ -2683,6 +2683,7 @@ bool CMPTxList::LoadFreezeState(int blockHeight) { assert(pdb); std::vector > loadOrder; + int txnsLoaded = 0; Iterator* it = NewIterator(); PrintToLog("Loading freeze state from levelDB\n"); @@ -2746,6 +2747,11 @@ bool CMPTxList::LoadFreezeState(int blockHeight) PrintToLog("ERROR: While loading freeze transaction %s: non-zero return from interpretPacket\n", hash.GetHex()); return false; } + txnsLoaded++; + } + + if (blockHeight > 497000 && !isNonMainNet()) { + assert(txnsLoaded >= 2); // sanity check against a failure to properly load the freeze state } return true; From 64150d99974a4dc2ca65e55959db585ebea9debc Mon Sep 17 00:00:00 2001 From: Zathras Date: Mon, 11 Dec 2017 18:48:06 +1100 Subject: [PATCH 62/62] Avoid merge conflict --- src/omnicore/tx.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/omnicore/tx.cpp b/src/omnicore/tx.cpp index 8671f0ea52c58..1e82ed112d195 100644 --- a/src/omnicore/tx.cpp +++ b/src/omnicore/tx.cpp @@ -14,6 +14,8 @@ #include "omnicore/sp.h" #include "omnicore/sto.h" #include "omnicore/utils.h" +#include "omnicore/utilsbitcoin.h" +#include "omnicore/version.h" #include "amount.h" #include "base58.h"