Skip to content

Commit

Permalink
Strict handling of number types and bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
dexX7 committed Apr 20, 2022
1 parent ea90386 commit 4b21c89
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 41 deletions.
6 changes: 2 additions & 4 deletions src/omnicore/omnicore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,7 @@ static int parseTransaction(bool bRPConly, const CTransaction& wtx, int nBlock,
std::vector<std::string> address_data;
std::vector<int64_t> value_data;

for (unsigned int n = 0; n < wtx.vout.size(); ++n) {
for (size_t n = 0; n < wtx.vout.size(); ++n) {
txnouttype whichType;
if (!GetOutputType(wtx.vout[n].scriptPubKey, whichType)) {
continue;
Expand All @@ -1078,9 +1078,7 @@ static int parseTransaction(bool bRPConly, const CTransaction& wtx, int nBlock,
GetScriptPushes(wtx.vout[n].scriptPubKey, script_data);
std::string address = EncodeDestination(dest);
address_data.push_back(address);
if (!address.empty()) {
mp_tx.addValidStmAddress(n, address);
}
mp_tx.addValidStmAddress(n, address);
value_data.push_back(wtx.vout[n].nValue);
if (msc_debug_parser_data) PrintToLog("saving address_data #%d: %s:%s\n", n, EncodeDestination(dest), ScriptToAsmStr(wtx.vout[n].scriptPubKey));
}
Expand Down
4 changes: 3 additions & 1 deletion src/omnicore/rpcpayload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include <univalue.h>

#include <stdint.h>

using std::runtime_error;
using namespace mastercore;

Expand Down Expand Up @@ -164,7 +166,7 @@ static UniValue omni_createpayload_sendtomany(const JSONRPCRequest& request)
const UniValue& uvOutput = find_value(o, "output");
const UniValue& uvAmount = find_value(o, "amount");

uint8_t output = uvOutput.get_int();
uint8_t output = ParseStmOutputIndex(uvOutput);
uint64_t amount = ParseAmount(uvAmount, isPropertyDivisible(propertyId));

outputValues.push_back(std::make_tuple(output, amount));
Expand Down
5 changes: 2 additions & 3 deletions src/omnicore/rpcrequirements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <tinyformat.h>

#include <stdint.h>
#include <limits>
#include <string>

void RequireBalance(const std::string& address, uint32_t propertyId, int64_t amount)
Expand Down Expand Up @@ -265,9 +264,9 @@ void RequireNonFungibleTokenOwner(const std::string& address, uint32_t propertyI
}
}

void RequireBoundedStmReceiverNumber(size_t numberOfReceivers)
void RequireBoundedStmReceiverNumber(size_t lastReceiverOutputIndex)
{
if (numberOfReceivers > std::numeric_limits<uint8_t>::max()) {
if (lastReceiverOutputIndex > std::numeric_limits<uint8_t>::max()) {
throw JSONRPCError(RPC_TYPE_ERROR, "Too many send-to-many receivers");
}
}
2 changes: 1 addition & 1 deletion src/omnicore/rpcrequirements.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void RequireSaneDExFee(const std::string& address, uint32_t propertyId);
void RequireSaneNonFungibleRange(int64_t tokenStart, int64_t tokenEnd);
void RequireHeightInChain(int blockHeight);
void RequireNonFungibleTokenOwner(const std::string& address, uint32_t propertyId, int64_t tokenStart, int64_t tokenEnd);
void RequireBoundedStmReceiverNumber(size_t numberOfReceivers);
void RequireBoundedStmReceiverNumber(size_t lastReceiverOutputIndex);

// TODO:
// Checks for MetaDEx orders for cancel operations
Expand Down
26 changes: 14 additions & 12 deletions src/omnicore/rpctx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,8 @@ static UniValue omni_sendtomany(const JSONRPCRequest& request)
std::string fromAddress = ParseAddress(request.params[0]);
uint32_t propertyId = ParsePropertyId(request.params[1]);

RequireBoundedStmReceiverNumber(request.params[2].size());
// first check, assuming one payload output
RequireBoundedStmReceiverNumber(request.params[2].size() + 1);

// ---
// dry run to get positions for send-to-many outputs
Expand All @@ -465,9 +466,9 @@ static UniValue omni_sendtomany(const JSONRPCRequest& request)
std::vector<std::tuple<uint8_t, uint64_t>> outputValues;

uint64_t amountToSend = 0;
uint8_t output = 1; // dummy position
size_t dummyOutputCount = 1; // dummy position

for (unsigned int idx = 0; idx < request.params[2].size(); idx++) {
for (size_t idx = 0; idx < request.params[2].size(); idx++) {
const UniValue& input = request.params[2][idx];
const UniValue& o = input.get_obj();

Expand All @@ -479,34 +480,35 @@ static UniValue omni_sendtomany(const JSONRPCRequest& request)

amountToSend += amount;
receiverAddresses.push_back(address);
outputValues.push_back(std::make_tuple(output, amount));
outputValues.push_back(std::make_tuple(dummyOutputCount, amount));

output += 1;
dummyOutputCount += 1;
}

std::vector<unsigned char> testPayload = CreatePayload_SendToMany(
propertyId,
outputValues);

int outputCount = GetDryPayloadOutputCount(fromAddress, "", testPayload, pwallet.get());
int payloadOutputCount = GetDryPayloadOutputCount(fromAddress, "", testPayload, pwallet.get());

// perform checks
RequireExistingProperty(propertyId);
RequireBalance(fromAddress, propertyId, amountToSend);

if (outputCount < 0) {
if (payloadOutputCount < 0) {
throw JSONRPCError(RPC_TYPE_ERROR, "Error creating send-to-many payload");
}
// actual check with proper payload count
RequireBoundedStmReceiverNumber(payloadOutputCount + dummyOutputCount);
RequireExistingProperty(propertyId);
RequireBalance(fromAddress, propertyId, amountToSend);

// ---
// actual run
// --

receiverAddresses.clear();
outputValues.clear();
output = outputCount;
uint8_t output = static_cast<uint8_t>(payloadOutputCount);

for (unsigned int idx = 0; idx < request.params[2].size(); idx++) {
for (size_t idx = 0; idx < request.params[2].size(); idx++) {
const UniValue& input = request.params[2][idx];
const UniValue& o = input.get_obj();

Expand Down
1 change: 0 additions & 1 deletion src/omnicore/rpctxobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,6 @@ void populateRPCTypeSendToMany(CMPTransaction& omniObj, UniValue& txobj)
UniValue outputValues(UniValue::VARR);

for (const std::tuple<uint8_t, uint64_t>& entry : omniObj.getStmOutputValues()) {

uint8_t output = std::get<0>(entry);
std::string amount = FormatMP(propertyId, std::get<1>(entry));
std::string destination;
Expand Down
10 changes: 10 additions & 0 deletions src/omnicore/rpcvalues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <univalue.h>

#include <limits>
#include <string>
#include <vector>

Expand Down Expand Up @@ -245,3 +246,12 @@ std::vector<PrevTxsEntry> ParsePrevTxs(const UniValue& value)

return prevTxsParsed;
}

uint8_t ParseStmOutputIndex(const UniValue& value)
{
int64_t index = value.get_int64();
if (index < 0 || index > std::numeric_limits<uint8_t>::max()) {
throw JSONRPCError(RPC_TYPE_ERROR, "Output index out of bounds (0..255)");
}
return static_cast<uint8_t>(index);
}
1 change: 1 addition & 0 deletions src/omnicore/rpcvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ CPubKey ParsePubKeyOrAddress(interfaces::Wallet *iWallet, const UniValue& value)
uint32_t ParseOutputIndex(const UniValue& value);
/** Parses previous transaction outputs. */
std::vector<PrevTxsEntry> ParsePrevTxs(const UniValue& value);
uint8_t ParseStmOutputIndex(const UniValue& value);


#endif // BITCOIN_OMNICORE_RPCVALUES_H
33 changes: 32 additions & 1 deletion src/omnicore/tx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <string.h>

#include <algorithm>
#include <limits>
#include <utility>
#include <vector>
#include <tuple>
Expand Down Expand Up @@ -110,6 +111,37 @@ bool CMPTransaction::isOverrun(const char* p)
return (pos > pkt_size);
}

// ** Returns number of STM receivers. */
uint8_t CMPTransaction::getStmNumberOfReceivers() {
return numberOfSTMReceivers;
}

/** Returns output valies. */
std::vector<std::tuple<uint8_t, uint64_t>> CMPTransaction::getStmOutputValues() {
return outputValuesForSTM;
}

/** Adds an address at position output. */
void CMPTransaction::addValidStmAddress(size_t output, const std::string& address) {
if (output <= std::numeric_limits<uint8_t>::max()) {
if (!address.empty()) {
validOutputAddressesForSTM[output] = address;
}
}
}

/** Return an output address, if it's considered as valid Omni destination. */
bool CMPTransaction::getValidStmAddressAt(uint8_t output, std::string& addressOut) {
if (validOutputAddressesForSTM.find(output) != validOutputAddressesForSTM.end()) {
addressOut = validOutputAddressesForSTM[output];
return true;
}

addressOut.clear();
return false;
}


// -------------------- PACKET PARSING -----------------------

/** Parses the packet or payload. */
Expand Down Expand Up @@ -1638,7 +1670,6 @@ int CMPTransaction::logicMath_SendToMany()

std::string receiver;
assert(getValidStmAddressAt(output, receiver));

assert(update_tally_map(sender, property, -amount, BALANCE));
assert(update_tally_map(receiver, property, amount, BALANCE));
}
Expand Down
23 changes: 5 additions & 18 deletions src/omnicore/tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,30 +245,17 @@ class CMPTransaction
std::string getNonFungibleData() const { return nonfungible_data; }

// Send To Many
uint8_t getStmNumberOfReceivers() const {
return numberOfSTMReceivers;
}
// ** Returns number of STM receivers. */
uint8_t getStmNumberOfReceivers();

/** Returns output valies. */
std::vector<std::tuple<uint8_t, uint64_t>> getStmOutputValues() const {
return outputValuesForSTM;
}
std::vector<std::tuple<uint8_t, uint64_t>> getStmOutputValues();

/** Adds an address at position output. */
void addValidStmAddress(uint8_t output, const std::string& address) {
validOutputAddressesForSTM[output] = address;
}
void addValidStmAddress(size_t output, const std::string& address);

/** Return an output address, if it's considered as valid Omni destination. */
bool getValidStmAddressAt(uint8_t output, std::string& addressOut) {
if (validOutputAddressesForSTM.find(output) != validOutputAddressesForSTM.end()) {
addressOut = validOutputAddressesForSTM[output];
return true;
}

addressOut.clear();
return false;
}
bool getValidStmAddressAt(uint8_t output, std::string& addressOut);

/** Creates a new CMPTransaction object. */
CMPTransaction()
Expand Down

0 comments on commit 4b21c89

Please sign in to comment.