forked from lthn/blockchain
Merge branch 'develop' into market_rpc_api
This commit is contained in:
commit
9d3e2dee6b
189 changed files with 7304 additions and 3390 deletions
|
|
@ -12,10 +12,9 @@ set_property(TARGET zlibstatic PROPERTY FOLDER "contrib")
|
|||
set_property(TARGET lmdb PROPERTY FOLDER "contrib")
|
||||
|
||||
|
||||
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET upnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -wd4244 -wd4267")
|
||||
else()
|
||||
set_property(TARGET upnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-unused-result -Wno-unused-value")
|
||||
set_property(TARGET upnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-unused-result -Wno-unused-value -Wno-implicit-fallthrough -Wno-discarded-qualifiers ")
|
||||
set_property(TARGET zlibstatic APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-unused-result -Wno-unused-value -Wno-implicit-fallthrough -Wno-discarded-qualifiers ")
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -1,70 +1,14 @@
|
|||
LMDB 0.9 Change Log
|
||||
|
||||
LMDB 0.9.24 Release (2019/07/24)
|
||||
ITS#8969 Tweak mdb_page_split
|
||||
ITS#8975 WIN32 fix writemap set_mapsize crash
|
||||
ITS#9007 Fix loose pages in WRITEMAP
|
||||
|
||||
LMDB 0.9.23 Release (2018/12/19)
|
||||
ITS#8756 Fix loose pages in dirty list
|
||||
ITS#8831 Fix mdb_load flag init
|
||||
ITS#8844 Fix mdb_env_close in forked process
|
||||
Documentation
|
||||
ITS#8857 mdb_cursor_del doesn't invalidate cursor
|
||||
ITS#8908 GET_MULTIPLE etc don't change passed in key
|
||||
|
||||
LMDB 0.9.22 Release (2018/03/22)
|
||||
Fix MDB_DUPSORT alignment bug (ITS#8819)
|
||||
Fix regression with new db from 0.9.19 (ITS#8760)
|
||||
Fix liblmdb to build on Solaris (ITS#8612)
|
||||
Fix delete behavior with DUPSORT DB (ITS#8622)
|
||||
Fix mdb_cursor_get/mdb_cursor_del behavior (ITS#8722)
|
||||
|
||||
LMDB 0.9.21 Release (2017/06/01)
|
||||
Fix xcursor after cursor_del (ITS#8622)
|
||||
|
||||
LMDB 0.9.20 (Withdrawn)
|
||||
Fix mdb_load with escaped plaintext (ITS#8558)
|
||||
Fix mdb_cursor_last / mdb_put interaction (ITS#8557)
|
||||
|
||||
LMDB 0.9.19 Release (2016/12/28)
|
||||
Fix mdb_env_cwalk cursor init (ITS#8424)
|
||||
Fix robust mutexes on Solaris 10/11 (ITS#8339)
|
||||
Tweak Win32 error message buffer
|
||||
Fix MDB_GET_BOTH on non-dup record (ITS#8393)
|
||||
Optimize mdb_drop
|
||||
Fix xcursors after mdb_cursor_del (ITS#8406)
|
||||
Fix MDB_NEXT_DUP after mdb_cursor_del (ITS#8412)
|
||||
Fix mdb_cursor_put resetting C_EOF (ITS#8489)
|
||||
Fix mdb_env_copyfd2 to return EPIPE on SIGPIPE (ITS#8504)
|
||||
Fix mdb_env_copy with empty DB (ITS#8209)
|
||||
Fix behaviors with fork (ITS#8505)
|
||||
Fix mdb_dbi_open with mainDB cursors (ITS#8542)
|
||||
Fix robust mutexes on kFreeBSD (ITS#8554)
|
||||
Fix utf8_to_utf16 error checks (ITS#7992)
|
||||
Fix F_NOCACHE on MacOS, error is non-fatal (ITS#7682)
|
||||
Build
|
||||
Make shared lib suffix overridable (ITS#8481)
|
||||
Documentation
|
||||
Cleanup doxygen nits
|
||||
Note reserved vs actual mem/disk usage
|
||||
|
||||
|
||||
LMDB 0.9.18 Release (2016/02/05)
|
||||
LMDB 0.9.18 Release Engineering
|
||||
Fix robust mutex detection on glibc 2.10-11 (ITS#8330)
|
||||
Fix page_search_root assert on FreeDB (ITS#8336)
|
||||
Fix MDB_APPENDDUP vs. rewrite(single item) (ITS#8334)
|
||||
Fix mdb_copy of large files on Windows
|
||||
Fix subcursor move after delete (ITS#8355)
|
||||
Fix mdb_midl_shirnk off-by-one (ITS#8363)
|
||||
Check for utf8_to_utf16 failures (ITS#7992)
|
||||
Catch strdup failure in mdb_dbi_open
|
||||
Build
|
||||
Additional makefile var tweaks (ITS#8169)
|
||||
Documentation
|
||||
Add Getting Started page
|
||||
Update WRITEMAP description
|
||||
|
||||
|
||||
|
||||
LMDB 0.9.17 Release (2015/11/30)
|
||||
Fix ITS#7377 catch calloc failure
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ set (lmdb_sources mdb.c midl.c)
|
|||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
if(NOT MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers -Wno-missing-braces -Wno-aggregate-return")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-field-initializers -Wno-missing-braces -Wno-aggregate-return -Wno-discarded-qualifiers -Wno-unused-but-set-variable -Wno-implicit-fallthrough -Wno-maybe-uninitialized ")
|
||||
endif()
|
||||
if(FREEBSD)
|
||||
add_definitions(-DMDB_DSYNC=O_SYNC)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Copyright 2011-2019 Howard Chu, Symas Corp.
|
||||
Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ IDL_PROPERTY_SUPPORT = YES
|
|||
# member in the group (if any) for the other members of the group. By default
|
||||
# all members of a group must be documented explicitly.
|
||||
|
||||
DISTRIBUTE_GROUP_DOC = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
|
||||
# the same type (for instance a group of public functions) to be put as a
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
# platforms; you should not need to change any of these.
|
||||
# Read their descriptions in mdb.c if you do:
|
||||
#
|
||||
# - MDB_USE_POSIX_SEM
|
||||
# - MDB_USE_POSIX_MUTEX, MDB_USE_POSIX_SEM, MDB_USE_SYSV_SEM
|
||||
# - MDB_DSYNC
|
||||
# - MDB_FDATASYNC
|
||||
# - MDB_FDATASYNC_WORKS
|
||||
|
|
@ -24,9 +24,8 @@ W = -W -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized
|
|||
THREADS = -pthread
|
||||
OPT = -O2 -g
|
||||
CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS)
|
||||
LDLIBS =
|
||||
SOLIBS =
|
||||
SOEXT = .so
|
||||
LDLIBS = # -lntdll # Windows needs ntdll
|
||||
SOLIBS = # -lntdll
|
||||
prefix = /usr/local
|
||||
exec_prefix = $(prefix)
|
||||
bindir = $(exec_prefix)/bin
|
||||
|
|
@ -38,7 +37,7 @@ mandir = $(datarootdir)/man
|
|||
########################################################################
|
||||
|
||||
IHDRS = lmdb.h
|
||||
ILIBS = liblmdb.a liblmdb$(SOEXT)
|
||||
ILIBS = liblmdb.a liblmdb.so
|
||||
IPROGS = mdb_stat mdb_copy mdb_dump mdb_load
|
||||
IDOCS = mdb_stat.1 mdb_copy.1 mdb_dump.1 mdb_load.1
|
||||
PROGS = $(IPROGS) mtest mtest2 mtest3 mtest4 mtest5
|
||||
|
|
@ -64,7 +63,7 @@ test: all
|
|||
liblmdb.a: mdb.o midl.o
|
||||
$(AR) rs $@ mdb.o midl.o
|
||||
|
||||
liblmdb$(SOEXT): mdb.lo midl.lo
|
||||
liblmdb.so: mdb.lo midl.lo
|
||||
# $(CC) $(LDFLAGS) -pthread -shared -Wl,-Bsymbolic -o $@ mdb.o midl.o $(SOLIBS)
|
||||
$(CC) $(LDFLAGS) -pthread -shared -o $@ mdb.lo midl.lo $(SOLIBS)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2015-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -53,14 +53,15 @@
|
|||
*
|
||||
* Fix: Check for stale readers periodically, using the
|
||||
* #mdb_reader_check function or the \ref mdb_stat_1 "mdb_stat" tool.
|
||||
* Stale writers will be cleared automatically on some systems:
|
||||
* Stale writers will be cleared automatically on most systems:
|
||||
* - Windows - automatic
|
||||
* - BSD, systems using SysV semaphores - automatic
|
||||
* - Linux, systems using POSIX mutexes with Robust option - automatic
|
||||
* - not on BSD, systems using POSIX semaphores.
|
||||
* Otherwise just make all programs using the database close it;
|
||||
* the lockfile is always reset on first open of the environment.
|
||||
*
|
||||
* - On BSD systems or others configured with MDB_USE_POSIX_SEM,
|
||||
* - On BSD systems or others configured with MDB_USE_SYSV_SEM or
|
||||
* MDB_USE_POSIX_SEM,
|
||||
* startup can fail due to semaphores owned by another userid.
|
||||
*
|
||||
* Fix: Open and close the database as the user which owns the
|
||||
|
|
@ -96,12 +97,11 @@
|
|||
* transactions. Each transaction belongs to one thread. See below.
|
||||
* The #MDB_NOTLS flag changes this for read-only transactions.
|
||||
*
|
||||
* - Use an MDB_env* in the process which opened it, not after fork().
|
||||
* - Use an MDB_env* in the process which opened it, without fork()ing.
|
||||
*
|
||||
* - Do not have open an LMDB database twice in the same process at
|
||||
* the same time. Not even from a plain open() call - close()ing it
|
||||
* breaks fcntl() advisory locking. (It is OK to reopen it after
|
||||
* fork() - exec*(), since the lockfile has FD_CLOEXEC set.)
|
||||
* breaks flock() advisory locking.
|
||||
*
|
||||
* - Avoid long-lived transactions. Read transactions prevent
|
||||
* reuse of pages freed by newer write transactions, thus the
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
*
|
||||
* @author Howard Chu, Symas Corporation.
|
||||
*
|
||||
* @copyright Copyright 2011-2019 Howard Chu, Symas Corp. All rights reserved.
|
||||
* @copyright Copyright 2011-2016 Howard Chu, Symas Corp. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
|
|
@ -166,6 +166,7 @@
|
|||
#define _LMDB_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -178,6 +179,13 @@ typedef int mdb_mode_t;
|
|||
typedef mode_t mdb_mode_t;
|
||||
#endif
|
||||
|
||||
#ifdef MDB_VL32
|
||||
typedef uint64_t mdb_size_t;
|
||||
#define mdb_env_create mdb_env_create_vl32 /**< Prevent mixing with non-VL32 builds */
|
||||
#else
|
||||
typedef size_t mdb_size_t;
|
||||
#endif
|
||||
|
||||
/** An abstraction for a file handle.
|
||||
* On POSIX systems file handles are small integers. On Windows
|
||||
* they're opaque pointers.
|
||||
|
|
@ -200,7 +208,7 @@ typedef int mdb_filehandle_t;
|
|||
/** Library minor version */
|
||||
#define MDB_VERSION_MINOR 9
|
||||
/** Library patch version */
|
||||
#define MDB_VERSION_PATCH 24
|
||||
#define MDB_VERSION_PATCH 70
|
||||
|
||||
/** Combine args a,b,c into a single integer for easy version comparisons */
|
||||
#define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
|
||||
|
|
@ -210,7 +218,7 @@ typedef int mdb_filehandle_t;
|
|||
MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
|
||||
|
||||
/** The release date of this library version */
|
||||
#define MDB_VERSION_DATE "July 24, 2019"
|
||||
#define MDB_VERSION_DATE "December 19, 2015"
|
||||
|
||||
/** A stringifier for the version info */
|
||||
#define MDB_VERSTR(a,b,c,d) "LMDB " #a "." #b "." #c ": (" d ")"
|
||||
|
|
@ -303,6 +311,8 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel
|
|||
#define MDB_NORDAHEAD 0x800000
|
||||
/** don't initialize malloc'd memory before writing to datafile */
|
||||
#define MDB_NOMEMINIT 0x1000000
|
||||
/** use the previous snapshot rather than the latest one */
|
||||
#define MDB_PREVSNAPSHOT 0x2000000
|
||||
/** @} */
|
||||
|
||||
/** @defgroup mdb_dbi_open Database Flags
|
||||
|
|
@ -370,7 +380,7 @@ typedef enum MDB_cursor_op {
|
|||
MDB_GET_BOTH, /**< Position at key/data pair. Only for #MDB_DUPSORT */
|
||||
MDB_GET_BOTH_RANGE, /**< position at key, nearest data. Only for #MDB_DUPSORT */
|
||||
MDB_GET_CURRENT, /**< Return key/data at current cursor position */
|
||||
MDB_GET_MULTIPLE, /**< Return up to a page of duplicate data items
|
||||
MDB_GET_MULTIPLE, /**< Return key and up to a page of duplicate data items
|
||||
from current cursor position. Move cursor to prepare
|
||||
for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */
|
||||
MDB_LAST, /**< Position at last key/data item */
|
||||
|
|
@ -379,7 +389,7 @@ typedef enum MDB_cursor_op {
|
|||
MDB_NEXT, /**< Position at next data item */
|
||||
MDB_NEXT_DUP, /**< Position at next data item of current key.
|
||||
Only for #MDB_DUPSORT */
|
||||
MDB_NEXT_MULTIPLE, /**< Return up to a page of duplicate data items
|
||||
MDB_NEXT_MULTIPLE, /**< Return key and up to a page of duplicate data items
|
||||
from next cursor position. Move cursor to prepare
|
||||
for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */
|
||||
MDB_NEXT_NODUP, /**< Position at first data item of next key */
|
||||
|
|
@ -390,7 +400,7 @@ typedef enum MDB_cursor_op {
|
|||
MDB_SET, /**< Position at specified key */
|
||||
MDB_SET_KEY, /**< Position at specified key, return key + data */
|
||||
MDB_SET_RANGE, /**< Position at first key greater than or equal to specified key. */
|
||||
MDB_PREV_MULTIPLE /**< Position at previous page and return up to
|
||||
MDB_PREV_MULTIPLE /**< Position at previous page and return key and up to
|
||||
a page of duplicate data items. Only for #MDB_DUPFIXED */
|
||||
} MDB_cursor_op;
|
||||
|
||||
|
|
@ -457,18 +467,18 @@ typedef struct MDB_stat {
|
|||
unsigned int ms_psize; /**< Size of a database page.
|
||||
This is currently the same for all databases. */
|
||||
unsigned int ms_depth; /**< Depth (height) of the B-tree */
|
||||
size_t ms_branch_pages; /**< Number of internal (non-leaf) pages */
|
||||
size_t ms_leaf_pages; /**< Number of leaf pages */
|
||||
size_t ms_overflow_pages; /**< Number of overflow pages */
|
||||
size_t ms_entries; /**< Number of data items */
|
||||
mdb_size_t ms_branch_pages; /**< Number of internal (non-leaf) pages */
|
||||
mdb_size_t ms_leaf_pages; /**< Number of leaf pages */
|
||||
mdb_size_t ms_overflow_pages; /**< Number of overflow pages */
|
||||
mdb_size_t ms_entries; /**< Number of data items */
|
||||
} MDB_stat;
|
||||
|
||||
/** @brief Information about the environment */
|
||||
typedef struct MDB_envinfo {
|
||||
void *me_mapaddr; /**< Address of map, if fixed */
|
||||
size_t me_mapsize; /**< Size of the data memory map */
|
||||
size_t me_last_pgno; /**< ID of the last used page */
|
||||
size_t me_last_txnid; /**< ID of the last committed transaction */
|
||||
mdb_size_t me_mapsize; /**< Size of the data memory map */
|
||||
mdb_size_t me_last_pgno; /**< ID of the last used page */
|
||||
mdb_size_t me_last_txnid; /**< ID of the last committed transaction */
|
||||
unsigned int me_maxreaders; /**< max reader slots in the environment */
|
||||
unsigned int me_numreaders; /**< max reader slots used in the environment */
|
||||
} MDB_envinfo;
|
||||
|
|
@ -614,6 +624,12 @@ int mdb_env_create(MDB_env **env);
|
|||
* caller is expected to overwrite all of the memory that was
|
||||
* reserved in that case.
|
||||
* This flag may be changed at any time using #mdb_env_set_flags().
|
||||
* <li>#MDB_PREVSNAPSHOT
|
||||
* Open the environment with the previous snapshot rather than the latest
|
||||
* one. This loses the latest transaction, but may help work around some
|
||||
* types of corruption. If opened with write access, this must be the
|
||||
* only process using the environment. This flag is automatically reset
|
||||
* after a write transaction is successfully committed.
|
||||
* </ul>
|
||||
* @param[in] mode The UNIX permissions to set on created files and semaphores.
|
||||
* This parameter is ignored on Windows.
|
||||
|
|
@ -680,7 +696,6 @@ int mdb_env_copyfd(MDB_env *env, mdb_filehandle_t fd);
|
|||
* <li>#MDB_CP_COMPACT - Perform compaction while copying: omit free
|
||||
* pages and sequentially renumber all pages in output. This option
|
||||
* consumes more CPU and runs more slowly than the default.
|
||||
* Currently it fails if the environment has suffered a page leak.
|
||||
* </ul>
|
||||
* @return A non-zero error value on failure and 0 on success.
|
||||
*/
|
||||
|
|
@ -795,10 +810,6 @@ int mdb_env_get_flags(MDB_env *env, unsigned int *flags);
|
|||
int mdb_env_get_path(MDB_env *env, const char **path);
|
||||
|
||||
/** @brief Return the filedescriptor for the given environment.
|
||||
*
|
||||
* This function may be called after fork(), so the descriptor can be
|
||||
* closed before exec*(). Other LMDB file descriptors have FD_CLOEXEC.
|
||||
* (Until LMDB 0.9.18, only the lockfile had that.)
|
||||
*
|
||||
* @param[in] env An environment handle returned by #mdb_env_create()
|
||||
* @param[out] fd Address of a mdb_filehandle_t to contain the descriptor.
|
||||
|
|
@ -842,7 +853,7 @@ int mdb_env_get_fd(MDB_env *env, mdb_filehandle_t *fd);
|
|||
* an active write transaction.
|
||||
* </ul>
|
||||
*/
|
||||
int mdb_env_set_mapsize(MDB_env *env, size_t size);
|
||||
int mdb_env_set_mapsize(MDB_env *env, mdb_size_t size);
|
||||
|
||||
/** @brief Set the maximum number of threads/reader slots for the environment.
|
||||
*
|
||||
|
|
@ -955,6 +966,10 @@ int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func);
|
|||
* <ul>
|
||||
* <li>#MDB_RDONLY
|
||||
* This transaction will not perform any write operations.
|
||||
* <li>#MDB_NOSYNC
|
||||
* Don't flush system buffers to disk when committing this transaction.
|
||||
* <li>#MDB_NOMETASYNC
|
||||
* Flush system buffers but omit metadata flush when committing this transaction.
|
||||
* </ul>
|
||||
* @param[out] txn Address where the new #MDB_txn handle will be stored
|
||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||
|
|
@ -987,7 +1002,7 @@ MDB_env *mdb_txn_env(MDB_txn *txn);
|
|||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||
* @return A transaction ID, valid if input is an active transaction.
|
||||
*/
|
||||
size_t mdb_txn_id(MDB_txn *txn);
|
||||
mdb_size_t mdb_txn_id(MDB_txn *txn);
|
||||
|
||||
/** @brief Commit all the operations of a transaction into the database.
|
||||
*
|
||||
|
|
@ -1103,9 +1118,8 @@ int mdb_txn_renew(MDB_txn *txn);
|
|||
* This flag may only be used in combination with #MDB_DUPSORT. This option
|
||||
* tells the library that the data items for this database are all the same
|
||||
* size, which allows further optimizations in storage and retrieval. When
|
||||
* all data items are the same size, the #MDB_GET_MULTIPLE, #MDB_NEXT_MULTIPLE
|
||||
* and #MDB_PREV_MULTIPLE cursor operations may be used to retrieve multiple
|
||||
* items at once.
|
||||
* all data items are the same size, the #MDB_GET_MULTIPLE and #MDB_NEXT_MULTIPLE
|
||||
* cursor operations may be used to retrieve multiple items at once.
|
||||
* <li>#MDB_INTEGERDUP
|
||||
* This option specifies that duplicate data items are binary integers,
|
||||
* similar to #MDB_INTEGERKEY keys.
|
||||
|
|
@ -1510,10 +1524,6 @@ int mdb_cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
|
|||
/** @brief Delete current key/data pair
|
||||
*
|
||||
* This function deletes the key/data pair to which the cursor refers.
|
||||
* This does not invalidate the cursor, so operations such as MDB_NEXT
|
||||
* can still be used on it.
|
||||
* Both MDB_NEXT and MDB_GET_CURRENT will return the same record after
|
||||
* this operation.
|
||||
* @param[in] cursor A cursor handle returned by #mdb_cursor_open()
|
||||
* @param[in] flags Options for this operation. This parameter
|
||||
* must be set to 0 or one of the values described here.
|
||||
|
|
@ -1542,7 +1552,7 @@ int mdb_cursor_del(MDB_cursor *cursor, unsigned int flags);
|
|||
* <li>EINVAL - cursor is not initialized, or an invalid parameter was specified.
|
||||
* </ul>
|
||||
*/
|
||||
int mdb_cursor_count(MDB_cursor *cursor, size_t *countp);
|
||||
int mdb_cursor_count(MDB_cursor *cursor, mdb_size_t *countp);
|
||||
|
||||
/** @brief Compare two data items according to a particular database.
|
||||
*
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_COPY 1 "2014/07/01" "LMDB 0.9.14"
|
||||
.\" Copyright 2012-2018 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_COPY 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_copy \- LMDB environment copy tool
|
||||
|
|
@ -11,6 +11,8 @@ mdb_copy \- LMDB environment copy tool
|
|||
.BR \-c ]
|
||||
[\c
|
||||
.BR \-n ]
|
||||
[\c
|
||||
.BR \-v ]
|
||||
.B srcpath
|
||||
[\c
|
||||
.BR dstpath ]
|
||||
|
|
@ -36,10 +38,13 @@ Write the library version number to the standard output, and exit.
|
|||
Compact while copying. Only current data pages will be copied; freed
|
||||
or unused pages will be omitted from the copy. This option will
|
||||
slow down the backup process as it is more CPU-intensive.
|
||||
Currently it fails if the environment has suffered a page leak.
|
||||
.TP
|
||||
.BR \-n
|
||||
Open LDMB environment(s) which do not use subdirectories.
|
||||
.TP
|
||||
.BR \-v
|
||||
Use the previous environment state instead of the latest state.
|
||||
This may be useful if the latest state has been corrupted.
|
||||
|
||||
.SH DIAGNOSTICS
|
||||
Exit status is zero if no errors occur.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mdb_copy.c - memory-mapped database backup tool */
|
||||
/*
|
||||
* Copyright 2012-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2012-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -38,6 +38,8 @@ int main(int argc,char * argv[])
|
|||
for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
|
||||
if (argv[1][1] == 'n' && argv[1][2] == '\0')
|
||||
flags |= MDB_NOSUBDIR;
|
||||
else if (argv[1][1] == 'v' && argv[1][2] == '\0')
|
||||
flags |= MDB_PREVSNAPSHOT;
|
||||
else if (argv[1][1] == 'c' && argv[1][2] == '\0')
|
||||
cpflags |= MDB_CP_COMPACT;
|
||||
else if (argv[1][1] == 'V' && argv[1][2] == '\0') {
|
||||
|
|
@ -48,7 +50,7 @@ int main(int argc,char * argv[])
|
|||
}
|
||||
|
||||
if (argc<2 || argc>3) {
|
||||
fprintf(stderr, "usage: %s [-V] [-c] [-n] srcpath [dstpath]\n", progname);
|
||||
fprintf(stderr, "usage: %s [-V] [-c] [-n] [-v] srcpath [dstpath]\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_DUMP 1 "2015/09/30" "LMDB 0.9.17"
|
||||
.\" Copyright 2014-2018 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_DUMP 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_dump \- LMDB environment export tool
|
||||
|
|
@ -14,6 +14,8 @@ mdb_dump \- LMDB environment export tool
|
|||
[\c
|
||||
.BR \-n ]
|
||||
[\c
|
||||
.BR \-v ]
|
||||
[\c
|
||||
.BR \-p ]
|
||||
[\c
|
||||
.BR \-a \ |
|
||||
|
|
@ -42,6 +44,10 @@ names will be listed, no data will be output.
|
|||
.BR \-n
|
||||
Dump an LMDB database which does not use subdirectories.
|
||||
.TP
|
||||
.BR \-v
|
||||
Use the previous environment state instead of the latest state.
|
||||
This may be useful if the latest state has been corrupted.
|
||||
.TP
|
||||
.BR \-p
|
||||
If characters in either the key or data items are printing characters (as
|
||||
defined by isprint(3)), output them directly. This option permits users to
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mdb_dump.c - memory-mapped database dump tool */
|
||||
/*
|
||||
* Copyright 2011-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -25,6 +25,15 @@
|
|||
#else
|
||||
#define Z "z"
|
||||
#endif
|
||||
#ifdef MDB_VL32
|
||||
#ifdef _WIN32
|
||||
#define Y "I64"
|
||||
#else
|
||||
#define Y "ll"
|
||||
#endif
|
||||
#else
|
||||
#define Y Z
|
||||
#endif
|
||||
|
||||
#define PRINT 1
|
||||
static int mode;
|
||||
|
|
@ -115,7 +124,7 @@ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
|||
if (name)
|
||||
printf("database=%s\n", name);
|
||||
printf("type=btree\n");
|
||||
printf("mapsize=%" Z "u\n", info.me_mapsize);
|
||||
printf("mapsize=%" Y "u\n", info.me_mapsize);
|
||||
if (info.me_mapaddr)
|
||||
printf("mapaddr=%p\n", info.me_mapaddr);
|
||||
printf("maxreaders=%u\n", info.me_maxreaders);
|
||||
|
|
@ -155,7 +164,7 @@ static int dumpit(MDB_txn *txn, MDB_dbi dbi, char *name)
|
|||
|
||||
static void usage(char *prog)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-a|-s subdb] dbpath\n", prog);
|
||||
fprintf(stderr, "usage: %s [-V] [-f output] [-l] [-n] [-p] [-v] [-a|-s subdb] dbpath\n", prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -179,6 +188,7 @@ int main(int argc, char *argv[])
|
|||
* -n: use NOSUBDIR flag on env_open
|
||||
* -p: use printable characters
|
||||
* -f: write to file instead of stdout
|
||||
* -v: use previous snapshot
|
||||
* -V: print version and exit
|
||||
* (default) dump only the main DB
|
||||
*/
|
||||
|
|
@ -206,6 +216,9 @@ int main(int argc, char *argv[])
|
|||
case 'n':
|
||||
envflags |= MDB_NOSUBDIR;
|
||||
break;
|
||||
case 'v':
|
||||
envflags |= MDB_PREVSNAPSHOT;
|
||||
break;
|
||||
case 'p':
|
||||
mode |= PRINT;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_LOAD 1 "2015/09/30" "LMDB 0.9.17"
|
||||
.\" Copyright 2014-2018 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_LOAD 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2014-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_load \- LMDB environment import tool
|
||||
|
|
@ -37,6 +37,13 @@ option below.
|
|||
.BR \-V
|
||||
Write the library version number to the standard output, and exit.
|
||||
.TP
|
||||
.BR \-a
|
||||
Append all records in the order they appear in the input. The input is assumed to already be
|
||||
in correctly sorted order and no sorting or checking for redundant values will be performed.
|
||||
This option must be used to reload data that was produced by running
|
||||
.B mdb_dump
|
||||
on a database that uses custom compare functions.
|
||||
.TP
|
||||
.BR \-f \ file
|
||||
Read from the specified file instead of from the standard input.
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mdb_load.c - memory-mapped database load tool */
|
||||
/*
|
||||
* Copyright 2011-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -37,12 +37,22 @@ static int Eof;
|
|||
static MDB_envinfo info;
|
||||
|
||||
static MDB_val kbuf, dbuf;
|
||||
static MDB_val k0buf;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define Z "I"
|
||||
#else
|
||||
#define Z "z"
|
||||
#endif
|
||||
#ifdef MDB_VL32
|
||||
#ifdef _WIN32
|
||||
#define Y "I64"
|
||||
#else
|
||||
#define Y "ll"
|
||||
#endif
|
||||
#else
|
||||
#define Y Z
|
||||
#endif
|
||||
|
||||
#define STRLENOF(s) (sizeof(s)-1)
|
||||
|
||||
|
|
@ -68,7 +78,6 @@ static void readhdr(void)
|
|||
{
|
||||
char *ptr;
|
||||
|
||||
flags = 0;
|
||||
while (fgets(dbuf.mv_data, dbuf.mv_size, stdin) != NULL) {
|
||||
lineno++;
|
||||
if (!strncmp(dbuf.mv_data, "VERSION=", STRLENOF("VERSION="))) {
|
||||
|
|
@ -113,7 +122,7 @@ static void readhdr(void)
|
|||
int i;
|
||||
ptr = memchr(dbuf.mv_data, '\n', dbuf.mv_size);
|
||||
if (ptr) *ptr = '\0';
|
||||
i = sscanf((char *)dbuf.mv_data+STRLENOF("mapsize="), "%" Z "u", &info.me_mapsize);
|
||||
i = sscanf((char *)dbuf.mv_data+STRLENOF("mapsize="), "%" Y "u", &info.me_mapsize);
|
||||
if (i != 1) {
|
||||
fprintf(stderr, "%s: line %" Z "d: invalid mapsize %s\n",
|
||||
prog, lineno, (char *)dbuf.mv_data+STRLENOF("mapsize="));
|
||||
|
|
@ -249,8 +258,7 @@ badend:
|
|||
c2 += 2;
|
||||
}
|
||||
} else {
|
||||
/* copies are redundant when no escapes were used */
|
||||
*c1++ = *c2++;
|
||||
c1++; c2++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -278,10 +286,15 @@ badend:
|
|||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-V] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
|
||||
fprintf(stderr, "usage: %s [-V] [-a] [-f input] [-n] [-s name] [-N] [-T] dbpath\n", prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int greater(const MDB_val *a, const MDB_val *b)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, rc;
|
||||
|
|
@ -291,7 +304,8 @@ int main(int argc, char *argv[])
|
|||
MDB_dbi dbi;
|
||||
char *envname;
|
||||
int envflags = 0, putflags = 0;
|
||||
int dohdr = 0;
|
||||
int dohdr = 0, append = 0;
|
||||
MDB_val prevk;
|
||||
|
||||
prog = argv[0];
|
||||
|
||||
|
|
@ -299,19 +313,23 @@ int main(int argc, char *argv[])
|
|||
usage();
|
||||
}
|
||||
|
||||
/* -f: load file instead of stdin
|
||||
/* -a: append records in input order
|
||||
* -f: load file instead of stdin
|
||||
* -n: use NOSUBDIR flag on env_open
|
||||
* -s: load into named subDB
|
||||
* -N: use NOOVERWRITE on puts
|
||||
* -T: read plaintext
|
||||
* -V: print version and exit
|
||||
*/
|
||||
while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) {
|
||||
while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) {
|
||||
switch(i) {
|
||||
case 'V':
|
||||
printf("%s\n", MDB_VERSION_STRING);
|
||||
exit(0);
|
||||
break;
|
||||
case 'a':
|
||||
append = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (freopen(optarg, "r", stdin) == NULL) {
|
||||
fprintf(stderr, "%s: %s: reopen: %s\n",
|
||||
|
|
@ -370,11 +388,17 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2;
|
||||
kbuf.mv_data = malloc(kbuf.mv_size);
|
||||
kbuf.mv_data = malloc(kbuf.mv_size * 2);
|
||||
k0buf.mv_size = kbuf.mv_size;
|
||||
k0buf.mv_data = (char *)kbuf.mv_data + kbuf.mv_size;
|
||||
prevk.mv_size = 0;
|
||||
prevk.mv_data = k0buf.mv_data;
|
||||
|
||||
while(!Eof) {
|
||||
MDB_val key, data;
|
||||
int batch = 0;
|
||||
flags = 0;
|
||||
int appflag;
|
||||
|
||||
if (!dohdr) {
|
||||
dohdr = 1;
|
||||
|
|
@ -392,6 +416,11 @@ int main(int argc, char *argv[])
|
|||
fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
|
||||
goto txn_abort;
|
||||
}
|
||||
if (append) {
|
||||
mdb_set_compare(txn, dbi, greater);
|
||||
if (flags & MDB_DUPSORT)
|
||||
mdb_set_dupsort(txn, dbi, greater);
|
||||
}
|
||||
|
||||
rc = mdb_cursor_open(txn, dbi, &mc);
|
||||
if (rc) {
|
||||
|
|
@ -410,7 +439,20 @@ int main(int argc, char *argv[])
|
|||
goto txn_abort;
|
||||
}
|
||||
|
||||
rc = mdb_cursor_put(mc, &key, &data, putflags);
|
||||
if (append) {
|
||||
appflag = MDB_APPEND;
|
||||
if (flags & MDB_DUPSORT) {
|
||||
if (prevk.mv_size == key.mv_size && !memcmp(prevk.mv_data, key.mv_data, key.mv_size))
|
||||
appflag = MDB_APPENDDUP;
|
||||
else {
|
||||
memcpy(prevk.mv_data, key.mv_data, key.mv_size);
|
||||
prevk.mv_size = key.mv_size;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appflag = 0;
|
||||
}
|
||||
rc = mdb_cursor_put(mc, &key, &data, putflags|appflag);
|
||||
if (rc == MDB_KEYEXIST && putflags)
|
||||
continue;
|
||||
if (rc) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.TH MDB_STAT 1 "2015/09/30" "LMDB 0.9.17"
|
||||
.\" Copyright 2012-2018 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.TH MDB_STAT 1 "2014/06/20" "LMDB 0.9.14"
|
||||
.\" Copyright 2012-2015 Howard Chu, Symas Corp. All Rights Reserved.
|
||||
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
|
||||
.SH NAME
|
||||
mdb_stat \- LMDB environment status tool
|
||||
|
|
@ -14,6 +14,8 @@ mdb_stat \- LMDB environment status tool
|
|||
[\c
|
||||
.BR \-n ]
|
||||
[\c
|
||||
.BR \-v ]
|
||||
[\c
|
||||
.BR \-r [ r ]]
|
||||
[\c
|
||||
.BR \-a \ |
|
||||
|
|
@ -39,6 +41,10 @@ If \fB\-fff\fP is given, display the full list of page IDs in the freelist.
|
|||
.BR \-n
|
||||
Display the status of an LMDB database which does not use subdirectories.
|
||||
.TP
|
||||
.BR \-v
|
||||
Use the previous environment state instead of the latest state.
|
||||
This may be useful if the latest state has been corrupted.
|
||||
.TP
|
||||
.BR \-r
|
||||
Display information about the environment reader table.
|
||||
Shows the process ID, thread ID, and transaction ID for each active
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mdb_stat.c - memory-mapped database status tool */
|
||||
/*
|
||||
* Copyright 2011-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -22,6 +22,15 @@
|
|||
#else
|
||||
#define Z "z"
|
||||
#endif
|
||||
#ifdef MDB_VL32
|
||||
#ifdef _WIN32
|
||||
#define Y "I64"
|
||||
#else
|
||||
#define Y "ll"
|
||||
#endif
|
||||
#else
|
||||
#define Y Z
|
||||
#endif
|
||||
|
||||
static void prstat(MDB_stat *ms)
|
||||
{
|
||||
|
|
@ -29,15 +38,15 @@ static void prstat(MDB_stat *ms)
|
|||
printf(" Page size: %u\n", ms->ms_psize);
|
||||
#endif
|
||||
printf(" Tree depth: %u\n", ms->ms_depth);
|
||||
printf(" Branch pages: %"Z"u\n", ms->ms_branch_pages);
|
||||
printf(" Leaf pages: %"Z"u\n", ms->ms_leaf_pages);
|
||||
printf(" Overflow pages: %"Z"u\n", ms->ms_overflow_pages);
|
||||
printf(" Entries: %"Z"u\n", ms->ms_entries);
|
||||
printf(" Branch pages: %"Y"u\n", ms->ms_branch_pages);
|
||||
printf(" Leaf pages: %"Y"u\n", ms->ms_leaf_pages);
|
||||
printf(" Overflow pages: %"Y"u\n", ms->ms_overflow_pages);
|
||||
printf(" Entries: %"Y"u\n", ms->ms_entries);
|
||||
}
|
||||
|
||||
static void usage(char *prog)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-a|-s subdb] dbpath\n", prog);
|
||||
fprintf(stderr, "usage: %s [-V] [-n] [-e] [-r[r]] [-f[f[f]]] [-v] [-a|-s subdb] dbpath\n", prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -64,6 +73,7 @@ int main(int argc, char *argv[])
|
|||
* -f: print freelist info
|
||||
* -r: print reader info
|
||||
* -n: use NOSUBDIR flag on env_open
|
||||
* -v: use previous snapshot
|
||||
* -V: print version and exit
|
||||
* (default) print stat of only the main DB
|
||||
*/
|
||||
|
|
@ -87,6 +97,9 @@ int main(int argc, char *argv[])
|
|||
case 'n':
|
||||
envflags |= MDB_NOSUBDIR;
|
||||
break;
|
||||
case 'v':
|
||||
envflags |= MDB_PREVSNAPSHOT;
|
||||
break;
|
||||
case 'r':
|
||||
rdrinfo++;
|
||||
break;
|
||||
|
|
@ -125,11 +138,11 @@ int main(int argc, char *argv[])
|
|||
(void)mdb_env_info(env, &mei);
|
||||
printf("Environment Info\n");
|
||||
printf(" Map address: %p\n", mei.me_mapaddr);
|
||||
printf(" Map size: %"Z"u\n", mei.me_mapsize);
|
||||
printf(" Map size: %"Y"u\n", mei.me_mapsize);
|
||||
printf(" Page size: %u\n", mst.ms_psize);
|
||||
printf(" Max pages: %"Z"u\n", mei.me_mapsize / mst.ms_psize);
|
||||
printf(" Number of pages used: %"Z"u\n", mei.me_last_pgno+1);
|
||||
printf(" Last transaction ID: %"Z"u\n", mei.me_last_txnid);
|
||||
printf(" Max pages: %"Y"u\n", mei.me_mapsize / mst.ms_psize);
|
||||
printf(" Number of pages used: %"Y"u\n", mei.me_last_pgno+1);
|
||||
printf(" Last transaction ID: %"Y"u\n", mei.me_last_txnid);
|
||||
printf(" Max readers: %u\n", mei.me_maxreaders);
|
||||
printf(" Number of readers used: %u\n", mei.me_numreaders);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2000-2019 The OpenLDAP Foundation.
|
||||
* Portions Copyright 2001-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2000-2015 The OpenLDAP Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -355,5 +354,67 @@ int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id )
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MDB_VL32
|
||||
unsigned mdb_mid3l_search( MDB_ID3L ids, MDB_ID id )
|
||||
{
|
||||
/*
|
||||
* binary search of id in ids
|
||||
* if found, returns position of id
|
||||
* if not found, returns first position greater than id
|
||||
*/
|
||||
unsigned base = 0;
|
||||
unsigned cursor = 1;
|
||||
int val = 0;
|
||||
unsigned n = (unsigned)ids[0].mid;
|
||||
|
||||
while( 0 < n ) {
|
||||
unsigned pivot = n >> 1;
|
||||
cursor = base + pivot + 1;
|
||||
val = CMP( id, ids[cursor].mid );
|
||||
|
||||
if( val < 0 ) {
|
||||
n = pivot;
|
||||
|
||||
} else if ( val > 0 ) {
|
||||
base = cursor;
|
||||
n -= pivot + 1;
|
||||
|
||||
} else {
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
if( val > 0 ) {
|
||||
++cursor;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int mdb_mid3l_insert( MDB_ID3L ids, MDB_ID3 *id )
|
||||
{
|
||||
unsigned x, i;
|
||||
|
||||
x = mdb_mid3l_search( ids, id->mid );
|
||||
|
||||
if( x < 1 ) {
|
||||
/* internal error */
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ( x <= ids[0].mid && ids[x].mid == id->mid ) {
|
||||
/* duplicate */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* insert id */
|
||||
ids[0].mid++;
|
||||
for (i=(unsigned)ids[0].mid; i>x; i--)
|
||||
ids[i] = ids[i-1];
|
||||
ids[x] = *id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MDB_VL32 */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@
|
|||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2000-2019 The OpenLDAP Foundation.
|
||||
* Portions Copyright 2001-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2000-2015 The OpenLDAP Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -28,6 +27,7 @@
|
|||
#define _MDB_MIDL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -43,7 +43,11 @@ extern "C" {
|
|||
/** A generic unsigned ID number. These were entryIDs in back-bdb.
|
||||
* Preferably it should have the same size as a pointer.
|
||||
*/
|
||||
#ifdef MDB_VL32
|
||||
typedef uint64_t MDB_ID;
|
||||
#else
|
||||
typedef size_t MDB_ID;
|
||||
#endif
|
||||
|
||||
/** An IDL is an ID List, a sorted array of IDs. The first
|
||||
* element of the array is a counter for how many actual
|
||||
|
|
@ -178,6 +182,20 @@ int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id );
|
|||
*/
|
||||
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id );
|
||||
|
||||
#ifdef MDB_VL32
|
||||
typedef struct MDB_ID3 {
|
||||
MDB_ID mid; /**< The ID */
|
||||
void *mptr; /**< The pointer */
|
||||
unsigned int mcnt; /**< Number of pages */
|
||||
unsigned int mref; /**< Refcounter */
|
||||
} MDB_ID3;
|
||||
|
||||
typedef MDB_ID3 *MDB_ID3L;
|
||||
|
||||
unsigned mdb_mid3l_search( MDB_ID3L ids, MDB_ID id );
|
||||
int mdb_mid3l_insert( MDB_ID3L ids, MDB_ID3 *id );
|
||||
|
||||
#endif /* MDB_VL32 */
|
||||
/** @} */
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest2.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest3.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest4.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest5.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* mtest6.c - memory-mapped database tester/toy */
|
||||
/*
|
||||
* Copyright 2011-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2011-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Do a line-by-line comparison of this and sample-mdb.txt
|
||||
*/
|
||||
/*
|
||||
* Copyright 2012-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2012-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Do a line-by-line comparison of this and sample-bdb.txt
|
||||
*/
|
||||
/*
|
||||
* Copyright 2012-2018 Howard Chu, Symas Corp.
|
||||
* Copyright 2012-2015 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#endif
|
||||
|
||||
#include "include_base_utils.h"
|
||||
#include "string_coding.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
|
|
@ -222,13 +223,23 @@ namespace file_io_utils
|
|||
return str_result;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline const std::wstring& convert_utf8_to_wstring_if_needed(const std::wstring& s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::wstring convert_utf8_to_wstring_if_needed(const std::string& s)
|
||||
{
|
||||
return epee::string_encoding::utf8_to_wstring(s);
|
||||
}
|
||||
|
||||
template<class t_string>
|
||||
bool is_file_exist(const t_string& path)
|
||||
{
|
||||
boost::filesystem::path p(path);
|
||||
return boost::filesystem::exists(p);
|
||||
}
|
||||
{
|
||||
boost::filesystem::path p(convert_utf8_to_wstring_if_needed(path));
|
||||
return boost::filesystem::exists(p);
|
||||
}
|
||||
|
||||
/*
|
||||
inline
|
||||
|
|
@ -261,19 +272,18 @@ namespace file_io_utils
|
|||
template<class t_string>
|
||||
bool save_string_to_file_throw(const t_string& path_to_file, const std::string& str)
|
||||
{
|
||||
//std::ofstream fstream;
|
||||
boost::filesystem::ofstream fstream;
|
||||
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(path_to_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
|
||||
fstream << str;
|
||||
fstream.close();
|
||||
return true;
|
||||
//std::ofstream fstream;
|
||||
boost::filesystem::ofstream fstream;
|
||||
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(convert_utf8_to_wstring_if_needed(path_to_file), std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
|
||||
fstream << str;
|
||||
fstream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class t_string>
|
||||
bool save_string_to_file(const t_string& path_to_file, const std::string& str)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
return save_string_to_file_throw(path_to_file, str);
|
||||
|
|
@ -290,13 +300,13 @@ namespace file_io_utils
|
|||
}
|
||||
|
||||
template<class t_string>
|
||||
bool load_file_to_string(const t_string& path_to_file, std::string& target_str)
|
||||
bool load_file_to_string(const t_string& path_to_file, std::string& target_str)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::filesystem::ifstream fstream;
|
||||
//fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
|
||||
fstream.open(convert_utf8_to_wstring_if_needed(path_to_file), std::ios_base::binary | std::ios_base::in | std::ios::ate);
|
||||
if (!fstream.good())
|
||||
return false;
|
||||
std::ifstream::pos_type file_size = fstream.tellg();
|
||||
|
|
@ -315,7 +325,6 @@ namespace file_io_utils
|
|||
fstream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -353,7 +362,7 @@ namespace file_io_utils
|
|||
bool get_file_time(const std::string& path_to_file, OUT time_t& ft)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
ft = boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ec);
|
||||
ft = boost::filesystem::last_write_time(epee::string_encoding::utf8_to_wstring(path_to_file), ec);
|
||||
if(!ec)
|
||||
return true;
|
||||
else
|
||||
|
|
@ -364,7 +373,7 @@ namespace file_io_utils
|
|||
bool set_file_time(const std::string& path_to_file, const time_t& ft)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ft, ec);
|
||||
boost::filesystem::last_write_time(epee::string_encoding::utf8_to_wstring(path_to_file), ft, ec);
|
||||
if(!ec)
|
||||
return true;
|
||||
else
|
||||
|
|
@ -380,16 +389,18 @@ namespace file_io_utils
|
|||
typedef int native_filesystem_handle;
|
||||
#endif
|
||||
|
||||
// uses UTF-8 for unicode names for all systems
|
||||
inline bool open_and_lock_file(const std::string file_path, native_filesystem_handle& h_file)
|
||||
{
|
||||
#ifdef WIN32
|
||||
h_file = ::CreateFileA(file_path.c_str(), // name of the write
|
||||
GENERIC_WRITE, // open for writing
|
||||
0, // do not share
|
||||
NULL, // default security
|
||||
OPEN_ALWAYS, // create new file only
|
||||
FILE_ATTRIBUTE_NORMAL, // normal file
|
||||
NULL); // no attr. template
|
||||
std::wstring file_path_w = epee::string_encoding::utf8_to_wstring(file_path);
|
||||
h_file = ::CreateFileW(file_path_w.c_str(), // name of the file
|
||||
GENERIC_WRITE, // open for writing
|
||||
0, // do not share
|
||||
NULL, // default security
|
||||
OPEN_ALWAYS, // create new file only
|
||||
FILE_ATTRIBUTE_NORMAL, // normal file
|
||||
NULL); // no attr. template
|
||||
if (h_file == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
else
|
||||
|
|
@ -465,20 +476,21 @@ namespace file_io_utils
|
|||
bool copy_file(const std::string& source, const std::string& destination)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::copy_file(source, destination, ec);
|
||||
boost::filesystem::copy_file(epee::string_encoding::utf8_to_wstring(source), epee::string_encoding::utf8_to_wstring(destination), ec);
|
||||
if (ec)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool append_string_to_file(const std::string& path_to_file, const std::string& str)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::ofstream fstream;
|
||||
boost::filesystem::ofstream fstream;
|
||||
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(path_to_file.c_str(), std::ios_base::binary | std::ios_base::out | std::ios_base::app);
|
||||
fstream.open(epee::string_encoding::utf8_to_wstring(path_to_file), std::ios_base::binary | std::ios_base::out | std::ios_base::app);
|
||||
fstream << str;
|
||||
fstream.close();
|
||||
return true;
|
||||
|
|
@ -550,7 +562,7 @@ namespace file_io_utils
|
|||
{
|
||||
|
||||
boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end
|
||||
for ( boost::filesystem::directory_iterator itr( path ); itr != end_itr; ++itr )
|
||||
for ( boost::filesystem::directory_iterator itr( epee::string_encoding::utf8_to_wstring(path) ); itr != end_itr; ++itr )
|
||||
{
|
||||
if ( only_files && boost::filesystem::is_directory(itr->status()) )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ namespace math_helper
|
|||
}
|
||||
|
||||
}
|
||||
PUSH_WARNINGS
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_GCC_WARNING(strict-aliasing)
|
||||
inline
|
||||
uint64_t generated_random_uint64()
|
||||
|
|
@ -248,7 +248,7 @@ DISABLE_GCC_WARNING(strict-aliasing)
|
|||
boost::uuids::uuid id___ = boost::uuids::random_generator()();
|
||||
return *reinterpret_cast<uint64_t*>(&id___.data[0]); //(*reinterpret_cast<uint64_t*>(&id___.data[0]) ^ *reinterpret_cast<uint64_t*>(&id___.data[8]));
|
||||
}
|
||||
POP_WARNINGS
|
||||
POP_GCC_WARNINGS
|
||||
template<int default_interval, bool start_immediate = true>
|
||||
class once_a_time_seconds
|
||||
{
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
#endif
|
||||
#include "os_defenitions.h"
|
||||
#include "warnings.h"
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4100)
|
||||
|
||||
|
||||
|
|
@ -65,6 +65,7 @@ DISABLE_VS_WARNINGS(4100)
|
|||
|
||||
#include "syncobj.h"
|
||||
#include "sync_locked_object.h"
|
||||
#include "string_coding.h"
|
||||
|
||||
|
||||
#define LOG_LEVEL_SILENT -1
|
||||
|
|
@ -150,7 +151,7 @@ DISABLE_VS_WARNINGS(4100)
|
|||
{std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, true, log_name);}}
|
||||
|
||||
#define LOG_ERROR2(log_name, x) { \
|
||||
std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << "[ERROR] Location: " << std::endl << LOCATION_SS << epee::misc_utils::print_trace() << " Message:" << std::endl << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str(), LOG_LEVEL_0, epee::log_space::console_color_red, true, log_name); LOCAL_ASSERT(0); epee::log_space::increase_error_count(LOG_DEFAULT_CHANNEL); }
|
||||
std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << "[ERROR] Location: " << std::endl << LOCATION_SS << epee::misc_utils::get_callstack() << " Message:" << std::endl << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str(), LOG_LEVEL_0, epee::log_space::console_color_red, true, log_name); LOCAL_ASSERT(0); epee::log_space::increase_error_count(LOG_DEFAULT_CHANNEL); }
|
||||
|
||||
#define LOG_FRAME2(log_name, x, y) epee::log_space::log_frame frame(x, y, log_name)
|
||||
|
||||
|
|
@ -694,13 +695,13 @@ namespace log_space
|
|||
class file_output_stream : public ibase_log_stream
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, std::ofstream*> named_log_streams;
|
||||
typedef std::map<std::string, boost::filesystem::ofstream*> named_log_streams;
|
||||
|
||||
file_output_stream( std::string default_log_file_name, std::string log_path )
|
||||
file_output_stream( const std::string& default_log_file_name, const std::string& log_path )
|
||||
{
|
||||
m_default_log_filename = default_log_file_name;
|
||||
m_max_logfile_size = 0;
|
||||
m_default_log_path = log_path;
|
||||
m_default_log_path_w = epee::string_encoding::utf8_to_wstring(log_path);
|
||||
m_pdefault_file_stream = add_new_stream_and_open(default_log_file_name.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -718,20 +719,22 @@ namespace log_space
|
|||
}
|
||||
private:
|
||||
named_log_streams m_log_file_names;
|
||||
std::string m_default_log_path;
|
||||
std::ofstream* m_pdefault_file_stream;
|
||||
std::wstring m_default_log_path_w;
|
||||
boost::filesystem::ofstream* m_pdefault_file_stream;
|
||||
std::string m_log_rotate_cmd;
|
||||
std::string m_default_log_filename;
|
||||
uint64_t m_max_logfile_size;
|
||||
|
||||
|
||||
std::ofstream* add_new_stream_and_open(const char* pstream_name)
|
||||
// gets utf-8 encoded string
|
||||
boost::filesystem::ofstream* add_new_stream_and_open(const char* pstream_name)
|
||||
{
|
||||
//log_space::rotate_log_file((m_default_log_path + "\\" + pstream_name).c_str());
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::create_directories(m_default_log_path, ec);
|
||||
std::ofstream* pstream = (m_log_file_names[pstream_name] = new std::ofstream);
|
||||
std::string target_path = m_default_log_path + "/" + pstream_name;
|
||||
boost::filesystem::create_directories(m_default_log_path_w, ec);
|
||||
boost::filesystem::ofstream* pstream = (m_log_file_names[pstream_name] = new boost::filesystem::ofstream);
|
||||
std::wstring target_path = m_default_log_path_w + L"/" + epee::string_encoding::utf8_to_wstring(pstream_name);
|
||||
|
||||
pstream->open( target_path.c_str(), std::ios_base::out | std::ios::app /*ios_base::trunc */);
|
||||
if(pstream->fail())
|
||||
return NULL;
|
||||
|
|
@ -754,7 +757,7 @@ namespace log_space
|
|||
|
||||
virtual bool out_buffer( const char* buffer, int buffer_len, int log_level, int color, const char* plog_name = NULL )
|
||||
{
|
||||
std::ofstream* m_target_file_stream = m_pdefault_file_stream;
|
||||
boost::filesystem::ofstream* m_target_file_stream = m_pdefault_file_stream;
|
||||
if(plog_name)
|
||||
{ //find named stream
|
||||
named_log_streams::iterator it = m_log_file_names.find(plog_name);
|
||||
|
|
@ -769,9 +772,10 @@ namespace log_space
|
|||
m_target_file_stream->write(buffer, buffer_len );
|
||||
m_target_file_stream->flush();
|
||||
|
||||
/*
|
||||
if(m_max_logfile_size)
|
||||
{
|
||||
std::ofstream::pos_type pt = m_target_file_stream->tellp();
|
||||
boost::filesystem::ofstream::pos_type pt = m_target_file_stream->tellp();
|
||||
uint64_t current_sz = pt;
|
||||
if(current_sz > m_max_logfile_size)
|
||||
{
|
||||
|
|
@ -818,12 +822,13 @@ namespace log_space
|
|||
misc_utils::call_sys_cmd(m_log_rotate_cmd_local_copy);
|
||||
}
|
||||
|
||||
m_target_file_stream->open( (m_default_log_path + "/" + log_file_name).c_str(), std::ios_base::out | std::ios::app /*ios_base::trunc */);
|
||||
|
||||
m_target_file_stream->open( (m_default_log_path + "/" + log_file_name).c_str(), std::ios_base::out | std::ios::app / * ios_base::trunc * /);
|
||||
if(m_target_file_stream->fail())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
int get_type(){return LOGGER_FILE;}
|
||||
|
|
@ -1369,7 +1374,7 @@ namespace log_space
|
|||
if(!plogger) return false;
|
||||
return plogger->remove_logger(type);
|
||||
}
|
||||
PUSH_WARNINGS
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||
static int get_set_log_detalisation_level(bool is_need_set = false, int log_level_to_set = LOG_LEVEL_1)
|
||||
{
|
||||
|
|
@ -1381,7 +1386,7 @@ DISABLE_GCC_WARNING(maybe-uninitialized)
|
|||
}
|
||||
return log_detalisation_level;
|
||||
}
|
||||
POP_WARNINGS
|
||||
POP_GCC_WARNINGS
|
||||
static int get_set_time_level(bool is_need_set = false, int time_log_level = LOG_LEVEL_0)
|
||||
{
|
||||
static int val_time_log_level = LOG_LEVEL_0;
|
||||
|
|
@ -1700,6 +1705,6 @@ POP_WARNINGS
|
|||
|
||||
} // namespace epee
|
||||
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
||||
#endif //_MISC_LOG_EX_H_
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ namespace misc_utils
|
|||
#include <execinfo.h>
|
||||
#include <boost/core/demangle.hpp>
|
||||
#endif
|
||||
inline std::string print_trace()
|
||||
inline std::string print_trace_default()
|
||||
{
|
||||
std::stringstream ss;
|
||||
#if defined(__GNUC__)
|
||||
|
|
@ -134,5 +134,33 @@ namespace misc_utils
|
|||
#endif
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
typedef std::string (stack_retrieving_function_t)();
|
||||
|
||||
//
|
||||
// To get stack trace call it with the defaults.
|
||||
//
|
||||
inline std::string get_callstack(stack_retrieving_function_t* p_stack_retrieving_function_to_be_added = nullptr, bool remove_func = false)
|
||||
{
|
||||
static stack_retrieving_function_t* p_srf = nullptr;
|
||||
|
||||
if (remove_func)
|
||||
{
|
||||
p_srf = nullptr;
|
||||
return "";
|
||||
}
|
||||
|
||||
if (p_stack_retrieving_function_to_be_added != nullptr)
|
||||
{
|
||||
p_srf = p_stack_retrieving_function_to_be_added;
|
||||
return "";
|
||||
}
|
||||
|
||||
if (p_srf != nullptr)
|
||||
return p_srf();
|
||||
|
||||
return print_trace_default();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
#include "misc_language.h"
|
||||
#include "warnings.h"
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
namespace epee {
|
||||
namespace net_utils {
|
||||
/************************************************************************/
|
||||
|
|
@ -474,8 +474,8 @@ bool boosted_tcp_server<t_protocol_handler>::init_server(uint32_t port, const st
|
|||
CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::init_server", false);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
PUSH_WARNINGS
|
||||
DISABLE_GCC_WARNING(maybe - uninitialized)
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||
template<class t_protocol_handler>
|
||||
bool boosted_tcp_server<t_protocol_handler>::init_server(const std::string port, const std::string& address)
|
||||
{
|
||||
|
|
@ -487,7 +487,7 @@ bool boosted_tcp_server<t_protocol_handler>::init_server(const std::string port,
|
|||
}
|
||||
return this->init_server(p, address);
|
||||
}
|
||||
POP_WARNINGS
|
||||
POP_GCC_WARNINGS
|
||||
//---------------------------------------------------------------------------------
|
||||
template<class t_protocol_handler>
|
||||
bool boosted_tcp_server<t_protocol_handler>::worker_thread()
|
||||
|
|
@ -794,4 +794,4 @@ bool boosted_tcp_server<t_protocol_handler>::connect_async(const std::string& ad
|
|||
}
|
||||
} // namespace net_utils
|
||||
} // namespace epee
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#define HTTP_MAX_PRE_COMMAND_LINE_CHARS 20
|
||||
#define HTTP_MAX_HEADER_LEN 100000
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||
|
||||
|
||||
|
|
@ -690,7 +690,7 @@ namespace net_utils
|
|||
}
|
||||
}
|
||||
|
||||
POP_WARNINGS
|
||||
POP_GCC_WARNINGS
|
||||
//--------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ namespace epee
|
|||
t_result result_struct = AUTO_VAL_INIT(result_struct);
|
||||
if( code <=0 )
|
||||
{
|
||||
LOG_PRINT_L2("BACKTRACE: " << ENDL << epee::misc_utils::print_trace());
|
||||
LOG_PRINT_L2("BACKTRACE: " << ENDL << epee::misc_utils::get_callstack());
|
||||
LOG_PRINT_L1("Failed to invoke command " << command << " return code " << code << "(" << epee::levin::get_err_descr(code) << ")context:" << print_connection_context(context));
|
||||
TRY_ENTRY()
|
||||
cb(code, result_struct, context);
|
||||
|
|
@ -150,7 +150,7 @@ namespace epee
|
|||
}, inv_timeout);
|
||||
if( res <=0 )
|
||||
{
|
||||
LOG_PRINT_L2("BACKTRACE: " << ENDL << epee::misc_utils::print_trace());
|
||||
LOG_PRINT_L2("BACKTRACE: " << ENDL << epee::misc_utils::get_callstack());
|
||||
LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res << "(" << epee::levin::get_err_descr(res) << ") conn_id=" << conn_id);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ namespace epee
|
|||
return load_t_from_binary(out, f_buff);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4100)
|
||||
template<class t_struct>
|
||||
bool store_t_to_binary(const t_struct& str_in, std::string& binary_buff, size_t indent = 0)
|
||||
|
|
@ -110,7 +110,7 @@ DISABLE_VS_WARNINGS(4100)
|
|||
str_in.store(ps);
|
||||
return ps.store_to_binary(binary_buff);
|
||||
}
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
std::string store_t_to_binary(const t_struct& str_in, size_t indent = 0)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace epee
|
|||
return sizeof(pack_value);
|
||||
}
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_GCC_WARNING(strict-aliasing)
|
||||
template<class t_stream>
|
||||
size_t pack_varint(t_stream& strm, size_t val)
|
||||
|
|
@ -67,7 +67,7 @@ namespace epee
|
|||
return pack_varint_t<uint64_t>(strm, PORTABLE_RAW_SIZE_MARK_INT64, val);
|
||||
}
|
||||
}
|
||||
POP_WARNINGS
|
||||
POP_GCC_WARNINGS
|
||||
|
||||
template<class t_stream>
|
||||
bool put_string(t_stream& strm, const std::string& v)
|
||||
|
|
|
|||
|
|
@ -41,33 +41,37 @@ namespace epee
|
|||
template<typename from_type, typename to_type>
|
||||
void convert_int_to_uint(const from_type& from, to_type& to)
|
||||
{
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4018)
|
||||
CHECK_AND_ASSERT_THROW_MES(from >=0, "unexpected int value with signed storage value less than 0, and unsigned receiver value: " << from);
|
||||
DISABLE_GCC_AND_CLANG_WARNING(sign-compare)
|
||||
CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits<to_type>::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits<to_type>::max());
|
||||
to = static_cast<to_type>(from);
|
||||
POP_WARNINGS
|
||||
POP_GCC_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
}
|
||||
template<typename from_type, typename to_type>
|
||||
void convert_int_to_int(const from_type& from, to_type& to)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(from >= boost::numeric::bounds<to_type>::lowest(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with lowest possible value = " << boost::numeric::bounds<to_type>::lowest());
|
||||
PUSH_WARNINGS
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare)
|
||||
CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits<to_type>::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits<to_type>::max());
|
||||
POP_WARNINGS
|
||||
POP_GCC_WARNINGS
|
||||
to = static_cast<to_type>(from);
|
||||
}
|
||||
template<typename from_type, typename to_type>
|
||||
void convert_uint_to_any_int(const from_type& from, to_type& to)
|
||||
{
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4018)
|
||||
DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare)
|
||||
CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits<to_type>::max(), "uint value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits<to_type>::max());
|
||||
to = static_cast<to_type>(from);
|
||||
POP_WARNINGS
|
||||
POP_GCC_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
}
|
||||
|
||||
template<typename from_type, typename to_type, bool, bool> //is from signed, is from to signed
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include <boost/filesystem.hpp>
|
||||
#include "warnings.h"
|
||||
#include "auto_val_init.h"
|
||||
#include "string_coding.h"
|
||||
|
||||
|
||||
#ifndef OUT
|
||||
|
|
@ -215,7 +216,7 @@ namespace string_tools
|
|||
return t_pod;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
PUSH_WARNINGS
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||
template<class XType>
|
||||
inline bool get_xtype_from_string(OUT XType& val, const std::string& str_id)
|
||||
|
|
@ -246,7 +247,7 @@ DISABLE_GCC_WARNING(maybe-uninitialized)
|
|||
|
||||
return true;
|
||||
}
|
||||
POP_WARNINGS
|
||||
POP_GCC_WARNINGS
|
||||
//---------------------------------------------------
|
||||
template<typename int_t>
|
||||
bool get_xnum_from_hex_string(const std::string str, int_t& res )
|
||||
|
|
@ -536,38 +537,15 @@ POP_WARNINGS
|
|||
return module_folder;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
#ifdef _WIN32
|
||||
inline std::string get_current_module_path()
|
||||
inline bool set_module_name_and_folder(const std::string& path_to_process_)
|
||||
{
|
||||
char pname [5000] = {0};
|
||||
GetModuleFileNameA( NULL, pname, sizeof(pname));
|
||||
pname[sizeof(pname)-1] = 0; //be happy ;)
|
||||
return pname;
|
||||
}
|
||||
#endif
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool set_module_name_and_folder(const std::string& path_to_process_)
|
||||
{
|
||||
std::string path_to_process = path_to_process_;
|
||||
boost::system::error_code ec;
|
||||
path_to_process = boost::filesystem::canonical(path_to_process, ec).string();
|
||||
#ifdef _WIN32
|
||||
path_to_process = get_current_module_path();
|
||||
#endif
|
||||
std::string::size_type a = path_to_process.rfind( '\\' );
|
||||
if(a == std::string::npos )
|
||||
{
|
||||
a = path_to_process.rfind( '/' );
|
||||
}
|
||||
if ( a != std::string::npos )
|
||||
{
|
||||
get_current_module_name() = path_to_process.substr(a+1, path_to_process.size());
|
||||
get_current_module_folder() = path_to_process.substr(0, a);
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
boost::filesystem::path path(epee::string_encoding::utf8_to_wstring(path_to_process_));
|
||||
|
||||
}
|
||||
get_current_module_folder() = epee::string_encoding::wstring_to_utf8(path.parent_path().wstring());
|
||||
get_current_module_name() = epee::string_encoding::wstring_to_utf8(path.filename().wstring());
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool trim_left(std::string& str)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,10 +59,10 @@ namespace misc_utils
|
|||
|
||||
char tmpbuf[200] = {0};
|
||||
tm* pt = NULL;
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4996)
|
||||
pt = localtime(&time_);
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
||||
if(pt)
|
||||
strftime( tmpbuf, 199, "%d.%m.%Y %H:%M:%S", pt );
|
||||
|
|
@ -81,10 +81,10 @@ POP_WARNINGS
|
|||
|
||||
char tmpbuf[200] = {0};
|
||||
tm* pt = NULL;
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4996)
|
||||
pt = localtime(&time_);
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
||||
if(pt)
|
||||
strftime( tmpbuf, 199, "%Y_%m_%d %H_%M_%S", pt );
|
||||
|
|
@ -109,10 +109,10 @@ POP_WARNINGS
|
|||
{
|
||||
char tmpbuf[200] = {0};
|
||||
tm* pt = NULL;
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4996)
|
||||
pt = gmtime(&time_);
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
strftime( tmpbuf, 199, "%a, %d %b %Y %H:%M:%S GMT", pt );
|
||||
return tmpbuf;
|
||||
}
|
||||
|
|
@ -126,7 +126,7 @@ POP_WARNINGS
|
|||
tail = -tail;
|
||||
res = "-";
|
||||
}
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4244)
|
||||
int days = tail/(60*60*24);
|
||||
tail = tail%(60*60*24);
|
||||
|
|
@ -135,7 +135,7 @@ DISABLE_VS_WARNINGS(4244)
|
|||
int minutes = tail/(60);
|
||||
tail = tail%(60);
|
||||
int seconds = tail;
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
res += std::string("d") + boost::lexical_cast<std::string>(days) + ".h" + boost::lexical_cast<std::string>(hours) + ".m" + boost::lexical_cast<std::string>(minutes) + ".s" + boost::lexical_cast<std::string>(seconds);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@
|
|||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#define PUSH_WARNINGS __pragma(warning(push))
|
||||
#define POP_WARNINGS __pragma(warning(pop))
|
||||
#define PUSH_VS_WARNINGS __pragma(warning(push))
|
||||
#define POP_VS_WARNINGS __pragma(warning(pop))
|
||||
|
||||
#define PUSH_GCC_WARNINGS
|
||||
#define POP_GCC_WARNINGS
|
||||
|
||||
#define DISABLE_VS_WARNINGS(w) __pragma(warning(disable: w))
|
||||
#define DISABLE_GCC_WARNING(w)
|
||||
#define DISABLE_CLANG_WARNING(w)
|
||||
|
|
@ -13,8 +17,12 @@
|
|||
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
|
||||
#define PUSH_WARNINGS _Pragma("GCC diagnostic push")
|
||||
#define POP_WARNINGS _Pragma("GCC diagnostic pop")
|
||||
#define PUSH_VS_WARNINGS
|
||||
#define POP_VS_WARNINGS
|
||||
|
||||
#define PUSH_GCC_WARNINGS _Pragma("GCC diagnostic push")
|
||||
#define POP_GCC_WARNINGS _Pragma("GCC diagnostic pop")
|
||||
|
||||
#define DISABLE_VS_WARNINGS(w)
|
||||
|
||||
#if defined(__clang__)
|
||||
|
|
|
|||
|
|
@ -145,7 +145,11 @@ epoch_context_full* create_epoch_context(
|
|||
|
||||
char* const alloc_data = static_cast<char*>(std::calloc(1, alloc_size));
|
||||
if (!alloc_data)
|
||||
return nullptr; // Signal out-of-memory by returning null pointer.
|
||||
{
|
||||
LOG_CUSTOM_WITH_CALLSTACK("CRITICAL: std::calloc(" << alloc_size << ") failed in create_epoch_context()", 0);
|
||||
return nullptr; // Signal out-of-memory by returning null pointer.
|
||||
}
|
||||
LOG_CUSTOM("context for epoch " << epoch_number << " allocated, size: " << alloc_size << " bytes", 0);
|
||||
|
||||
hash512* const light_cache = reinterpret_cast<hash512*>(alloc_data + context_alloc_size);
|
||||
const hash256 epoch_seed = calculate_epoch_seed(epoch_number);
|
||||
|
|
@ -373,6 +377,33 @@ search_result search(const epoch_context_full& context, const hash256& header_ha
|
|||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
custom_log_level_function*& access_custom_log_level_function()
|
||||
{
|
||||
static custom_log_level_function* p_custom_log_level_function = nullptr;
|
||||
return p_custom_log_level_function;
|
||||
}
|
||||
|
||||
custom_log_function*& access_custom_log_function()
|
||||
{
|
||||
static custom_log_function* p_custom_log_function = nullptr;
|
||||
return p_custom_log_function;
|
||||
}
|
||||
|
||||
int get_custom_log_level()
|
||||
{
|
||||
if (access_custom_log_level_function() != nullptr)
|
||||
return access_custom_log_level_function()();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void custom_log(const std::string& m, bool add_callstack)
|
||||
{
|
||||
if (access_custom_log_function() != nullptr)
|
||||
access_custom_log_function()(m, add_callstack);
|
||||
}
|
||||
|
||||
|
||||
} // namespace ethash
|
||||
|
||||
using namespace ethash;
|
||||
|
|
@ -434,6 +465,8 @@ void ethash_destroy_epoch_context_full(epoch_context_full* context) noexcept
|
|||
|
||||
void ethash_destroy_epoch_context(epoch_context* context) noexcept
|
||||
{
|
||||
LOG_CUSTOM("context for epoch " << context->epoch_number << " is about to be freed", 0);
|
||||
|
||||
context->~epoch_context();
|
||||
std::free(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace ethash
|
||||
{
|
||||
|
|
@ -156,5 +158,34 @@ int find_epoch_number(const hash256& seed) noexcept;
|
|||
const epoch_context& get_global_epoch_context(int epoch_number);
|
||||
|
||||
/// Get global shared epoch context with full dataset initialized.
|
||||
const epoch_context_full& get_global_epoch_context_full(int epoch_number);
|
||||
std::shared_ptr<epoch_context_full> get_global_epoch_context_full(int epoch_number);
|
||||
|
||||
typedef int (custom_log_level_function)();
|
||||
typedef void (custom_log_function)(const std::string& m, bool add_callstack);
|
||||
|
||||
custom_log_level_function*& access_custom_log_level_function();
|
||||
custom_log_function*& access_custom_log_function();
|
||||
int get_custom_log_level();
|
||||
void custom_log(const std::string& m, bool add_callstack);
|
||||
|
||||
#define LOG_CUSTOM(msg, level) \
|
||||
{ \
|
||||
if (level <= ethash::get_custom_log_level()) \
|
||||
{ \
|
||||
std::stringstream ss; \
|
||||
ss << msg << std::endl; \
|
||||
ethash::custom_log(ss.str(), false); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LOG_CUSTOM_WITH_CALLSTACK(msg, level) \
|
||||
{ \
|
||||
if (level <= ethash::get_custom_log_level()) \
|
||||
{ \
|
||||
std::stringstream ss; \
|
||||
ss << msg << std::endl; \
|
||||
ethash::custom_log(ss.str(), true); \
|
||||
} \
|
||||
}
|
||||
|
||||
} // namespace ethash
|
||||
|
|
|
|||
|
|
@ -89,12 +89,12 @@ const epoch_context& get_global_epoch_context(int epoch_number)
|
|||
return *thread_local_context;
|
||||
}
|
||||
|
||||
const epoch_context_full& get_global_epoch_context_full(int epoch_number)
|
||||
std::shared_ptr<epoch_context_full> get_global_epoch_context_full(int epoch_number)
|
||||
{
|
||||
// Check if local context matches epoch number.
|
||||
if (!thread_local_context_full || thread_local_context_full->epoch_number != epoch_number)
|
||||
update_local_context_full(epoch_number);
|
||||
|
||||
return *thread_local_context_full;
|
||||
return thread_local_context_full;
|
||||
}
|
||||
} // namespace ethash
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace tools
|
|||
bool serialize_obj_to_file(t_object& obj, const std::string& file_path)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::ofstream data_file;
|
||||
data_file.open( file_path , std::ios_base::binary | std::ios_base::out| std::ios::trunc);
|
||||
boost::filesystem::ofstream data_file;
|
||||
data_file.open( epee::string_encoding::utf8_to_wstring(file_path) , std::ios_base::binary | std::ios_base::out| std::ios::trunc);
|
||||
if(data_file.fail())
|
||||
return false;
|
||||
|
||||
|
|
@ -64,8 +64,8 @@ namespace tools
|
|||
{
|
||||
TRY_ENTRY();
|
||||
|
||||
std::ifstream data_file;
|
||||
data_file.open( file_path, std::ios_base::binary | std::ios_base::in);
|
||||
boost::filesystem::ifstream data_file;
|
||||
data_file.open( epee::string_encoding::utf8_to_wstring(file_path), std::ios_base::binary | std::ios_base::in);
|
||||
if(data_file.fail())
|
||||
return false;
|
||||
boost::archive::binary_iarchive a(data_file);
|
||||
|
|
|
|||
179
src/common/callstack_helper.cpp
Normal file
179
src/common/callstack_helper.cpp
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
// Copyright (c) 2019 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <Psapi.h>
|
||||
#pragma comment(lib, "psapi.lib")
|
||||
#pragma comment(lib, "dbghelp.lib")
|
||||
|
||||
#pragma pack( push, before_imagehlp, 8 )
|
||||
#include <imagehlp.h>
|
||||
#pragma pack( pop, before_imagehlp )
|
||||
|
||||
#include "include_base_utils.h"
|
||||
#include "callstack_helper.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct module_data
|
||||
{
|
||||
std::string image_name;
|
||||
std::string module_name;
|
||||
void *base_address;
|
||||
DWORD load_size;
|
||||
};
|
||||
|
||||
|
||||
class get_mod_info
|
||||
{
|
||||
HANDLE process;
|
||||
static const int buffer_length = 4096;
|
||||
public:
|
||||
get_mod_info(HANDLE h) : process(h) {}
|
||||
|
||||
module_data operator()(HMODULE module)
|
||||
{
|
||||
module_data ret;
|
||||
char temp[buffer_length];
|
||||
MODULEINFO mi;
|
||||
|
||||
GetModuleInformation(process, module, &mi, sizeof(mi));
|
||||
ret.base_address = mi.lpBaseOfDll;
|
||||
ret.load_size = mi.SizeOfImage;
|
||||
|
||||
GetModuleFileNameEx(process, module, temp, sizeof(temp));
|
||||
ret.image_name = temp;
|
||||
GetModuleBaseName(process, module, temp, sizeof(temp));
|
||||
ret.module_name = temp;
|
||||
std::vector<char> img(ret.image_name.begin(), ret.image_name.end());
|
||||
std::vector<char> mod(ret.module_name.begin(), ret.module_name.end());
|
||||
SymLoadModule64(process, 0, &img[0], &mod[0], (DWORD64)ret.base_address, ret.load_size);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
std::string get_symbol_undecorated_name(HANDLE process, DWORD64 address, std::stringstream& ss)
|
||||
{
|
||||
SYMBOL_INFO* sym;
|
||||
static const int max_name_len = 1024;
|
||||
std::vector<char> sym_buffer(sizeof(SYMBOL_INFO) + max_name_len, '\0');
|
||||
sym = (SYMBOL_INFO *)sym_buffer.data();
|
||||
sym->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
sym->MaxNameLen = max_name_len;
|
||||
|
||||
DWORD64 displacement;
|
||||
if (!SymFromAddr(process, address, &displacement, sym))
|
||||
return std::string("SymFromAddr failed1: ") + epee::string_tools::num_to_string_fast(GetLastError());
|
||||
|
||||
if (*sym->Name == '\0')
|
||||
return std::string("SymFromAddr failed2: ") + epee::string_tools::num_to_string_fast(GetLastError());
|
||||
|
||||
/*
|
||||
ss << " SizeOfStruct : " << sym->SizeOfStruct << ENDL;
|
||||
ss << " TypeIndex : " << sym->TypeIndex << ENDL; // Type Index of symbol
|
||||
ss << " Index : " << sym->Index << ENDL;
|
||||
ss << " Size : " << sym->Size << ENDL;
|
||||
ss << " ModBase : " << sym->ModBase << ENDL; // Base Address of module comtaining this symbol
|
||||
ss << " Flags : " << sym->Flags << ENDL;
|
||||
ss << " Value : " << sym->Value << ENDL; // Value of symbol, ValuePresent should be 1
|
||||
ss << " Address : " << sym->Address << ENDL; // Address of symbol including base address of module
|
||||
ss << " Register : " << sym->Register << ENDL; // register holding value or pointer to value
|
||||
ss << " Scope : " << sym->Scope << ENDL; // scope of the symbol
|
||||
ss << " Tag : " << sym->Tag << ENDL; // pdb classification
|
||||
ss << " NameLen : " << sym->NameLen << ENDL; // Actual length of name
|
||||
ss << " MaxNameLen : " << sym->MaxNameLen << ENDL;
|
||||
ss << " Name[1] : " << &sym->Name << ENDL; // Name of symbol
|
||||
*/
|
||||
|
||||
std::string und_name(max_name_len, '\0');
|
||||
DWORD chars_written = UnDecorateSymbolName(sym->Name, &und_name.front(), max_name_len, UNDNAME_COMPLETE);
|
||||
und_name.resize(chars_written);
|
||||
return und_name;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace tools
|
||||
{
|
||||
|
||||
std::string get_callstack_win_x64()
|
||||
{
|
||||
HANDLE h_process = GetCurrentProcess();
|
||||
HANDLE h_thread = GetCurrentThread();
|
||||
|
||||
PCSTR user_search_path = NULL; // may be path to a pdb?
|
||||
if (!SymInitialize(h_process, user_search_path, false))
|
||||
return "<win callstack error 1>";
|
||||
|
||||
DWORD sym_options = SymGetOptions();
|
||||
sym_options |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME;
|
||||
SymSetOptions(sym_options);
|
||||
|
||||
DWORD cb_needed;
|
||||
std::vector<HMODULE> module_handles(1);
|
||||
EnumProcessModules(h_process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cb_needed);
|
||||
module_handles.resize(cb_needed / sizeof(HMODULE));
|
||||
EnumProcessModules(h_process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cb_needed);
|
||||
|
||||
std::vector<module_data> modules;
|
||||
std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(h_process));
|
||||
void *base = modules[0].base_address;
|
||||
|
||||
CONTEXT context;
|
||||
memset(&context, 0, sizeof context);
|
||||
RtlCaptureContext( &context );
|
||||
|
||||
STACKFRAME64 frame;
|
||||
memset(&frame, 0, sizeof frame);
|
||||
frame.AddrPC.Offset = context.Rip;
|
||||
frame.AddrPC.Mode = AddrModeFlat;
|
||||
frame.AddrStack.Offset = context.Rsp;
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
frame.AddrFrame.Offset = context.Rbp;
|
||||
frame.AddrFrame.Mode = AddrModeFlat;
|
||||
|
||||
IMAGEHLP_LINE64 line = { 0 };
|
||||
line.SizeOfStruct = sizeof line;
|
||||
IMAGE_NT_HEADERS *image_nt_header = ImageNtHeader(base);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << ENDL;
|
||||
// ss << "main module loaded at 0x" << std::hex << std::setw(16) << std::setfill('0') << base << std::dec << " from " << modules[0].image_name << ENDL;
|
||||
for (size_t n = 0; n < 250; ++n)
|
||||
{
|
||||
if (!StackWalk64(image_nt_header->FileHeader.Machine, h_process, h_thread, &frame, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
|
||||
break;
|
||||
if (frame.AddrReturn.Offset == 0)
|
||||
break;
|
||||
|
||||
std::string fnName = get_symbol_undecorated_name(h_process, frame.AddrPC.Offset, ss);
|
||||
ss << "0x" << std::setw(16) << std::setfill('0') << std::hex << frame.AddrPC.Offset << " " << std::dec << fnName;
|
||||
DWORD offset_from_line = 0;
|
||||
if (SymGetLineFromAddr64(h_process, frame.AddrPC.Offset, &offset_from_line, &line))
|
||||
ss << "+" << offset_from_line << " " << line.FileName << "(" << line.LineNumber << ")";
|
||||
|
||||
for (auto el : modules)
|
||||
{
|
||||
if ((DWORD64)el.base_address <= frame.AddrPC.Offset && frame.AddrPC.Offset < (DWORD64)el.base_address + (DWORD64)el.load_size)
|
||||
{
|
||||
ss << " : " << el.module_name << " @ 0x" << std::setw(0) << std::hex << (DWORD64)el.base_address << ENDL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
SymCleanup(h_process);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace tools
|
||||
|
||||
#endif // #if defined(WIN32)
|
||||
24
src/common/callstack_helper.h
Normal file
24
src/common/callstack_helper.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) 2019 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
#include <epee/include/misc_os_dependent.h>
|
||||
|
||||
namespace tools
|
||||
{
|
||||
#if defined(WIN32)
|
||||
extern std::string get_callstack_win_x64();
|
||||
#endif
|
||||
|
||||
inline std::string get_callstack()
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
return epee::misc_utils::print_trace_default();
|
||||
#elif defined(WIN32)
|
||||
return get_callstack_win_x64();
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace tools
|
||||
|
|
@ -122,7 +122,7 @@ namespace command_line
|
|||
boost::program_options::basic_parsed_options<charT> parse_command_line(int argc, const charT* const argv[],
|
||||
const boost::program_options::options_description& desc, bool allow_unregistered = false)
|
||||
{
|
||||
auto parser = boost::program_options::command_line_parser(argc, argv);
|
||||
auto parser = boost::program_options::basic_command_line_parser<charT>(argc, argv);
|
||||
parser.options(desc);
|
||||
if (allow_unregistered)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -241,9 +241,9 @@ namespace tools
|
|||
m_is_open = false;
|
||||
return m_backend->close();
|
||||
}
|
||||
bool open(const std::string& path, uint64_t flags = 0)
|
||||
bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE)
|
||||
{
|
||||
bool r = m_backend->open(path, flags);
|
||||
bool r = m_backend->open(path, cache_sz);
|
||||
if(r)
|
||||
m_is_open = true;
|
||||
|
||||
|
|
@ -558,10 +558,10 @@ namespace tools
|
|||
bool init(const std::string& container_name)
|
||||
{
|
||||
#ifdef ENABLE_PROFILING
|
||||
m_get_profiler.m_name = container_name +":get";
|
||||
m_set_profiler.m_name = container_name + ":set";
|
||||
m_explicit_get_profiler.m_name = container_name + ":explicit_get";
|
||||
m_explicit_set_profiler.m_name = container_name + ":explicit_set";
|
||||
m_get_profiler.m_name = container_name +":get";
|
||||
m_set_profiler.m_name = container_name + ":set";
|
||||
m_explicit_get_profiler.m_name = container_name + ":explicit_get";
|
||||
m_explicit_set_profiler.m_name = container_name + ":explicit_set";
|
||||
m_commit_profiler.m_name = container_name + ":commit";
|
||||
#endif
|
||||
return bdb.get_backend()->open_container(container_name, m_h);
|
||||
|
|
@ -659,28 +659,27 @@ namespace tools
|
|||
{
|
||||
return bdb.size(m_h);
|
||||
}
|
||||
size_t clear()
|
||||
|
||||
bool clear()
|
||||
{
|
||||
bdb.clear(m_h);
|
||||
bool result = bdb.clear(m_h);
|
||||
m_isolation.isolated_write_access<bool>([&](){
|
||||
size_cache_valid = false;
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool erase_validate(const t_key& k)
|
||||
{
|
||||
auto res_ptr = this->get(k);
|
||||
bdb.erase(m_h, k);
|
||||
bool result = bdb.erase(m_h, k);
|
||||
m_isolation.isolated_write_access<bool>([&](){
|
||||
size_cache_valid = false;
|
||||
return true;
|
||||
});
|
||||
return static_cast<bool>(res_ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void erase(const t_key& k)
|
||||
{
|
||||
bdb.erase(m_h, k);
|
||||
|
|
@ -861,13 +860,10 @@ namespace tools
|
|||
|
||||
operator t_value() const
|
||||
{
|
||||
static_assert(std::is_pod<t_value>::value, "t_value must be a POD type.");
|
||||
std::shared_ptr<const t_value> value_ptr = m_accessor.template explicit_get<t_key, t_value, access_strategy_selector<is_t_strategy> >(m_key);
|
||||
if (value_ptr.get())
|
||||
return *value_ptr.get();
|
||||
|
||||
std::shared_ptr<const t_value> vptr = m_accessor.template explicit_get<t_key, t_value, access_strategy_selector<false> >(m_key);
|
||||
if (vptr.get())
|
||||
{
|
||||
return *vptr.get();
|
||||
}
|
||||
return AUTO_VAL_INIT(t_value());
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifndef ENV32BIT
|
||||
#define CACHE_SIZE uint64_t(uint64_t(1UL * 128UL) * 1024UL * 1024UL * 1024UL)
|
||||
#else
|
||||
#define CACHE_SIZE (1 * 1024UL * 1024UL * 1024UL)
|
||||
#endif
|
||||
|
||||
|
||||
namespace tools
|
||||
{
|
||||
namespace db
|
||||
|
|
@ -25,20 +32,20 @@ namespace tools
|
|||
|
||||
struct i_db_backend
|
||||
{
|
||||
virtual bool close() = 0;
|
||||
virtual bool close()=0;
|
||||
virtual bool begin_transaction(bool read_only = false) = 0;
|
||||
virtual bool commit_transaction() = 0;
|
||||
virtual void abort_transaction() = 0;
|
||||
virtual bool open(const std::string& path, uint64_t flags = 0) = 0;
|
||||
virtual bool open_container(const std::string& name, container_handle& h) = 0;
|
||||
virtual bool commit_transaction()=0;
|
||||
virtual void abort_transaction()=0;
|
||||
virtual bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE) = 0;
|
||||
virtual bool open_container(const std::string& name, container_handle& h)=0;
|
||||
virtual bool erase(container_handle h, const char* k, size_t s) = 0;
|
||||
virtual uint64_t size(container_handle h) = 0;
|
||||
virtual bool get(container_handle h, const char* k, size_t s, std::string& res_buff) = 0;
|
||||
virtual bool set(container_handle h, const char* k, size_t s, const char* v, size_t vs) = 0;
|
||||
virtual bool clear(container_handle h) = 0;
|
||||
virtual bool enumerate(container_handle h, i_db_callback* pcb) = 0;
|
||||
virtual bool enumerate(container_handle h, i_db_callback* pcb)=0;
|
||||
virtual bool get_stat_info(stat_info& si) = 0;
|
||||
virtual ~i_db_backend() {};
|
||||
virtual ~i_db_backend(){};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,10 +10,6 @@
|
|||
#include "util.h"
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
#define DB_RESIZE_MIN_FREE_SIZE (100 * 1024 * 1024) // DB map size will grow if that much space left on DB
|
||||
#define DB_RESIZE_MIN_MAX_SIZE (50 * 1024 * 1024) // Minimum DB map size (starting size)
|
||||
#define DB_RESIZE_INCREMENT_SIZE (100 * 1024 * 1024) // Grow step size
|
||||
#define DB_RESIZE_COMMITS_TO_CHECK 50
|
||||
|
||||
#define CHECK_AND_ASSERT_MESS_LMDB_DB(rc, ret, mess) CHECK_AND_ASSERT_MES(res == MDB_SUCCESS, ret, "[DB ERROR]:(" << rc << ")" << mdb_strerror(rc) << ", [message]: " << mess);
|
||||
#define CHECK_AND_ASSERT_THROW_MESS_LMDB_DB(rc, mess) CHECK_AND_ASSERT_THROW_MES(res == MDB_SUCCESS, "[DB ERROR]:(" << rc << ")" << mdb_strerror(rc) << ", [message]: " << mess);
|
||||
|
|
@ -27,13 +23,10 @@ namespace tools
|
|||
{
|
||||
namespace db
|
||||
{
|
||||
lmdb_db_backend::lmdb_db_backend()
|
||||
: m_penv(AUTO_VAL_INIT(m_penv))
|
||||
, m_commits_count(0)
|
||||
lmdb_db_backend::lmdb_db_backend() : m_penv(AUTO_VAL_INIT(m_penv))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
lmdb_db_backend::~lmdb_db_backend()
|
||||
{
|
||||
NESTED_TRY_ENTRY();
|
||||
|
|
@ -43,31 +36,23 @@ namespace tools
|
|||
NESTED_CATCH_ENTRY(__func__);
|
||||
}
|
||||
|
||||
bool lmdb_db_backend::open(const std::string& path_, uint64_t /* flags -- unused atm */)
|
||||
bool lmdb_db_backend::open(const std::string& path_, uint64_t cache_sz)
|
||||
{
|
||||
int res = 0;
|
||||
res = mdb_env_create(&m_penv);
|
||||
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_create");
|
||||
|
||||
MDB_dbi max_dbs = 15;
|
||||
res = mdb_env_set_maxdbs(m_penv, max_dbs);
|
||||
res = mdb_env_set_maxdbs(m_penv, 15);
|
||||
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_set_maxdbs");
|
||||
|
||||
res = mdb_env_set_mapsize(m_penv, cache_sz);
|
||||
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_set_mapsize");
|
||||
|
||||
m_path = path_;
|
||||
#ifdef WIN32
|
||||
m_path = epee::string_encoding::convert_ansii_to_utf8(m_path);
|
||||
#endif
|
||||
|
||||
CHECK_AND_ASSERT_MES(tools::create_directories_if_necessary(m_path), false, "create_directories_if_necessary failed: " << m_path);
|
||||
|
||||
// TODO: convert flags to lmdb_flags (implement fast lmdb modes)
|
||||
unsigned int lmdb_flags = MDB_NORDAHEAD /*| MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC*/;
|
||||
mdb_mode_t lmdb_mode = 0644;
|
||||
|
||||
res = mdb_env_open(m_penv, m_path.c_str(), lmdb_flags, lmdb_mode);
|
||||
res = mdb_env_open(m_penv, m_path.c_str(), MDB_NORDAHEAD , 0644);
|
||||
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_open, m_path=" << m_path);
|
||||
|
||||
resize_if_needed();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -116,13 +101,6 @@ namespace tools
|
|||
{
|
||||
LOG_PRINT_CYAN("[DB " << m_path << "] WRITE LOCKED", LOG_LEVEL_3);
|
||||
CRITICAL_SECTION_LOCK(m_write_exclusive_lock);
|
||||
|
||||
if (m_commits_count.fetch_add(1, std::memory_order_relaxed) % DB_RESIZE_COMMITS_TO_CHECK == DB_RESIZE_COMMITS_TO_CHECK - 1)
|
||||
{
|
||||
if (!resize_if_needed())
|
||||
m_commits_count.store(DB_RESIZE_COMMITS_TO_CHECK - 1, std::memory_order_relaxed); // if failed, try again on next commit
|
||||
}
|
||||
|
||||
}
|
||||
PROFILE_FUNC("lmdb_db_backend::begin_transaction");
|
||||
{
|
||||
|
|
@ -347,7 +325,6 @@ namespace tools
|
|||
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_put");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lmdb_db_backend::enumerate(container_handle h, i_db_callback* pcb)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(pcb, false, "null capback ptr passed to enumerate");
|
||||
|
|
@ -402,42 +379,6 @@ namespace tools
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lmdb_db_backend::resize_if_needed()
|
||||
{
|
||||
LOG_PRINT_CYAN("[DB " << m_path << "] WRITE LOCKED in resize_if_needed()", LOG_LEVEL_3);
|
||||
CRITICAL_REGION_LOCAL(m_write_exclusive_lock);
|
||||
|
||||
if (have_tx())
|
||||
{
|
||||
LOG_PRINT_RED("[DB " << m_path << "] : resize_if_needed(): Have txs on stack, unable to resize!", LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
|
||||
MDB_stat st = AUTO_VAL_INIT(st);
|
||||
mdb_env_stat(m_penv, &st);
|
||||
MDB_envinfo ei = AUTO_VAL_INIT(ei);
|
||||
mdb_env_info(m_penv, &ei);
|
||||
|
||||
uint64_t dirty_size = ei.me_last_pgno * st.ms_psize;
|
||||
int64_t size_diff = ei.me_mapsize - dirty_size;
|
||||
if (size_diff >= DB_RESIZE_MIN_FREE_SIZE && ei.me_mapsize >= DB_RESIZE_MIN_MAX_SIZE)
|
||||
return true; // resize is not needed
|
||||
|
||||
double gigabyte = 1024 * 1024 * 1024;
|
||||
const uint64_t increment_size_pg_aligned = DB_RESIZE_INCREMENT_SIZE - (DB_RESIZE_INCREMENT_SIZE % st.ms_psize);
|
||||
|
||||
// need to resize DB
|
||||
uint64_t new_size = ei.me_mapsize - (ei.me_mapsize % increment_size_pg_aligned) + increment_size_pg_aligned;
|
||||
|
||||
int res = mdb_env_set_mapsize(m_penv, new_size);
|
||||
CHECK_AND_ASSERT_MESS_LMDB_DB(res, false, "Unable to mdb_env_set_mapsize");
|
||||
|
||||
LOG_PRINT_CYAN("[DB " << m_path << "] has grown: " << std::fixed << std::setprecision(2) << ei.me_mapsize / gigabyte << " GiB -> " << std::fixed << std::setprecision(2) << new_size / gigabyte << " GiB", LOG_LEVEL_0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Copyright (c) 2014-2019 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
@ -6,7 +6,6 @@
|
|||
#pragma once
|
||||
#include <thread>
|
||||
|
||||
|
||||
#include "include_base_utils.h"
|
||||
|
||||
#include "db_backend_base.h"
|
||||
|
|
@ -17,9 +16,6 @@ namespace tools
|
|||
{
|
||||
namespace db
|
||||
{
|
||||
|
||||
|
||||
|
||||
class lmdb_db_backend : public i_db_backend
|
||||
{
|
||||
|
||||
|
|
@ -38,11 +34,7 @@ namespace tools
|
|||
boost::recursive_mutex m_cs;
|
||||
boost::recursive_mutex m_write_exclusive_lock;
|
||||
std::map<std::thread::id, transactions_list> m_txs; // size_t -> count of nested read_only transactions
|
||||
std::atomic<uint64_t> m_commits_count;
|
||||
|
||||
bool pop_tx_entry(tx_entry& txe);
|
||||
|
||||
|
||||
public:
|
||||
lmdb_db_backend();
|
||||
~lmdb_db_backend();
|
||||
|
|
@ -52,7 +44,7 @@ namespace tools
|
|||
bool begin_transaction(bool read_only = false);
|
||||
bool commit_transaction();
|
||||
void abort_transaction();
|
||||
bool open(const std::string& path, uint64_t flags = 0);
|
||||
bool open(const std::string& path, uint64_t cache_sz = CACHE_SIZE);
|
||||
bool open_container(const std::string& name, container_handle& h);
|
||||
bool erase(container_handle h, const char* k, size_t s);
|
||||
bool get(container_handle h, const char* k, size_t s, std::string& res_buff);
|
||||
|
|
@ -64,8 +56,7 @@ namespace tools
|
|||
//-------------------------------------------------------------------------------------
|
||||
bool have_tx();
|
||||
MDB_txn* get_current_tx();
|
||||
bool resize_if_needed();
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
265
src/common/ntp.cpp
Normal file
265
src/common/ntp.cpp
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
// Copyright (c) 2019 Zano Project
|
||||
|
||||
// Note: class udp_blocking_client is a slightly modified version of an example
|
||||
// taken from https://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/example/timeouts/blocking_udp_client.cpp
|
||||
//
|
||||
// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/udp.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <epee/include/misc_log_ex.h>
|
||||
#include <chrono>
|
||||
#include "ntp.h"
|
||||
|
||||
using boost::asio::deadline_timer;
|
||||
using boost::asio::ip::udp;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// This class manages socket timeouts by applying the concept of a deadline.
|
||||
// Each asynchronous operation is given a deadline by which it must complete.
|
||||
// Deadlines are enforced by an "actor" that persists for the lifetime of the
|
||||
// client object:
|
||||
//
|
||||
// +----------------+
|
||||
// | |
|
||||
// | check_deadline |<---+
|
||||
// | | |
|
||||
// +----------------+ | async_wait()
|
||||
// | |
|
||||
// +---------+
|
||||
//
|
||||
// If the actor determines that the deadline has expired, any outstanding
|
||||
// socket operations are cancelled. The socket operations themselves are
|
||||
// implemented as transient actors:
|
||||
//
|
||||
// +---------------+
|
||||
// | |
|
||||
// | receive |
|
||||
// | |
|
||||
// +---------------+
|
||||
// |
|
||||
// async_- | +----------------+
|
||||
// receive() | | |
|
||||
// +--->| handle_receive |
|
||||
// | |
|
||||
// +----------------+
|
||||
//
|
||||
// The client object runs the io_service to block thread execution until the
|
||||
// actor completes.
|
||||
//
|
||||
namespace
|
||||
{
|
||||
class udp_blocking_client
|
||||
{
|
||||
public:
|
||||
udp_blocking_client(const udp::endpoint& listen_endpoint, udp::socket& socket, boost::asio::io_service& io_service)
|
||||
: socket_(socket),
|
||||
io_service_(io_service),
|
||||
deadline_(io_service)
|
||||
{
|
||||
// No deadline is required until the first socket operation is started. We
|
||||
// set the deadline to positive infinity so that the actor takes no action
|
||||
// until a specific deadline is set.
|
||||
deadline_.expires_at(boost::posix_time::pos_infin);
|
||||
|
||||
// Start the persistent actor that checks for deadline expiry.
|
||||
check_deadline();
|
||||
}
|
||||
|
||||
std::size_t receive(const boost::asio::mutable_buffer& buffer,
|
||||
boost::posix_time::time_duration timeout, boost::system::error_code& ec)
|
||||
{
|
||||
// Set a deadline for the asynchronous operation.
|
||||
deadline_.expires_from_now(timeout);
|
||||
|
||||
// Set up the variables that receive the result of the asynchronous
|
||||
// operation. The error code is set to would_block to signal that the
|
||||
// operation is incomplete. Asio guarantees that its asynchronous
|
||||
// operations will never fail with would_block, so any other value in
|
||||
// ec indicates completion.
|
||||
ec = boost::asio::error::would_block;
|
||||
std::size_t length = 0;
|
||||
|
||||
// Start the asynchronous operation itself. The handle_receive function
|
||||
// used as a callback will update the ec and length variables.
|
||||
socket_.async_receive(boost::asio::buffer(buffer),
|
||||
boost::bind(&udp_blocking_client::handle_receive, _1, _2, &ec, &length));
|
||||
|
||||
// Block until the asynchronous operation has completed.
|
||||
do io_service_.run_one(); while (ec == boost::asio::error::would_block);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private:
|
||||
void check_deadline()
|
||||
{
|
||||
// Check whether the deadline has passed. We compare the deadline against
|
||||
// the current time since a new asynchronous operation may have moved the
|
||||
// deadline before this actor had a chance to run.
|
||||
if (deadline_.expires_at() <= deadline_timer::traits_type::now())
|
||||
{
|
||||
// The deadline has passed. The outstanding asynchronous operation needs
|
||||
// to be cancelled so that the blocked receive() function will return.
|
||||
//
|
||||
// Please note that cancel() has portability issues on some versions of
|
||||
// Microsoft Windows, and it may be necessary to use close() instead.
|
||||
// Consult the documentation for cancel() for further information.
|
||||
socket_.cancel();
|
||||
|
||||
// There is no longer an active deadline. The expiry is set to positive
|
||||
// infinity so that the actor takes no action until a new deadline is set.
|
||||
deadline_.expires_at(boost::posix_time::pos_infin);
|
||||
}
|
||||
|
||||
// Put the actor back to sleep.
|
||||
deadline_.async_wait(boost::bind(&udp_blocking_client::check_deadline, this));
|
||||
}
|
||||
|
||||
static void handle_receive(
|
||||
const boost::system::error_code& ec, std::size_t length,
|
||||
boost::system::error_code* out_ec, std::size_t* out_length)
|
||||
{
|
||||
*out_ec = ec;
|
||||
*out_length = length;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::io_service& io_service_;
|
||||
udp::socket& socket_;
|
||||
deadline_timer deadline_;
|
||||
};
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ntp_packet
|
||||
{
|
||||
|
||||
uint8_t li_vn_mode; // Eight bits. li, vn, and mode.
|
||||
// li. Two bits. Leap indicator.
|
||||
// vn. Three bits. Version number of the protocol.
|
||||
// mode. Three bits. Client will pick mode 3 for client.
|
||||
|
||||
uint8_t stratum; // Eight bits. Stratum level of the local clock.
|
||||
uint8_t poll; // Eight bits. Maximum interval between successive messages.
|
||||
uint8_t precision; // Eight bits. Precision of the local clock.
|
||||
|
||||
uint32_t rootDelay; // 32 bits. Total round trip delay time.
|
||||
uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source.
|
||||
uint32_t refId; // 32 bits. Reference clock identifier.
|
||||
|
||||
uint32_t refTm_s; // 32 bits. Reference time-stamp seconds.
|
||||
uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second.
|
||||
|
||||
uint64_t orig_tm; // 64 bits. Originate time-stamp (set by client)
|
||||
|
||||
uint32_t rxTm_s; // 32 bits. Received time-stamp seconds.
|
||||
uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second.
|
||||
|
||||
uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds.
|
||||
uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second.
|
||||
|
||||
}; // Total: 384 bits or 48 bytes.
|
||||
#pragma pack(pop)
|
||||
|
||||
static_assert(sizeof(ntp_packet) == 48, "ntp_packet has invalid size");
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace tools
|
||||
{
|
||||
int64_t get_ntp_time(const std::string& host_name, size_t timeout_sec)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::asio::io_service io_service;
|
||||
boost::asio::ip::udp::resolver resolver(io_service);
|
||||
boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), host_name, "ntp");
|
||||
boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query);
|
||||
boost::asio::ip::udp::socket socket(io_service);
|
||||
socket.open(boost::asio::ip::udp::v4());
|
||||
|
||||
ntp_packet packet_sent = AUTO_VAL_INIT(packet_sent);
|
||||
packet_sent.li_vn_mode = 0x1b;
|
||||
auto packet_sent_time = std::chrono::high_resolution_clock::now();
|
||||
socket.send_to(boost::asio::buffer(&packet_sent, sizeof packet_sent), receiver_endpoint);
|
||||
|
||||
ntp_packet packet_received = AUTO_VAL_INIT(packet_received);
|
||||
boost::asio::ip::udp::endpoint sender_endpoint;
|
||||
|
||||
udp_blocking_client ubc(sender_endpoint, socket, io_service);
|
||||
boost::system::error_code ec;
|
||||
size_t len = ubc.receive(boost::asio::buffer(&packet_received, sizeof packet_received), boost::posix_time::seconds(timeout_sec), ec);
|
||||
if (ec)
|
||||
{
|
||||
LOG_PRINT_L3("NTP: get_ntp_time(" << host_name << "): boost error: " << ec.message());
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto packet_received_time = std::chrono::high_resolution_clock::now();
|
||||
int64_t roundtrip_mcs = std::chrono::duration_cast<std::chrono::microseconds>(packet_received_time - packet_sent_time).count();
|
||||
uint64_t roundtrip_s = roundtrip_mcs > 2000000 ? roundtrip_mcs / 2000000 : 0;
|
||||
|
||||
time_t ntp_time = ntohl(packet_received.txTm_s);
|
||||
if (ntp_time <= 2208988800U)
|
||||
{
|
||||
LOG_PRINT_L3("NTP: get_ntp_time(" << host_name << "): wrong txTm_s: " << packet_received.txTm_s);
|
||||
return 0;
|
||||
}
|
||||
// LOG_PRINT_L2("NTP: get_ntp_time(" << host_name << "): RAW time received: " << ntp_time << ", refTm_s: " << ntohl(packet_received.refTm_s) << ", stratum: " << packet_received.stratum << ", round: " << roundtrip_mcs);
|
||||
ntp_time -= 2208988800U; // Unix time starts from 01/01/1970 == 2208988800U
|
||||
ntp_time += roundtrip_s;
|
||||
return ntp_time;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_PRINT_L2("NTP: get_ntp_time(" << host_name << "): exception: " << e.what());
|
||||
return 0;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_PRINT_L2("NTP: get_ntp_time(" << host_name << "): unknown exception");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define TIME_SYNC_NTP_SERVERS "time1.google.com", "time2.google.com", "time3.google.com", "time4.google.com" /* , "pool.ntp.org" -- we need to request a vender zone before using this pool */
|
||||
#define TIME_SYNC_NTP_TIMEOUT_SEC 5
|
||||
#define TIME_SYNC_NTP_ATTEMPTS_COUNT 3 // max number of attempts when getting time from NTP server
|
||||
|
||||
int64_t get_ntp_time()
|
||||
{
|
||||
static const std::vector<std::string> ntp_servers { TIME_SYNC_NTP_SERVERS };
|
||||
|
||||
for (size_t att = 0; att < TIME_SYNC_NTP_ATTEMPTS_COUNT; ++att)
|
||||
{
|
||||
const std::string& ntp_server = ntp_servers[att % ntp_servers.size()];
|
||||
LOG_PRINT_L3("NTP: trying to get time from " << ntp_server);
|
||||
int64_t time = get_ntp_time(ntp_server, TIME_SYNC_NTP_TIMEOUT_SEC);
|
||||
if (time > 0)
|
||||
{
|
||||
LOG_PRINT_L3("NTP: " << ntp_server << " responded with " << time << " (" << epee::misc_utils::get_time_str_v2(time) << ")");
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_PRINT_RED("NTP: unable to get time from NTP with " << TIME_SYNC_NTP_ATTEMPTS_COUNT << " trials", LOG_LEVEL_2);
|
||||
return 0; // smth went wrong
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace tools
|
||||
18
src/common/ntp.h
Normal file
18
src/common/ntp.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) 2019 Zano Project
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace tools
|
||||
{
|
||||
|
||||
// requests current time via NTP from 'host_hame' using 'timeout_sec'
|
||||
// may return zero -- means error
|
||||
int64_t get_ntp_time(const std::string& host_name, size_t timeout_sec = 5);
|
||||
|
||||
// request time via predefined NTP servers
|
||||
// may return zero -- mean error
|
||||
int64_t get_ntp_time();
|
||||
|
||||
} // namespace tools
|
||||
|
|
@ -10,6 +10,7 @@ using namespace epee;
|
|||
|
||||
#include "util.h"
|
||||
#include "currency_core/currency_config.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
|
|
@ -23,6 +24,8 @@ using namespace epee;
|
|||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "string_coding.h"
|
||||
|
||||
namespace tools
|
||||
{
|
||||
std::function<void(void)> signal_handler::m_handler;
|
||||
|
|
@ -362,7 +365,69 @@ namespace tools
|
|||
return pszOS;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
void signal_handler::GenerateCrashDump(EXCEPTION_POINTERS *pep /* = NULL*/)
|
||||
{
|
||||
SYSTEMTIME sysTime = { 0 };
|
||||
GetSystemTime(&sysTime);
|
||||
// get the computer name
|
||||
char compName[MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
|
||||
DWORD compNameLen = ARRAYSIZE(compName);
|
||||
GetComputerNameA(compName, &compNameLen);
|
||||
// build the filename: APPNAME_COMPUTERNAME_DATE_TIME.DMP
|
||||
char path[MAX_PATH*10] = { 0 };
|
||||
std::string folder = epee::log_space::log_singletone::get_default_log_folder();
|
||||
sprintf_s(path, ARRAYSIZE(path),"%s\\crashdump_" PROJECT_VERSION_LONG "_%s_%04u-%02u-%02u_%02u-%02u-%02u.dmp",
|
||||
folder.c_str(), compName, sysTime.wYear, sysTime.wMonth, sysTime.wDay,
|
||||
sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
|
||||
|
||||
HANDLE hFile = CreateFileA(path, GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
|
||||
{
|
||||
// Create the minidump
|
||||
MINIDUMP_EXCEPTION_INFORMATION mdei;
|
||||
|
||||
mdei.ThreadId = GetCurrentThreadId();
|
||||
mdei.ExceptionPointers = pep;
|
||||
mdei.ClientPointers = FALSE;
|
||||
|
||||
MINIDUMP_CALLBACK_INFORMATION mci;
|
||||
|
||||
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback;
|
||||
mci.CallbackParam = 0;
|
||||
|
||||
MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory |
|
||||
MiniDumpWithDataSegs |
|
||||
MiniDumpWithHandleData |
|
||||
MiniDumpWithFullMemoryInfo |
|
||||
MiniDumpWithThreadInfo |
|
||||
MiniDumpWithUnloadedModules);
|
||||
|
||||
BOOL rv = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
||||
hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci);
|
||||
|
||||
if (!rv)
|
||||
{
|
||||
LOG_ERROR("Minidump file create FAILED(error " << GetLastError() << ") on path: " << path);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_PRINT_L0("Minidump file created on path: " << path);
|
||||
}
|
||||
// Close the file
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Minidump FAILED to create file (error " << GetLastError() << ") on path: " << path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else // ifdef WIN32
|
||||
std::string get_nix_version_display_string()
|
||||
{
|
||||
utsname un;
|
||||
|
|
@ -387,18 +452,22 @@ std::string get_nix_version_display_string()
|
|||
|
||||
|
||||
#ifdef WIN32
|
||||
std::string get_special_folder_path(int nfolder, bool iscreate)
|
||||
std::wstring get_special_folder_path_w(int nfolder, bool iscreate)
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
char psz_path[MAX_PATH] = "";
|
||||
wchar_t psz_path[MAX_PATH] = L"";
|
||||
|
||||
if(SHGetSpecialFolderPathA(NULL, psz_path, nfolder, iscreate))
|
||||
if (SHGetSpecialFolderPathW(NULL, psz_path, nfolder, iscreate))
|
||||
{
|
||||
return psz_path;
|
||||
}
|
||||
|
||||
LOG_ERROR("SHGetSpecialFolderPathA() failed, could not obtain requested path.");
|
||||
return "";
|
||||
LOG_ERROR("SHGetSpecialFolderPathW(" << nfolder << ", " << iscreate << ") failed, could not obtain requested path.");
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::string get_special_folder_path_utf8(int nfolder, bool iscreate)
|
||||
{
|
||||
return epee::string_encoding::wstring_to_utf8(get_special_folder_path_w(nfolder, iscreate));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -413,9 +482,9 @@ std::string get_nix_version_display_string()
|
|||
#ifdef WIN32
|
||||
// Windows
|
||||
#ifdef _M_X64
|
||||
config_folder = get_special_folder_path(CSIDL_APPDATA, true) + "/" + CURRENCY_NAME_SHORT;
|
||||
config_folder = get_special_folder_path_utf8(CSIDL_APPDATA, true) + "/" + CURRENCY_NAME_SHORT;
|
||||
#else
|
||||
config_folder = get_special_folder_path(CSIDL_APPDATA, true) + "/" + CURRENCY_NAME_SHORT + "-x86";
|
||||
config_folder = get_special_folder_path_utf8(CSIDL_APPDATA, true) + "/" + CURRENCY_NAME_SHORT + "-x86";
|
||||
#endif
|
||||
#else
|
||||
std::string pathRet;
|
||||
|
|
@ -455,7 +524,7 @@ std::string get_nix_version_display_string()
|
|||
std::string wallets_dir;
|
||||
#ifdef WIN32
|
||||
// Windows
|
||||
wallets_dir = get_special_folder_path(CSIDL_PERSONAL, true) + "/" + CURRENCY_NAME_BASE;
|
||||
wallets_dir = get_special_folder_path_utf8(CSIDL_PERSONAL, true) + "/" + CURRENCY_NAME_BASE;
|
||||
#else
|
||||
std::string pathRet;
|
||||
char* pszHome = getenv("HOME");
|
||||
|
|
@ -490,7 +559,7 @@ std::string get_nix_version_display_string()
|
|||
{
|
||||
namespace fs = boost::filesystem;
|
||||
boost::system::error_code ec;
|
||||
fs::path fs_path(path);
|
||||
fs::path fs_path = epee::string_encoding::utf8_to_wstring(path);
|
||||
if (fs::is_directory(fs_path, ec))
|
||||
{
|
||||
return true;
|
||||
|
|
@ -589,38 +658,4 @@ std::string get_nix_version_display_string()
|
|||
return static_cast<uint64_t>(in.tellg());
|
||||
}
|
||||
|
||||
int64_t get_ntp_time(const std::string& host_name)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::asio::io_service io_service;
|
||||
boost::asio::ip::udp::resolver resolver(io_service);
|
||||
boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), host_name, "ntp");
|
||||
boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query);
|
||||
boost::asio::ip::udp::socket socket(io_service);
|
||||
socket.open(boost::asio::ip::udp::v4());
|
||||
|
||||
boost::array<unsigned char, 48> send_buf = { { 010, 0, 0, 0, 0, 0, 0, 0, 0 } };
|
||||
socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint);
|
||||
|
||||
boost::array<unsigned long, 1024> recv_buf;
|
||||
boost::asio::ip::udp::endpoint sender_endpoint;
|
||||
size_t len = socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint);
|
||||
|
||||
time_t time_recv = ntohl((time_t)recv_buf[4]);
|
||||
time_recv -= 2208988800U; //Unix time starts from 01/01/1970 == 2208988800U
|
||||
return time_recv;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_PRINT_L2("get_ntp_time(): exception: " << e.what());
|
||||
return 0;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace tools
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "crypto/hash.h"
|
||||
#include "misc_language.h"
|
||||
#include "p2p/p2p_protocol_defs.h"
|
||||
#include "ntp.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <dbghelp.h>
|
||||
|
|
@ -231,67 +232,7 @@ namespace tools
|
|||
|
||||
}
|
||||
|
||||
static void GenerateCrashDump(EXCEPTION_POINTERS *pep = NULL)
|
||||
|
||||
{
|
||||
SYSTEMTIME sysTime = { 0 };
|
||||
GetSystemTime(&sysTime);
|
||||
// get the computer name
|
||||
char compName[MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
|
||||
DWORD compNameLen = ARRAYSIZE(compName);
|
||||
GetComputerNameA(compName, &compNameLen);
|
||||
// build the filename: APPNAME_COMPUTERNAME_DATE_TIME.DMP
|
||||
char path[MAX_PATH*10] = { 0 };
|
||||
std::string folder = epee::log_space::log_singletone::get_default_log_folder();
|
||||
sprintf_s(path, ARRAYSIZE(path),"%s\\crashdump_%s_%04u-%02u-%02u_%02u-%02u-%02u.dmp",
|
||||
folder.c_str(), compName, sysTime.wYear, sysTime.wMonth, sysTime.wDay,
|
||||
sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
|
||||
|
||||
HANDLE hFile = CreateFileA(path, GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
|
||||
{
|
||||
// Create the minidump
|
||||
MINIDUMP_EXCEPTION_INFORMATION mdei;
|
||||
|
||||
mdei.ThreadId = GetCurrentThreadId();
|
||||
mdei.ExceptionPointers = pep;
|
||||
mdei.ClientPointers = FALSE;
|
||||
|
||||
MINIDUMP_CALLBACK_INFORMATION mci;
|
||||
|
||||
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback;
|
||||
mci.CallbackParam = 0;
|
||||
|
||||
MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithPrivateReadWriteMemory |
|
||||
MiniDumpWithDataSegs |
|
||||
MiniDumpWithHandleData |
|
||||
MiniDumpWithFullMemoryInfo |
|
||||
MiniDumpWithThreadInfo |
|
||||
MiniDumpWithUnloadedModules);
|
||||
|
||||
BOOL rv = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
||||
hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci);
|
||||
|
||||
if (!rv)
|
||||
{
|
||||
LOG_ERROR("Minidump file create FAILED(error " << GetLastError() << ") on path: " << path);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_PRINT_L0("Minidump file created on path: " << path);
|
||||
}
|
||||
// Close the file
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Minidump FAILED to create file (error " << GetLastError() << ") on path: " << path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void GenerateCrashDump(EXCEPTION_POINTERS *pep = NULL);
|
||||
|
||||
static LONG WINAPI win_unhandled_exception_handler(_In_ struct _EXCEPTION_POINTERS *ep)
|
||||
{
|
||||
|
|
@ -334,6 +275,4 @@ namespace tools
|
|||
static std::function<void(int, void*)> m_fatal_handler;
|
||||
};
|
||||
|
||||
|
||||
int64_t get_ntp_time(const std::string& host_name);
|
||||
}
|
||||
|
|
|
|||
160
src/crypto/blake2-impl.h
Normal file
160
src/crypto/blake2-impl.h
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
#ifndef BLAKE2_IMPL_H
|
||||
#define BLAKE2_IMPL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_INLINE __inline
|
||||
#elif defined(__GNUC__)
|
||||
#define BLAKE2_INLINE __inline__
|
||||
#else
|
||||
#define BLAKE2_INLINE
|
||||
#endif
|
||||
#else
|
||||
#define BLAKE2_INLINE inline
|
||||
#endif
|
||||
|
||||
static BLAKE2_INLINE uint32_t load32( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint32_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint32_t )( p[0] ) << 0) |
|
||||
(( uint32_t )( p[1] ) << 8) |
|
||||
(( uint32_t )( p[2] ) << 16) |
|
||||
(( uint32_t )( p[3] ) << 24) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load64( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint64_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint64_t )( p[0] ) << 0) |
|
||||
(( uint64_t )( p[1] ) << 8) |
|
||||
(( uint64_t )( p[2] ) << 16) |
|
||||
(( uint64_t )( p[3] ) << 24) |
|
||||
(( uint64_t )( p[4] ) << 32) |
|
||||
(( uint64_t )( p[5] ) << 40) |
|
||||
(( uint64_t )( p[6] ) << 48) |
|
||||
(( uint64_t )( p[7] ) << 56) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint16_t load16( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint16_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return ( uint16_t )((( uint32_t )( p[0] ) << 0) |
|
||||
(( uint32_t )( p[1] ) << 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store16( void *dst, uint16_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
*p++ = ( uint8_t )w; w >>= 8;
|
||||
*p++ = ( uint8_t )w;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store32( void *dst, uint32_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store64( void *dst, uint64_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
p[4] = (uint8_t)(w >> 32);
|
||||
p[5] = (uint8_t)(w >> 40);
|
||||
p[6] = (uint8_t)(w >> 48);
|
||||
p[7] = (uint8_t)(w >> 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load48( const void *src )
|
||||
{
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint64_t )( p[0] ) << 0) |
|
||||
(( uint64_t )( p[1] ) << 8) |
|
||||
(( uint64_t )( p[2] ) << 16) |
|
||||
(( uint64_t )( p[3] ) << 24) |
|
||||
(( uint64_t )( p[4] ) << 32) |
|
||||
(( uint64_t )( p[5] ) << 40) ;
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store48( void *dst, uint64_t w )
|
||||
{
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
p[4] = (uint8_t)(w >> 32);
|
||||
p[5] = (uint8_t)(w >> 40);
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 32 - c ) );
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 64 - c ) );
|
||||
}
|
||||
|
||||
/* prevents compiler optimizing out memset() */
|
||||
static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
|
||||
{
|
||||
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
|
||||
memset_v(v, 0, n);
|
||||
}
|
||||
|
||||
#endif
|
||||
200
src/crypto/blake2.h
Normal file
200
src/crypto/blake2.h
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
#ifndef BLAKE2_H
|
||||
#define BLAKE2_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
|
||||
#else
|
||||
#define BLAKE2_PACKED(x) x __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum blake2s_constant
|
||||
{
|
||||
BLAKE2S_BLOCKBYTES = 64,
|
||||
BLAKE2S_OUTBYTES = 32,
|
||||
BLAKE2S_KEYBYTES = 32,
|
||||
BLAKE2S_SALTBYTES = 8,
|
||||
BLAKE2S_PERSONALBYTES = 8
|
||||
};
|
||||
|
||||
enum blake2b_constant
|
||||
{
|
||||
BLAKE2B_BLOCKBYTES = 128,
|
||||
BLAKE2B_OUTBYTES = 64,
|
||||
BLAKE2B_KEYBYTES = 64,
|
||||
BLAKE2B_SALTBYTES = 16,
|
||||
BLAKE2B_PERSONALBYTES = 16
|
||||
};
|
||||
|
||||
typedef struct blake2s_state__
|
||||
{
|
||||
uint32_t h[8];
|
||||
uint32_t t[2];
|
||||
uint32_t f[2];
|
||||
uint8_t buf[BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2s_state;
|
||||
|
||||
typedef struct blake2b_state__
|
||||
{
|
||||
uint64_t h[8];
|
||||
uint64_t t[2];
|
||||
uint64_t f[2];
|
||||
uint8_t buf[BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2b_state;
|
||||
|
||||
typedef struct blake2sp_state__
|
||||
{
|
||||
blake2s_state S[8][1];
|
||||
blake2s_state R[1];
|
||||
uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
} blake2sp_state;
|
||||
|
||||
typedef struct blake2bp_state__
|
||||
{
|
||||
blake2b_state S[4][1];
|
||||
blake2b_state R[1];
|
||||
uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
} blake2bp_state;
|
||||
|
||||
|
||||
BLAKE2_PACKED(struct blake2s_param__
|
||||
{
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint16_t xof_length; /* 14 */
|
||||
uint8_t node_depth; /* 15 */
|
||||
uint8_t inner_length; /* 16 */
|
||||
/* uint8_t reserved[0]; */
|
||||
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
|
||||
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
|
||||
});
|
||||
|
||||
typedef struct blake2s_param__ blake2s_param;
|
||||
|
||||
BLAKE2_PACKED(struct blake2b_param__
|
||||
{
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint32_t xof_length; /* 16 */
|
||||
uint8_t node_depth; /* 17 */
|
||||
uint8_t inner_length; /* 18 */
|
||||
uint8_t reserved[14]; /* 32 */
|
||||
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
|
||||
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
|
||||
});
|
||||
|
||||
typedef struct blake2b_param__ blake2b_param;
|
||||
|
||||
typedef struct blake2xs_state__
|
||||
{
|
||||
blake2s_state S[1];
|
||||
blake2s_param P[1];
|
||||
} blake2xs_state;
|
||||
|
||||
typedef struct blake2xb_state__
|
||||
{
|
||||
blake2b_state S[1];
|
||||
blake2b_param P[1];
|
||||
} blake2xb_state;
|
||||
|
||||
|
||||
/* Padded structs result in a compile-time error */
|
||||
|
||||
enum {
|
||||
BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
|
||||
BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
|
||||
};
|
||||
// static_assert(sizeof(blake2s_param) == BLAKE2S_OUTBYTES, "Wrong size of blake2s_param");
|
||||
// static_assert(sizeof(blake2b_param) == BLAKE2B_OUTBYTES, "Wrong size of blake2b_param");
|
||||
|
||||
|
||||
/* Streaming API */
|
||||
int blake2s_init( blake2s_state *S, size_t outlen );
|
||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
|
||||
int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
|
||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2b_init( blake2b_state *S, size_t outlen );
|
||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
|
||||
int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
|
||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2sp_init( blake2sp_state *S, size_t outlen );
|
||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
|
||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2bp_init( blake2bp_state *S, size_t outlen );
|
||||
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
|
||||
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
|
||||
|
||||
/* Variable output length API */
|
||||
int blake2xs_init( blake2xs_state *S, const size_t outlen );
|
||||
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
|
||||
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
|
||||
|
||||
int blake2xb_init( blake2xb_state *S, const size_t outlen );
|
||||
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
|
||||
int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
|
||||
|
||||
/* Simple API */
|
||||
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
/* This is simply an alias for blake2b */
|
||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
379
src/crypto/blake2b-ref.c
Normal file
379
src/crypto/blake2b-ref.c
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
static const uint64_t blake2b_IV[8] =
|
||||
{
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
static const uint8_t blake2b_sigma[12][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
|
||||
};
|
||||
|
||||
|
||||
static void blake2b_set_lastnode( blake2b_state *S )
|
||||
{
|
||||
S->f[1] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static int blake2b_is_lastblock( const blake2b_state *S )
|
||||
{
|
||||
return S->f[0] != 0;
|
||||
}
|
||||
|
||||
static void blake2b_set_lastblock( blake2b_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2b_set_lastnode( S );
|
||||
|
||||
S->f[0] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
|
||||
{
|
||||
S->t[0] += inc;
|
||||
S->t[1] += ( S->t[0] < inc );
|
||||
}
|
||||
|
||||
static void blake2b_init0( blake2b_state *S )
|
||||
{
|
||||
size_t i;
|
||||
memset( S, 0, sizeof( blake2b_state ) );
|
||||
|
||||
for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
|
||||
}
|
||||
|
||||
/* init xors IV with input parameter block */
|
||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
||||
{
|
||||
const uint8_t *p = ( const uint8_t * )( P );
|
||||
size_t i;
|
||||
|
||||
blake2b_init0( S );
|
||||
|
||||
/* IV XOR ParamBlock */
|
||||
for( i = 0; i < 8; ++i )
|
||||
S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
|
||||
|
||||
S->outlen = P->digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int blake2b_init( blake2b_state *S, size_t outlen )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store32( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2b_init_param( S, P );
|
||||
}
|
||||
|
||||
|
||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
|
||||
|
||||
if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store32( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
|
||||
if( blake2b_init_param( S, P ) < 0 ) return -1;
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
|
||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define G(r,i,a,b,c,d) \
|
||||
do { \
|
||||
a = a + b + m[blake2b_sigma[r][2*i+0]]; \
|
||||
d = rotr64(d ^ a, 32); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 24); \
|
||||
a = a + b + m[blake2b_sigma[r][2*i+1]]; \
|
||||
d = rotr64(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 63); \
|
||||
} while(0)
|
||||
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
|
||||
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
|
||||
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
|
||||
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
|
||||
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
|
||||
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
|
||||
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
|
||||
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
|
||||
} while(0)
|
||||
|
||||
static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
|
||||
{
|
||||
uint64_t m[16];
|
||||
uint64_t v[16];
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < 16; ++i ) {
|
||||
m[i] = load64( block + i * sizeof( m[i] ) );
|
||||
}
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
v[i] = S->h[i];
|
||||
}
|
||||
|
||||
v[ 8] = blake2b_IV[0];
|
||||
v[ 9] = blake2b_IV[1];
|
||||
v[10] = blake2b_IV[2];
|
||||
v[11] = blake2b_IV[3];
|
||||
v[12] = blake2b_IV[4] ^ S->t[0];
|
||||
v[13] = blake2b_IV[5] ^ S->t[1];
|
||||
v[14] = blake2b_IV[6] ^ S->f[0];
|
||||
v[15] = blake2b_IV[7] ^ S->f[1];
|
||||
|
||||
ROUND( 0 );
|
||||
ROUND( 1 );
|
||||
ROUND( 2 );
|
||||
ROUND( 3 );
|
||||
ROUND( 4 );
|
||||
ROUND( 5 );
|
||||
ROUND( 6 );
|
||||
ROUND( 7 );
|
||||
ROUND( 8 );
|
||||
ROUND( 9 );
|
||||
ROUND( 10 );
|
||||
ROUND( 11 );
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
|
||||
int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
|
||||
{
|
||||
const unsigned char * in = (const unsigned char *)pin;
|
||||
if( inlen > 0 )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = BLAKE2B_BLOCKBYTES - left;
|
||||
if( inlen > fill )
|
||||
{
|
||||
S->buflen = 0;
|
||||
memcpy( S->buf + left, in, fill ); /* Fill buffer */
|
||||
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
|
||||
blake2b_compress( S, S->buf ); /* Compress */
|
||||
in += fill; inlen -= fill;
|
||||
while(inlen > BLAKE2B_BLOCKBYTES) {
|
||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
||||
blake2b_compress( S, in );
|
||||
in += BLAKE2B_BLOCKBYTES;
|
||||
inlen -= BLAKE2B_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
memcpy( S->buf + S->buflen, in, inlen );
|
||||
S->buflen += inlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen )
|
||||
{
|
||||
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
||||
size_t i;
|
||||
|
||||
if( out == NULL || outlen < S->outlen )
|
||||
return -1;
|
||||
|
||||
if( blake2b_is_lastblock( S ) )
|
||||
return -1;
|
||||
|
||||
blake2b_increment_counter( S, S->buflen );
|
||||
blake2b_set_lastblock( S );
|
||||
memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
|
||||
blake2b_compress( S, S->buf );
|
||||
|
||||
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
|
||||
store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
|
||||
|
||||
memcpy( out, buffer, S->outlen );
|
||||
secure_zero_memory(buffer, sizeof(buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* inlen, at least, should be uint64_t. Others can be size_t. */
|
||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2b_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if ( NULL == in && inlen > 0 ) return -1;
|
||||
|
||||
if ( NULL == out ) return -1;
|
||||
|
||||
if( NULL == key && keylen > 0 ) return -1;
|
||||
|
||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
|
||||
|
||||
if( keylen > BLAKE2B_KEYBYTES ) return -1;
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( blake2b_init( S, outlen ) < 0 ) return -1;
|
||||
}
|
||||
|
||||
blake2b_update( S, ( const uint8_t * )in, inlen );
|
||||
blake2b_final( S, out, outlen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
|
||||
return blake2b(out, outlen, in, inlen, key, keylen);
|
||||
}
|
||||
|
||||
#if defined(SUPERCOP)
|
||||
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
||||
{
|
||||
return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLAKE2B_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2B_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step;
|
||||
|
||||
for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
|
||||
key[i] = ( uint8_t )i;
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
buf[i] = ( uint8_t )i;
|
||||
|
||||
/* Test simple API */
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
{
|
||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||
blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
|
||||
|
||||
if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
|
||||
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
|
||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||
blake2b_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = i;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -304,7 +304,7 @@ namespace crypto {
|
|||
ge_tobytes(&image, &point2);
|
||||
}
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4200)
|
||||
struct rs_comm_entry
|
||||
{
|
||||
|
|
@ -314,7 +314,7 @@ struct rs_comm_entry
|
|||
hash h;
|
||||
struct rs_comm_entry ab[];
|
||||
};
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
||||
static inline size_t rs_comm_size(size_t pubs_count) {
|
||||
return sizeof(rs_comm)+pubs_count * sizeof(rs_comm_entry);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include "warnings.h"
|
||||
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_GCC_WARNINGS
|
||||
DISABLE_CLANG_WARNING(unused-private-field)
|
||||
|
||||
|
||||
|
|
@ -236,3 +236,4 @@ POD_MAKE_COMPARABLE(crypto, signature)
|
|||
POD_MAKE_COMPARABLE(crypto, key_derivation)
|
||||
POD_MAKE_LESS_OPERATOR(crypto, hash)
|
||||
POD_MAKE_LESS_OPERATOR(crypto, key_image)
|
||||
POP_GCC_WARNINGS
|
||||
|
|
@ -22,7 +22,7 @@ static inline const void *cpadd(const void *p, size_t i) {
|
|||
return (const char *) p + i;
|
||||
}
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4267)
|
||||
static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t must be 4 or 8 bytes long");
|
||||
static inline void place_length(uint8_t *buffer, size_t bufsize, size_t length) {
|
||||
|
|
@ -32,7 +32,7 @@ static inline void place_length(uint8_t *buffer, size_t bufsize, size_t length)
|
|||
*(uint64_t *) padd(buffer, bufsize - 8) = swap64be(length);
|
||||
}
|
||||
}
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
||||
#pragma pack(push, 1)
|
||||
union hash_state {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@
|
|||
|
||||
#include "common/pod-class.h"
|
||||
#include "generic-ops.h"
|
||||
|
||||
#include "warnings.h"
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4804)
|
||||
#include "blake2.h"
|
||||
POP_VS_WARNINGS
|
||||
namespace crypto {
|
||||
|
||||
extern "C" {
|
||||
|
|
@ -41,6 +45,12 @@ namespace crypto {
|
|||
tree_hash(reinterpret_cast<const char (*)[HASH_SIZE]>(hashes), count, reinterpret_cast<char *>(&root_hash));
|
||||
}
|
||||
|
||||
inline hash blake2_hash(const void *data, std::size_t length) {
|
||||
hash h;
|
||||
blake2(&h, sizeof(h), data, length, nullptr, 0);
|
||||
return h;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
POD_MAKE_HASHABLE(crypto, hash)
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@
|
|||
//#include "initializer.h"
|
||||
#include "random.h"
|
||||
|
||||
static void generate_system_random_bytes(size_t n, void *result);
|
||||
static_assert(RANDOM_STATE_SIZE >= HASH_DATA_AREA, "Invalid RANDOM_STATE_SIZE");
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
static void generate_system_random_bytes(size_t n, void *result) {
|
||||
void generate_system_random_bytes(size_t n, void *result) {
|
||||
HCRYPTPROV prov;
|
||||
#define must_succeed(x) do if (!(x)) assert(0); while (0)
|
||||
if(!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||
|
|
@ -40,7 +40,7 @@ static void generate_system_random_bytes(size_t n, void *result) {
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void generate_system_random_bytes(size_t n, void *result) {
|
||||
void generate_system_random_bytes(size_t n, void *result) {
|
||||
int fd;
|
||||
if ((fd = open("/dev/urandom", O_RDONLY | O_NOCTTY | O_CLOEXEC)) < 0) {
|
||||
err(EXIT_FAILURE, "open /dev/urandom");
|
||||
|
|
@ -68,7 +68,7 @@ static void generate_system_random_bytes(size_t n, void *result) {
|
|||
|
||||
#endif
|
||||
|
||||
/* static */ union hash_state state; // NOTE: 'static' is commented out here to be able to store/load global random generator state in tests (see also random_helper.h)
|
||||
static union hash_state state;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
static volatile int curstate; /* To catch thread safety problems. */
|
||||
|
|
@ -105,6 +105,57 @@ void grant_random_initialize(void)
|
|||
}
|
||||
}
|
||||
|
||||
void random_prng_initialize_with_seed(uint64_t seed)
|
||||
{
|
||||
grant_random_initialize();
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 1);
|
||||
curstate = 3;
|
||||
#endif
|
||||
memset(&state, 0, sizeof state);
|
||||
memcpy(&state, &seed, sizeof seed);
|
||||
for(size_t i = 0, count = seed & 31; i < count; ++i)
|
||||
hash_permutation(&state);
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 3);
|
||||
curstate = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void random_prng_get_state(void *state_buffer, const size_t buffer_size)
|
||||
{
|
||||
grant_random_initialize();
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 1);
|
||||
curstate = 4;
|
||||
#endif
|
||||
|
||||
assert(sizeof state == buffer_size);
|
||||
memcpy(state_buffer, &state, buffer_size);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 4);
|
||||
curstate = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void random_prng_set_state(const void *state_buffer, const size_t buffer_size)
|
||||
{
|
||||
grant_random_initialize();
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 1);
|
||||
curstate = 5;
|
||||
#endif
|
||||
|
||||
assert(sizeof state == buffer_size);
|
||||
memcpy(&state, state_buffer, buffer_size);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
assert(curstate == 5);
|
||||
curstate = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void generate_random_bytes(size_t n, void *result) {
|
||||
grant_random_initialize();
|
||||
#if !defined(NDEBUG)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// Copyright (c) 2018-2019 Zano Project
|
||||
// Copyright (c) 2014-2018 The Boolberry developers
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
@ -5,6 +7,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// use the cryptographically secure Pseudo-Random Number Generator provided by the operating system
|
||||
void generate_system_random_bytes(size_t n, void *result);
|
||||
|
||||
void generate_random_bytes(size_t n, void *result);
|
||||
void grant_random_initialize(void);
|
||||
|
||||
// checks if PRNG is initialized and initializes it if necessary
|
||||
void grant_random_initialize(void);
|
||||
|
||||
#define RANDOM_STATE_SIZE 200
|
||||
|
||||
// explicitly define USE_INSECURE_RANDOM_RPNG_ROUTINES for using random_initialize_with_seed
|
||||
#ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES
|
||||
// reinitializes PRNG with the given seed
|
||||
// !!!ATTENTION!!!! Improper use of this routine may lead to SECURITY BREACH!
|
||||
// Use with care and ONLY for tests or debug purposes!
|
||||
void random_prng_initialize_with_seed(uint64_t seed);
|
||||
|
||||
// gets internal RPNG state (state_buffer should be 200 bytes long)
|
||||
void random_prng_get_state(void *state_buffer, const size_t buffer_size);
|
||||
|
||||
// sets internal RPNG state (state_buffer should be 200 bytes long)
|
||||
// !!!ATTENTION!!!! Improper use of this routine may lead to SECURITY BREACH!
|
||||
// Use with care and ONLY for tests or debug purposes!
|
||||
void random_prng_set_state(const void *state_buffer, const size_t buffer_size);
|
||||
|
||||
#endif // #ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES
|
||||
|
|
|
|||
|
|
@ -22,17 +22,31 @@ namespace currency
|
|||
{
|
||||
|
||||
//--------------------------------------------------------------
|
||||
//global object
|
||||
// crypto::ethash::cache_manager cache;
|
||||
// void ethash_set_use_dag(bool use_dag)
|
||||
// {
|
||||
// cache.set_use_dag(use_dag);
|
||||
// }
|
||||
// //------------------------------------------------------------------
|
||||
// const uint8_t* ethash_get_dag(uint64_t epoch, uint64_t& dag_size)
|
||||
// {
|
||||
// return cache.get_dag(epoch, dag_size);
|
||||
// }
|
||||
int ethash_custom_log_get_level()
|
||||
{
|
||||
return epee::log_space::get_set_log_detalisation_level();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
void ethash_custom_log(const std::string& m, bool add_callstack)
|
||||
{
|
||||
std::string msg = epee::log_space::log_singletone::get_prefix_entry() + "[ETHASH]" + m;
|
||||
if (add_callstack)
|
||||
msg = msg + "callstask: " + epee::misc_utils::get_callstack();
|
||||
|
||||
epee::log_space::log_singletone::do_log_message(msg, LOG_LEVEL_0, epee::log_space::console_color_default, true, LOG_DEFAULT_TARGET);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
void init_ethash_log_if_necessary()
|
||||
{
|
||||
static bool inited = false;
|
||||
if (inited)
|
||||
return;
|
||||
|
||||
ethash::access_custom_log_level_function() = ðash_custom_log_get_level;
|
||||
ethash::access_custom_log_function() = ðash_custom_log;
|
||||
|
||||
inited = true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
int ethash_height_to_epoch(uint64_t height)
|
||||
{
|
||||
|
|
@ -49,9 +63,11 @@ namespace currency
|
|||
//--------------------------------------------------------------
|
||||
crypto::hash get_block_longhash(uint64_t height, const crypto::hash& block_header_hash, uint64_t nonce)
|
||||
{
|
||||
init_ethash_log_if_necessary();
|
||||
int epoch = ethash_height_to_epoch(height);
|
||||
const auto& context = progpow::get_global_epoch_context_full(static_cast<int>(epoch));
|
||||
auto res_eth = progpow::hash(context, static_cast<int>(height), *(ethash::hash256*)&block_header_hash, nonce);
|
||||
std::shared_ptr<ethash::epoch_context_full> p_context = progpow::get_global_epoch_context_full(static_cast<int>(epoch));
|
||||
CHECK_AND_ASSERT_THROW_MES(p_context, "progpow::get_global_epoch_context_full returned null");
|
||||
auto res_eth = progpow::hash(*p_context, static_cast<int>(height), *(ethash::hash256*)&block_header_hash, nonce);
|
||||
crypto::hash result = currency::null_hash;
|
||||
memcpy(&result.data, &res_eth.final_hash, sizeof(res_eth.final_hash));
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ DISABLE_VS_WARNINGS(4267)
|
|||
|
||||
namespace
|
||||
{
|
||||
const command_line::arg_descriptor<uint32_t> arg_db_cache_l1 = { "db-cache-l1", "Specify size of memory mapped db cache file", 0, true };
|
||||
const command_line::arg_descriptor<uint32_t> arg_db_cache_l2 = { "db-cache-l2", "Specify cached elements in db helpers", 0, true };
|
||||
}
|
||||
|
||||
|
|
@ -151,10 +152,10 @@ std::shared_ptr<transaction> blockchain_storage::get_tx(const crypto::hash &id)
|
|||
//------------------------------------------------------------------
|
||||
void blockchain_storage::init_options(boost::program_options::options_description& desc)
|
||||
{
|
||||
command_line::add_arg(desc, arg_db_cache_l1);
|
||||
command_line::add_arg(desc, arg_db_cache_l2);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
||||
uint64_t blockchain_storage::get_block_h_older_then(uint64_t timestamp) const
|
||||
{
|
||||
// get avarage block position
|
||||
|
|
@ -213,20 +214,36 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
|
|||
return false;
|
||||
}
|
||||
|
||||
uint64_t cache_size_l1 = CACHE_SIZE;
|
||||
if (command_line::has_arg(vm, arg_db_cache_l1))
|
||||
{
|
||||
cache_size_l1 = command_line::get_arg(vm, arg_db_cache_l1);
|
||||
}
|
||||
LOG_PRINT_GREEN("Using db file cache size(L1): " << cache_size_l1, LOG_LEVEL_0);
|
||||
|
||||
m_config_folder = config_folder;
|
||||
|
||||
// remove old incompatible DB
|
||||
const std::string old_db_folder_path = m_config_folder + "/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD;
|
||||
if (boost::filesystem::exists(epee::string_encoding::utf8_to_wstring(old_db_folder_path)))
|
||||
{
|
||||
LOG_PRINT_YELLOW("Removing old DB in " << old_db_folder_path << "...", LOG_LEVEL_0);
|
||||
boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(old_db_folder_path));
|
||||
}
|
||||
|
||||
const std::string db_folder_path = m_config_folder + "/" CURRENCY_BLOCKCHAINDATA_FOLDERNAME;
|
||||
LOG_PRINT_L0("Loading blockchain from " << db_folder_path);
|
||||
|
||||
bool db_opened_okay = false;
|
||||
for(size_t loading_attempt_no = 0; loading_attempt_no < 2; ++loading_attempt_no)
|
||||
{
|
||||
bool res = m_db.open(db_folder_path);
|
||||
bool res = m_db.open(db_folder_path, cache_size_l1);
|
||||
if (!res)
|
||||
{
|
||||
// if DB could not be opened -- try to remove the whole folder and re-open DB
|
||||
LOG_PRINT_YELLOW("Failed to initialize database in folder: " << db_folder_path << ", first attempt", LOG_LEVEL_0);
|
||||
boost::filesystem::remove_all(db_folder_path);
|
||||
res = m_db.open(db_folder_path);
|
||||
boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(db_folder_path));
|
||||
res = m_db.open(db_folder_path, cache_size_l1);
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to initialize database in folder: " << db_folder_path << ", second attempt");
|
||||
}
|
||||
|
||||
|
|
@ -295,7 +312,7 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
|
|||
m_db_addr_to_alias.deinit();
|
||||
m_db_per_block_gindex_incs.deinit();
|
||||
m_db.close();
|
||||
size_t files_removed = boost::filesystem::remove_all(db_folder_path);
|
||||
size_t files_removed = boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(db_folder_path));
|
||||
LOG_PRINT_L1(files_removed << " files at " << db_folder_path << " removed");
|
||||
|
||||
// try to re-create DB and re-init containers
|
||||
|
|
@ -1803,10 +1820,19 @@ bool blockchain_storage::is_reorganize_required(const block_extended_info& main_
|
|||
wide_difficulty_type main_pow_diff_begin = get_last_alt_x_block_cumulative_precise_adj_difficulty(alt_chain_type(), connection_point.height - 1, false);
|
||||
main_cumul_diff.pow_diff = main_pow_diff_end - main_pow_diff_begin;
|
||||
|
||||
//TODO: measurment of precise cumulative difficult
|
||||
wide_difficulty_type alt = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, alt_cumul_diff, main_cumul_diff);
|
||||
wide_difficulty_type main = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, main_cumul_diff, alt_cumul_diff);
|
||||
|
||||
//TODO: measurement of precise cumulative difficult
|
||||
boost::multiprecision::uint1024_t alt = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, alt_cumul_diff, main_cumul_diff);
|
||||
boost::multiprecision::uint1024_t main = get_a_to_b_relative_cumulative_difficulty(difficulty_pos_at_split_point, difficulty_pow_at_split_point, main_cumul_diff, alt_cumul_diff);
|
||||
LOG_PRINT_L1("[FORK_CHOICE]: " << ENDL
|
||||
<< "difficulty_pow_at_split_point:" << difficulty_pow_at_split_point << ENDL
|
||||
<< "difficulty_pos_at_split_point:" << difficulty_pos_at_split_point << ENDL
|
||||
<< "alt_cumul_diff.pow_diff:" << alt_cumul_diff.pow_diff << ENDL
|
||||
<< "alt_cumul_diff.pos_diff:" << alt_cumul_diff.pos_diff << ENDL
|
||||
<< "main_cumul_diff.pow_diff:" << main_cumul_diff.pow_diff << ENDL
|
||||
<< "main_cumul_diff.pos_diff:" << main_cumul_diff.pos_diff << ENDL
|
||||
<< "alt:" << alt << ENDL
|
||||
<< "main:" << main << ENDL
|
||||
);
|
||||
if (main < alt)
|
||||
return true;
|
||||
else if (main > alt)
|
||||
|
|
@ -1821,7 +1847,7 @@ bool blockchain_storage::is_reorganize_required(const block_extended_info& main_
|
|||
if (std::memcmp(&main_chain_bei.stake_hash, &proof_alt, sizeof(main_chain_bei.stake_hash)) >= 0)
|
||||
return false;
|
||||
|
||||
LOG_PRINT_L2("[is_reorganize_required]:TRUE, \"by order of memcmp\" main_stake_hash:" << &main_chain_bei.stake_hash << ", alt_stake_hash" << proof_alt);
|
||||
LOG_PRINT_L1("[is_reorganize_required]:TRUE, \"by order of memcmp\" main_stake_hash:" << &main_chain_bei.stake_hash << ", alt_stake_hash" << proof_alt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2618,7 +2644,8 @@ void blockchain_storage::print_blockchain_with_tx(uint64_t start_index, uint64_t
|
|||
{
|
||||
boost::filesystem::ofstream ss;
|
||||
ss.exceptions(/*std::ifstream::failbit |*/ std::ifstream::badbit);
|
||||
ss.open(log_space::log_singletone::get_default_log_folder() + "/blockchain_with_tx.txt", std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
|
||||
ss.open(epee::string_encoding::utf8_to_wstring(log_space::log_singletone::get_default_log_folder() + "/blockchain_with_tx.txt"),
|
||||
std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
|
||||
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
|
@ -2697,7 +2724,6 @@ void blockchain_storage::print_db_cache_perfeormance_data() const
|
|||
void blockchain_storage::get_last_n_x_blocks(uint64_t n, bool pos_blocks, std::list<std::shared_ptr<const block_extended_info>>& blocks) const
|
||||
{
|
||||
uint64_t count = 0;
|
||||
bool looking_for_a_pos = true;
|
||||
for (uint64_t i = m_db_blocks.size() - 1; i != 0; --i)
|
||||
{
|
||||
auto block_ptr = m_db_blocks[i];
|
||||
|
|
@ -3892,14 +3918,14 @@ bool blockchain_storage::is_tx_spendtime_unlocked(uint64_t unlock_time) const
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& max_unlock_time) const
|
||||
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
//TIME_MEASURE_START_PD(tx_check_inputs_loop_ch_in_get_keys_loop);
|
||||
|
||||
std::vector<crypto::public_key> output_keys;
|
||||
if(!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, max_unlock_time))
|
||||
if(!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase))
|
||||
{
|
||||
LOG_PRINT_L0("Failed to get output keys for input #" << in_index << " (amount = " << print_money(txin.amount) << ", key_offset.size = " << txin.key_offsets.size() << ")");
|
||||
return false;
|
||||
|
|
@ -3918,7 +3944,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
// 1) source tx unlock time validity
|
||||
// 2) mixin restrictions
|
||||
// 3) general gindex/ref_by_id corectness
|
||||
bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& max_unlock_time) const
|
||||
bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
|
|
@ -3926,10 +3952,13 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
{
|
||||
std::vector<crypto::public_key >& m_results_collector;
|
||||
const blockchain_storage& m_bch;
|
||||
uint64_t& m_max_unlock_time;
|
||||
uint64_t& m_source_max_unlock_time_for_pos_coinbase;
|
||||
outputs_visitor(std::vector<crypto::public_key>& results_collector,
|
||||
const blockchain_storage& bch,
|
||||
uint64_t& max_unlock_time) :m_results_collector(results_collector), m_bch(bch), m_max_unlock_time(max_unlock_time)
|
||||
uint64_t& source_max_unlock_time_for_pos_coinbase)
|
||||
: m_results_collector(results_collector)
|
||||
, m_bch(bch)
|
||||
, m_source_max_unlock_time_for_pos_coinbase(source_max_unlock_time_for_pos_coinbase)
|
||||
{}
|
||||
bool handle_output(const transaction& source_tx, const transaction& validated_tx, const tx_out& out, uint64_t out_i)
|
||||
{
|
||||
|
|
@ -3938,8 +3967,9 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
//let coinbase sources for PoS block to have locked inputs, the outputs supposed to be locked same way, except the reward
|
||||
if (is_coinbase(validated_tx) && is_pos_block(validated_tx))
|
||||
{
|
||||
if (source_out_unlock_time > m_max_unlock_time)
|
||||
m_max_unlock_time = source_out_unlock_time;
|
||||
CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(source_out_unlock_time), false, "source output #" << out_i << " is locked by time, not by height, which is not allowed for PoS coinbase");
|
||||
if (source_out_unlock_time > m_source_max_unlock_time_for_pos_coinbase)
|
||||
m_source_max_unlock_time_for_pos_coinbase = source_out_unlock_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3950,7 +3980,6 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if(out.target.type() != typeid(txout_to_key))
|
||||
{
|
||||
LOG_PRINT_L0("Output have wrong type id, which=" << out.target.which());
|
||||
|
|
@ -3962,7 +3991,7 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
}
|
||||
};
|
||||
|
||||
outputs_visitor vi(output_keys, *this, max_unlock_time);
|
||||
outputs_visitor vi(output_keys, *this, source_max_unlock_time_for_pos_coinbase);
|
||||
return scan_outputkeys_for_indexes(tx, txin, vi, max_related_block_height);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -4420,13 +4449,13 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t max_unlock_time)const
|
||||
bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const
|
||||
{
|
||||
uint64_t major_unlock_time = get_tx_x_detail<etc_tx_details_unlock_time>(miner_tx);
|
||||
if (major_unlock_time)
|
||||
{
|
||||
//if there was etc_tx_details_unlock_time present in tx, then ignore etc_tx_details_unlock_time2
|
||||
if (major_unlock_time < max_unlock_time)
|
||||
if (major_unlock_time < source_max_unlock_time)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
|
@ -4440,11 +4469,13 @@ bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transactio
|
|||
CHECK_AND_ASSERT_MES(ut2.unlock_time_array.size() == miner_tx.vout.size(), false, "ut2.unlock_time_array.size()<" << ut2.unlock_time_array.size()
|
||||
<< "> != miner_tx.vout.size()<" << miner_tx.vout.size() << ">");
|
||||
|
||||
uint64_t amount_of_coins_in_unlock_in_range = 0;
|
||||
uint64_t amount_of_coins_in_unlock_in_range = 0; // amount of outputs locked for at least the same time
|
||||
|
||||
for (uint64_t i = 0; i != miner_tx.vout.size(); i++)
|
||||
{
|
||||
if (ut2.unlock_time_array[i] >= max_unlock_time)
|
||||
uint64_t unlock_value = ut2.unlock_time_array[i];
|
||||
CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(unlock_value), false, "output #" << i << " is locked by time, not buy height, which is not allowed for PoS coinbase");
|
||||
if (unlock_value >= source_max_unlock_time)
|
||||
amount_of_coins_in_unlock_in_range += miner_tx.vout[i].amount;
|
||||
}
|
||||
|
||||
|
|
@ -4531,22 +4562,22 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
{
|
||||
// Do coinstake input validation for main chain only.
|
||||
// Txs in alternative PoS blocks (including miner_tx) are validated by validate_alt_block_txs()
|
||||
uint64_t max_unlock_time = 0;
|
||||
r = check_tx_input(b.miner_tx, 1, coinstake_in, id, b.miner_tx.signatures[0], max_related_block_height, max_unlock_time);
|
||||
uint64_t source_max_unlock_time_for_pos_coinbase = 0;
|
||||
r = check_tx_input(b.miner_tx, 1, coinstake_in, id, b.miner_tx.signatures[0], max_related_block_height, source_max_unlock_time_for_pos_coinbase);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to validate coinstake input in miner tx, block_id = " << get_block_hash(b));
|
||||
|
||||
if (get_block_height(b) > m_core_runtime_config.hard_fork1_starts_after_height)
|
||||
{
|
||||
uint64_t last_pow_h = get_last_x_block_height(false);
|
||||
CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to failed to validate coinbase in pos block, condition failed: max_related_block_height(" << max_related_block_height << ") < last_pow_h(" << last_pow_h << ")");
|
||||
CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")");
|
||||
//let's check that coinbase amount and unlock time
|
||||
r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, max_unlock_time);
|
||||
r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b)
|
||||
<< "max_unlock_time=" << max_unlock_time);
|
||||
<< "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(max_unlock_time), false, "Failed to failed to validate coinbase in pos block, condition failed: is_tx_spendtime_unlocked(max_unlock_time)(" << max_unlock_time << ")");
|
||||
CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase), false, "Failed to validate coinbase in PoS block, condition failed: is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase)(" << source_max_unlock_time_for_pos_coinbase << ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4839,7 +4870,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
CHECK_AND_ASSERT_MES_NO_RET(add_res, "handle_block_to_main_chain: failed to add transaction back to transaction pool");
|
||||
purge_block_data_from_blockchain(bl, tx_processed_count);
|
||||
add_block_as_invalid(bl, id);
|
||||
LOG_PRINT_L0("Block with id " << id << " added as invalid becouse of wrong inputs in transactions");
|
||||
LOG_PRINT_L0("Block with id " << id << " added as invalid because of wrong inputs in transactions");
|
||||
bvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -5339,7 +5370,7 @@ bool blockchain_storage::build_stake_modifier(stake_modifier_type& sm, const alt
|
|||
else
|
||||
{
|
||||
bool r = string_tools::parse_tpod_from_hex_string(POS_STARTER_KERNEL_HASH, sm.last_pos_kernel_id);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse POS_STARTER_MODFIFIER");
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse POS_STARTER_KERNEL_HASH");
|
||||
}
|
||||
|
||||
sm.last_pow_id = get_block_hash(pbei_last_pow->bl);
|
||||
|
|
|
|||
|
|
@ -267,14 +267,14 @@ namespace currency
|
|||
uint64_t get_aliases_count()const;
|
||||
uint64_t get_block_h_older_then(uint64_t timestamp) const;
|
||||
bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& max_unlock_time)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height)const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height)const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height, crypto::hash& max_used_block_id)const;
|
||||
bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const transaction& source_tx, size_t out_n) const;
|
||||
bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id, uint64_t block_height) const;
|
||||
bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& max_unlock_time) const;
|
||||
bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const;
|
||||
bool check_tokey_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const std::vector<const crypto::public_key*>& output_keys_ptrs) const;
|
||||
uint64_t get_current_comulative_blocksize_limit()const;
|
||||
uint64_t get_current_hashrate(size_t aprox_count)const;
|
||||
|
|
@ -312,7 +312,7 @@ namespace currency
|
|||
bool build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0, crypto::hash *p_last_block_hash = nullptr) const;
|
||||
|
||||
bool scan_pos(const COMMAND_RPC_SCAN_POS::request& sp, COMMAND_RPC_SCAN_POS::response& rsp)const;
|
||||
bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t max_unlock_time)const;
|
||||
bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const;
|
||||
bool validate_pos_block(const block& b, const crypto::hash& id, bool for_altchain)const;
|
||||
bool validate_pos_block(const block& b, wide_difficulty_type basic_diff, const crypto::hash& id, bool for_altchain)const;
|
||||
bool validate_pos_block(const block& b,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ namespace currency
|
|||
FIELD(block_cumulative_size)
|
||||
FIELD(cumulative_diff_adjusted)
|
||||
FIELD(cumulative_diff_precise)
|
||||
FIELD(cumulative_diff_precise_adjusted)
|
||||
FIELD(difficulty)
|
||||
FIELD(already_generated_coins)
|
||||
FIELD(stake_hash)
|
||||
|
|
|
|||
|
|
@ -255,13 +255,13 @@ namespace currency
|
|||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_message
|
||||
struct tx_derivation_hint
|
||||
{
|
||||
std::string msg;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(msg)
|
||||
END_SERIALIZE()
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_service_attachment
|
||||
|
|
@ -382,7 +382,7 @@ namespace currency
|
|||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct etc_tx_derivation_hint
|
||||
struct etc_tx_uint16_t
|
||||
{
|
||||
uint16_t v;
|
||||
BEGIN_SERIALIZE()
|
||||
|
|
@ -390,7 +390,7 @@ namespace currency
|
|||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
typedef boost::mpl::vector<tx_service_attachment, tx_comment, tx_payer, tx_receiver, tx_message, std::string, tx_crypto_checksum, etc_tx_time, etc_tx_details_unlock_time, etc_tx_details_expiration_time, etc_tx_details_flags, crypto::public_key, extra_attachment_info, extra_alias_entry, extra_user_data, extra_padding, etc_tx_derivation_hint, etc_tx_details_unlock_time2> all_payload_types;
|
||||
typedef boost::mpl::vector<tx_service_attachment, tx_comment, tx_payer, tx_receiver, tx_derivation_hint, std::string, tx_crypto_checksum, etc_tx_time, etc_tx_details_unlock_time, etc_tx_details_expiration_time, etc_tx_details_flags, crypto::public_key, extra_attachment_info, extra_alias_entry, extra_user_data, extra_padding, etc_tx_uint16_t, etc_tx_details_unlock_time2> all_payload_types;
|
||||
typedef boost::make_variant_over<all_payload_types>::type attachment_v;
|
||||
typedef boost::make_variant_over<all_payload_types>::type extra_v;
|
||||
typedef boost::make_variant_over<all_payload_types>::type payload_items_v;
|
||||
|
|
@ -602,7 +602,7 @@ SET_VARIANT_TAGS(currency::tx_comment, 7, "comment");
|
|||
SET_VARIANT_TAGS(currency::tx_payer, 8, "payer");
|
||||
SET_VARIANT_TAGS(std::string, 9, "string");
|
||||
SET_VARIANT_TAGS(currency::tx_crypto_checksum, 10, "checksum");
|
||||
SET_VARIANT_TAGS(currency::tx_message, 11, "message");
|
||||
SET_VARIANT_TAGS(currency::tx_derivation_hint, 11, "derivation_hint");
|
||||
SET_VARIANT_TAGS(currency::tx_service_attachment, 12, "attachment");
|
||||
//SET_VARIANT_TAGS(currency::tx_onetime_secret_key, 13, "sec_key");
|
||||
SET_VARIANT_TAGS(currency::etc_tx_details_unlock_time, 14, "unlock_time");
|
||||
|
|
@ -616,7 +616,7 @@ SET_VARIANT_TAGS(currency::extra_user_data, 19, "user_data");
|
|||
SET_VARIANT_TAGS(currency::extra_alias_entry, 20, "alias_entry");
|
||||
SET_VARIANT_TAGS(currency::extra_padding, 21, "extra_padding");
|
||||
SET_VARIANT_TAGS(crypto::public_key, 22, "pub_key");
|
||||
SET_VARIANT_TAGS(currency::etc_tx_derivation_hint, 23, "derive_hint");
|
||||
SET_VARIANT_TAGS(currency::etc_tx_uint16_t, 23, "etc_tx_uint16");
|
||||
SET_VARIANT_TAGS(uint16_t, 24, "derive_xor");
|
||||
//txout_v
|
||||
SET_VARIANT_TAGS(currency::ref_by_id, 25, "ref_by_id");
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ namespace boost
|
|||
a & x.derivation_hash;
|
||||
}
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, currency::tx_message &x, const boost::serialization::version_type ver)
|
||||
inline void serialize(Archive &a, currency::tx_derivation_hint &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & x.msg;
|
||||
}
|
||||
|
|
@ -211,7 +211,7 @@ namespace boost
|
|||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, currency::etc_tx_derivation_hint &at, const boost::serialization::version_type ver)
|
||||
inline void serialize(Archive &a, currency::etc_tx_uint16_t&at, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & at.v;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,8 +187,10 @@
|
|||
#define CURRENCY_CORE_INSTANCE_LOCK_FILE "lock.lck"
|
||||
|
||||
|
||||
#define CURRENCY_POOLDATA_FOLDERNAME "poolstate"
|
||||
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME "blockchain"
|
||||
#define CURRENCY_POOLDATA_FOLDERNAME_OLD "poolstate"
|
||||
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME_OLD "blockchain"
|
||||
#define CURRENCY_POOLDATA_FOLDERNAME "poolstate_lmdb_v1"
|
||||
#define CURRENCY_BLOCKCHAINDATA_FOLDERNAME "blockchain_lmdb_v1"
|
||||
#define P2P_NET_DATA_FILENAME "p2pstate.bin"
|
||||
#define MINER_CONFIG_FILENAME "miner_conf.json"
|
||||
#define GUI_SECURE_CONFIG_FILENAME "gui_secure_conf.bin"
|
||||
|
|
@ -200,7 +202,7 @@
|
|||
#define CURRENT_TRANSACTION_CHAIN_ENTRY_ARCHIVE_VER 3
|
||||
#define CURRENT_BLOCK_EXTENDED_INFO_ARCHIVE_VER 1
|
||||
|
||||
#define BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION CURRENCY_FORMATION_VERSION + 8
|
||||
#define BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION CURRENCY_FORMATION_VERSION + 9
|
||||
#define BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION 1
|
||||
|
||||
|
||||
|
|
@ -217,13 +219,12 @@
|
|||
#define BLOCK_MINOR_VERSION_GENESIS 0
|
||||
#define BLOCK_MAJOR_VERSION_INITAL 0
|
||||
#ifndef TESTNET
|
||||
#define ZANO_HARDFORK_1_AFTER_HEIGHT 172200
|
||||
#define ZANO_HARDFORK_1_AFTER_HEIGHT 194624
|
||||
#else
|
||||
#define ZANO_HARDFORK_1_AFTER_HEIGHT 1440
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static_assert(CURRENCY_MINER_TX_MAX_OUTS <= CURRENCY_TX_MAX_ALLOWED_OUTS, "Miner tx must obey normal tx max outs limit");
|
||||
static_assert(PREMINE_AMOUNT / WALLET_MAX_ALLOWED_OUTPUT_AMOUNT < CURRENCY_MINER_TX_MAX_OUTS, "Premine can't be divided into reasonable number of outs");
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ using namespace epee;
|
|||
#include "currency_core/currency_config.h"
|
||||
#include "currency_format_utils.h"
|
||||
#include "misc_language.h"
|
||||
#include "string_coding.h"
|
||||
|
||||
#define MINIMUM_REQUIRED_FREE_SPACE_BYTES (1024 * 1024 * 100)
|
||||
|
||||
DISABLE_VS_WARNINGS(4355)
|
||||
#undef LOG_DEFAULT_CHANNEL
|
||||
|
|
@ -136,6 +139,9 @@ namespace currency
|
|||
{
|
||||
bool r = handle_command_line(vm);
|
||||
|
||||
uint64_t available_space = 0;
|
||||
CHECK_AND_ASSERT_MES(!check_if_free_space_critically_low(&available_space), false, "free space in data folder is critically low: " << std::fixed << available_space / (1024 * 1024) << " MB");
|
||||
|
||||
r = m_mempool.init(m_config_folder);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
|
||||
|
||||
|
|
@ -710,18 +716,39 @@ namespace currency
|
|||
l->on_blockchain_update();
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
#define MINIMUM_REQUIRED_FREE_SPACE_BYTES (1024 * 1024 * 100)
|
||||
bool core::check_if_free_space_critically_low(uint64_t* p_available_space /* = nullptr */)
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
try
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(tools::create_directories_if_necessary(m_config_folder), false, "create_directories_if_necessary failed: " << m_config_folder);
|
||||
std::wstring config_folder_w = epee::string_encoding::utf8_to_wstring(m_config_folder);
|
||||
fs::space_info si = fs::space(config_folder_w);
|
||||
if (p_available_space != nullptr)
|
||||
*p_available_space = si.available;
|
||||
return si.available < MINIMUM_REQUIRED_FREE_SPACE_BYTES;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG_ERROR("failed to determine free space: " << e.what());
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_ERROR("failed to determine free space: unknown exception");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void core::check_free_space()
|
||||
{
|
||||
if (!m_critical_error_handler)
|
||||
return;
|
||||
|
||||
boost::filesystem::space_info si = boost::filesystem::space(m_config_folder);
|
||||
|
||||
if (si.available < MINIMUM_REQUIRED_FREE_SPACE_BYTES)
|
||||
{
|
||||
m_critical_error_handler->on_critical_low_free_space(si.available, MINIMUM_REQUIRED_FREE_SPACE_BYTES);
|
||||
}
|
||||
uint64_t available_space = 0;
|
||||
if (check_if_free_space_critically_low(&available_space))
|
||||
m_critical_error_handler->on_critical_low_free_space(available_space, MINIMUM_REQUIRED_FREE_SPACE_BYTES);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include "warnings.h"
|
||||
#include "crypto/hash.h"
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4355)
|
||||
|
||||
namespace currency
|
||||
|
|
@ -136,8 +136,9 @@ namespace currency
|
|||
|
||||
void notify_blockchain_update_listeners();
|
||||
|
||||
bool check_if_free_space_critically_low(uint64_t* p_available_space = nullptr);
|
||||
void check_free_space();
|
||||
|
||||
|
||||
|
||||
blockchain_storage m_blockchain_storage;
|
||||
tx_memory_pool m_mempool;
|
||||
|
|
@ -158,4 +159,4 @@ namespace currency
|
|||
};
|
||||
}
|
||||
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
|
|
|||
|
|
@ -516,6 +516,17 @@ namespace currency
|
|||
return r;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
uint16_t get_derivation_hint(const crypto::key_derivation& derivation)
|
||||
{
|
||||
crypto::hash h = blake2_hash(&derivation, sizeof(derivation));
|
||||
|
||||
uint16_t* pderiv_hash_as_array = (uint16_t*)&h;
|
||||
uint16_t res = pderiv_hash_as_array[0];
|
||||
for (size_t i = 1; i != sizeof(h) / sizeof(uint16_t); i++)
|
||||
res ^= pderiv_hash_as_array[i];
|
||||
return res;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
uint64_t get_string_uint64_hash(const std::string& str)
|
||||
{
|
||||
crypto::hash h = crypto::cn_fast_hash(str.data(), str.size());
|
||||
|
|
@ -523,15 +534,22 @@ namespace currency
|
|||
return phash_as_array[0] ^ phash_as_array[1] ^ phash_as_array[2] ^ phash_as_array[3];
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
uint16_t get_derivation_xor(const crypto::key_derivation& derivation)
|
||||
tx_derivation_hint make_tx_derivation_hint_from_uint16(uint16_t hint)
|
||||
{
|
||||
uint16_t* pderiv_as_array = (uint16_t*)&derivation;
|
||||
uint16_t res = pderiv_as_array[0];
|
||||
for (size_t i = 1; i != sizeof(derivation) / sizeof(uint16_t); i++)
|
||||
res ^= pderiv_as_array[i];
|
||||
return res;
|
||||
tx_derivation_hint dh = AUTO_VAL_INIT(dh);
|
||||
dh.msg.assign((const char*)&hint, sizeof(hint));
|
||||
return dh;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// bool get_uint16_from_tx_derivation_hint(const tx_derivation_hint& dh, uint16_t& hint)
|
||||
// {
|
||||
// tx_derivation_hint dh;
|
||||
// if (dh.msg.size() != sizeof(hint))
|
||||
// return false;
|
||||
// hint = *((uint16_t*)dh.msg.data());
|
||||
// return true;
|
||||
// }
|
||||
//---------------------------------------------------------------
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, uint8_t tx_outs_attr)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(de.addr.size() == 1 || (de.addr.size() > 1 && de.minimum_sigs <= de.addr.size()), false, "Invalid destination entry: amount: " << de.amount << " minimum_sigs: " << de.minimum_sigs << " addr.size(): " << de.addr.size());
|
||||
|
|
@ -551,12 +569,12 @@ namespace currency
|
|||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
bool r = derive_public_key_from_target_address(apa, tx_sec_key, output_index, out_eph_public_key, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to derive_public_key_from_target_address");
|
||||
etc_tx_derivation_hint dh = AUTO_VAL_INIT(dh);
|
||||
dh.v = get_derivation_xor(derivation);
|
||||
if (deriv_cache.count(dh.v) == 0)
|
||||
|
||||
uint16_t hint = get_derivation_hint(derivation);
|
||||
if (deriv_cache.count(hint) == 0)
|
||||
{
|
||||
tx.extra.push_back(dh);
|
||||
deriv_cache.insert(dh.v);
|
||||
tx.extra.push_back(make_tx_derivation_hint_from_uint16(hint));
|
||||
deriv_cache.insert(hint);
|
||||
}
|
||||
}
|
||||
target_keys.push_back(out_eph_public_key);
|
||||
|
|
@ -646,11 +664,6 @@ namespace currency
|
|||
crypto::chacha_crypt(m.acc_addr, m_key);
|
||||
m_was_crypted_entries = true;
|
||||
}
|
||||
void operator()(tx_message& m)
|
||||
{
|
||||
crypto::chacha_crypt(m.msg, m_key);
|
||||
m_was_crypted_entries = true;
|
||||
}
|
||||
void operator()(tx_service_attachment& sa)
|
||||
{
|
||||
if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
|
||||
|
|
@ -686,13 +699,6 @@ namespace currency
|
|||
rdecrypted_att.push_back(local_comment);
|
||||
}
|
||||
|
||||
void operator()(const tx_message& m)
|
||||
{
|
||||
tx_message local_msg = m;
|
||||
crypto::chacha_crypt(local_msg.msg, rkey);
|
||||
rdecrypted_att.push_back(local_msg);
|
||||
}
|
||||
|
||||
void operator()(const tx_service_attachment& sa)
|
||||
{
|
||||
tx_service_attachment local_sa = sa;
|
||||
|
|
@ -1544,14 +1550,19 @@ namespace currency
|
|||
bool check_tx_derivation_hint(const transaction& tx, const crypto::key_derivation& derivation)
|
||||
{
|
||||
bool found_der_xor = false;
|
||||
uint16_t my_derive_xor = get_derivation_xor(derivation);
|
||||
uint16_t hint = get_derivation_hint(derivation);
|
||||
tx_derivation_hint dh = make_tx_derivation_hint_from_uint16(hint);
|
||||
for (auto& e : tx.extra)
|
||||
{
|
||||
if (e.type() == typeid(etc_tx_derivation_hint))
|
||||
if (e.type() == typeid(tx_derivation_hint))
|
||||
{
|
||||
found_der_xor = true;
|
||||
if (my_derive_xor == boost::get<etc_tx_derivation_hint>(e).v)
|
||||
return true;
|
||||
const tx_derivation_hint& tdh = boost::get<tx_derivation_hint>(e);
|
||||
if (tdh.msg.size() == sizeof(uint16_t))
|
||||
{
|
||||
found_der_xor = true;
|
||||
if (dh.msg == tdh.msg)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//if tx doesn't have any hints - feature is not supported, use full scan
|
||||
|
|
@ -1726,7 +1737,13 @@ namespace currency
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
bool validate_password(const std::string& password)
|
||||
{
|
||||
static const std::string allowed_password_symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!?@#$%^&*_+|{}[]()<>:;\"'-=\\/.,";
|
||||
size_t n = password.find_first_not_of(allowed_password_symbols, 0);
|
||||
return n == std::string::npos;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
#define ANTI_OVERFLOW_AMOUNT 1000000
|
||||
|
|
@ -2204,9 +2221,9 @@ namespace currency
|
|||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const tx_message& ee)
|
||||
bool operator()(const tx_derivation_hint& ee)
|
||||
{
|
||||
tv.type = "message";
|
||||
tv.type = "derivation_hint";
|
||||
tv.short_view = std::to_string(ee.msg.size()) + " bytes";
|
||||
tv.datails_view = epee::string_tools::buff_to_hex_nodelimer(ee.msg);
|
||||
|
||||
|
|
@ -2220,7 +2237,7 @@ namespace currency
|
|||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const etc_tx_derivation_hint& dh)
|
||||
bool operator()(const etc_tx_uint16_t& dh)
|
||||
{
|
||||
tv.type = "XOR";
|
||||
tv.short_view = epee::string_tools::pod_to_hex(dh);
|
||||
|
|
@ -2702,7 +2719,7 @@ namespace currency
|
|||
}
|
||||
|
||||
|
||||
wide_difficulty_type get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
const wide_difficulty_type& difficulty_pow_at_split_point,
|
||||
const difficulties& a_diff,
|
||||
const difficulties& b_diff )
|
||||
|
|
@ -2715,22 +2732,22 @@ namespace currency
|
|||
|
||||
boost::multiprecision::uint1024_t basic_sum = boost::multiprecision::uint1024_t(a_pow_cumulative_difficulty) + (boost::multiprecision::uint1024_t(a_pos_cumulative_difficulty)*difficulty_pow_at_split_point) / difficulty_pos_at_split_point;
|
||||
boost::multiprecision::uint1024_t res =
|
||||
(basic_sum * a_pow_cumulative_difficulty * a_pos_cumulative_difficulty) / (boost::multiprecision::uint1024_t(a_pow_cumulative_difficulty)*a_pos_cumulative_difficulty);
|
||||
(basic_sum * a_pow_cumulative_difficulty * a_pos_cumulative_difficulty) / (boost::multiprecision::uint1024_t(b_pow_cumulative_difficulty)*b_pos_cumulative_difficulty);
|
||||
|
||||
if (res > boost::math::tools::max_value<wide_difficulty_type>())
|
||||
{
|
||||
ASSERT_MES_AND_THROW("[INTERNAL ERROR]: Failed to get_a_to_b_relative_cumulative_difficulty, res = " << res << ENDL
|
||||
<< ", difficulty_pos_at_split_point: " << difficulty_pos_at_split_point << ENDL
|
||||
<< ", difficulty_pow_at_split_point:" << difficulty_pow_at_split_point << ENDL
|
||||
<< ", a_pos_cumulative_difficulty:" << a_pos_cumulative_difficulty << ENDL
|
||||
<< ", b_pos_cumulative_difficulty:" << b_pos_cumulative_difficulty << ENDL
|
||||
<< ", a_pow_cumulative_difficulty:" << a_pow_cumulative_difficulty << ENDL
|
||||
<< ", b_pow_cumulative_difficulty:" << b_pow_cumulative_difficulty << ENDL
|
||||
);
|
||||
}
|
||||
// if (res > boost::math::tools::max_value<wide_difficulty_type>())
|
||||
// {
|
||||
// ASSERT_MES_AND_THROW("[INTERNAL ERROR]: Failed to get_a_to_b_relative_cumulative_difficulty, res = " << res << ENDL
|
||||
// << ", difficulty_pos_at_split_point: " << difficulty_pos_at_split_point << ENDL
|
||||
// << ", difficulty_pow_at_split_point:" << difficulty_pow_at_split_point << ENDL
|
||||
// << ", a_pos_cumulative_difficulty:" << a_pos_cumulative_difficulty << ENDL
|
||||
// << ", b_pos_cumulative_difficulty:" << b_pos_cumulative_difficulty << ENDL
|
||||
// << ", a_pow_cumulative_difficulty:" << a_pow_cumulative_difficulty << ENDL
|
||||
// << ", b_pow_cumulative_difficulty:" << b_pow_cumulative_difficulty << ENDL
|
||||
// );
|
||||
// }
|
||||
TRY_ENTRY();
|
||||
wide_difficulty_type short_res = res.convert_to<wide_difficulty_type>();
|
||||
return short_res;
|
||||
// wide_difficulty_type short_res = res.convert_to<wide_difficulty_type>();
|
||||
return res;
|
||||
CATCH_ENTRY_WITH_FORWARDING_EXCEPTION();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ namespace currency
|
|||
uint64_t get_string_uint64_hash(const std::string& str);
|
||||
bool construct_tx_out(const tx_destination_entry& de, const crypto::secret_key& tx_sec_key, size_t output_index, transaction& tx, std::set<uint16_t>& deriv_cache, uint8_t tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED);
|
||||
bool validate_alias_name(const std::string& al);
|
||||
bool validate_password(const std::string& password);
|
||||
void get_attachment_extra_info_details(const std::vector<attachment_v>& attachment, extra_attachment_info& eai);
|
||||
bool construct_tx(const account_keys& sender_account_keys,
|
||||
const std::vector<tx_source_entry>& sources,
|
||||
|
|
@ -604,7 +605,7 @@ namespace currency
|
|||
wide_difficulty_type pow_diff;
|
||||
};
|
||||
|
||||
wide_difficulty_type get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
boost::multiprecision::uint1024_t get_a_to_b_relative_cumulative_difficulty(const wide_difficulty_type& difficulty_pos_at_split_point,
|
||||
const wide_difficulty_type& difficulty_pow_at_split_point,
|
||||
const difficulties& a_diff,
|
||||
const difficulties& b_diff
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace currency
|
|||
return 0;
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(ut2.unlock_time_array.size() > o_i, "unlock_time_array.size=" << ut2.unlock_time_array.size()
|
||||
<< " is less then o_i=" << o_i << " in tx: " << get_transaction_hash(tx));
|
||||
<< " is less or equal to o_i=" << o_i << " in tx: " << get_transaction_hash(tx));
|
||||
|
||||
return ut2.unlock_time_array[o_i];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ namespace currency
|
|||
uint64_t get_tx_unlock_time(const transaction& tx, uint64_t o_i);
|
||||
uint64_t get_tx_max_unlock_time(const transaction& tx);
|
||||
bool get_tx_max_min_unlock_time(const transaction& tx, uint64_t& max_unlock_time, uint64_t& min_unlock_time);
|
||||
inline bool should_unlock_value_be_treated_as_block_height(uint64_t v) { return v < CURRENCY_MAX_BLOCK_NUMBER; }
|
||||
inline uint64_t get_tx_flags(const transaction& tx) { return get_tx_x_detail<etc_tx_details_flags>(tx); }
|
||||
inline uint64_t get_tx_expiration_time(const transaction& tx) {return get_tx_x_detail<etc_tx_details_expiration_time>(tx); }
|
||||
inline void set_tx_unlock_time(transaction& tx, uint64_t v) { set_tx_x_detail<etc_tx_details_unlock_time>(tx, v); }
|
||||
|
|
@ -106,4 +107,4 @@ namespace currency
|
|||
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size);
|
||||
blobdata tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ namespace currency
|
|||
else
|
||||
{
|
||||
// this tx has no fee
|
||||
LOG_ERROR("Transaction with id= " << id << " has too small fee: " << tx_fee << ", expected fee: " << m_blockchain.get_core_runtime_config().tx_pool_min_fee);
|
||||
LOG_PRINT_RED_L0("Transaction with id= " << id << " has too small fee: " << tx_fee << ", expected fee: " << m_blockchain.get_core_runtime_config().tx_pool_min_fee);
|
||||
tvc.m_verification_failed = false;
|
||||
tvc.m_should_be_relayed = false;
|
||||
tvc.m_added_to_pool = false;
|
||||
|
|
@ -1120,19 +1120,30 @@ namespace currency
|
|||
{
|
||||
m_config_folder = config_folder;
|
||||
|
||||
LOG_PRINT_L0("Loading blockchain...");
|
||||
uint64_t cache_size_l1 = CACHE_SIZE;
|
||||
LOG_PRINT_GREEN("Using pool db file cache size(L1): " << cache_size_l1, LOG_LEVEL_0);
|
||||
|
||||
// remove old incompartible DB
|
||||
const std::string old_db_folder_path = m_config_folder + "/" CURRENCY_POOLDATA_FOLDERNAME_OLD;
|
||||
if (boost::filesystem::exists(epee::string_encoding::utf8_to_wstring(old_db_folder_path)))
|
||||
{
|
||||
LOG_PRINT_YELLOW("Removing old DB in " << old_db_folder_path << "...", LOG_LEVEL_0);
|
||||
boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(old_db_folder_path));
|
||||
}
|
||||
|
||||
const std::string db_folder_path = m_config_folder + "/" CURRENCY_POOLDATA_FOLDERNAME;
|
||||
|
||||
LOG_PRINT_L0("Loading blockchain from " << db_folder_path << "...");
|
||||
|
||||
bool db_opened_okay = false;
|
||||
for(size_t loading_attempt_no = 0; loading_attempt_no < 2; ++loading_attempt_no)
|
||||
{
|
||||
bool res = m_db.open(db_folder_path);
|
||||
bool res = m_db.open(db_folder_path, cache_size_l1);
|
||||
if (!res)
|
||||
{
|
||||
// if DB could not be opened -- try to remove the whole folder and re-open DB
|
||||
LOG_PRINT_YELLOW("Failed to initialize database in folder: " << db_folder_path << ", first attempt", LOG_LEVEL_0);
|
||||
boost::filesystem::remove_all(db_folder_path);
|
||||
res = m_db.open(db_folder_path);
|
||||
boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(db_folder_path));
|
||||
res = m_db.open(db_folder_path, cache_size_l1);
|
||||
CHECK_AND_ASSERT_MES(res, false, "Failed to initialize database in folder: " << db_folder_path << ", second attempt");
|
||||
}
|
||||
|
||||
|
|
@ -1171,7 +1182,7 @@ namespace currency
|
|||
m_db_alias_addresses.deinit();
|
||||
m_db_solo_options.deinit();
|
||||
m_db.close();
|
||||
size_t files_removed = boost::filesystem::remove_all(db_folder_path);
|
||||
size_t files_removed = boost::filesystem::remove_all(epee::string_encoding::utf8_to_wstring(db_folder_path));
|
||||
LOG_PRINT_L1(files_removed << " files at " << db_folder_path << " removed");
|
||||
|
||||
// try to re-create DB and re-init containers
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#undef LOG_DEFAULT_CHANNEL
|
||||
#define LOG_DEFAULT_CHANNEL "currency_protocol"
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4355)
|
||||
|
||||
#define ASYNC_RELAY_MODE
|
||||
|
|
@ -145,4 +145,4 @@ namespace currency
|
|||
#undef LOG_DEFAULT_CHANNEL
|
||||
#define LOG_DEFAULT_CHANNEL NULL
|
||||
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
|
|
|||
|
|
@ -770,36 +770,14 @@ namespace currency
|
|||
#define TIME_SYNC_DELTA_RING_BUFFER_SIZE 8
|
||||
#define TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE (60 * 5) // max acceptable difference between time delta median among peers and local time (seconds)
|
||||
#define TIME_SYNC_NTP_TO_LOCAL_MAX_DIFFERENCE (60 * 5) // max acceptable difference between NTP time and local time (seconds)
|
||||
#define TIME_SYNC_NTP_SERVERS { "time.google.com", "0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org", "3.pool.ntp.org" }
|
||||
#define TIME_SYNC_NTP_ATTEMPTS_COUNT 3 // max number of attempts when getting time from NTP server
|
||||
|
||||
static int64_t get_ntp_time()
|
||||
{
|
||||
static const std::vector<std::string> ntp_servers TIME_SYNC_NTP_SERVERS;
|
||||
|
||||
for (size_t att = 0; att < TIME_SYNC_NTP_ATTEMPTS_COUNT; ++att)
|
||||
{
|
||||
size_t i = 0;
|
||||
crypto::generate_random_bytes(sizeof(i), &i);
|
||||
const std::string& ntp_server = ntp_servers[i % ntp_servers.size()];
|
||||
LOG_PRINT_L3("NTP: trying to get time from " << ntp_server);
|
||||
int64_t time = tools::get_ntp_time(ntp_server);
|
||||
if (time > 0)
|
||||
{
|
||||
LOG_PRINT_L2("NTP: " << ntp_server << " responded with " << time << " (" << epee::misc_utils::get_time_str_v2(time) << ")");
|
||||
return time;
|
||||
}
|
||||
LOG_PRINT_L2("NTP: cannot get time from " << ntp_server);
|
||||
}
|
||||
|
||||
return 0; // smth went wrong
|
||||
}
|
||||
|
||||
template<class t_core>
|
||||
bool t_currency_protocol_handler<t_core>::add_time_delta_and_check_time_sync(int64_t time_delta)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_time_deltas_lock);
|
||||
|
||||
auto get_core_time = [this] { return m_core.get_blockchain_storage().get_core_runtime_config().get_core_time(); };
|
||||
|
||||
m_time_deltas.push_back(time_delta);
|
||||
while (m_time_deltas.size() > TIME_SYNC_DELTA_RING_BUFFER_SIZE)
|
||||
m_time_deltas.pop_front();
|
||||
|
|
@ -813,7 +791,8 @@ namespace currency
|
|||
LOG_PRINT_MAGENTA("TIME: network time difference is " << m_last_median2local_time_difference << " (max is " << TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE << ")", LOG_LEVEL_2);
|
||||
if (std::abs(m_last_median2local_time_difference) > TIME_SYNC_DELTA_TO_LOCAL_MAX_DIFFERENCE)
|
||||
{
|
||||
int64_t ntp_time = get_ntp_time();
|
||||
int64_t ntp_time = tools::get_ntp_time();
|
||||
LOG_PRINT_L2("NTP: received time " << ntp_time << " (" << epee::misc_utils::get_time_str_v2(ntp_time) << "), diff: " << std::showpos << get_core_time() - ntp_time);
|
||||
if (ntp_time == 0)
|
||||
{
|
||||
// error geting ntp time
|
||||
|
|
@ -823,7 +802,7 @@ namespace currency
|
|||
|
||||
// got ntp time correctly
|
||||
// update local time, because getting ntp time could be time consuming
|
||||
uint64_t local_time_2 = m_core.get_blockchain_storage().get_core_runtime_config().get_core_time();
|
||||
uint64_t local_time_2 = get_core_time();
|
||||
m_last_ntp2local_time_difference = local_time_2 - ntp_time;
|
||||
if (std::abs(m_last_ntp2local_time_difference) > TIME_SYNC_NTP_TO_LOCAL_MAX_DIFFERENCE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ using namespace epee;
|
|||
#include "common/miniupnp_helper.h"
|
||||
#include "version.h"
|
||||
#include "currency_core/core_tools.h"
|
||||
#include "common/callstack_helper.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
|
|
@ -86,6 +87,13 @@ struct core_critical_error_handler_t : public currency::i_critical_error_handler
|
|||
bool dont_stop_on_low_space;
|
||||
};
|
||||
|
||||
void terminate_handler_func()
|
||||
{
|
||||
LOG_ERROR("\n\nTERMINATE HANDLER\n"); // should print callstack
|
||||
std::fflush(nullptr); // all open output streams are flushed
|
||||
std::abort(); // default terminate handler's behavior
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
try
|
||||
|
|
@ -100,7 +108,7 @@ int main(int argc, char* argv[])
|
|||
#endif
|
||||
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2);
|
||||
log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL);
|
||||
log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,wallet,lmdb");
|
||||
log_space::log_singletone::enable_channels("core,currency_protocol,tx_pool,wallet");
|
||||
LOG_PRINT_L0("Starting...");
|
||||
|
||||
tools::signal_handler::install_fatal([](int sig_number, void* address) {
|
||||
|
|
@ -108,6 +116,12 @@ int main(int argc, char* argv[])
|
|||
std::fflush(nullptr); // all open output streams are flushed
|
||||
});
|
||||
|
||||
// setup custom callstack retrieving function
|
||||
epee::misc_utils::get_callstack(tools::get_callstack);
|
||||
|
||||
// setup custom terminate functions
|
||||
std::set_terminate(&terminate_handler_func);
|
||||
|
||||
po::options_description desc_cmd_only("Command line options");
|
||||
po::options_description desc_cmd_sett("Command line options and settings options", 130, 83);
|
||||
|
||||
|
|
@ -159,8 +173,8 @@ int main(int argc, char* argv[])
|
|||
std::string data_dir = command_line::get_arg(vm, command_line::arg_data_dir);
|
||||
std::string config = command_line::get_arg(vm, command_line::arg_config_file);
|
||||
|
||||
boost::filesystem::path data_dir_path(data_dir);
|
||||
boost::filesystem::path config_path(config);
|
||||
boost::filesystem::path data_dir_path(epee::string_encoding::utf8_to_wstring(data_dir));
|
||||
boost::filesystem::path config_path(epee::string_encoding::utf8_to_wstring(config));
|
||||
if (!config_path.has_parent_path())
|
||||
{
|
||||
config_path = data_dir_path / config_path;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include "currency_core/bc_offers_service.h"
|
||||
#include "serialization/binary_utils.h"
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4100)
|
||||
|
||||
class daemon_commands_handler
|
||||
|
|
@ -70,6 +70,9 @@ public:
|
|||
m_cmd_binder.set_handler("print_tx_outputs_usage", boost::bind(&daemon_commands_handler::print_tx_outputs_usage, this, _1), "Analyse if tx outputs for involved in subsequent transactions");
|
||||
m_cmd_binder.set_handler("print_difficulties_of_last_n_blocks", boost::bind(&daemon_commands_handler::print_difficulties_of_last_n_blocks, this, _1), "Print difficulties of last n blocks");
|
||||
|
||||
#ifdef _DEBUG
|
||||
m_cmd_binder.set_handler("debug_set_time_adj", boost::bind(&daemon_commands_handler::debug_set_time_adj, this, _1), "DEBUG: set core time adjustment");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool start_handling()
|
||||
|
|
@ -499,8 +502,15 @@ private:
|
|||
bool r = m_srv.get_payload_object().get_core().get_blockchain_storage().get_main_blocks_rpc_details(height, 1, false, blocks);
|
||||
if (r && blocks.size())
|
||||
{
|
||||
currency::block b = AUTO_VAL_INIT(b);
|
||||
m_srv.get_payload_object().get_core().get_blockchain_storage().get_block_by_height(height, b);
|
||||
currency::blobdata blob = block_to_blob(b);
|
||||
std::string block_hex = epee::string_tools::buff_to_hex_nodelimer(blob);
|
||||
|
||||
currency::block_rpc_extended_info& rbei = blocks.back();
|
||||
LOG_PRINT_GREEN("------------------ block_id: " << rbei.id << " ------------------" << ENDL << epee::serialization::store_t_to_json(rbei), LOG_LEVEL_0);
|
||||
LOG_PRINT_GREEN("------------------ block_id: " << rbei.id << " ------------------" <<
|
||||
ENDL << epee::serialization::store_t_to_json(rbei) << ENDL
|
||||
<< " ------------------ hex_blob: " << ENDL << block_hex, LOG_LEVEL_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -523,8 +533,14 @@ private:
|
|||
|
||||
if (r)
|
||||
{
|
||||
currency::block b = AUTO_VAL_INIT(b);
|
||||
m_srv.get_payload_object().get_core().get_blockchain_storage().get_block_by_hash(block_hash, b);
|
||||
currency::blobdata blob = block_to_blob(b);
|
||||
std::string block_hex = epee::string_tools::buff_to_hex_nodelimer(blob);
|
||||
// currency::block& block = bei.bl;
|
||||
LOG_PRINT_GREEN("------------------ block_id: " << bei.id << " ------------------" << ENDL << epee::serialization::store_t_to_json(bei), LOG_LEVEL_0);
|
||||
LOG_PRINT_GREEN("------------------ block_id: " << bei.id << " ------------------" << ENDL
|
||||
<< epee::serialization::store_t_to_json(bei) << ENDL
|
||||
<< " ------------------ hex_blob: " << ENDL << block_hex, LOG_LEVEL_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -811,9 +827,51 @@ private:
|
|||
LOG_PRINT_L0(ENDL << epee::deadlock_guard_singleton::get_dlg_state());
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
#ifdef _DEBUG
|
||||
static std::atomic<int64_t>& debug_core_time_shift_accessor()
|
||||
{
|
||||
static std::atomic<int64_t> time_shift(0);
|
||||
return time_shift;
|
||||
}
|
||||
|
||||
static uint64_t debug_core_time_function()
|
||||
{
|
||||
return (int64_t)time(NULL) + debug_core_time_shift_accessor().load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
bool debug_set_time_adj(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.size() != 1)
|
||||
{
|
||||
LOG_PRINT_RED("one arg required: signed time shift in seconds", LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t time_shift = 0;
|
||||
if (!epee::string_tools::string_to_num_fast(args[0], time_shift))
|
||||
{
|
||||
LOG_PRINT_RED("could not parse: " << args[0], LOG_LEVEL_0);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t time_before = debug_core_time_function();
|
||||
debug_core_time_shift_accessor().store(time_shift);
|
||||
uint64_t time_after = debug_core_time_function();
|
||||
|
||||
currency::blockchain_storage& bcs = m_srv.get_payload_object().get_core().get_blockchain_storage();
|
||||
|
||||
currency::core_runtime_config crc = bcs.get_core_runtime_config();
|
||||
crc.get_core_time = &debug_core_time_function;
|
||||
bcs.set_core_runtime_config(crc);
|
||||
|
||||
LOG_PRINT_L0("debug time shift set to " << time_shift << " : time before: " << time_before << ", time_after: " << time_after);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
};
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
#include "core_fast_rpc_proxy.h"
|
||||
#include "string_coding.h"
|
||||
#include "currency_core/core_tools.h"
|
||||
//#include <codecvt>
|
||||
#include "common/callstack_helper.h"
|
||||
|
||||
#define GET_WALLET_OPT_BY_ID(wallet_id, name) \
|
||||
CRITICAL_REGION_LOCAL(m_wallets_lock); \
|
||||
|
|
@ -40,7 +40,8 @@ daemon_backend::daemon_backend():m_pview(&m_view_stub),
|
|||
m_offers_service(nullptr),
|
||||
m_ui_opt(AUTO_VAL_INIT(m_ui_opt)),
|
||||
m_remote_node_mode(false),
|
||||
m_is_pos_allowed(false)
|
||||
m_is_pos_allowed(false),
|
||||
m_qt_logs_enbaled(false)
|
||||
{
|
||||
m_offers_service.set_disabled(true);
|
||||
//m_ccore.get_blockchain_storage().get_attachment_services_manager().add_service(&m_offers_service);
|
||||
|
|
@ -52,6 +53,7 @@ const command_line::arg_descriptor<std::string> arg_xcode_stub = {"-NSDocumentRe
|
|||
const command_line::arg_descriptor<bool> arg_enable_gui_debug_mode = { "gui-debug-mode", "Enable debug options in GUI", false, true };
|
||||
const command_line::arg_descriptor<uint32_t> arg_qt_remote_debugging_port = { "remote-debugging-port", "Specify port for Qt remote debugging", 30333, true };
|
||||
const command_line::arg_descriptor<std::string> arg_remote_node = { "remote-node", "Switch GUI to work with remote node instead of local daemon", "", true };
|
||||
const command_line::arg_descriptor<bool> arg_enable_qt_logs = { "enable-qt-logs", "Forward Qt log messages into main log", false, true };
|
||||
|
||||
void wallet_lock_time_watching_policy::watch_lock_time(uint64_t lock_time)
|
||||
{
|
||||
|
|
@ -66,6 +68,13 @@ daemon_backend::~daemon_backend()
|
|||
stop();
|
||||
}
|
||||
|
||||
void terminate_handler_func()
|
||||
{
|
||||
LOG_ERROR("\n\nTERMINATE HANDLER\n"); // should print callstack
|
||||
std::fflush(nullptr); // all open output streams are flushed
|
||||
std::abort(); // default terminate handler's behavior
|
||||
}
|
||||
|
||||
bool daemon_backend::init(int argc, char* argv[], view::i_view* pview_handler)
|
||||
{
|
||||
m_stop_singal_sent = false;
|
||||
|
|
@ -85,6 +94,11 @@ bool daemon_backend::init(int argc, char* argv[], view::i_view* pview_handler)
|
|||
std::fflush(nullptr); // all open output streams are flushed
|
||||
});
|
||||
|
||||
// setup custom callstack retrieving function
|
||||
epee::misc_utils::get_callstack(tools::get_callstack);
|
||||
|
||||
// setup custom terminate functions
|
||||
std::set_terminate(&terminate_handler_func);
|
||||
|
||||
//#if !defined(NDEBUG)
|
||||
// log_space::log_singletone::add_logger(LOGGER_DEBUGGER, nullptr, nullptr);
|
||||
|
|
@ -112,9 +126,7 @@ bool daemon_backend::init(int argc, char* argv[], view::i_view* pview_handler)
|
|||
command_line::add_arg(desc_cmd_sett, arg_enable_gui_debug_mode);
|
||||
command_line::add_arg(desc_cmd_sett, arg_qt_remote_debugging_port);
|
||||
command_line::add_arg(desc_cmd_sett, arg_remote_node);
|
||||
|
||||
|
||||
|
||||
command_line::add_arg(desc_cmd_sett, arg_enable_qt_logs);
|
||||
|
||||
|
||||
currency::core::init_options(desc_cmd_sett);
|
||||
|
|
@ -142,8 +154,8 @@ bool daemon_backend::init(int argc, char* argv[], view::i_view* pview_handler)
|
|||
m_data_dir = command_line::get_arg(m_vm, command_line::arg_data_dir);
|
||||
std::string config = command_line::get_arg(m_vm, command_line::arg_config_file);
|
||||
|
||||
boost::filesystem::path data_dir_path(m_data_dir);
|
||||
boost::filesystem::path config_path(config);
|
||||
boost::filesystem::path data_dir_path(epee::string_encoding::utf8_to_wstring(m_data_dir));
|
||||
boost::filesystem::path config_path(epee::string_encoding::utf8_to_wstring(config));
|
||||
if (!config_path.has_parent_path())
|
||||
{
|
||||
config_path = data_dir_path / config_path;
|
||||
|
|
@ -208,6 +220,8 @@ bool daemon_backend::init(int argc, char* argv[], view::i_view* pview_handler)
|
|||
// configure for remote node
|
||||
}
|
||||
|
||||
m_qt_logs_enbaled = command_line::get_arg(m_vm, arg_enable_qt_logs);
|
||||
|
||||
m_pview->init(path_to_html);
|
||||
|
||||
if (!coomand_line_parsed)
|
||||
|
|
@ -381,6 +395,7 @@ bool daemon_backend::deinit_local_daemon()
|
|||
LOG_PRINT_L0("Deinitializing p2p...");
|
||||
//dsi.text_state = "Deinitializing p2p";
|
||||
m_pview->update_daemon_status(dsi);
|
||||
m_p2psrv.deinit();
|
||||
|
||||
m_ccore.set_currency_protocol(NULL);
|
||||
m_cprotocol.set_p2p_endpoint(NULL);
|
||||
|
|
@ -427,7 +442,8 @@ void daemon_backend::main_worker(const po::variables_map& m_vm)
|
|||
//m_pview->update_daemon_status(dsi);
|
||||
try
|
||||
{
|
||||
wo.second.stop = true;
|
||||
wo.second.major_stop = true;
|
||||
wo.second.stop_for_refresh = true;
|
||||
wo.second.w.unlocked_get()->stop();
|
||||
|
||||
wo.second.w->get()->store();
|
||||
|
|
@ -541,7 +557,8 @@ void daemon_backend::init_wallet_entry(wallet_vs_options& wo, uint64_t id)
|
|||
{
|
||||
wo.wallet_id = id;
|
||||
wo.do_mining = false;
|
||||
wo.stop = false;
|
||||
wo.major_stop = false;
|
||||
wo.stop_for_refresh = false;
|
||||
wo.plast_daemon_height = &m_last_daemon_height;
|
||||
wo.plast_daemon_network_state = &m_last_daemon_network_state;
|
||||
wo.plast_daemon_is_disconnected = &m_last_daemon_is_disconnected;
|
||||
|
|
@ -835,7 +852,8 @@ std::string daemon_backend::close_wallet(size_t wallet_id)
|
|||
|
||||
try
|
||||
{
|
||||
it->second.stop = true;
|
||||
it->second.major_stop = true;
|
||||
it->second.stop_for_refresh = true;
|
||||
it->second.w.unlocked_get()->stop();
|
||||
|
||||
it->second.w->get()->store();
|
||||
|
|
@ -1482,8 +1500,9 @@ void daemon_backend::wallet_vs_options::worker_func()
|
|||
epee::math_helper::once_a_time_seconds<1> scan_pool_interval;
|
||||
epee::math_helper::once_a_time_seconds<POS_WALLET_MINING_SCAN_INTERVAL> pos_minin_interval;
|
||||
view::wallet_status_info wsi = AUTO_VAL_INIT(wsi);
|
||||
while (!stop)
|
||||
while (!major_stop)
|
||||
{
|
||||
stop_for_refresh = false;
|
||||
try
|
||||
{
|
||||
wsi.wallet_state = view::wallet_status_info::wallet_state_ready;
|
||||
|
|
@ -1510,7 +1529,7 @@ void daemon_backend::wallet_vs_options::worker_func()
|
|||
prepare_wallet_status_info(*this, wsi);
|
||||
pview->update_wallet_status(wsi);
|
||||
}
|
||||
w->get()->refresh(stop);
|
||||
w->get()->refresh(stop_for_refresh);
|
||||
w->get()->resend_unconfirmed();
|
||||
{
|
||||
auto w_ptr = *w; // get locked exclusive access to the wallet first (it's more likely that wallet is locked for a long time than 'offers')
|
||||
|
|
@ -1542,11 +1561,11 @@ void daemon_backend::wallet_vs_options::worker_func()
|
|||
});
|
||||
}
|
||||
|
||||
if (stop)
|
||||
if (major_stop || stop_for_refresh)
|
||||
break;
|
||||
//******************************************************************************************
|
||||
//mining zone
|
||||
if (do_mining)
|
||||
if (do_mining && *plast_daemon_network_state == currency::COMMAND_RPC_GET_INFO::daemon_network_state_online)
|
||||
{
|
||||
pos_minin_interval.do_call([this](){
|
||||
tools::wallet2::mining_context ctx = AUTO_VAL_INIT(ctx);
|
||||
|
|
@ -1608,7 +1627,8 @@ void daemon_backend::wallet_vs_options::worker_func()
|
|||
daemon_backend::wallet_vs_options::~wallet_vs_options()
|
||||
{
|
||||
do_mining = false;
|
||||
stop = true;
|
||||
major_stop = true;
|
||||
stop_for_refresh = true;
|
||||
break_mining_loop = true;
|
||||
if (miner_thread.joinable())
|
||||
miner_thread.join();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <boost/program_options.hpp>
|
||||
#include "warnings.h"
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4100)
|
||||
DISABLE_VS_WARNINGS(4503)
|
||||
#include "include_base_utils.h"
|
||||
|
|
@ -30,7 +30,7 @@ using namespace epee;
|
|||
#include "wallet/wallet2.h"
|
||||
#include "wallet_id_adapter.h"
|
||||
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
|
|
@ -56,7 +56,10 @@ public:
|
|||
currency::core_runtime_config core_conf;
|
||||
epee::locked_object<std::shared_ptr<tools::wallet2>, wallet_lock_time_watching_policy> w;
|
||||
std::atomic<bool> do_mining;
|
||||
std::atomic<bool> stop;
|
||||
std::atomic<bool> major_stop;
|
||||
std::atomic<bool> stop_for_refresh; //use separate var for passing to "refresh" member function,
|
||||
//because it can be changed there due to internal interruption logis
|
||||
|
||||
std::atomic<bool> break_mining_loop;
|
||||
std::atomic<uint64_t> wallet_state;
|
||||
std::atomic<uint64_t> last_wallet_synch_height;
|
||||
|
|
@ -135,6 +138,7 @@ public:
|
|||
void unsubscribe_to_core_events();
|
||||
void get_gui_options(view::gui_options& opt);
|
||||
std::string get_wallet_log_prefix(size_t wallet_id) const;
|
||||
bool is_qt_logs_enabled() const { return m_qt_logs_enbaled; }
|
||||
|
||||
private:
|
||||
void main_worker(const po::variables_map& vm);
|
||||
|
|
@ -180,6 +184,7 @@ private:
|
|||
currency::core_rpc_server m_rpc_server;
|
||||
|
||||
bool m_remote_node_mode;
|
||||
bool m_qt_logs_enbaled;
|
||||
std::atomic<bool> m_is_pos_allowed;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -75,14 +75,14 @@ namespace gui_tools
|
|||
{
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
char pszPath[MAX_PATH] = "";
|
||||
wchar_t pszPath[MAX_PATH] = L"";
|
||||
|
||||
if (SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
|
||||
if (SHGetSpecialFolderPathW(NULL, pszPath, nFolder, fCreate))
|
||||
{
|
||||
return fs::path(pszPath);
|
||||
}
|
||||
|
||||
//LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
|
||||
//LogPrintf("SHGetSpecialFolderPathW() failed, could not obtain requested path.\n");
|
||||
return fs::path("");
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -316,12 +316,12 @@ bool MainWindow::load_app_config()
|
|||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
||||
bool MainWindow::init(const std::string& htmlPath)
|
||||
bool MainWindow::init(const std::string& html_path)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
//QtWebEngine::initialize();
|
||||
init_tray_icon(htmlPath);
|
||||
set_html_path(htmlPath);
|
||||
init_tray_icon(html_path);
|
||||
set_html_path(html_path);
|
||||
|
||||
m_backend.subscribe_to_core_events(this);
|
||||
|
||||
|
|
@ -354,7 +354,7 @@ void MainWindow::on_menu_show()
|
|||
CATCH_ENTRY2(void());
|
||||
}
|
||||
|
||||
void MainWindow::init_tray_icon(const std::string& htmlPath)
|
||||
void MainWindow::init_tray_icon(const std::string& html_path)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if (!QSystemTrayIcon::isSystemTrayAvailable())
|
||||
|
|
@ -384,14 +384,14 @@ void MainWindow::init_tray_icon(const std::string& htmlPath)
|
|||
|
||||
//setup icon
|
||||
#ifdef TARGET_OS_MAC
|
||||
m_normal_icon_path = htmlPath + "/files/app22macos.png"; // X11 tray icon size is 22x22
|
||||
m_blocked_icon_path = htmlPath + "/files/app22macos_blocked.png"; // X11 tray icon size is 22x22
|
||||
m_normal_icon_path = html_path + "/files/app22macos.png"; // X11 tray icon size is 22x22
|
||||
m_blocked_icon_path = html_path + "/files/app22macos_blocked.png"; // X11 tray icon size is 22x22
|
||||
#else
|
||||
m_normal_icon_path = htmlPath + "/files/app22windows.png"; // X11 tray icon size is 22x22
|
||||
m_blocked_icon_path = htmlPath + "/files/app22windows_blocked.png"; // X11 tray icon size
|
||||
m_normal_icon_path = html_path + "/files/app22windows.png"; // X11 tray icon size is 22x22
|
||||
m_blocked_icon_path = html_path + "/files/app22windows_blocked.png"; // X11 tray icon size
|
||||
#endif
|
||||
//setWindowIcon(QIcon(iconPath.c_str()));
|
||||
QIcon qi(m_normal_icon_path.c_str());
|
||||
QIcon qi( QString::fromWCharArray(epee::string_encoding::utf8_to_wstring(m_normal_icon_path).c_str()) );
|
||||
qi.setIsMask(true);
|
||||
m_tray_icon->setIcon(qi);
|
||||
m_tray_icon->setToolTip(CURRENCY_NAME_BASE);
|
||||
|
|
@ -411,7 +411,7 @@ void MainWindow::bool_toggle_icon(const QString& param)
|
|||
else
|
||||
path = m_normal_icon_path;
|
||||
|
||||
QIcon qi(path.c_str());
|
||||
QIcon qi( QString::fromWCharArray(epee::string_encoding::utf8_to_wstring(path).c_str()) );
|
||||
qi.setIsMask(true);
|
||||
m_tray_icon->setIcon(qi);
|
||||
CATCH_ENTRY2(void());
|
||||
|
|
@ -609,10 +609,45 @@ bool MainWindow::show_msg_box(const std::string& message)
|
|||
return true;
|
||||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
||||
void qt_log_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||
{
|
||||
QByteArray local_msg = msg.toLocal8Bit();
|
||||
const char* msg_type = "";
|
||||
switch (type)
|
||||
{
|
||||
case QtDebugMsg: msg_type = "DEBG "; break;
|
||||
case QtInfoMsg: msg_type = "INFO "; break;
|
||||
case QtWarningMsg: msg_type = "WARN "; break;
|
||||
case QtCriticalMsg: msg_type = "CRIT "; break;
|
||||
case QtFatalMsg: msg_type = "FATAL "; break;
|
||||
}
|
||||
|
||||
if (context.file == nullptr && context.function == nullptr)
|
||||
{
|
||||
// no debug info
|
||||
LOG_PRINT("[QT] " << msg_type << local_msg.constData(), LOG_LEVEL_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// some debug info
|
||||
LOG_PRINT("[QT] " << msg_type << local_msg.constData() << " @ " << (context.file ? context.file : "") << ":" << context.line << ", " << (context.function ? context.function : ""), LOG_LEVEL_0);
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::init_backend(int argc, char* argv[])
|
||||
{
|
||||
TRY_ENTRY();
|
||||
return m_backend.init(argc, argv, this);
|
||||
if (!m_backend.init(argc, argv, this))
|
||||
return false;
|
||||
|
||||
if (m_backend.is_qt_logs_enabled())
|
||||
{
|
||||
qInstallMessageHandler(qt_log_message_handler);
|
||||
QLoggingCategory::setFilterRules("*=true"); // enable all logs
|
||||
}
|
||||
|
||||
return true;
|
||||
CATCH_ENTRY2(false);
|
||||
}
|
||||
|
||||
|
|
@ -771,7 +806,7 @@ bool MainWindow::set_html_path(const std::string& path)
|
|||
TRY_ENTRY();
|
||||
//init_tray_icon(path);
|
||||
#ifdef _MSC_VER
|
||||
QString url = QString::fromUtf8(epee::string_encoding::convert_ansii_to_utf8(path).c_str()) + "/index.html";
|
||||
QString url = QString::fromUtf8(path.c_str()) + "/index.html";
|
||||
load_file(url);
|
||||
#else
|
||||
// load_file(QString((std::string("file://") + path + "/index.html").c_str()));
|
||||
|
|
@ -999,6 +1034,7 @@ void MainWindow::on_complete_events()
|
|||
}
|
||||
CATCH_ENTRY2(void());
|
||||
}
|
||||
|
||||
void MainWindow::on_clear_events()
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -1020,9 +1056,13 @@ QString MainWindow::get_secure_app_data(const QString& param)
|
|||
}
|
||||
|
||||
std::string app_data_buff;
|
||||
bool r = file_io_utils::load_file_to_string(m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME, app_data_buff);
|
||||
std::string filename = m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME;
|
||||
bool r = file_io_utils::load_file_to_string(filename, app_data_buff);
|
||||
if (!r)
|
||||
{
|
||||
LOG_PRINT_L1("config file was not loaded: " << m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME);
|
||||
return "";
|
||||
}
|
||||
|
||||
if (app_data_buff.size() < sizeof(app_data_file_binary_header))
|
||||
{
|
||||
|
|
@ -1037,7 +1077,7 @@ QString MainWindow::get_secure_app_data(const QString& param)
|
|||
const app_data_file_binary_header* phdr = reinterpret_cast<const app_data_file_binary_header*>(app_data_buff.data());
|
||||
if (phdr->m_signature != APP_DATA_FILE_BINARY_SIGNATURE)
|
||||
{
|
||||
LOG_ERROR("password missmatch: provided pass: " << pwd.pass);
|
||||
LOG_ERROR("password missmatch");
|
||||
view::api_response ar;
|
||||
ar.error_code = API_RETURN_CODE_WRONG_PASSWORD;
|
||||
return MAKE_RESPONSE(ar);
|
||||
|
|
@ -1045,23 +1085,38 @@ QString MainWindow::get_secure_app_data(const QString& param)
|
|||
|
||||
m_master_password = pwd.pass;
|
||||
|
||||
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
|
||||
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
|
||||
LOG_PRINT_L0("get_secure_app_data, pass hash: " << master_password_hash);
|
||||
|
||||
return app_data_buff.substr(sizeof(app_data_file_binary_header)).c_str();
|
||||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
QString MainWindow::set_master_password(const QString& param)
|
||||
{
|
||||
view::api_response ar;
|
||||
|
||||
view::password_data pwd = AUTO_VAL_INIT(pwd);
|
||||
|
||||
if (!epee::serialization::load_t_from_json(pwd, param.toStdString()))
|
||||
{
|
||||
view::api_response ar;
|
||||
ar.error_code = API_RETURN_CODE_BAD_ARG;
|
||||
return MAKE_RESPONSE(ar);
|
||||
}
|
||||
|
||||
if (!currency::validate_password(pwd.pass))
|
||||
{
|
||||
ar.error_code = API_RETURN_CODE_BAD_ARG;
|
||||
return MAKE_RESPONSE(ar);
|
||||
}
|
||||
|
||||
m_master_password = pwd.pass;
|
||||
|
||||
view::api_response ar;
|
||||
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
|
||||
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
|
||||
LOG_PRINT_L0("set_master_password, pass hash: " << master_password_hash);
|
||||
|
||||
ar.error_code = API_RETURN_CODE_OK;
|
||||
return MAKE_RESPONSE(ar);
|
||||
}
|
||||
|
|
@ -1076,11 +1131,18 @@ QString MainWindow::check_master_password(const QString& param)
|
|||
ar.error_code = API_RETURN_CODE_BAD_ARG;
|
||||
return MAKE_RESPONSE(ar);
|
||||
}
|
||||
|
||||
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
|
||||
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
|
||||
crypto::hash pwd_pre_hash = crypto::cn_fast_hash(pwd.pass.c_str(), pwd.pass.length());
|
||||
crypto::hash pwd_hash = crypto::cn_fast_hash(&pwd_pre_hash, sizeof pwd_pre_hash);
|
||||
|
||||
if (m_master_password != pwd.pass)
|
||||
{
|
||||
ar.error_code = API_RETURN_CODE_WRONG_PASSWORD;
|
||||
}else
|
||||
LOG_PRINT_L0("check_master_password: pwd hash: " << pwd_hash << ", expected: " << master_password_hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
ar.error_code = API_RETURN_CODE_OK;
|
||||
}
|
||||
|
|
@ -1099,18 +1161,27 @@ QString MainWindow::store_app_data(const QString& param)
|
|||
return MAKE_RESPONSE(ar);
|
||||
}
|
||||
|
||||
//bool r = file_io_utils::save_string_to_file(m_backend.get_config_folder() + "/" + GUI_CONFIG_FILENAME, param.toStdString());
|
||||
bool r = file_io_utils::save_string_to_file(m_backend.get_config_folder() + "/" + GUI_CONFIG_FILENAME, param.toStdString());
|
||||
//view::api_response ar;
|
||||
if (r)
|
||||
ar.error_code = API_RETURN_CODE_OK;
|
||||
else
|
||||
ar.error_code = API_RETURN_CODE_FAIL;
|
||||
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
|
||||
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
|
||||
LOG_PRINT_L0("store_app_data, pass hash: " << master_password_hash);
|
||||
|
||||
std::string filename = m_backend.get_config_folder() + "/" + GUI_CONFIG_FILENAME;
|
||||
bool r = file_io_utils::save_string_to_file(filename, param.toStdString());
|
||||
if (r)
|
||||
{
|
||||
ar.error_code = API_RETURN_CODE_OK;
|
||||
LOG_PRINT_L1("config saved: " << filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
ar.error_code = API_RETURN_CODE_FAIL;
|
||||
LOG_PRINT_L1("config save failed: " << filename);
|
||||
}
|
||||
|
||||
//ar.error_code = store_to_file((m_backend.get_config_folder() + "/" + GUI_CONFIG_FILENAME).c_str(), param).toStdString();
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::is_file_exist(const QString& path)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -1123,7 +1194,7 @@ QString MainWindow::is_file_exist(const QString& path)
|
|||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
LOG_ERROR("FILED TO STORE TO FILE: " << path.toStdString() << " ERROR:" << ex.what());
|
||||
LOG_ERROR("failed to check file existance: " << path.toStdString() << " ERROR:" << ex.what());
|
||||
return QString(API_RETURN_CODE_ALREADY_EXISTS) + ": " + ex.what();
|
||||
}
|
||||
|
||||
|
|
@ -1133,6 +1204,7 @@ QString MainWindow::is_file_exist(const QString& path)
|
|||
}
|
||||
CATCH_ENTRY2(API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
QString MainWindow::store_to_file(const QString& path, const QString& buff)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -1221,6 +1293,10 @@ QString MainWindow::store_secure_app_data(const QString& param)
|
|||
else
|
||||
ar.error_code = API_RETURN_CODE_FAIL;
|
||||
|
||||
crypto::hash master_password_pre_hash = crypto::cn_fast_hash(m_master_password.c_str(), m_master_password.length());
|
||||
crypto::hash master_password_hash = crypto::cn_fast_hash(&master_password_pre_hash, sizeof master_password_pre_hash);
|
||||
LOG_PRINT_L0("store_secure_app_data, r = " << r << ", pass hash: " << master_password_hash);
|
||||
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
|
@ -1232,7 +1308,7 @@ QString MainWindow::have_secure_app_data()
|
|||
view::api_response ar = AUTO_VAL_INIT(ar);
|
||||
|
||||
boost::system::error_code ec;
|
||||
if (boost::filesystem::exists(m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME, ec))
|
||||
if (boost::filesystem::exists(epee::string_encoding::utf8_to_wstring(m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME), ec))
|
||||
ar.error_code = API_RETURN_CODE_TRUE;
|
||||
else
|
||||
ar.error_code = API_RETURN_CODE_FALSE;
|
||||
|
|
@ -1240,6 +1316,7 @@ QString MainWindow::have_secure_app_data()
|
|||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::drop_secure_app_data()
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
@ -1247,13 +1324,14 @@ QString MainWindow::drop_secure_app_data()
|
|||
view::api_response ar = AUTO_VAL_INIT(ar);
|
||||
|
||||
boost::system::error_code ec;
|
||||
if (boost::filesystem::remove(m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME, ec))
|
||||
if (boost::filesystem::remove(epee::string_encoding::utf8_to_wstring(m_backend.get_config_folder() + "/" + GUI_SECURE_CONFIG_FILENAME), ec))
|
||||
ar.error_code = API_RETURN_CODE_TRUE;
|
||||
else
|
||||
ar.error_code = API_RETURN_CODE_FALSE;
|
||||
return MAKE_RESPONSE(ar);
|
||||
CATCH_ENTRY_FAIL_API_RESPONCE();
|
||||
}
|
||||
|
||||
QString MainWindow::get_all_aliases()
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#ifndef Q_MOC_RUN
|
||||
#include "warnings.h"
|
||||
|
||||
PUSH_WARNINGS
|
||||
PUSH_VS_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4100)
|
||||
DISABLE_VS_WARNINGS(4503)
|
||||
#include "serialization/keyvalue_serialization.h"
|
||||
|
|
@ -20,7 +20,7 @@ DISABLE_VS_WARNINGS(4503)
|
|||
#include "wallet/wallet_public_structs_defs.h"
|
||||
#include "currency_core/offers_services_helpers.h"
|
||||
#include "currency_core/basic_api_response_codes.h"
|
||||
POP_WARNINGS
|
||||
POP_VS_WARNINGS
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
"FORM_ERRORS": {
|
||||
"PASS_REQUIRED": "Passwort ist erforderlich",
|
||||
"CONFIRM_REQUIRED": "Bestätigung ist erforderlich",
|
||||
"MISMATCH": "Mismatch"
|
||||
"MISMATCH": "Fehlanpassung"
|
||||
}
|
||||
},
|
||||
"COMMON": {
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
"TITLE": "Wallets",
|
||||
"ADD_NEW": "+ Hinzufügen",
|
||||
"ACCOUNT": {
|
||||
"STAKING": "Staking (Anlegen)",
|
||||
"STAKING": "Staking",
|
||||
"MESSAGES": "Neue Angebote/Nachrichten",
|
||||
"SYNCING": "Wallet synchronisieren"
|
||||
},
|
||||
|
|
@ -159,15 +159,15 @@
|
|||
"PASS_NOT_MATCH": "Old password not match",
|
||||
"CONFIRM_NOT_MATCH": "Confirm password not match"
|
||||
},
|
||||
"LAST_BUILD": "Current build: {{value}}",
|
||||
"APP_LOG_TITLE": "Log level:"
|
||||
"LAST_BUILD": "Aktueller Build: {{value}}",
|
||||
"APP_LOG_TITLE": "Log-Level:"
|
||||
},
|
||||
"WALLET": {
|
||||
"REGISTER_ALIAS": "Alias registrieren",
|
||||
"DETAILS": "Details",
|
||||
"LOCK": "Verschlüsseln",
|
||||
"AVAILABLE_BALANCE": "Verfügbar <b>{{verfügbar}} {{Währung}}<b/>",
|
||||
"LOCKED_BALANCE": "Gesperrt <b>{{gesperrt}} {{Währung}}<b/>",
|
||||
"AVAILABLE_BALANCE": "Verfügbar <b>{{available}} {{currency}}<b/>",
|
||||
"LOCKED_BALANCE": "Gesperrt <b>{{locked}} {{currency}}<b/>",
|
||||
"LOCKED_BALANCE_LINK": "Was bedeutet das?",
|
||||
"TABS": {
|
||||
"SEND": "Senden",
|
||||
|
|
@ -175,7 +175,7 @@
|
|||
"HISTORY": "Verlauf",
|
||||
"CONTRACTS": "Verträge",
|
||||
"MESSAGES": "Nachrichten",
|
||||
"STAKING": "Staking (Anlegen)"
|
||||
"STAKING": "Staking"
|
||||
}
|
||||
},
|
||||
"WALLET_DETAILS": {
|
||||
|
|
@ -195,14 +195,14 @@
|
|||
"NAME": {
|
||||
"LABEL": "Alias",
|
||||
"PLACEHOLDER": "@ Alias eingeben",
|
||||
"TOOLTIP": "An alias is a shortened form or your account. An alias can only include Latin letters, numbers and characters “.” and “-”. It must start with “@”."
|
||||
"TOOLTIP": "Ein Alias ist eine verkürzte Form Ihres Kontos. Ein Alias kann nur lateinische Buchstaben, Zahlen und die Zeichen „.“ und “-” enthalten. Es muss mit “@” beginnen."
|
||||
},
|
||||
"COMMENT": {
|
||||
"LABEL": "Kommentar",
|
||||
"PLACEHOLDER": "",
|
||||
"TOOLTIP": "The comment will be visible to anyone who wants to make a payment to your alias. You can provide details about your business, contacts, or include any text. Comments can be edited later."
|
||||
"TOOLTIP": "Der Kommentar wird für jeden sichtbar sein, der eine Zahlung an Ihren Alias vornehmen möchte. Sie können Details über Ihre Geschäfte, Kontakte oder Text angeben. Kommentare können später bearbeitet werden."
|
||||
},
|
||||
"COST": "Alias fee {{value}} {{currency}}",
|
||||
"COST": "Alias-Gebühr {{value}} {{currency}}",
|
||||
"BUTTON_ASSIGN": "Zuweisen",
|
||||
"FORM_ERRORS": {
|
||||
"NAME_REQUIRED": "Name ist erforderlich",
|
||||
|
|
@ -228,7 +228,7 @@
|
|||
"NO_MONEY": "Sie haben nicht genügend Geldmittel, um den Kommentar zu diesem Alias zu ändern",
|
||||
"MAX_LENGTH": "Maximale Kommentarlänge erreicht"
|
||||
},
|
||||
"COST": "Gebühr {{Wert}} {{Währung}}",
|
||||
"COST": "Gebühr {{value}} {{currency}}",
|
||||
"BUTTON_EDIT": "Bearbeiten"
|
||||
},
|
||||
"TRANSFER_ALIAS": {
|
||||
|
|
@ -249,7 +249,7 @@
|
|||
"ALIAS_EXISTS": "Dieses Konto hat bereits einen Alias",
|
||||
"NO_MONEY": "Du hast nicht genug Geldmittel, um diesen Alias zu transferieren"
|
||||
},
|
||||
"COST": "Transfer fee {{value}} {{currency}}",
|
||||
"COST": "Überweisungsgebühr {{value}} {{currency}}",
|
||||
"BUTTON_TRANSFER": "Transfer",
|
||||
"BUTTON_CANCEL": "Abbrechen",
|
||||
"REQUEST_SEND_REG": "Der Alias wird innerhalb von 10 Minuten übertragen"
|
||||
|
|
@ -271,14 +271,14 @@
|
|||
"AMOUNT_REQUIRED": "Betrag ist erforderlich",
|
||||
"AMOUNT_ZERO": "Betrag ist Null",
|
||||
"FEE_REQUIRED": "Gebühr ist erforderlich",
|
||||
"FEE_MINIMUM": "Mindestgebühr: {{Gebühr}}",
|
||||
"FEE_MINIMUM": "Mindestgebühr: {{fee}}",
|
||||
"MAX_LENGTH": "Maximale Kommentarlänge erreicht"
|
||||
}
|
||||
},
|
||||
"HISTORY": {
|
||||
"STATUS": "Status",
|
||||
"STATUS_TOOLTIP": "Confirmations {{current}}/{{total}}",
|
||||
"LOCK_TOOLTIP": "Gesperrt bis {{Datum}}",
|
||||
"STATUS_TOOLTIP": "Bestätigungen {{current}}/{{total}}",
|
||||
"LOCK_TOOLTIP": "Gesperrt bis {{date}}",
|
||||
"SEND": "Gesendet",
|
||||
"RECEIVED": "Empfangen",
|
||||
"DATE": "Datum",
|
||||
|
|
@ -289,7 +289,7 @@
|
|||
"PAYMENT_ID": "Zahlungs-ID",
|
||||
"ID": "Transaktions-ID",
|
||||
"SIZE": "Transaktionsgröße",
|
||||
"SIZE_VALUE": "{{Wert}} Bytes",
|
||||
"SIZE_VALUE": "{{value}} Bytes",
|
||||
"HEIGHT": "Höhe",
|
||||
"CONFIRMATION": "Bestätigung",
|
||||
"INPUTS": "Inputs",
|
||||
|
|
@ -306,10 +306,10 @@
|
|||
"POW_REWARD": "POW-Belohnung",
|
||||
"POS_REWARD": "POS-Belohnung",
|
||||
"CREATE_CONTRACT": "Vertragsvorschlag",
|
||||
"PLEDGE_CONTRACT": "Contract deposit",
|
||||
"PLEDGE_CONTRACT": "Vertrag-Einzahlung",
|
||||
"NULLIFY_CONTRACT": "Einzahlungen verbrennen",
|
||||
"PROPOSAL_CANCEL_CONTRACT": "Stornierungsanfrage",
|
||||
"CANCEL_CONTRACT": "Cancel and return deposits"
|
||||
"CANCEL_CONTRACT": "Abbrechen und Einzahlungen zurückzahlen"
|
||||
}
|
||||
},
|
||||
"CONTRACTS": {
|
||||
|
|
@ -322,17 +322,17 @@
|
|||
"STATUS": "Status",
|
||||
"COMMENTS": "Kommentare",
|
||||
"PURCHASE_BUTTON": "Neuer Kauf",
|
||||
"LISTING_BUTTON": "Create listing",
|
||||
"LISTING_BUTTON": "Auflistung erstellen",
|
||||
"TIME_LEFT": {
|
||||
"REMAINING_LESS_ONE": "Weniger als eine Stunde, um zu antworten",
|
||||
"REMAINING_ONE": "{{Zeit}} verbleibende Stunde",
|
||||
"REMAINING_MANY": "{{Zeit}} verbleibende Stunden",
|
||||
"REMAINING_MANY_ALT": "{{Zeit}} verbleibende Stunden",
|
||||
"REMAINING_ONE_RESPONSE": "{{Zeit}} verbleibende Stunde",
|
||||
"REMAINING_MANY_RESPONSE": "{{Zeit}} verbleibende Stunde",
|
||||
"REMAINING_MANY_ALT_RESPONSE": "{{Zeit}} verbleibende Stunden",
|
||||
"REMAINING_ONE_WAITING": "Warte für {{Zeit}} Stunde",
|
||||
"REMAINING_MANY_WAITING": "Warte für {{Zeit}} Stunden",
|
||||
"REMAINING_ONE": "{{time}} verbleibende Stunde",
|
||||
"REMAINING_MANY": "{{time}} verbleibende Stunden",
|
||||
"REMAINING_MANY_ALT": "{{time}} verbleibende Stunden",
|
||||
"REMAINING_ONE_RESPONSE": "{{time}} verbleibende Stunde",
|
||||
"REMAINING_MANY_RESPONSE": "{{time}} verbleibende Stunde",
|
||||
"REMAINING_MANY_ALT_RESPONSE": "{{time}} verbleibende Stunden",
|
||||
"REMAINING_ONE_WAITING": "Warte für {{time}} Stunde",
|
||||
"REMAINING_MANY_WAITING": "Warte für {{time}} Stunden",
|
||||
"REMAINING_MANY_ALT_WAITING": "Warte für {{Zeit}} Stunden"
|
||||
},
|
||||
"STATUS_MESSAGES": {
|
||||
|
|
@ -354,7 +354,7 @@
|
|||
"BUYER": {
|
||||
"WAITING": "Warte auf Antwort",
|
||||
"IGNORED": "Verkäufer ignorierte Ihren Vertragsvorschlag",
|
||||
"ACCEPTED": "Seller accepted your contract proposal",
|
||||
"ACCEPTED": "Verkäufer hat Ihren Vertragsvorschlag akzeptiert",
|
||||
"WAIT": "Warten auf die Bestätigung der Einzahlungen",
|
||||
"WAITING_SELLER": "Warte auf Sendung",
|
||||
"COMPLETED": "Vertrag abgeschlossen",
|
||||
|
|
@ -381,7 +381,7 @@
|
|||
"SEND_BUTTON": "Senden",
|
||||
"FORM_ERRORS": {
|
||||
"DESC_REQUIRED": "Beschreibung erforderlich",
|
||||
"DESC_MAXIMUM": "Maximum field length reached",
|
||||
"DESC_MAXIMUM": "Maximale Feldlänge erreicht",
|
||||
"SELLER_REQUIRED": "Adresse benötigt",
|
||||
"SELLER_NOT_VALID": "Ungültige Adresse",
|
||||
"ALIAS_NOT_VALID": "Ungültiger Alias",
|
||||
|
|
@ -390,7 +390,7 @@
|
|||
"YOUR_DEPOSIT_REQUIRED": "Einzahlung erforderlich",
|
||||
"SELLER_DEPOSIT_REQUIRED": "Verkäufer-Einzahlung erforderlich",
|
||||
"SELLER_SAME": "Anderes Konto verwenden",
|
||||
"COMMENT_MAXIMUM": "Maximum field length reached"
|
||||
"COMMENT_MAXIMUM": "Maximale Feldlänge erreicht"
|
||||
},
|
||||
"PROGRESS_NEW": "Neuer Kauf",
|
||||
"PROGRESS_WAIT": "Warte auf Antwort",
|
||||
|
|
@ -428,7 +428,7 @@
|
|||
"NEED_MONEY": "Unzureichendes Guthaben",
|
||||
"BUTTON_MAKE_PLEDGE": "Akzeptieren und Einzahlung tätigen",
|
||||
"BUTTON_IGNORE": "Angebot ignorieren und ausblenden",
|
||||
"BUTTON_NULLIFY": "Terminate and burn deposits",
|
||||
"BUTTON_NULLIFY": "Beenden und Einzahlungen verbrennen",
|
||||
"BUTTON_RECEIVED": "Einzahlungen abschließen und freigeben",
|
||||
"BUTTON_CANCEL_BUYER": "Einzahlungen abbrechen und zurückzahlen",
|
||||
"BUTTON_NOT_CANCEL": "Anfrage ignorieren",
|
||||
|
|
@ -464,7 +464,7 @@
|
|||
}
|
||||
},
|
||||
"STAKING": {
|
||||
"TITLE": "Staking (Anlegen)",
|
||||
"TITLE": "Staking",
|
||||
"TITLE_PENDING": "Ausstehend",
|
||||
"TITLE_TOTAL": "Gesamt",
|
||||
"TITLE_PERIOD": "Zeitspanne:",
|
||||
|
|
@ -518,7 +518,7 @@
|
|||
"ADDRESS_NOT_VALID": "Adresse ungültig",
|
||||
"SET_MASTER_PASSWORD": "Master-Passwort festlegen",
|
||||
"ADDRESS_DUBLICATED": "Adresse existiert bereits",
|
||||
"MAX_LENGTH": "Maximum notes length reached",
|
||||
"MAX_LENGTH": "Maximale Länge der Notiz erreicht",
|
||||
"NAME_LENGTH": "Der Name muss 4-25 Zeichen lang sein"
|
||||
},
|
||||
"BUTTON": {
|
||||
|
|
@ -532,19 +532,21 @@
|
|||
},
|
||||
"SUCCESS_SENT": "Kontakt hinzugefügt",
|
||||
"SUCCESS_SAVE": "Kontakt wurde bearbeitet",
|
||||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"SUCCESS_IMPORT": "Kontakte wurden importiert",
|
||||
"SUCCESS_EXPORT": "Kontakte wurden exportiert",
|
||||
"ERROR_IMPORT": "Fehler beim Lesen der Datei!",
|
||||
"ERROR_TYPE_FILE": "Bitte importieren Sie eine gültige .csv Datei.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Ungültiger Dateityp. Datei als .csv speichern",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Nicht genügend Geld",
|
||||
"NOT_ENOUGH_MONEY": "Unzureichendes Guthaben im Konto",
|
||||
"CORE_BUSY": "Interner Fehler: Kern ist beschäftigt",
|
||||
"DAEMON_BUSY": "Interner Fehler: Daemon ist beschäftigt",
|
||||
"NO_MONEY_REMOVE_OFFER": "There is no fee for deleting an offer, but in order to protect the network against flood transactions you need to have at least {{fee}} {{currency}} in your wallet",
|
||||
"NOT_ENOUGH_OUTPUTS_TO_MIX": "Mix-in number is too big for current blockchain state. There are not enough unspent outputs to mix with",
|
||||
"NO_MONEY_REMOVE_OFFER": "Es gibt keine Gebühr für das Löschen eines Angebots, aber um das Netzwerk vor Spam-Transaktionen zu schützen, müssen Sie mindestens {{fee}} {{currency}} in Ihrer Wallet haben",
|
||||
"NOT_ENOUGH_OUTPUTS_TO_MIX": "Mix-in-Nummer ist zu groß für den aktuellen Blockchain-Status. Nicht genügend unverbrauchte outputs zum Mischen",
|
||||
"TRANSACTION_IS_TO_BIG": "Transaktion überschreitet das Netzwerk-Limit. Sendet benötigten Betrag mit mehreren Transaktionen.",
|
||||
"TRANSFER_ATTEMPT": "Keine Verbindung zum Zano-Netzwerk",
|
||||
"ACCESS_DENIED": "Zugriff verweigert",
|
||||
|
|
@ -561,7 +563,7 @@
|
|||
"TX_TYPE_NORMAL_END": "wurde nicht abgeschlossen.",
|
||||
"TX_TYPE_NEW_ALIAS": "Fehler. Fehler beim Registrieren des Alias zum Speichern",
|
||||
"TX_TYPE_NEW_ALIAS_END": "Bitte nochmals versuchen.",
|
||||
"TX_TYPE_UPDATE_ALIAS": "Error. Failed to change comment to alias in safe",
|
||||
"TX_TYPE_UPDATE_ALIAS": "Fehler. Fehlgeschlagen Kommentar von gespeichertem Alias zu ändern",
|
||||
"TX_TYPE_COIN_BASE": "Fehler. Die Zahlung wurde nicht abgeschlossen."
|
||||
},
|
||||
"CONTEXT_MENU": {
|
||||
|
|
@ -577,8 +579,8 @@
|
|||
"INCOME_TRANSFER_CONFIRMED": "Zahlung erhalten",
|
||||
"MINED": "Mined",
|
||||
"LOCKED": "Blockiert",
|
||||
"IS_MINIMIZE": "Zano application is minimized to the system tray",
|
||||
"RESTORE": "You can recover it by clicking or using the context menu",
|
||||
"IS_MINIMIZE": "Zano-Anwendung wird auf die Systemleiste minimiert",
|
||||
"RESTORE": "Sie können es wiederherstellen, indem Sie auf das Kontextmenü benutzen oder anklicken ",
|
||||
"TRAY_MENU_SHOW": "Größe ändern",
|
||||
"TRAY_MENU_MINIMIZE": "Minimieren"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
|
|
@ -39,15 +39,18 @@
|
|||
"SYNCING": "Syncing wallet"
|
||||
},
|
||||
"CONTACTS": "Contacts",
|
||||
"CONTACTS_TOOLTIP": "Contacts option available only with Master Password enabled",
|
||||
"SETTINGS": "Settings",
|
||||
"LOG_OUT": "Log out",
|
||||
"LOG_OUT_TOOLTIP": "Logout option available only with Master Password enabled",
|
||||
"SYNCHRONIZATION": {
|
||||
"OFFLINE": "Offline",
|
||||
"ONLINE": "Online",
|
||||
"ERROR": "System error",
|
||||
"COMPLETE": "Completion",
|
||||
"SYNCING": "Syncing blockchain",
|
||||
"LOADING": "Loading blockchain data"
|
||||
"SYNCING": "Syncing block",
|
||||
"LOADING": "Loading blockchain data",
|
||||
"SLASH": "/"
|
||||
},
|
||||
"UPDATE": {
|
||||
"STANDARD": "Update available",
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Erreur lors de la lecture du fichier !",
|
||||
"ERROR_TYPE_FILE": "Veuillez importer un fichier .csv valide.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Pas assez de fonds",
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
|
|
@ -535,8 +535,10 @@
|
|||
"SUCCESS_IMPORT": "Contacts are imported",
|
||||
"SUCCESS_EXPORT": "Contacts are exported",
|
||||
"ERROR_IMPORT": "Error is occured while reading file!",
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file.",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv"
|
||||
"ERROR_TYPE_FILE": "Please import valid .csv file",
|
||||
"ERROR_EXPORT": "Invalid file type. Save file as .csv",
|
||||
"ERROR_EMPTY_LIST": "Contact list is empty",
|
||||
"ERROR_IMPORT_EMPTY": "File is empty"
|
||||
},
|
||||
"ERRORS": {
|
||||
"NO_MONEY": "Not enough money",
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue