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.
296 lines
11 KiB
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 */
|