initial (wip) test path

pull/29/head
Paul Shapiro 6 years ago
parent 7d50c44bc5
commit 5abda04c86

31
.gitignore vendored

@ -1 +1,32 @@
.DS_Store
build
Debug
xcode
cmake-build-debug/
.idea
CMakeFiles
CMakeScripts
CMakeCache.txt
CTestTestfile.cmake
cmake_install.cmake
TEST.build
DerivedData/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
*.moved-aside
*.xccheckout
*.xcscmblueprint

@ -0,0 +1,91 @@
cmake_minimum_required(VERSION 3.4.1)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
project(TEST)
enable_testing()
#Find openSSL
find_package(OpenSSL COMPONENTS
crypto REQUIRED
ssl REQUIRED
)
#Prep ourselves for compiling boost
find_package(Boost COMPONENTS
unit_test_framework REQUIRED
atomic REQUIRED
chrono REQUIRED
context REQUIRED
date_time REQUIRED
exception REQUIRED
filesystem REQUIRED
graph REQUIRED
iostreams REQUIRED
math_c99 REQUIRED
math_c99f REQUIRED
math_c99l REQUIRED
math_tr1 REQUIRED
math_tr1f REQUIRED
math_tr1l REQUIRED
prg_exec_monitor REQUIRED
program_options REQUIRED
random REQUIRED
regex REQUIRED
serialization REQUIRED
signals REQUIRED
system REQUIRED
test_exec_monitor REQUIRED
thread REQUIRED
timer REQUIRED
wave REQUIRED
wserialization REQUIRED
)
include_directories(${Boost_INCLUDE_DIRS})
include_directories("src")
include_directories("test")
# keeping test files in a separate source directory
file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/test_*.cpp)
set(
SRC_FILES
#
# src/monero_address_utils.hpp
# src/monero_address_utils.cpp
# src/monero_paymentID_utils.hpp
# src/monero_paymentID_utils.cpp
# src/monero_wallet_utils.hpp
# src/monero_wallet_utils.cpp
src/tools__ret_vals.hpp
src/tools__ret_vals.cpp
)
#Run through each source
foreach(testSrc ${TEST_SRCS})
# extract the filename without an extension (NAME_WE)
get_filename_component(testName ${testSrc} NAME_WE)
add_executable(
${testName}
${testSrc}
${SRC_FILES}
)
target_link_libraries(
${testName}
#
OpenSSL::SSL
${Boost_LIBRARIES}
)
set_target_properties(
${testName} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/build/products
)
add_test(
NAME ${testName}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build/products
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build/products/${testName} --catch_system_error=yes
)
endforeach(testSrc)

@ -0,0 +1,27 @@
// 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.

@ -0,0 +1,8 @@
#!/usr/bin/env bash
mkdir -p build;
cd build &&
cmake .. -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl &&
cmake --build . &&
CTEST_OUTPUT_ON_FAILURE=1 ctest -VV

@ -0,0 +1,13 @@
#!/usr/bin/env bash
ESCAPEDSRCROOT="$(pwd | sed 's/\//\\\//g')";
mkdir -p xcode;
cd xcode &&
cmake -G Xcode .. -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl &&
echo "$ 's/$ESCAPEDSRCROOT/\${SRCROOT}/g'" && #remove personally identifying info of proj generator
LC_CTYPE=C LANG=C find TEST.xcodeproj -type f -print0 -exec sed -i "" 's/'"$ESCAPEDSRCROOT"'/${SRCROOT}/g' {} + &&
echo "" #newline

@ -0,0 +1,127 @@
//
// monero_address_utils.cpp
// 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.
//
//
#import "index.hpp"
//
#include "cryptonote_basic_impl.h"
#include "string_tools.h"
#include "tools__ret_vals.hpp"
using namespace epee;
//
#include "monero_paymentID_utils.hpp"
//
// Accessors - Implementations
Monero_DecodedAddress_RetVals decodedAddress(string addressString, bool isTestnet)
{
Monero_DecodedAddress_RetVals *retVals = [Monero_DecodedAddress_RetVals new];
//
cryptonote::address_parse_info info;
bool didSucceed = cryptonote::get_account_address_from_str(info, isTestnet ? cryptonote::TESTNET : cryptonote::MAINNET, std::string(addressString.UTF8String));
if (didSucceed == false) {
retVals.errStr_orNil = NSLocalizedString(@"Invalid address", nil);
//
return retVals;
}
cryptonote::account_public_address address = info.address;
std::string pub_viewKey_hexString = string_tools::pod_to_hex(address.m_view_public_key);
std::string pub_spendKey_hexString = string_tools::pod_to_hex(address.m_spend_public_key);
//
NSString *pub_viewKey_NSString = [NSString stringWithUTF8String:pub_viewKey_hexString.c_str()];
NSString *pub_spendKey_NSString = [NSString stringWithUTF8String:pub_spendKey_hexString.c_str()];
NSString *paymentID_NSString_orNil = nil;
if (info.has_payment_id == true) {
crypto::hash8 payment_id = info.payment_id;
std::string payment_id_hexString = string_tools::pod_to_hex(payment_id);
paymentID_NSString_orNil = [NSString stringWithUTF8String:payment_id_hexString.c_str()];
}
{
retVals.pub_viewKey_NSString = pub_viewKey_NSString;
retVals.pub_spendKey_NSString = pub_spendKey_NSString;
retVals.paymentID_NSString_orNil = paymentID_NSString_orNil;
retVals.isSubaddress = info.is_subaddress;
}
return retVals;
}
+ (BOOL)isSubAddress:(NSString *)addressString isTestnet:(BOOL)isTestnet
{
Monero_DecodedAddress_RetVals *retVals = [self decodedAddress:addressString isTestnet:isTestnet];
//
return retVals.isSubaddress;
}
+ (BOOL)isIntegratedAddress:(NSString *)addressString isTestnet:(BOOL)isTestnet
{
Monero_DecodedAddress_RetVals *retVals = [self decodedAddress:addressString isTestnet:isTestnet];
//
return retVals.paymentID_NSString_orNil != nil;
}
+ (NSString *)new_integratedAddrFromStdAddr:(NSString *)std_address_NSString andShortPID:(NSString *)short_paymentID isTestnet:(BOOL)isTestnet
{
std::string payment_id__string = std::string(short_paymentID.UTF8String);
crypto::hash8 payment_id_short;
bool didParse = monero_paymentID_utils::parse_short_payment_id(payment_id__string, payment_id_short);
if (!didParse) {
return nil;
}
cryptonote::address_parse_info info;
bool didSucceed = cryptonote::get_account_address_from_str(info, isTestnet ? cryptonote::TESTNET : cryptonote::MAINNET, std::string(std_address_NSString.UTF8String));
if (didSucceed == false) {
return nil;
}
if (info.is_subaddress) {
NSString *msg = [NSString stringWithFormat:@"%@ must not be called with a subaddress", NSStringFromSelector(_cmd)];
NSAssert(false, msg);
[NSException raise:@"Illegal address value" format:@"%@", msg];
//
return nil;
}
if (info.has_payment_id != false) {
// could even throw / fatalError here
return nil; // that was not a std_address!
}
std::string int_address_string = cryptonote::get_account_integrated_address_as_str(
isTestnet ? cryptonote::TESTNET : cryptonote::MAINNET,
info.address,
payment_id_short
);
NSString *int_address_NSString = [NSString stringWithUTF8String:int_address_string.c_str()];
//
return int_address_NSString;
}
+ (NSString *)new_integratedAddrFromStdAddr:(NSString *)std_address_NSString andShortPID:(NSString *)short_paymentID // mainnet
{
return [self
new_integratedAddrFromStdAddr:std_address_NSString
andShortPID:short_paymentID
isTestnet:NO];
}
@end

@ -0,0 +1,50 @@
//
// monero_address_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.
//
//
#include "tools__ret_vals.hpp"
//
struct Monero_DecodedAddress_RetVals: tools::RetVals_base
{ // TODO: inherit from tools__ret_vals
optional<string> errStr;
//
string pub_viewKey_string;
string pub_spendKey_string;
bool isSubaddress;
optional<string> paymentID_string;
};
//
//
Monero_DecodedAddress_RetVals decodedAddress(string addressString, bool isTestnet);
+ (BOOL)isSubAddress:(NSString *)addressString isTestnet:(BOOL)isTestnet;
+ (BOOL)isIntegratedAddress:(NSString *)addressString isTestnet:(BOOL)isTestnet;
//
+ (NSString *)new_integratedAddrFromStdAddr:(NSString *)std_address_NSString andShortPID:(NSString *)short_paymentID isTestnet:(BOOL)isTestnet;
+ (NSString *)new_integratedAddrFromStdAddr:(NSString *)std_address_NSString andShortPID:(NSString *)short_paymentID; // mainnet

