Skip to content

Commit

Permalink
Merge bitcoin#507: Persist the parsing result and include the reason …
Browse files Browse the repository at this point in the history
…for tx invalidation in RPC response

df61819 Increment DB_VERSION to force a reparse (to add invalid reasons to levelDB) (Zathras)
abdbbd7 Add 'invalidreason' attribute to RPC response for omni_gettransaction (Zathras)
86514d1 Port parsing errors to errors.h (Zathras)
d1ec205 Add FetchInvalidReason() to OmniTXDB (Zathras)
59996fe Update OmniTXDB to also store the processing result (Zathras)
  • Loading branch information
dexX7 committed Nov 23, 2017
2 parents 724e990 + df61819 commit 3e040ef
Show file tree
Hide file tree
Showing 5 changed files with 294 additions and 11 deletions.
246 changes: 246 additions & 0 deletions src/omnicore/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <string>

#include "omnicore/omnicore.h"

enum MPRPCErrorCode
{
//INTERNAL_1packet
Expand Down Expand Up @@ -76,6 +78,250 @@ inline std::string error_str(int ec) {
case MP_ERR_COMMIT_TX:
ec_str = "Error committing transaction";
break;

case PKT_ERROR -1:
ec_str = "Attempt to execute logic in RPC mode";
break;
case PKT_ERROR -2:
ec_str = "Failed to interpret transaction";
break;
case PKT_ERROR -22:
ec_str = "Transaction type or version not permitted";
break;
case PKT_ERROR -51:
ec_str = "Sender is not authorized";
break;
case PKT_ERROR -54:
ec_str = "Activation failed";
break;

case PKT_ERROR -100:
ec_str = "Transaction is not a supported type";
break;
case PKT_ERROR -500:
ec_str = "Transaction version is not supported";
break;
case PKT_ERROR -999:
ec_str = "Failed to determine subaction";
break;

case PKT_ERROR_SEND -22:
ec_str = "Transaction type or version not permitted";
break;
case PKT_ERROR_SEND -23:
ec_str = "Value out of range or zero";
break;
case PKT_ERROR_SEND -24:
ec_str = "Property does not exist";
break;
case PKT_ERROR_SEND -25:
ec_str = "Sender has insufficient balance";
break;

case PKT_ERROR_STO -22:
ec_str = "Transaction type or version not permitted";
break;
case PKT_ERROR_STO -23:
ec_str = "Value out of range or zero";
break;
case PKT_ERROR_STO -24:
ec_str = "Property does not exist";
break;
case PKT_ERROR_STO -25:
ec_str = "Sender has insufficient balance";
break;
case PKT_ERROR_STO -26:
ec_str = "No other owners of the property";
break;
case PKT_ERROR_STO -27:
ec_str = "Sender has insufficient balance to pay for fee";
break;
case PKT_ERROR_STO -28:
ec_str = "Sender has insufficient balance to pay for amount + fee";
break;

case PKT_ERROR_SEND_ALL -22:
ec_str = "Transaction type or version not permitted";
break;
case PKT_ERROR_SEND_ALL -54:
ec_str = "Sender has no tokens to send";
break;
case PKT_ERROR_SEND_ALL -55:
ec_str = "Sender has no tokens to send";
break;

case PKT_ERROR_TRADEOFFER -22:
ec_str = "Transaction type or version not permitted";
break;
case PKT_ERROR_TRADEOFFER -23:
ec_str = "Value out of range or zero";
break;
case PKT_ERROR_TRADEOFFER -47:
ec_str = "Property for sale must be OMNI or TOMNI";
break;
case PKT_ERROR_TRADEOFFER -49:
ec_str = "Sender has no active sell offer for the property";
break;
case PKT_ERROR_TRADEOFFER -48:
ec_str = "Sender already has an active sell offer for the property";
break;

case DEX_ERROR_SELLOFFER -101:
ec_str = "Value out of range or zero";
break;
case DEX_ERROR_SELLOFFER -10:
ec_str = "Sender already has an active sell offer for the property";
break;
case DEX_ERROR_SELLOFFER -25:
ec_str = "Sender has insufficient balance";
break;
case DEX_ERROR_SELLOFFER -11:
ec_str = "Sender has no active sell offer for the property";
break;
case DEX_ERROR_SELLOFFER -12:
ec_str = "Sender has no active sell offer for the property";
break;

case DEX_ERROR_ACCEPT -15:
ec_str = "No matching sell offer for accept order found";
break;
case DEX_ERROR_ACCEPT -20:
ec_str = "Cannot locate accept to destroy";
break;
case DEX_ERROR_ACCEPT -22:
ec_str = "Transaction type or version not permitted";
break;
case DEX_ERROR_ACCEPT -23:
ec_str = "Value out of range or zero";
break;
case DEX_ERROR_ACCEPT -205:
ec_str = "An accept from the sender to the recipient already exists";
break;
case DEX_ERROR_ACCEPT -105:
ec_str = "Transaction fee too small";
break;

case PKT_ERROR_METADEX -21:
ec_str = "Ecosystem is invalid";
break;
case PKT_ERROR_METADEX -22:
ec_str = "Transaction type or version not permitted";
break;
case PKT_ERROR_METADEX -25:
ec_str = "Sender has insufficient balance";
break;
case PKT_ERROR_METADEX -29:
ec_str = "Property for sale and desired property are not be equal";
break;
case PKT_ERROR_METADEX -30:
ec_str = "Property for sale and desired property are not in the same ecosystem";
break;
case PKT_ERROR_METADEX -31:
ec_str = "Property for sale does not exist";
break;
case PKT_ERROR_METADEX -32:
ec_str = "Property desired does not exist";
break;
case PKT_ERROR_METADEX -33:
ec_str = "Amount for sale out of range or zero";
break;
case PKT_ERROR_METADEX -34:
ec_str = "Amount desired out of range or zero";
break;
case PKT_ERROR_METADEX -35:
ec_str = "One side of the trade must be OMNI or TOMNI";
break;

case METADEX_ERROR -1:
ec_str = "Unknown MetaDEx (Add) error";
break;
case METADEX_ERROR -20:
ec_str = "Unknown MetaDEx (Cancel Price) error";
break;
case METADEX_ERROR -30:
ec_str = "Unknown MetaDEx (Cancel Pair) error";
break;
case METADEX_ERROR -40:
ec_str = "Unknown MetaDEx (Cancel Everything) error";
break;
case METADEX_ERROR -66:
ec_str = "Trade has a unit price of zero";
break;
case METADEX_ERROR -70:
ec_str = "Trade already exists";
break;

case PKT_ERROR_SP -20:
ec_str = "Block is not in the active chain";
break;
case PKT_ERROR_SP -21:
ec_str = "Ecosystem is invalid";
break;
case PKT_ERROR_SP -22:
ec_str = "Transaction type or version not permitted";
break;
case PKT_ERROR_SP -23:
ec_str = "Value out of range or zero";
break;
case PKT_ERROR_SP -24:
ec_str = "Desired property does not exist";
break;
case PKT_ERROR_SP -36:
ec_str = "Invalid property type";
break;
case PKT_ERROR_SP -37:
ec_str = "Property name is empty";
break;
case PKT_ERROR_SP -38:
ec_str = "Deadline is in the past";
break;
case PKT_ERROR_SP -39:
ec_str = "Sender has an active crowdsale";
break;
case PKT_ERROR_SP -40:
ec_str = "Sender has no active crowdsale";
break;
case PKT_ERROR_SP -41:
ec_str = "Property identifier mismatch";
break;
case PKT_ERROR_SP -42:
ec_str = "Property is not managed";
break;
case PKT_ERROR_SP -43:
ec_str = "Sender is not the issuer of the property";
break;
case PKT_ERROR_SP -44:
ec_str = "Attempt to grant more than the maximum number of tokens";
break;
case PKT_ERROR_SP -50:
ec_str = "Tokens to issue and desired property are not in the same ecosystem";
break;

case PKT_ERROR_TOKENS -22:
ec_str = "Transaction type or version not permitted";
break;
case PKT_ERROR_TOKENS -23:
ec_str = "Value out of range or zero";
break;
case PKT_ERROR_TOKENS -24:
ec_str = "Property does not exist";
break;
case PKT_ERROR_TOKENS -25:
ec_str = "Sender has insufficient balance";
break;
case PKT_ERROR_TOKENS -39:
ec_str = "Sender has an active crowdsale";
break;
case PKT_ERROR_TOKENS -43:
ec_str = "Sender is not the issuer of the property";
break;
case PKT_ERROR_TOKENS -45:
ec_str = "Receiver is empty";
break;
case PKT_ERROR_TOKENS -46:
ec_str = "Receiver has an active crowdsale";
break;

default:
ec_str = "Unknown error";
}
Expand Down
49 changes: 40 additions & 9 deletions src/omnicore/omnicore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2344,7 +2344,7 @@ bool mastercore_handler_tx(const CTransaction& tx, int nBlock, unsigned int idx,
if (interp_ret != PKT_ERROR - 2) {
bool bValid = (0 <= interp_ret);
p_txlistdb->recordTX(tx.GetHash(), bValid, nBlock, mp_obj.getType(), mp_obj.getNewAmount());
p_OmniTXDB->RecordTransaction(tx.GetHash(), idx);
p_OmniTXDB->RecordTransaction(tx.GetHash(), idx, interp_ret);
}
fFoundTx |= (interp_ret == 0);
}
Expand Down Expand Up @@ -2456,33 +2456,64 @@ int mastercore::WalletTxBuilder(const std::string& senderAddress, const std::str

}

void COmniTransactionDB::RecordTransaction(const uint256& txid, uint32_t posInBlock)
void COmniTransactionDB::RecordTransaction(const uint256& txid, uint32_t posInBlock, int processingResult)
{
assert(pdb);

const std::string key = txid.ToString();
const std::string value = strprintf("%d", posInBlock);
const std::string value = strprintf("%d:%d", posInBlock, processingResult);

Status status = pdb->Put(writeoptions, key, value);
++nWritten;
}

uint32_t COmniTransactionDB::FetchTransactionPosition(const uint256& txid)
std::vector<std::string> COmniTransactionDB::FetchTransactionDetails(const uint256& txid)
{
assert(pdb);

const std::string key = txid.ToString();
std::string strValue;
uint32_t posInBlock = 999999; // setting an initial arbitrarily high value will ensure transaction is always "last" in event of bug/exploit
std::vector<std::string> vTransactionDetails;

Status status = pdb->Get(readoptions, key, &strValue);
Status status = pdb->Get(readoptions, txid.ToString(), &strValue);
if (status.ok()) {
posInBlock = boost::lexical_cast<uint32_t>(strValue);
std::vector<std::string> vStr;
boost::split(vStr, strValue, boost::is_any_of(":"), boost::token_compress_on);
if (vStr.size() == 2) {
vTransactionDetails.push_back(vStr[0]);
vTransactionDetails.push_back(vStr[1]);
} else {
PrintToLog("ERROR: Entry (%s) found in OmniTXDB with unexpected number of attributes!\n", txid.GetHex());
}
} else {
PrintToLog("ERROR: Entry (%s) could not be loaded from OmniTXDB!\n", txid.GetHex());
}

return vTransactionDetails;
}

uint32_t COmniTransactionDB::FetchTransactionPosition(const uint256& txid)
{
uint32_t posInBlock = 999999; // setting an initial arbitrarily high value will ensure transaction is always "last" in event of bug/exploit

std::vector<std::string> vTransactionDetails = FetchTransactionDetails(txid);
if (vTransactionDetails.size() == 2) {
posInBlock = boost::lexical_cast<uint32_t>(vTransactionDetails[0]);
}

return posInBlock;
}

std::string COmniTransactionDB::FetchInvalidReason(const uint256& txid)
{
int processingResult = -999999;

std::vector<std::string> vTransactionDetails = FetchTransactionDetails(txid);
if (vTransactionDetails.size() == 2) {
processingResult = boost::lexical_cast<int>(vTransactionDetails[1]);
}

return error_str(processingResult);
}

std::set<int> CMPTxList::GetSeedBlocks(int startHeight, int endHeight)
{
std::set<int> setSeedBlocks;
Expand Down
6 changes: 4 additions & 2 deletions src/omnicore/omnicore.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 3
#define DB_VERSION 5

// could probably also use: int64_t maxInt64 = std::numeric_limits<int64_t>::max();
// maximum numeric values from the spec:
Expand Down Expand Up @@ -177,8 +177,10 @@ class COmniTransactionDB : public CDBBase
*
* and so on...
*/
void RecordTransaction(const uint256& txid, uint32_t posInBlock);
void RecordTransaction(const uint256& txid, uint32_t posInBlock, int processingResult);
std::vector<std::string> FetchTransactionDetails(const uint256& txid);
uint32_t FetchTransactionPosition(const uint256& txid);
std::string FetchInvalidReason(const uint256& txid);
};

/** LevelDB based storage for STO recipients.
Expand Down
1 change: 1 addition & 0 deletions src/omnicore/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,7 @@ UniValue omni_gettransaction(const UniValue& params, bool fHelp)
" \"fee\" : \"n.nnnnnnnn\", (string) the transaction fee in bitcoins\n"
" \"blocktime\" : nnnnnnnnnn, (number) the timestamp of the block that contains the transaction\n"
" \"valid\" : true|false, (boolean) whether the transaction is valid\n"
" \"invalidreason\" : \"reason\", (string) if a transaction is invalid, the reason \n"
" \"version\" : n, (number) the transaction version\n"
" \"type_int\" : n, (number) the transaction type as number\n"
" \"type\" : \"type\", (string) the transaction type as string\n"
Expand Down
3 changes: 3 additions & 0 deletions src/omnicore/rpctxobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ int populateRPCTransactionObject(const CTransaction& tx, const uint256& blockHas
// state and chain related information
if (confirmations != 0 && !blockHash.IsNull()) {
txobj.push_back(Pair("valid", valid));
if (!valid) {
txobj.push_back(Pair("invalidreason", p_OmniTXDB->FetchInvalidReason(txid)));
}
txobj.push_back(Pair("blockhash", blockHash.GetHex()));
txobj.push_back(Pair("blocktime", blockTime));
txobj.push_back(Pair("positioninblock", positionInBlock));
Expand Down

0 comments on commit 3e040ef

Please sign in to comment.