You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mymonero-core-cpp/src/monero_transfer_utils.hpp

296 lines
11 KiB

//
// monero_transfer_utils.hpp
// Copyright (c) 2014-2019, MyMonero.com
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//
#ifndef monero_transfer_utils_hpp
#define monero_transfer_utils_hpp
//
#include <boost/optional.hpp>
//
#include "string_tools.h"
//
#include "crypto.h"
#include "cryptonote_basic.h"
#include "cryptonote_format_utils.h"
#include "cryptonote_tx_utils.h"
#include "ringct/rctSigs.h"
//
#include "monero_fork_rules.hpp"
#include "monero_fee_utils.hpp"
//
using namespace tools;
#include "tools__ret_vals.hpp"
//
namespace monero_transfer_utils
{
using namespace std;
using namespace boost;
using namespace cryptonote;
using namespace monero_fork_rules;
using namespace crypto;
//
bool is_transfer_unlocked(uint64_t unlock_time, uint64_t block_height, uint64_t blockchain_size, network_type nettype = MAINNET);
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_height, uint64_t blockchain_size, network_type nettype = MAINNET);
//
// Types - Arguments
struct SpendableOutput
{
uint64_t amount;
string public_key;
optional<string> rct;
uint64_t global_index;
uint64_t index;
string tx_pub_key;
};
struct RandomAmountOutput
{
uint64_t global_index; // this is, I believe, presently supplied as a string by the API, probably to avoid overflow
string public_key;
optional<string> rct;
};
struct RandomAmountOutputs
{
uint64_t amount;
vector<RandomAmountOutput> outputs;
};
//
// Types - Return value
enum CreateTransactionErrorCode // TODO: switch to enum class to fix namespacing
{ // These codes have values for serialization
noError = 0,
//
noDestinations = 1,
wrongNumberOfMixOutsProvided = 2,
notEnoughOutputsForMixing = 3,
invalidSecretKeys = 4,
outputAmountOverflow = 5,
inputAmountOverflow = 6,
mixRCTOutsMissingCommit = 7,
resultFeeNotEqualToGiven = 8,
invalidDestinationAddress = 9,
nonZeroPIDWithIntAddress = 10,
cantUsePIDWithSubAddress = 11,
couldntAddPIDNonceToTXExtra = 12,
givenAnInvalidPubKey = 13,
invalidCommitOrMaskOnOutputRCT = 14,
transactionNotConstructed = 15,
transactionTooBig = 16,
notYetImplemented = 17,
couldntDecodeToAddress = 18,
invalidPID = 19,
enteredAmountTooLow = 20,
cantGetDecryptedMaskFromRCTHex = 21,
needMoreMoneyThanFound = 90
};
static inline string err_msg_from_err_code__create_transaction(CreateTransactionErrorCode code)
{
switch (code) {
case noError:
return "No error";
case couldntDecodeToAddress:
return "Couldn't decode address";
case noDestinations:
return "No destinations provided";
case wrongNumberOfMixOutsProvided:
return "Wrong number of mix outputs provided";
case notEnoughOutputsForMixing:
return "Not enough outputs for mixing";
case invalidSecretKeys:
return "Invalid secret keys";
case outputAmountOverflow:
return "Output amount overflow";
case inputAmountOverflow:
return "Input amount overflow";
case mixRCTOutsMissingCommit:
return "Mix RCT outs missing commit";
case resultFeeNotEqualToGiven:
return "Result fee not equal to given fee";
case needMoreMoneyThanFound:
return "Spendable balance too low";
case invalidDestinationAddress:
return "Invalid destination address";
case nonZeroPIDWithIntAddress:
return "Payment ID must be blank when using an integrated address";
case cantUsePIDWithSubAddress:
return "Payment ID must be blank when using a subaddress";
case couldntAddPIDNonceToTXExtra:
return "Couldn't add nonce to tx extra";
case givenAnInvalidPubKey:
return "Invalid pub key";
case invalidCommitOrMaskOnOutputRCT:
return "Invalid commit or mask on output rct";
case transactionNotConstructed:
return "Transaction not constructed";
case transactionTooBig:
return "Transaction too big";
case notYetImplemented:
return "Not yet implemented";
case invalidPID:
return "Invalid payment ID";
case enteredAmountTooLow:
return "The amount you've entered is too low";
case cantGetDecryptedMaskFromRCTHex:
return "Can't get decrypted mask from 'rct' hex";
}
}
//
// See monero_send_routine for actual app-lvl interface used by lightwallets
//
//
// Send_Step* functions procedure for integrators:
// 1. call GetUnspentOuts endpoint
// 2. call step1__prepare_params_for_get_decoys to get params for calling RandomOuts; call GetRandomOuts
// 3. call step2__try_… with retVals from Step1 (incl using_outs, RandomOuts)
// 3a. While tx must be reconstructed, re-call step1 passing step2 fee_actually_needed as passedIn_attemptAt_fee, then re-request RandomOuts again, and call step2 again
// 3b. If good tx constructed, proceed to submit/save the tx
// Note: This separation of steps fully encodes SendFunds_ProcessStep
//
struct Send_Step1_RetVals
{
CreateTransactionErrorCode errCode; // if != noError, abort Send process
// for display / information purposes on errCode=needMoreMoneyThanFound during step1:
uint64_t spendable_balance; // (effectively but not the same as spendable_balance)
uint64_t required_balance; // for display / information purposes on errCode=needMoreMoneyThanFound during step1
//
// Success case return values
uint32_t mixin;
vector<SpendableOutput> using_outs;
uint64_t using_fee;
uint64_t final_total_wo_fee;
uint64_t change_amount;
};
void send_step1__prepare_params_for_get_decoys(
Send_Step1_RetVals &retVals,
//
const optional<string>& payment_id_string,
uint64_t sending_amount,
bool is_sweeping,
uint32_t simple_priority,
use_fork_rules_fn_type use_fork_rules_fn,
//
const vector<SpendableOutput> &unspent_outs,
uint64_t fee_per_b, // per v8
//
optional<uint64_t> passedIn_attemptAt_fee // use this for passing step2 "must-reconstruct" return values back in, i.e. re-entry; when nil, defaults to attempt at network min
);
//
struct Send_Step2_RetVals
{
CreateTransactionErrorCode errCode; // if != noError, abort Send process
//
// Reconstruct-required parameters:
bool tx_must_be_reconstructed; // if true, re-request RandomOuts with the following parameters and retry step3
uint64_t fee_actually_needed; // will be non-zero if tx_must_be_reconstructed
//
// Success parameters:
optional<string> signed_serialized_tx_string;
optional<string> tx_hash_string;
optional<string> tx_key_string; // this includes additional_tx_keys
optional<string> tx_pub_key_string; // from get_tx_pub_key_from_extra()
};
void send_step2__try_create_transaction(
Send_Step2_RetVals &retVals,
//
const string &from_address_string,
const string &sec_viewKey_string,
const string &sec_spendKey_string,
const string &to_address_string,
const optional<string>& payment_id_string,
uint64_t final_total_wo_fee, // this gets passed to create_transaction's 'sending_amount'
uint64_t change_amount,
uint64_t fee_amount,
uint32_t simple_priority,
const vector<SpendableOutput> &using_outs,
uint64_t fee_per_b, // per v8
vector<RandomAmountOutputs> &mix_outs, // it gets sorted
use_fork_rules_fn_type use_fork_rules_fn,
uint64_t unlock_time, // or 0
cryptonote::network_type nettype
);
//
//
// Lower level functions - generally you won't need to call these (these are what used to live in cn_utils.js)
//
struct Convenience_TransactionConstruction_RetVals
{
CreateTransactionErrorCode errCode;
//
optional<string> signed_serialized_tx_string;
optional<string> tx_hash_string;
optional<string> tx_key_string; // this includes additional_tx_keys
optional<string> tx_pub_key_string; // from get_tx_pub_key_from_extra()
optional<transaction> tx; // for block weight
optional<size_t> txBlob_byteLength;
};
void convenience__create_transaction(
Convenience_TransactionConstruction_RetVals &retVals,
const string &from_address_string,
const string &sec_viewKey_string,
const string &sec_spendKey_string,
const string &to_address_string,
const optional<string>& payment_id_string,
uint64_t sending_amount,
uint64_t change_amount,
uint64_t fee_amount,
const vector<SpendableOutput> &outputs,
vector<RandomAmountOutputs> &mix_outs, // get sorted
use_fork_rules_fn_type use_fork_rules_fn,
uint64_t unlock_time = 0, // or 0
network_type nettype = MAINNET
);
struct TransactionConstruction_RetVals
{
CreateTransactionErrorCode errCode;
//
optional<transaction> tx;
optional<secret_key> tx_key;
optional<vector<secret_key>> additional_tx_keys;
};
void create_transaction(
TransactionConstruction_RetVals &retVals,
const account_keys& sender_account_keys, // this will reference a particular hw::device
const uint32_t subaddr_account_idx, // pass 0 for no subaddrs
const std::unordered_map<crypto::public_key, cryptonote::subaddress_index> &subaddresses,
const address_parse_info &to_addr, // this _must_ include correct .is_subaddr
uint64_t sending_amount,
uint64_t change_amount,
uint64_t fee_amount,
const vector<SpendableOutput> &outputs,
vector<RandomAmountOutputs> &mix_outs,
const std::vector<uint8_t> &extra, // this is not declared const b/c it may have the output tx pub key appended to it
use_fork_rules_fn_type use_fork_rules_fn,
uint64_t unlock_time = 0, // or 0
bool rct = true,
network_type nettype = MAINNET
);
}
#endif /* monero_transfer_utils_hpp */