mirror of https://github.com/oxen-io/oxen-core.git
Merge commit '8f9c381' into LokiMergeUpstream
This commit is contained in:
commit
997c0a9991
|
@ -204,6 +204,9 @@ set(PER_BLOCK_CHECKPOINT 1)
|
|||
|
||||
if(PER_BLOCK_CHECKPOINT)
|
||||
add_definitions("-DPER_BLOCK_CHECKPOINT")
|
||||
set(Blocks "blocks")
|
||||
else()
|
||||
set(Blocks "")
|
||||
endif()
|
||||
|
||||
list(INSERT CMAKE_MODULE_PATH 0
|
||||
|
@ -679,12 +682,10 @@ else()
|
|||
add_linker_flag_if_supported(-Wl,-z,noexecstack noexecstack_SUPPORTED)
|
||||
if (noexecstack_SUPPORTED)
|
||||
set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecstack")
|
||||
set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecstack)
|
||||
endif()
|
||||
add_linker_flag_if_supported(-Wl,-z,noexecheap noexecheap_SUPPORTED)
|
||||
if (noexecheap_SUPPORTED)
|
||||
set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecheap")
|
||||
set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecheap)
|
||||
endif()
|
||||
|
||||
# some windows linker bits
|
||||
|
|
|
@ -147,6 +147,8 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
|
|||
CONF_SWAPSIZE=1024
|
||||
sudo /etc/init.d/dphys-swapfile start
|
||||
```
|
||||
* If using an external hard disk without an external power supply, ensure it gets enough power to avoid hardware issues when syncing, by adding the line "max_usb_current=1" to /boot/config.txt
|
||||
|
||||
* Clone loki and checkout most recent release version:
|
||||
```
|
||||
git clone https://github.com/loki-project/loki.git
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace rdln
|
|||
|
||||
private:
|
||||
std::streambuf* m_cout_buf;
|
||||
size_t m_prompt_length;
|
||||
static std::vector<std::string>& completion_commands();
|
||||
};
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ std::vector<std::string>& rdln::readline_buffer::completion_commands()
|
|||
}
|
||||
|
||||
rdln::readline_buffer::readline_buffer()
|
||||
: std::stringbuf(), m_cout_buf(NULL)
|
||||
: std::stringbuf(), m_cout_buf(NULL), m_prompt_length(0)
|
||||
{
|
||||
current = this;
|
||||
}
|
||||
|
@ -86,8 +86,11 @@ void rdln::readline_buffer::set_prompt(const std::string& prompt)
|
|||
if(m_cout_buf == NULL)
|
||||
return;
|
||||
boost::lock_guard<boost::mutex> lock(sync_mutex);
|
||||
rl_set_prompt(std::string(m_prompt_length, ' ').c_str());
|
||||
rl_redisplay();
|
||||
rl_set_prompt(prompt.c_str());
|
||||
rl_redisplay();
|
||||
m_prompt_length = prompt.size();
|
||||
}
|
||||
|
||||
void rdln::readline_buffer::add_completion(const std::string& command)
|
||||
|
|
|
@ -27,20 +27,6 @@
|
|||
# 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.
|
||||
|
||||
set(blocksdat "")
|
||||
if(PER_BLOCK_CHECKPOINT)
|
||||
if(APPLE AND DEPENDS)
|
||||
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
|
||||
elseif(APPLE AND NOT DEPENDS)
|
||||
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
|
||||
elseif(LINUX_32)
|
||||
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
|
||||
else()
|
||||
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
|
||||
endif()
|
||||
set(blocksdat "blocksdat.o")
|
||||
endif()
|
||||
|
||||
set(blockchain_import_sources
|
||||
blockchain_import.cpp
|
||||
bootstrap_file.cpp
|
||||
|
@ -118,8 +104,7 @@ loki_private_headers(blockchain_depth
|
|||
|
||||
loki_add_executable(blockchain_import
|
||||
${blockchain_import_sources}
|
||||
${blockchain_import_private_headers}
|
||||
${blocksdat})
|
||||
${blockchain_import_private_headers})
|
||||
|
||||
target_link_libraries(blockchain_import
|
||||
PRIVATE
|
||||
|
@ -131,7 +116,8 @@ target_link_libraries(blockchain_import
|
|||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${EXTRA_LIBRARIES})
|
||||
${EXTRA_LIBRARIES}
|
||||
${Blocks})
|
||||
|
||||
if(ARCH_WIDTH)
|
||||
target_compile_definitions(blockchain_import
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "misc_log_ex.h"
|
||||
#include "bootstrap_file.h"
|
||||
#include "bootstrap_serialization.h"
|
||||
#include "blocks/blocks.h"
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "serialization/binary_utils.h" // dump_binary(), parse_binary()
|
||||
#include "serialization/json_utils.h" // dump_json()
|
||||
|
@ -759,7 +760,12 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
|
||||
core.disable_dns_checkpoints(true);
|
||||
if (!core.init(vm, NULL))
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
const GetCheckpointsCallback& get_checkpoints = blocks::GetCheckpointsData;
|
||||
#else
|
||||
const GetCheckpointsCallback& get_checkpoints = nullptr;
|
||||
#endif
|
||||
if (!core.init(vm, nullptr, nullptr, get_checkpoints))
|
||||
{
|
||||
std::cerr << "Failed to initialize core" << ENDL;
|
||||
return 1;
|
||||
|
|
|
@ -26,20 +26,23 @@
|
|||
# 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.
|
||||
|
||||
if(APPLE)
|
||||
add_library(blocks STATIC blockexports.c)
|
||||
set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C)
|
||||
else()
|
||||
if(LINUX_32)
|
||||
add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat)
|
||||
add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat)
|
||||
add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat)
|
||||
else()
|
||||
add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat)
|
||||
add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat)
|
||||
add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat)
|
||||
endif()
|
||||
add_library(blocks STATIC blocks.o testnet_blocks.o stagenet_blocks.o blockexports.c)
|
||||
set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C)
|
||||
endif()
|
||||
set(GENERATED_SOURCES "")
|
||||
|
||||
foreach(BLOB_NAME checkpoints testnet_blocks stagenet_blocks)
|
||||
set(OUTPUT_C_SOURCE "generated_${BLOB_NAME}.c")
|
||||
list(APPEND GENERATED_SOURCES ${OUTPUT_C_SOURCE})
|
||||
set(INPUT_DAT_FILE "${BLOB_NAME}.dat")
|
||||
add_custom_command(
|
||||
OUTPUT ${OUTPUT_C_SOURCE}
|
||||
MAIN_DEPENDENCY ${INPUT_DAT_FILE}
|
||||
COMMAND
|
||||
cd ${CMAKE_CURRENT_BINARY_DIR} &&
|
||||
echo "'#include\t<stddef.h>'" > ${OUTPUT_C_SOURCE} &&
|
||||
echo "'const\tunsigned\tchar\t${BLOB_NAME}[]={'" >> ${OUTPUT_C_SOURCE} &&
|
||||
od -v -An -tu1 ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_DAT_FILE} | sed -e "'s/[0-9]\\{1,\\}/&,/g'" -e "'$$s/.$$//'" >> ${OUTPUT_C_SOURCE} &&
|
||||
echo "'};'" >> ${OUTPUT_C_SOURCE} &&
|
||||
echo "'const\tsize_t\t${BLOB_NAME}_len\t=\tsizeof(${BLOB_NAME});'" >> ${OUTPUT_C_SOURCE}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
add_library(blocks STATIC blocks.cpp ${GENERATED_SOURCES})
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
#include <stddef.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <mach-o/getsect.h>
|
||||
#ifdef BUILD_SHARED_LIBS
|
||||
#if !defined(__LP64__)
|
||||
const struct mach_header _mh_execute_header;
|
||||
#else
|
||||
const struct mach_header_64 _mh_execute_header;
|
||||
#endif
|
||||
#else
|
||||
#if !defined(__LP64__)
|
||||
extern const struct mach_header _mh_execute_header;
|
||||
#else
|
||||
extern const struct mach_header_64 _mh_execute_header;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const unsigned char *get_blocks_dat_start(int testnet, int stagenet)
|
||||
{
|
||||
size_t size;
|
||||
if (testnet)
|
||||
return getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size);
|
||||
else if (stagenet)
|
||||
return getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size);
|
||||
else
|
||||
return getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size);
|
||||
}
|
||||
|
||||
size_t get_blocks_dat_size(int testnet, int stagenet)
|
||||
{
|
||||
size_t size;
|
||||
if (testnet)
|
||||
getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size);
|
||||
else if (stagenet)
|
||||
getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size);
|
||||
else
|
||||
getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size);
|
||||
return size;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
#define _binary_blocks_start binary_blocks_dat_start
|
||||
#define _binary_blocks_end binary_blocks_dat_end
|
||||
#define _binary_testnet_blocks_start binary_testnet_blocks_dat_start
|
||||
#define _binary_testnet_blocks_end binary_testnet_blocks_dat_end
|
||||
#define _binary_stagenet_blocks_start binary_stagenet_blocks_dat_start
|
||||
#define _binary_stagenet_blocks_end binary_stagenet_blocks_dat_end
|
||||
#else
|
||||
#define _binary_blocks_start _binary_blocks_dat_start
|
||||
#define _binary_blocks_end _binary_blocks_dat_end
|
||||
#define _binary_testnet_blocks_start _binary_testnet_blocks_dat_start
|
||||
#define _binary_testnet_blocks_end _binary_testnet_blocks_dat_end
|
||||
#define _binary_stagenet_blocks_start _binary_stagenet_blocks_dat_start
|
||||
#define _binary_stagenet_blocks_end _binary_stagenet_blocks_dat_end
|
||||
#endif
|
||||
|
||||
extern const unsigned char _binary_blocks_start[];
|
||||
extern const unsigned char _binary_blocks_end[];
|
||||
extern const unsigned char _binary_testnet_blocks_start[];
|
||||
extern const unsigned char _binary_testnet_blocks_end[];
|
||||
extern const unsigned char _binary_stagenet_blocks_start[];
|
||||
extern const unsigned char _binary_stagenet_blocks_end[];
|
||||
|
||||
const unsigned char *get_blocks_dat_start(int testnet, int stagenet)
|
||||
{
|
||||
if (testnet)
|
||||
return _binary_testnet_blocks_start;
|
||||
else if (stagenet)
|
||||
return _binary_stagenet_blocks_start;
|
||||
else
|
||||
return _binary_blocks_start;
|
||||
}
|
||||
|
||||
size_t get_blocks_dat_size(int testnet, int stagenet)
|
||||
{
|
||||
if (testnet)
|
||||
return (size_t) (_binary_testnet_blocks_end - _binary_testnet_blocks_start);
|
||||
else if (stagenet)
|
||||
return (size_t) (_binary_stagenet_blocks_end - _binary_stagenet_blocks_start);
|
||||
else
|
||||
return (size_t) (_binary_blocks_end - _binary_blocks_start);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
#include "blocks.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
extern const unsigned char checkpoints[];
|
||||
extern const size_t checkpoints_len;
|
||||
extern const unsigned char stagenet_blocks[];
|
||||
extern const size_t stagenet_blocks_len;
|
||||
extern const unsigned char testnet_blocks[];
|
||||
extern const size_t testnet_blocks_len;
|
||||
|
||||
namespace blocks
|
||||
{
|
||||
|
||||
const std::unordered_map<cryptonote::network_type, const epee::span<const unsigned char>, std::hash<size_t>> CheckpointsByNetwork = {
|
||||
{cryptonote::network_type::MAINNET, {checkpoints, checkpoints_len}},
|
||||
{cryptonote::network_type::STAGENET, {stagenet_blocks, stagenet_blocks_len}},
|
||||
{cryptonote::network_type::TESTNET, {testnet_blocks, testnet_blocks_len}}
|
||||
};
|
||||
|
||||
const epee::span<const unsigned char> GetCheckpointsData(cryptonote::network_type network)
|
||||
{
|
||||
const auto it = CheckpointsByNetwork.find(network);
|
||||
if (it != CheckpointsByNetwork.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +1,12 @@
|
|||
#ifndef SRC_BLOCKS_BLOCKS_H_
|
||||
#define SRC_BLOCKS_BLOCKS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "cryptonote_config.h"
|
||||
#include "span.h"
|
||||
|
||||
const unsigned char *get_blocks_dat_start(int testnet, int stagenet);
|
||||
size_t get_blocks_dat_size(int testnet, int stagenet);
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace blocks
|
||||
{
|
||||
const epee::span<const unsigned char> GetCheckpointsData(cryptonote::network_type network);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* SRC_BLOCKS_BLOCKS_H_ */
|
||||
|
|
|
@ -309,10 +309,19 @@ namespace tools
|
|||
StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));
|
||||
|
||||
// Test for the specific product.
|
||||
if ( osvi.dwMajorVersion == 10 )
|
||||
{
|
||||
if ( osvi.dwMinorVersion == 0 )
|
||||
{
|
||||
if( osvi.wProductType == VER_NT_WORKSTATION )
|
||||
StringCchCat(pszOS, BUFSIZE, TEXT("Windows 10 "));
|
||||
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2016 " ));
|
||||
}
|
||||
}
|
||||
|
||||
if ( osvi.dwMajorVersion == 6 )
|
||||
{
|
||||
if( osvi.dwMinorVersion == 0 )
|
||||
if ( osvi.dwMinorVersion == 0 )
|
||||
{
|
||||
if( osvi.wProductType == VER_NT_WORKSTATION )
|
||||
StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
|
||||
|
@ -326,6 +335,20 @@ namespace tools
|
|||
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 " ));
|
||||
}
|
||||
|
||||
if ( osvi.dwMinorVersion == 2 )
|
||||
{
|
||||
if( osvi.wProductType == VER_NT_WORKSTATION )
|
||||
StringCchCat(pszOS, BUFSIZE, TEXT("Windows 8 "));
|
||||
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2012 " ));
|
||||
}
|
||||
|
||||
if ( osvi.dwMinorVersion == 3 )
|
||||
{
|
||||
if( osvi.wProductType == VER_NT_WORKSTATION )
|
||||
StringCchCat(pszOS, BUFSIZE, TEXT("Windows 8.1 "));
|
||||
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2012 R2 " ));
|
||||
}
|
||||
|
||||
pGPI = (PGPI) GetProcAddress(
|
||||
GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"GetProductInfo");
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <stdexcept>
|
||||
|
|
|
@ -48,12 +48,6 @@ set(cryptonote_core_private_headers
|
|||
tx_pool.h
|
||||
cryptonote_tx_utils.h)
|
||||
|
||||
if(PER_BLOCK_CHECKPOINT)
|
||||
set(Blocks "blocks")
|
||||
else()
|
||||
set(Blocks "")
|
||||
endif()
|
||||
|
||||
loki_private_headers(cryptonote_core
|
||||
${cryptonote_core_private_headers})
|
||||
loki_add_library(cryptonote_core
|
||||
|
@ -76,5 +70,4 @@ target_link_libraries(cryptonote_core
|
|||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
PRIVATE
|
||||
${Blocks}
|
||||
${EXTRA_LIBRARIES})
|
||||
|
|
|
@ -56,9 +56,6 @@
|
|||
#include "ringct/rctSigs.h"
|
||||
#include "common/perf_timer.h"
|
||||
#include "common/notify.h"
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
#include "blocks/blocks.h"
|
||||
#endif
|
||||
#include "service_node_deregister.h"
|
||||
#include "service_node_list.h"
|
||||
|
||||
|
@ -303,7 +300,7 @@ uint64_t Blockchain::get_current_blockchain_height() const
|
|||
//------------------------------------------------------------------
|
||||
//FIXME: possibly move this into the constructor, to avoid accidentally
|
||||
// dereferencing a null BlockchainDB pointer
|
||||
bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty)
|
||||
bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty, const GetCheckpointsCallback& get_checkpoints/* = nullptr*/)
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
|
||||
|
@ -406,7 +403,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
|
|||
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
if (m_nettype != FAKECHAIN)
|
||||
load_compiled_in_block_hashes();
|
||||
load_compiled_in_block_hashes(get_checkpoints);
|
||||
#endif
|
||||
|
||||
MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block());
|
||||
|
@ -4546,19 +4543,21 @@ void Blockchain::cancel()
|
|||
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
static const char expected_block_hashes_hash[] = "63b6445540c13f74d73fd753906e80bb84328c57b5a5a90c73353ed8405e7043";
|
||||
void Blockchain::load_compiled_in_block_hashes()
|
||||
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
|
||||
{
|
||||
const bool testnet = m_nettype == TESTNET;
|
||||
const bool stagenet = m_nettype == STAGENET;
|
||||
if (m_fast_sync && get_blocks_dat_start(testnet, stagenet) != nullptr && get_blocks_dat_size(testnet, stagenet) > 0)
|
||||
if (get_checkpoints == nullptr || !m_fast_sync)
|
||||
{
|
||||
MINFO("Loading precomputed blocks (" << get_blocks_dat_size(testnet, stagenet) << " bytes)");
|
||||
|
||||
return;
|
||||
}
|
||||
const epee::span<const unsigned char> &checkpoints = get_checkpoints(m_nettype);
|
||||
if (!checkpoints.empty())
|
||||
{
|
||||
MINFO("Loading precomputed blocks (" << checkpoints.size() << " bytes)");
|
||||
if (m_nettype == MAINNET)
|
||||
{
|
||||
// first check hash
|
||||
crypto::hash hash;
|
||||
if (!tools::sha256sum(get_blocks_dat_start(testnet, stagenet), get_blocks_dat_size(testnet, stagenet), hash))
|
||||
if (!tools::sha256sum(checkpoints.data(), checkpoints.size(), hash))
|
||||
{
|
||||
MERROR("Failed to hash precomputed blocks data");
|
||||
return;
|
||||
|
@ -4578,9 +4577,9 @@ void Blockchain::load_compiled_in_block_hashes()
|
|||
}
|
||||
}
|
||||
|
||||
if (get_blocks_dat_size(testnet, stagenet) > 4)
|
||||
if (checkpoints.size() > 4)
|
||||
{
|
||||
const unsigned char *p = get_blocks_dat_start(testnet, stagenet);
|
||||
const unsigned char *p = checkpoints.data();
|
||||
const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24);
|
||||
if (nblocks > (std::numeric_limits<uint32_t>::max() - 4) / sizeof(hash))
|
||||
{
|
||||
|
@ -4588,7 +4587,7 @@ void Blockchain::load_compiled_in_block_hashes()
|
|||
return;
|
||||
}
|
||||
const size_t size_needed = 4 + nblocks * sizeof(crypto::hash);
|
||||
if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(testnet, stagenet) >= size_needed)
|
||||
if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && checkpoints.size() >= size_needed)
|
||||
{
|
||||
p += sizeof(uint32_t);
|
||||
m_blocks_hash_of_hashes.reserve(nblocks);
|
||||
|
|
|
@ -38,9 +38,11 @@
|
|||
#include <boost/multi_index/hashed_index.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "span.h"
|
||||
#include "syncobj.h"
|
||||
#include "string_tools.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
|
@ -75,6 +77,15 @@ namespace cryptonote
|
|||
db_nosync //!< Leave syncing up to the backing db (safest, but slowest because of disk I/O)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Callback routine that returns checkpoints data for specific network type
|
||||
*
|
||||
* @param network network type
|
||||
*
|
||||
* @return checkpoints data, empty span if there ain't any checkpoints for specific network type
|
||||
*/
|
||||
typedef std::function<const epee::span<const unsigned char>(cryptonote::network_type network)> GetCheckpointsCallback;
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
@ -151,10 +162,11 @@ namespace cryptonote
|
|||
* @param offline true if running offline, else false
|
||||
* @param test_options test parameters
|
||||
* @param fixed_difficulty fixed difficulty for testing purposes; 0 means disabled
|
||||
* @param get_checkpoints if set, will be called to get checkpoints data
|
||||
*
|
||||
* @return true on success, false if any initialization steps fail
|
||||
*/
|
||||
bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0);
|
||||
bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0, const GetCheckpointsCallback& get_checkpoints = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Initialize the Blockchain state
|
||||
|
@ -1426,8 +1438,10 @@ namespace cryptonote
|
|||
* A (possibly empty) set of block hashes can be compiled into the
|
||||
* monero daemon binary. This function loads those hashes into
|
||||
* a useful state.
|
||||
*
|
||||
* @param get_checkpoints if set, will be called to get checkpoints data
|
||||
*/
|
||||
void load_compiled_in_block_hashes();
|
||||
void load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints);
|
||||
|
||||
/**
|
||||
* @brief expands v2 transaction data from blockchain
|
||||
|
|
|
@ -404,7 +404,7 @@ namespace cryptonote
|
|||
return m_blockchain_storage.get_alternative_blocks_count();
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options)
|
||||
bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options, const GetCheckpointsCallback& get_checkpoints/* = nullptr */)
|
||||
{
|
||||
start_time = std::time(nullptr);
|
||||
|
||||
|
@ -593,7 +593,7 @@ namespace cryptonote
|
|||
BlockchainDB *initialized_db = db.release();
|
||||
m_service_node_list.set_db_pointer(initialized_db);
|
||||
m_service_node_list.register_hooks(m_quorum_cop);
|
||||
r = m_blockchain_storage.init(initialized_db, m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty);
|
||||
r = m_blockchain_storage.init(initialized_db, m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty, get_checkpoints);
|
||||
|
||||
r = m_mempool.init(max_txpool_weight);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
|
||||
|
|
|
@ -260,10 +260,11 @@ namespace cryptonote
|
|||
* @param vm command line parameters
|
||||
* @param config_subdir subdirectory for config storage
|
||||
* @param test_options configuration options for testing
|
||||
* @param get_checkpoints if set, will be called to get checkpoints data, must return checkpoints data pointer and size or nullptr if there ain't any checkpoints for specific network type
|
||||
*
|
||||
* @return false if one of the init steps fails, otherwise true
|
||||
*/
|
||||
bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL);
|
||||
bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL, const GetCheckpointsCallback& get_checkpoints = nullptr);
|
||||
|
||||
/**
|
||||
* @copydoc Blockchain::reset_and_set_genesis_block
|
||||
|
|
|
@ -27,20 +27,6 @@
|
|||
# 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.
|
||||
|
||||
set(blocksdat "")
|
||||
if(PER_BLOCK_CHECKPOINT)
|
||||
if(APPLE AND DEPENDS)
|
||||
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
|
||||
elseif(APPLE AND NOT DEPENDS)
|
||||
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
|
||||
elseif(LINUX_32)
|
||||
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
|
||||
else()
|
||||
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
|
||||
endif()
|
||||
set(blocksdat "blocksdat.o")
|
||||
endif()
|
||||
|
||||
set(daemon_sources
|
||||
command_parser_executor.cpp
|
||||
command_server.cpp
|
||||
|
@ -82,9 +68,7 @@ loki_private_headers(daemon
|
|||
loki_add_executable(daemon
|
||||
${daemon_sources}
|
||||
${daemon_headers}
|
||||
${daemon_private_headers}
|
||||
${blocksdat}
|
||||
)
|
||||
${daemon_private_headers})
|
||||
target_link_libraries(daemon
|
||||
PRIVATE
|
||||
rpc
|
||||
|
@ -107,7 +91,8 @@ target_link_libraries(daemon
|
|||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${ZMQ_LIB}
|
||||
${GNU_READLINE_LIBRARY}
|
||||
${EXTRA_LIBRARIES})
|
||||
${EXTRA_LIBRARIES}
|
||||
${Blocks})
|
||||
set_property(TARGET daemon
|
||||
PROPERTY
|
||||
OUTPUT_NAME "lokid")
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "blocks/blocks.h"
|
||||
#include "cryptonote_core/cryptonote_core.h"
|
||||
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
|
||||
#include "misc_log_ex.h"
|
||||
|
@ -86,7 +87,12 @@ public:
|
|||
//initialize core here
|
||||
MGINFO("Initializing core...");
|
||||
std::string config_subdir = get_config_subdir();
|
||||
if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str()))
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
const cryptonote::GetCheckpointsCallback& get_checkpoints = blocks::GetCheckpointsData;
|
||||
#else
|
||||
const cryptonote::GetCheckpointsCallback& get_checkpoints = nullptr;
|
||||
#endif
|
||||
if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str(), nullptr, get_checkpoints))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -59,12 +59,6 @@ endif()
|
|||
set(device_private_headers)
|
||||
|
||||
|
||||
if(PER_BLOCK_CHECKPOINT)
|
||||
set(Blocks "blocks")
|
||||
else()
|
||||
set(Blocks "")
|
||||
endif()
|
||||
|
||||
loki_private_headers(device
|
||||
${device_private_headers})
|
||||
|
||||
|
@ -80,5 +74,4 @@ target_link_libraries(device
|
|||
ringct_basic
|
||||
${OPENSSL_CRYPTO_LIBRARIES}
|
||||
PRIVATE
|
||||
${Blocks}
|
||||
${EXTRA_LIBRARIES})
|
||||
|
|
|
@ -4726,8 +4726,6 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
|||
if (!try_connect_to_daemon())
|
||||
return true;
|
||||
|
||||
SCOPED_WALLET_UNLOCK();
|
||||
|
||||
std::vector<std::string> local_args = args_;
|
||||
|
||||
std::set<uint32_t> subaddr_indices;
|
||||
|
@ -4905,6 +4903,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
|||
}
|
||||
}
|
||||
|
||||
SCOPED_WALLET_UNLOCK();
|
||||
|
||||
try
|
||||
{
|
||||
// figure out what tx will be necessary
|
||||
|
@ -5523,6 +5523,13 @@ bool simple_wallet::register_service_node(const std::vector<std::string> &args_)
|
|||
}
|
||||
|
||||
stop();
|
||||
m_idle_run.store(false, std::memory_order_relaxed);
|
||||
m_wallet->stop();
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(m_idle_mutex);
|
||||
m_idle_cond.notify_one();
|
||||
}
|
||||
|
||||
m_idle_thread.join();
|
||||
#ifndef WIN32
|
||||
success_msg_writer(true /*color*/) << tr("Successfully entered autostaking mode, this wallet is moving into the background to automatically renew your service node every period.");
|
||||
|
@ -6008,7 +6015,13 @@ bool simple_wallet::stake(const std::vector<std::string> &args_)
|
|||
success_msg_writer(false/*color*/) << "\n";
|
||||
}
|
||||
|
||||
stop();
|
||||
m_idle_run.store(false, std::memory_order_relaxed);
|
||||
m_wallet->stop();
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(m_idle_mutex);
|
||||
m_idle_cond.notify_one();
|
||||
}
|
||||
|
||||
m_idle_thread.join();
|
||||
#ifndef WIN32
|
||||
success_msg_writer() << tr("Entering autostaking mode, forking to background...");
|
||||
|
@ -8035,12 +8048,6 @@ bool simple_wallet::run()
|
|||
void simple_wallet::stop()
|
||||
{
|
||||
m_cmd_binder.stop_handling();
|
||||
|
||||
m_idle_run.store(false, std::memory_order_relaxed);
|
||||
m_wallet->stop();
|
||||
// make the background refresh thread quit
|
||||
boost::unique_lock<boost::mutex> lock(m_idle_mutex);
|
||||
m_idle_cond.notify_one();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||
|
|
|
@ -5652,6 +5652,10 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
|
|||
ptx.construction_data = sd;
|
||||
|
||||
txs.push_back(ptx);
|
||||
|
||||
// add tx keys only to ptx
|
||||
txs.back().tx_key = tx_key;
|
||||
txs.back().additional_tx_keys = additional_tx_keys;
|
||||
}
|
||||
|
||||
// add key images
|
||||
|
@ -10595,7 +10599,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
|
|||
+ boost::lexical_cast<std::string>(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image));
|
||||
|
||||
THROW_WALLET_EXCEPTION_IF(!crypto::check_ring_signature((const crypto::hash&)key_image, key_image, pkeys, &signature),
|
||||
error::wallet_internal_error, "Signature check failed: input " + boost::lexical_cast<std::string>(n) + "/"
|
||||
error::signature_check_failed, boost::lexical_cast<std::string>(n) + "/"
|
||||
+ boost::lexical_cast<std::string>(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image)
|
||||
+ ", signature " + epee::string_tools::pod_to_hex(signature) + ", pubkey " + epee::string_tools::pod_to_hex(*pkeys[0]));
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ namespace tools
|
|||
// tx_parse_error
|
||||
// get_tx_pool_error
|
||||
// out_of_hashchain_bounds_error
|
||||
// signature_check_failed
|
||||
// transfer_error *
|
||||
// get_outs_general_error
|
||||
// not_enough_unlocked_money
|
||||
|
@ -422,6 +423,14 @@ namespace tools
|
|||
std::string to_string() const { return refresh_error::to_string(); }
|
||||
};
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
struct signature_check_failed : public wallet_logic_error
|
||||
{
|
||||
explicit signature_check_failed(std::string&& loc, const std::string& message)
|
||||
: wallet_logic_error(std::move(loc), "Signature check failed " + message)
|
||||
{
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
struct transfer_error : public wallet_logic_error
|
||||
{
|
||||
protected:
|
||||
|
|
|
@ -982,6 +982,8 @@ namespace tools
|
|||
for (auto &ptx: ptxs)
|
||||
{
|
||||
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
|
||||
if (req.get_tx_keys)
|
||||
res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
|
||||
}
|
||||
|
||||
if (req.export_raw)
|
||||
|
@ -995,6 +997,171 @@ namespace tools
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_describe_transfer(const wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
if (m_restricted)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DENIED;
|
||||
er.message = "Command unavailable in restricted mode.";
|
||||
return false;
|
||||
}
|
||||
if (m_wallet->key_on_device())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "command not supported by HW wallet";
|
||||
return false;
|
||||
}
|
||||
if(m_wallet->watch_only())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WATCH_ONLY;
|
||||
er.message = "command not supported by watch-only wallet";
|
||||
return false;
|
||||
}
|
||||
|
||||
tools::wallet2::unsigned_tx_set exported_txs;
|
||||
try
|
||||
{
|
||||
cryptonote::blobdata blob;
|
||||
if (!epee::string_tools::parse_hexstr_to_binbuff(req.unsigned_txset, blob))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
|
||||
er.message = "Failed to parse hex.";
|
||||
return false;
|
||||
}
|
||||
if(!m_wallet->parse_unsigned_tx_from_str(blob, exported_txs))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||
er.message = "cannot load unsigned_txset";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||
er.message = "failed to parse unsigned transfers: " + std::string(e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<tools::wallet2::pending_tx> ptx;
|
||||
try
|
||||
{
|
||||
// gather info to ask the user
|
||||
std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> dests;
|
||||
int first_known_non_zero_change_index = -1;
|
||||
for (size_t n = 0; n < exported_txs.txes.size(); ++n)
|
||||
{
|
||||
const tools::wallet2::tx_construction_data &cd = exported_txs.txes[n];
|
||||
res.desc.push_back({0, 0, std::numeric_limits<uint32_t>::max(), 0, {}, "", 0, "", 0, 0, ""});
|
||||
wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::transfer_description &desc = res.desc.back();
|
||||
|
||||
std::vector<cryptonote::tx_extra_field> tx_extra_fields;
|
||||
bool has_encrypted_payment_id = false;
|
||||
crypto::hash8 payment_id8 = crypto::null_hash8;
|
||||
if (cryptonote::parse_tx_extra(cd.extra, tx_extra_fields))
|
||||
{
|
||||
cryptonote::tx_extra_nonce extra_nonce;
|
||||
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
|
||||
{
|
||||
crypto::hash payment_id;
|
||||
if(cryptonote::get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
|
||||
{
|
||||
desc.payment_id = epee::string_tools::pod_to_hex(payment_id8);
|
||||
has_encrypted_payment_id = true;
|
||||
}
|
||||
else if (cryptonote::get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
|
||||
{
|
||||
desc.payment_id = epee::string_tools::pod_to_hex(payment_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t s = 0; s < cd.sources.size(); ++s)
|
||||
{
|
||||
desc.amount_in += cd.sources[s].amount;
|
||||
size_t ring_size = cd.sources[s].outputs.size();
|
||||
if (ring_size < desc.ring_size)
|
||||
desc.ring_size = ring_size;
|
||||
}
|
||||
for (size_t d = 0; d < cd.splitted_dsts.size(); ++d)
|
||||
{
|
||||
const cryptonote::tx_destination_entry &entry = cd.splitted_dsts[d];
|
||||
std::string address = cryptonote::get_account_address_as_str(m_wallet->nettype(), entry.is_subaddress, entry.addr);
|
||||
if (has_encrypted_payment_id && !entry.is_subaddress)
|
||||
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), entry.addr, payment_id8);
|
||||
auto i = dests.find(entry.addr);
|
||||
if (i == dests.end())
|
||||
dests.insert(std::make_pair(entry.addr, std::make_pair(address, entry.amount)));
|
||||
else
|
||||
i->second.second += entry.amount;
|
||||
desc.amount_out += entry.amount;
|
||||
}
|
||||
if (cd.change_dts.amount > 0)
|
||||
{
|
||||
auto it = dests.find(cd.change_dts.addr);
|
||||
if (it == dests.end())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||
er.message = "Claimed change does not go to a paid address";
|
||||
return false;
|
||||
}
|
||||
if (it->second.second < cd.change_dts.amount)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||
er.message = "Claimed change is larger than payment to the change address";
|
||||
return false;
|
||||
}
|
||||
if (cd.change_dts.amount > 0)
|
||||
{
|
||||
if (first_known_non_zero_change_index == -1)
|
||||
first_known_non_zero_change_index = n;
|
||||
const tools::wallet2::tx_construction_data &cdn = exported_txs.txes[first_known_non_zero_change_index];
|
||||
if (memcmp(&cd.change_dts.addr, &cdn.change_dts.addr, sizeof(cd.change_dts.addr)))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||
er.message = "Change goes to more than one address";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
desc.change_amount += cd.change_dts.amount;
|
||||
it->second.second -= cd.change_dts.amount;
|
||||
if (it->second.second == 0)
|
||||
dests.erase(cd.change_dts.addr);
|
||||
}
|
||||
|
||||
size_t n_dummy_outputs = 0;
|
||||
for (auto i = dests.begin(); i != dests.end(); )
|
||||
{
|
||||
if (i->second.second > 0)
|
||||
{
|
||||
desc.recipients.push_back({i->second.first, i->second.second});
|
||||
}
|
||||
else
|
||||
++desc.dummy_outputs;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (desc.change_amount > 0)
|
||||
{
|
||||
const tools::wallet2::tx_construction_data &cd0 = exported_txs.txes[0];
|
||||
desc.change_address = get_account_address_as_str(m_wallet->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr);
|
||||
}
|
||||
|
||||
desc.fee = desc.amount_in - desc.amount_out;
|
||||
desc.unlock_time = cd.unlock_time;
|
||||
desc.extra = epee::to_hex::string({cd.extra.data(), cd.extra.size()});
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
|
||||
er.message = "failed to parse unsigned transfers";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_submit_transfer(const wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
|
@ -2906,6 +3073,11 @@ namespace tools
|
|||
er.code = WALLET_RPC_ERROR_CODE_ADDRESS_INDEX_OUT_OF_BOUNDS;
|
||||
er.message = e.what();
|
||||
}
|
||||
catch (const error::signature_check_failed& e)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_SIGNATURE;
|
||||
er.message = e.what();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
er.code = default_error_code;
|
||||
|
|
|
@ -88,6 +88,7 @@ namespace tools
|
|||
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
|
||||
MAP_JON_RPC_WE("transfer_split", on_transfer_split, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT)
|
||||
MAP_JON_RPC_WE("sign_transfer", on_sign_transfer, wallet_rpc::COMMAND_RPC_SIGN_TRANSFER)
|
||||
MAP_JON_RPC_WE("describe_transfer", on_describe_transfer, wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER)
|
||||
MAP_JON_RPC_WE("submit_transfer", on_submit_transfer, wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER)
|
||||
MAP_JON_RPC_WE("sweep_dust", on_sweep_dust, wallet_rpc::COMMAND_RPC_SWEEP_DUST)
|
||||
MAP_JON_RPC_WE("sweep_unmixable", on_sweep_dust, wallet_rpc::COMMAND_RPC_SWEEP_DUST)
|
||||
|
@ -168,6 +169,7 @@ namespace tools
|
|||
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er);
|
||||
bool on_transfer_split(const wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::request& req, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::response& res, epee::json_rpc::error& er);
|
||||
bool on_sign_transfer(const wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::response& res, epee::json_rpc::error& er);
|
||||
bool on_describe_transfer(const wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::response& res, epee::json_rpc::error& er);
|
||||
bool on_submit_transfer(const wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::response& res, epee::json_rpc::error& er);
|
||||
bool on_sweep_dust(const wallet_rpc::COMMAND_RPC_SWEEP_DUST::request& req, wallet_rpc::COMMAND_RPC_SWEEP_DUST::response& res, epee::json_rpc::error& er);
|
||||
bool on_sweep_all(const wallet_rpc::COMMAND_RPC_SWEEP_ALL::request& req, wallet_rpc::COMMAND_RPC_SWEEP_ALL::response& res, epee::json_rpc::error& er);
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
// advance which version they will stop working with
|
||||
// Don't go over 32767 for any of these
|
||||
#define WALLET_RPC_VERSION_MAJOR 1
|
||||
#define WALLET_RPC_VERSION_MINOR 4
|
||||
#define WALLET_RPC_VERSION_MINOR 5
|
||||
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
||||
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
|
||||
namespace tools
|
||||
|
@ -532,16 +532,79 @@ namespace wallet_rpc
|
|||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_DESCRIBE_TRANSFER
|
||||
{
|
||||
struct recipient
|
||||
{
|
||||
std::string address;
|
||||
uint64_t amount;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(address)
|
||||
KV_SERIALIZE(amount)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct transfer_description
|
||||
{
|
||||
uint64_t amount_in;
|
||||
uint64_t amount_out;
|
||||
uint32_t ring_size;
|
||||
uint64_t unlock_time;
|
||||
std::list<recipient> recipients;
|
||||
std::string payment_id;
|
||||
uint64_t change_amount;
|
||||
std::string change_address;
|
||||
uint64_t fee;
|
||||
uint32_t dummy_outputs;
|
||||
std::string extra;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount_in)
|
||||
KV_SERIALIZE(amount_out)
|
||||
KV_SERIALIZE(ring_size)
|
||||
KV_SERIALIZE(unlock_time)
|
||||
KV_SERIALIZE(recipients)
|
||||
KV_SERIALIZE(payment_id)
|
||||
KV_SERIALIZE(change_amount)
|
||||
KV_SERIALIZE(change_address)
|
||||
KV_SERIALIZE(fee)
|
||||
KV_SERIALIZE(dummy_outputs)
|
||||
KV_SERIALIZE(extra)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct request
|
||||
{
|
||||
std::string unsigned_txset;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(unsigned_txset)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::list<transfer_description> desc;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(desc)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_SIGN_TRANSFER
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string unsigned_txset;
|
||||
bool export_raw;
|
||||
bool get_tx_keys;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(unsigned_txset)
|
||||
KV_SERIALIZE_OPT(export_raw, false)
|
||||
KV_SERIALIZE_OPT(get_tx_keys, false)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
@ -550,11 +613,13 @@ namespace wallet_rpc
|
|||
std::string signed_txset;
|
||||
std::list<std::string> tx_hash_list;
|
||||
std::list<std::string> tx_raw_list;
|
||||
std::list<std::string> tx_key_list;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(signed_txset)
|
||||
KV_SERIALIZE(tx_hash_list)
|
||||
KV_SERIALIZE(tx_raw_list)
|
||||
KV_SERIALIZE(tx_key_list)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue