1
0
Fork 0
forked from lthn/blockchain

Merge branch 'develop' into market_rpc_api

This commit is contained in:
cryptozoidberg 2019-10-02 21:06:50 +02:00
commit 9d3e2dee6b
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
189 changed files with 7304 additions and 3390 deletions

View file

@ -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()

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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);
}

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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) {

View file

@ -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

View file

@ -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);
}

View file

@ -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 */
/** @} */
/** @} */

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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()) )
{

View file

@ -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
{

View file

@ -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_

View file

@ -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();
}
}
}

View file

@ -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

View file

@ -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
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------

View file

@ -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;
}

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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)
{

View file

@ -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;
}

View file

@ -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__)

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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);

View 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)

View 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

View file

@ -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)
{

View file

@ -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());
}
};

View file

@ -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(){};
};
}
}
}

View file

@ -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;
}
}
}

View file

@ -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
View 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
View 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

View file

@ -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

View file

@ -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
View 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
View 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
View 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

View file

@ -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);

View file

@ -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

View file

@ -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 {

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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() = &ethash_custom_log_get_level;
ethash::access_custom_log_function() = &ethash_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;

View file

@ -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);

View file

@ -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,

View file

@ -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)

View file

@ -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");

View file

@ -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;
}

View file

@ -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");

View file

@ -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);
}
//-----------------------------------------------------------------------------------------------

View file

@ -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

View file

@ -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();
}

View file

@ -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

View file

@ -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];
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View file

@ -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)
{

View file

@ -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;

View file

@ -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

View file

@ -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();

View file

@ -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;

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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"
}

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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",

View file

@ -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