@ -0,0 +1,84 @@
//
// monero_paymentID_utils.cpp
// 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.
//
//
#include "monero_paymentID_utils.hpp"
#include "cryptonote_basic.h"
#include "cryptonote_basic/blobdatatype.h"
//
#include "string_tools.h"
using namespace epee;
//
//
crypto::hash8 monero_paymentID_utils::new_short_plain_paymentID()
{
return crypto::rand<crypto::hash8>();
}
//
bool monero_paymentID_utils::parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
{
cryptonote::blobdata payment_id_data;
if (!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data)) {
return false;
}
if (sizeof(crypto::hash) != payment_id_data.size()) {
return false;
}
payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_data.data());
//
return true;
}
bool monero_paymentID_utils::parse_short_payment_id(const std::string& payment_id_str, crypto::hash8& payment_id)
{
cryptonote::blobdata payment_id_data;
if (!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data)) {
return false;
}
if (sizeof(crypto::hash8) != payment_id_data.size()) {
return false;
}
payment_id = *reinterpret_cast<const crypto::hash8*>(payment_id_data.data());
//
return true;
}
bool monero_paymentID_utils::parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
{
if (parse_long_payment_id(payment_id_str, payment_id)) {
return true;
}
crypto::hash8 payment_id8;
if (parse_short_payment_id(payment_id_str, payment_id8)) {
memcpy(payment_id.data, payment_id8.data, 8);
memset(payment_id.data + 8, 0, 24);
return true;
}
return false;
}

@ -0,0 +1,51 @@
//
// monero_paymentID_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_paymentID_utils_hpp
#define monero_paymentID_utils_hpp
#include <stdio.h>
#include "crypto.h"
namespace monero_paymentID_utils
{
//
// Generating Payment IDs
crypto::hash8 new_short_plain_paymentID(); // This is favored - its length will be detected and encrypted automatically on send
//
// Parsing and Detecting Payment IDs
bool parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id);
bool parse_short_payment_id(const std::string& payment_id_str, crypto::hash8& payment_id);
bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id);
}
#endif /* monero_paymentID_utils_hpp */

