//
// monero_transfer_utils.hpp
// Copyright (c) 2014-2018, 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"
//
using namespace tools ;
# include "tools__ret_vals.hpp"
//
// used to choose when to stop adding outputs to a tx
# define APPROXIMATE_INPUT_BYTES 80
//
namespace monero_transfer_utils
{
using namespace std ;
using namespace boost ;
using namespace cryptonote ;
using namespace monero_fork_rules ;
using namespace crypto ;
//
uint64_t get_upper_transaction_size_limit ( uint64_t upper_transaction_size_limit__or_0_for_default , use_fork_rules_fn_type use_fork_rules_fn ) ;
uint64_t get_fee_multiplier ( uint32_t priority , uint32_t default_priority , int fee_algorithm , use_fork_rules_fn_type use_fork_rules_fn ) ;
int get_fee_algorithm ( use_fork_rules_fn_type use_fork_rules_fn ) ;
//
uint64_t calculate_fee ( uint64_t fee_per_kb , size_t bytes , uint64_t fee_multiplier ) ;
uint64_t calculate_fee ( uint64_t fee_per_kb , const blobdata & blob , uint64_t fee_multiplier ) ;
//
size_t estimate_rct_tx_size ( int n_inputs , int mixin , int n_outputs , size_t extra_size , bool bulletproof ) ;
size_t estimate_tx_size ( bool use_rct , int n_inputs , int mixin , int n_outputs , size_t extra_size , bool bulletproof ) ;
uint64_t estimated_tx_network_fee ( // convenience function for size + calc
uint64_t fee_per_kb ,
uint32_t priority , // when priority=0, falls back to monero_transfer_utils::default_priority()
use_fork_rules_fn_type use_fork_rules_fn // this is extracted to a function so that implementations can optionally query the daemon (although this presently implies that such a call remains blocking)
) ;
//
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 ) ;
//
uint32_t fixed_ringsize ( ) ; // not mixinsize, which would be ringsize-1
uint32_t fixed_mixinsize ( ) ; // not ringsize, which would be mixinsize+1
uint32_t default_priority ( ) ;
//
string new_dummy_address_string_for_rct_tx ( 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 ,
needMoreMoneyThanFound = 9 ,
invalidDestinationAddress = 10 ,
nonZeroPIDWithIntAddress = 11 ,
cantUsePIDWithSubAddress = 12 ,
couldntSetPIDToTXExtra = 13 ,
givenAnInvalidPubKey = 14 ,
invalidCommitOrMaskOnOutputRCT = 15 ,
transactionNotConstructed = 16 ,
transactionTooBig = 17 ,
notYetImplemented = 18
} ;
static inline string err_msg_from_err_code__create_transaction ( CreateTransactionErrorCode code )
{
switch ( code ) {
case noError :
return " No error " ;
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 " Need more money than found " ;
case invalidDestinationAddress :
return " Invalid destination address " ;
case nonZeroPIDWithIntAddress :
return " Can't supply a PID with an integrated address " ;
case cantUsePIDWithSubAddress :
return " Can't use PID with subaddress " ;
case couldntSetPIDToTXExtra :
return " Couldn't set PID 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 " ;
}
}
struct TransactionConstruction_RetVals
{
CreateTransactionErrorCode errCode ;
//
optional < transaction > tx ;
optional < secret_key > tx_key ;
optional < vector < secret_key > > additional_tx_keys ;
} ;
// TODO: add priority
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 vector < tx_destination_entry > & dsts , // presently, this must include change as well as, if necessary, dummy output
vector < SpendableOutput > & outputs ,
vector < RandomAmountOutputs > & mix_outs ,
uint64_t fee_amount ,
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
) ;
//
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
} ;
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 ,
optional < string > payment_id_string ,
uint64_t amount , // to send
uint64_t fee_amount ,
const std : : vector < cryptonote : : tx_destination_entry > & dsts , // this must include change or else dummy address
vector < SpendableOutput > & outputs ,
vector < RandomAmountOutputs > & mix_outs ,
use_fork_rules_fn_type use_fork_rules_fn ,
uint64_t unlock_time = 0 , // or 0
network_type nettype = MAINNET
) ;
}
# endif /* monero_transfer_utils_hpp */