@ -0,0 +1,328 @@
//
// monero_wallet_utils.cpp
// 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.
//
//
//
#include "monero_wallet_utils.hpp"
#include <boost/algorithm/string.hpp>
#include "cryptonote_basic/account.h"
//
#include "string_tools.h"
using namespace epee;
//
extern "C" {
#include "crypto-ops.h"
}
//
using namespace monero_wallet_utils;
using namespace crypto; // for extension
//
bool monero_wallet_utils::new_wallet(
std::string mnemonic_language,
WalletDescriptionRetVals &retVals,
bool isTestnet
)
{
retVals = {};
//
cryptonote::account_base account{}; // this initializes the wallet and should call the default constructor
crypto::secret_key nonLegacy32B_sec_seed = account.generate();
//
const cryptonote::account_keys& keys = account.get_keys();
std::string address_string = account.get_public_address_str(isTestnet); // getting the string here instead of leaving it to the consumer b/c get_public_address_str could potentially change in implementation (see TODO) so it's not right to duplicate that here
//
std::string mnemonic_string;
bool r = crypto::ElectrumWords::bytes_to_words(nonLegacy32B_sec_seed, mnemonic_string, std::move(mnemonic_language));
// ^-- it's OK to directly call ElectrumWords w/ crypto::secret_key as we are generating new wallet, not reading
if (!r) {
retVals.did_error = true;
retVals.err_string = "Unable to create new wallet";
// TODO: return code of unable to convert seed to mnemonic
//
return false;
}
retVals.optl__desc =
{
string_tools::pod_to_hex(nonLegacy32B_sec_seed),
//
address_string,
//
keys.m_spend_secret_key,
keys.m_view_secret_key,
keys.m_account_address.m_spend_public_key,
keys.m_account_address.m_view_public_key,
//
mnemonic_string
};
return true;
}
//
bool monero_wallet_utils::decoded_seed(
std::string mnemonic_string,
std::string mnemonic_language,
MnemonicDecodedSeed_RetVals &retVals
) {
retVals = {};
//
// sanitize inputs
if (mnemonic_string.empty()) {
retVals.did_error = true;
retVals.err_string = "Please enter a valid seed";
//
return false;
}
boost::algorithm::to_lower(mnemonic_string); // critical
// TODO: strip wrapping whitespace? anything else?
//
std::stringstream stream(mnemonic_string); // to count words…
unsigned long word_count = std::distance(std::istream_iterator<std::string>(stream), std::istream_iterator<std::string>());
// unsigned long word_count = boost::range::distance(boost::algorithm::make_split_iterator(mnemonic_string, boost::algorithm::is_space())); // TODO: get this workin
//
crypto::secret_key sec_seed;
std::string sec_seed_string; // TODO/FIXME: needed this for shared ref outside of if branch below… not intending extra default constructor call but not sure how to get around it yet
bool from_legacy16B_lw_seed = false;
if (word_count == crypto::ElectrumWords::stable_32B_seed_mnemonic_word_count) {
from_legacy16B_lw_seed = false; // to be clear
bool r = crypto::ElectrumWords::words_to_bytes(mnemonic_string, sec_seed, mnemonic_language);
if (!r) {
retVals.did_error = true;
retVals.err_string = "Invalid 25-word mnemonic";
//
return false;
}
sec_seed_string = string_tools::pod_to_hex(sec_seed);
} else if (word_count == crypto::ElectrumWords::legacy_16B_seed_mnemonic_word_count) {
from_legacy16B_lw_seed = true;
crypto::legacy16B_secret_key legacy16B_sec_seed;
bool r = crypto::ElectrumWords::words_to_bytes(mnemonic_string, legacy16B_sec_seed, mnemonic_language); // special 16 byte function
if (!r) {
retVals.did_error = true;
retVals.err_string = "Invalid 13-word mnemonic";
//
return false;
}
crypto::coerce_valid_sec_key_from(legacy16B_sec_seed, sec_seed);
sec_seed_string = string_tools::pod_to_hex(legacy16B_sec_seed); // <- NOTE: we are returning the _LEGACY_ seed as the string… this is important so we don't lose the fact it was 16B/13-word originally!
} else {
retVals.did_error = true;
retVals.err_string = "Please enter a 25- or 13-word secret mnemonic.";
//
return false;
}
retVals.optl__sec_seed = sec_seed;
retVals.optl__sec_seed_string = sec_seed_string;
retVals.optl__mnemonic_string = mnemonic_string;
retVals.from_legacy16B_lw_seed = from_legacy16B_lw_seed;
//
return true;
}
//
bool monero_wallet_utils::wallet_with(
std::string mnemonic_string,
std::string mnemonic_language,
WalletDescriptionRetVals &retVals,
bool isTestnet
) {
retVals = {};
//
MnemonicDecodedSeed_RetVals decodedSeed_retVals;
bool r = decoded_seed(std::move(mnemonic_string), std::move(mnemonic_language), decodedSeed_retVals);
if (!r) {
retVals.did_error = true;
retVals.err_string = *decodedSeed_retVals.err_string; // TODO: assert?
return false;
}
cryptonote::account_base account{}; // this initializes the wallet and should call the default constructor
account.generate(
*decodedSeed_retVals.optl__sec_seed, // is this an extra copy? maybe have consumer pass ref as arg instead
true/*recover*/,
false/*two_random*/,
decodedSeed_retVals.from_legacy16B_lw_seed // assumed set if r
);
const cryptonote::account_keys& keys = account.get_keys();
retVals.optl__desc =
{
*decodedSeed_retVals.optl__sec_seed_string, // assumed non nil if r
//
account.get_public_address_str(isTestnet),
//
keys.m_spend_secret_key,
keys.m_view_secret_key,
keys.m_account_address.m_spend_public_key,
keys.m_account_address.m_view_public_key,
//
*decodedSeed_retVals.optl__mnemonic_string, // assumed non nil if r; copied for return
};
return true;
}
bool monero_wallet_utils::validate_wallet_components_with(
const WalletComponentsToValidate &inputs,
WalletComponentsValidationResults &outputs
)
{ // TODO: how can the err_strings be prepared for localization?
outputs = {};
bool r = false;
//
// Address
cryptonote::address_parse_info decoded_address_info;
r = cryptonote::get_account_address_from_str(
decoded_address_info,
inputs.isTestnet,
inputs.address_string
);
if (r == false) {
outputs.did_error = true;
outputs.err_string = "Invalid address";
//
return false;
}
//
// View key:
crypto::secret_key sec_viewKey;
r = string_tools::hex_to_pod(inputs.sec_viewKey_string, sec_viewKey);
if (r == false) {
outputs.did_error = true;
outputs.err_string = "Invalid view key";
//
return false;
}
// Validate pub key derived from sec view key matches decoded_address-cached pub key
crypto::public_key expected_pub_viewKey;
r = crypto::secret_key_to_public_key(sec_viewKey, expected_pub_viewKey);
if (r == false) {
outputs.did_error = true;
outputs.err_string = "Invalid view key";
//
return false;
}
if (decoded_address_info.address.m_view_public_key != expected_pub_viewKey) {
outputs.did_error = true;
outputs.err_string = "View key does not match address";
//
return false;
}
//
// View-only vs spend-key/seed
outputs.isInViewOnlyMode = true; // setting the ground state
//
crypto::secret_key sec_spendKey; // may be initialized
if (inputs.optl__sec_spendKey_string) {
// First check if spend key content actually exists before passing to valid_sec_key_from - so that a spend key decode error can be treated as a failure instead of detecting empty spend keys too
if ((*inputs.optl__sec_spendKey_string).empty() == false) {
r = string_tools::hex_to_pod(*inputs.optl__sec_spendKey_string, sec_spendKey);
if (r == false) { // this is an actual parse error exit condition
outputs.did_error = true;
outputs.err_string = "Invalid spend key";
//
return false;
}
// Validate pub key derived from sec spend key matches decoded_address_info-cached pub key
crypto::public_key expected_pub_spendKey;
r = crypto::secret_key_to_public_key(sec_spendKey, expected_pub_spendKey);
if (r == false) {
outputs.did_error = true;
outputs.err_string = "Invalid spend key";
//
return false;
}
if (decoded_address_info.address.m_spend_public_key != expected_pub_spendKey) {
outputs.did_error = true;
outputs.err_string = "Spend key does not match address";
//
return false;
}
outputs.isInViewOnlyMode = false;
}
}
if (inputs.optl__sec_seed_string) {
if ((*inputs.optl__sec_seed_string).empty() == false) {
unsigned long sec_seed_string_length = (*inputs.optl__sec_seed_string).length();
crypto::secret_key sec_seed;
bool from_legacy16B_lw_seed = false;
if (sec_seed_string_length == crypto::sec_seed_hex_string_length) { // normal seed
from_legacy16B_lw_seed = false; // to be clear
bool r = string_tools::hex_to_pod((*inputs.optl__sec_seed_string), sec_seed);
if (!r) {
outputs.did_error = true;
outputs.err_string = "Invalid seed";
//
return false;
}
} else if (sec_seed_string_length == crypto::legacy16B__sec_seed_hex_string_length) {
from_legacy16B_lw_seed = true;
crypto::legacy16B_secret_key legacy16B_sec_seed;
bool r = string_tools::hex_to_pod((*inputs.optl__sec_seed_string), legacy16B_sec_seed);
if (!r) {
outputs.did_error = true;
outputs.err_string = "Invalid seed";
//
return false;
}
crypto::coerce_valid_sec_key_from(legacy16B_sec_seed, sec_seed);
}
cryptonote::account_base expected_account{}; // this initializes the wallet and should call the default constructor
expected_account.generate(sec_seed, true/*recover*/, false/*two_random*/, from_legacy16B_lw_seed);
const cryptonote::account_keys& expected_account_keys = expected_account.get_keys();
// TODO: assert sec_spendKey initialized?
if (expected_account_keys.m_view_secret_key != sec_viewKey) {
outputs.did_error = true;
outputs.err_string = "Private view key does not match generated key";
//
return false;
}
if (expected_account_keys.m_spend_secret_key != sec_spendKey) {
outputs.did_error = true;
outputs.err_string = "Private spend key does not match generated key";
//
return false;
}
if (expected_account_keys.m_account_address.m_view_public_key != decoded_address_info.address.m_view_public_key) {
outputs.did_error = true;
outputs.err_string = "Public view key does not match generated key";
//
return false;
}
if (expected_account_keys.m_account_address.m_spend_public_key != decoded_address_info.address.m_spend_public_key) {
outputs.did_error = true;
outputs.err_string = "Public spend key does not match generated key";
//
return false;
}
//
outputs.isInViewOnlyMode = false; // TODO: should this ensure that sec_spendKey is not nil? spendKey should always be available if the seed is…
}
}
outputs.pub_viewKey_string = string_tools::pod_to_hex(decoded_address_info.address.m_view_public_key);
outputs.pub_spendKey_string = string_tools::pod_to_hex(decoded_address_info.address.m_spend_public_key);
outputs.isValid = true;
//
return true;
}

@ -0,0 +1,116 @@
//
// monero_wallet_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_wallet_utils_hpp
#define monero_wallet_utils_hpp
#include <boost/optional.hpp>
#include "crypto.h"
#include "cryptonote_basic.h"
#include "cryptonote_basic_impl.h"
#include "electrum-words.h"
#include "mnemonics/singleton.h"
#include "mnemonics/english.h"
//
using namespace tools;
#include "tools__ret_vals.hpp"
//
namespace monero_wallet_utils
{
//
// Accounts
struct MnemonicDecodedSeed_RetVals: RetVals_base
{
boost::optional<crypto::secret_key> optl__sec_seed = boost::none;
boost::optional<std::string> optl__sec_seed_string = boost::none;
boost::optional<std::string> optl__mnemonic_string = boost::none;
bool from_legacy16B_lw_seed = false;
};
bool decoded_seed(
std::string mnemonic_string,
std::string mnemonic_language_string,
//
MnemonicDecodedSeed_RetVals &retVals
);
//
// Convenience functions - Wallets
struct WalletDescription
{
std::string sec_seed_string; // as string bc it might by legacy 16B style aside from crypto::secret_key
//
std::string address_string;
//
crypto::secret_key sec_spendKey;
crypto::secret_key sec_viewKey;
crypto::public_key pub_spendKey;
crypto::public_key pub_viewKey;
//
std::string mnemonic_string; // mnemonic_language is not returned because it must be provided to all functions which can return a WalletDescription
};
struct WalletDescriptionRetVals: RetVals_base
{
boost::optional<WalletDescription> optl__desc = boost::none;
};
bool new_wallet(
std::string mnemonic_language,
WalletDescriptionRetVals &retVals,
bool isTestnet = false
);
bool wallet_with(
std::string mnemonic_string,
std::string mnemonic_language,
WalletDescriptionRetVals &retVals,
bool isTestnet = false
);
//
struct WalletComponentsToValidate
{
std::string address_string; // Required
std::string sec_viewKey_string; // Required
const std::string *optl__sec_spendKey_string;
const std::string *optl__sec_seed_string;
bool isTestnet;
};
struct WalletComponentsValidationResults: RetVals_base
{
bool isValid; // this will naturally remain false if did_error=true
std::string pub_spendKey_string;
std::string pub_viewKey_string;
bool isInViewOnlyMode; // !sec_seed && !sec_spendKey
};
bool validate_wallet_components_with( // returns !did_error
const WalletComponentsToValidate &inputs,
WalletComponentsValidationResults &outputs
);
}
#endif /* monero_wallet_utils_hpp */

@ -0,0 +1,9 @@
//
// tools__ret_vals.cpp
// Copyright © 2018 MyMonero. All rights reserved.
//
//
#include "tools__ret_vals.hpp"
//

@ -0,0 +1,48 @@
//
// tools__ret_vals.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 tools__ret_vals_hpp
#define tools__ret_vals_hpp
//
#include <string>
#include <boost/optional.hpp>
//
namespace tools
{
struct RetVals_base
{
bool did_error = false;
boost::optional<std::string> err_string = boost::none;
//
// derive *_RetVals structs from this type and add your own members
};
}
#endif /* tools__ret_vals_hpp */

@ -0,0 +1,54 @@
//
// test_all.cpp
// MyMonero
//
// 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.
//
//
// Test module setup
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE LibMoneroTests
#include <boost/test/unit_test.hpp> // last
//
// Includes & namespaces
#include <iostream>
#include <iterator>
#include <sstream>
using namespace std;
// using namespace boost;
//
// Shared code
//
// Test suites
// #include "../src/monero_address_utils.hpp"
BOOST_AUTO_TEST_CASE(mockedPlainStringDoc_insert)
{
BOOST_REQUIRE(true);
std::cout << "Testing...." << std::endl;
}
Loading…
Cancel
Save