Browse Source

REGENERATING...

psy 8 months ago
parent
commit
acb75fc76a
100 changed files with 22324 additions and 0 deletions
  1. 106 0
      ecoin/INSTALL
  2. 2 0
      ecoin/build/build.h
  3. 11 0
      ecoin/doc/DNSSEEDS.txt
  4. 20 0
      ecoin/doc/MINING.txt
  5. 42 0
      ecoin/doc/REWARDS.txt
  6. 23 0
      ecoin/doc/TRANSLATIONS.txt
  7. 87 0
      ecoin/doc/build-linux.txt
  8. 85 0
      ecoin/doc/build-osx.txt
  9. 51 0
      ecoin/doc/build-win32.txt
  10. 21 0
      ecoin/doc/qr-codes.txt
  11. 427 0
      ecoin/ecoin-qt.pro
  12. 30 0
      ecoin/share/genbuild.sh
  13. BIN
      ecoin/share/pixmaps/addressbook16.bmp
  14. BIN
      ecoin/share/pixmaps/addressbook16mask.bmp
  15. BIN
      ecoin/share/pixmaps/addressbook20.bmp
  16. BIN
      ecoin/share/pixmaps/addressbook20mask.bmp
  17. BIN
      ecoin/share/pixmaps/check.ico
  18. BIN
      ecoin/share/pixmaps/ecoin.ico
  19. 608 0
      ecoin/share/pixmaps/ecoin32.xpm
  20. 2645 0
      ecoin/share/pixmaps/ecoin80.xpm
  21. BIN
      ecoin/share/pixmaps/favicon.ico
  22. BIN
      ecoin/share/pixmaps/nsis-header.bmp
  23. BIN
      ecoin/share/pixmaps/nsis-wizard.bmp
  24. BIN
      ecoin/share/pixmaps/send16.bmp
  25. BIN
      ecoin/share/pixmaps/send16mask.bmp
  26. BIN
      ecoin/share/pixmaps/send16masknoshadow.bmp
  27. BIN
      ecoin/share/pixmaps/send20.bmp
  28. BIN
      ecoin/share/pixmaps/send20mask.bmp
  29. 58 0
      ecoin/share/qt/extract_strings_qt.py
  30. BIN
      ecoin/share/qt/img/reload.xcf
  31. 42 0
      ecoin/share/qt/make_spinner.py
  32. 5 0
      ecoin/share/qt/make_windows_icon.sh
  33. 157 0
      ecoin/share/setup.nsi
  34. 18 0
      ecoin/share/ui.rc
  35. 525 0
      ecoin/src/addrman.cpp
  36. 449 0
      ecoin/src/addrman.h
  37. 228 0
      ecoin/src/alert.cpp
  38. 88 0
      ecoin/src/alert.h
  39. 211 0
      ecoin/src/allocators.h
  40. 434 0
      ecoin/src/base58.h
  41. 717 0
      ecoin/src/bignum.h
  42. 406 0
      ecoin/src/checkpoints.cpp
  43. 152 0
      ecoin/src/checkpoints.h
  44. 10 0
      ecoin/src/clientversion.h
  45. 57 0
      ecoin/src/coincontrol.h
  46. 60 0
      ecoin/src/compat.h
  47. 127 0
      ecoin/src/crypter.cpp
  48. 101 0
      ecoin/src/crypter.h
  49. 551 0
      ecoin/src/db.cpp
  50. 283 0
      ecoin/src/db.h
  51. 1225 0
      ecoin/src/ecoinrpc.cpp
  52. 179 0
      ecoin/src/ecoinrpc.h
  53. 837 0
      ecoin/src/init.cpp
  54. 14 0
      ecoin/src/init.h
  55. 364 0
      ecoin/src/irc.cpp
  56. 8 0
      ecoin/src/irc.h
  57. 24 0
      ecoin/src/json/LICENSE.txt
  58. 14 0
      ecoin/src/json/json_spirit.h
  59. 46 0
      ecoin/src/json/json_spirit_error_position.h
  60. 134 0
      ecoin/src/json/json_spirit_reader.cpp
  61. 58 0
      ecoin/src/json/json_spirit_reader.h
  62. 592 0
      ecoin/src/json/json_spirit_reader_template.h
  63. 62 0
      ecoin/src/json/json_spirit_stream_reader.h
  64. 57 0
      ecoin/src/json/json_spirit_utils.h
  65. 8 0
      ecoin/src/json/json_spirit_value.cpp
  66. 507 0
      ecoin/src/json/json_spirit_value.h
  67. 91 0
      ecoin/src/json/json_spirit_writer.cpp
  68. 43 0
      ecoin/src/json/json_spirit_writer.h
  69. 238 0
      ecoin/src/json/json_spirit_writer_template.h
  70. 308 0
      ecoin/src/kernel.cpp
  71. 37 0
      ecoin/src/kernel.h
  72. 385 0
      ecoin/src/key.cpp
  73. 119 0
      ecoin/src/key.h
  74. 217 0
      ecoin/src/keystore.cpp
  75. 160 0
      ecoin/src/keystore.h
  76. 13 0
      ecoin/src/leveldb/.gitignore
  77. 11 0
      ecoin/src/leveldb/AUTHORS
  78. 27 0
      ecoin/src/leveldb/LICENSE
  79. 206 0
      ecoin/src/leveldb/Makefile
  80. 17 0
      ecoin/src/leveldb/NEWS
  81. 51 0
      ecoin/src/leveldb/README
  82. 14 0
      ecoin/src/leveldb/TODO
  83. 39 0
      ecoin/src/leveldb/WINDOWS.md
  84. 214 0
      ecoin/src/leveldb/build_detect_platform
  85. 88 0
      ecoin/src/leveldb/db/builder.cc
  86. 34 0
      ecoin/src/leveldb/db/builder.h
  87. 595 0
      ecoin/src/leveldb/db/c.cc
  88. 390 0
      ecoin/src/leveldb/db/c_test.c
  89. 359 0
      ecoin/src/leveldb/db/corruption_test.cc
  90. 979 0
      ecoin/src/leveldb/db/db_bench.cc
  91. 1485 0
      ecoin/src/leveldb/db/db_impl.cc
  92. 203 0
      ecoin/src/leveldb/db/db_impl.h
  93. 299 0
      ecoin/src/leveldb/db/db_iter.cc
  94. 26 0
      ecoin/src/leveldb/db/db_iter.h
  95. 2092 0
      ecoin/src/leveldb/db/db_test.cc
  96. 140 0
      ecoin/src/leveldb/db/dbformat.cc
  97. 227 0
      ecoin/src/leveldb/db/dbformat.h
  98. 112 0
      ecoin/src/leveldb/db/dbformat_test.cc
  99. 139 0
      ecoin/src/leveldb/db/filename.cc
  100. 0 0
      ecoin/src/leveldb/db/filename.h

+ 106 - 0
ecoin/INSTALL

@@ -0,0 +1,106 @@
+
+ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+===================================================
+# BUILDS - ECOlogical P2P Crypto-Currency (ECOin) #
+===================================================
+
+=================
++ Build Makefile:
+=================
+
+cd ecoin/
+
+  + GNU/Linux:
+
+	/usr/lib/x86_64-linux-gnu/qt4/bin/qmake USE_UPNP=0 -o Makefile ecoin-qt.pro
+
+================
++ Build leveldb:
+================
+
+cd src/leveldb
+
+  + GNU/Linux:
+
+        TARGET_OS=Linux make libleveldb.a libmemenv.a
+
+  + MacOS X:
+
+        TARGET_OS=Darwin make libleveldb.a libmemenv.a
+
+  + Windows:
+
+        TARGET_OS=NATIVE_WINDOWS make libleveldb.a libmemenv.a
+
+===================================================
+
+===============
++ Build Wallet:
+===============
+
+See doc/build-*.txt for detailed instructions on building /ecoin-qt/ on different platforms.
+
+  + GNU/Linux:
+
+	cd ..
+	qmake USE_UPNP=- (or USE_UPNP=0)
+	make
+
+        ./ecoin-qt
+
+===============
++ Build Daemon:
+===============
+
+See doc/build-*.txt for detailed instructions on building /ecoind/ on different platforms.
+
+  + GNU/Linux:
+
+	cd src/
+	make -f makefile.linux USE_UPNP=- (or USE_UPNP=0)
+	strip ecoind
+
+        ./ecoind
+
+==========================
++ Configuration (Example):
+==========================
+
+  + GNU/Linux:
+
+     - File: /home/$USER/.ecoin/ecoin.conf # chmod 600 ecoin.conf
+
+        rpcuser=ecoinrpc
+        rpcpassword=YourPassWord2021 # use lowercase, upper case and numbers
+        rpcallowip=127.0.0.1
+        noirc=1
+        listen=1
+        server=1
+        daemon=1
+        testnet=0
+	addnode = 176.28.23.46 # 03c8.net
+
+     ./ecoind -conf=/home/$USER/.ecoin/ecoin.conf 
+
+====================
++ Testnet (Running):
+====================
+
+  + GNU/Linux:
+
+     cd src/
+     ./ecoind -testnet
+
+====================
++ Ports (Listening):
+====================
+
+  + Default P2P Port: 7408
+
+  + Default RPC Port (main): 7474
+
+  + Default RPC Port (testnet): 17474
+
+===================================================
+

+ 2 - 0
ecoin/build/build.h

@@ -0,0 +1,2 @@
+// No build information available
+#define BUILD_DATE "2014-05-10 14:37:22 -0500"

+ 11 - 0
ecoin/doc/DNSSEEDS.txt

@@ -0,0 +1,11 @@
+
+ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+=====================================================
+# DNSSEEDS - ECOlogical P2P Crypto-Currency (ECOin) #
+=====================================================
+
+  + ecoinseed.03c8.net
+
+=====================================================
+

+ 20 - 0
ecoin/doc/MINING.txt

@@ -0,0 +1,20 @@
+
+ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+===================================================
+# MINING - ECOlogical P2P Crypto-Currency (ECOin) #
+===================================================
+
+  + Solo-Mining:
+
+       1) cpuminer-multi:
+
+          git clone https://github.com/tpruvot/cpuminer-multi
+          cd cpuminer-multi/
+          sh build.sh
+
+             a) ./ecoin-qt -server
+             b) ./cpuminer -o http://0.0.0.0:7474 -O <USER>:<PASSWORD> --coinbase-addr=<YOUR_ECOIN_ADDRESS>
+
+===================================================
+

+ 42 - 0
ecoin/doc/REWARDS.txt

@@ -0,0 +1,42 @@
+
+ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+====================================================
+# REWARDS - ECOlogical P2P Crypto-Currency (ECOin) #
+====================================================
+
+ + Proof-Of-Work Mining (POW) Rewards (halving every 262,800 blocks):
+
+       -------------------------------------------------------------
+	Block	 		Reward
+       -------------------------------------------------------------
+	Block 1 - 3263: 	Random 500 5000 (1 minute blocks)
+	Block 3264 - 22000: 	Random 1000 10000 (2 minute blocks)
+	Block 22001 - 34750: 	Static reward 5000
+	Block 34751 - 39791: 	Static reward 2500
+	Block 39792 - 44832: 	Static reward 1250
+	Block 44833 - 49873: 	Static reward 625
+	Block 49874 - 54914: 	Static reward 312.50
+	Block 54915 - 59955: 	Static reward 156.25
+	Block 59956 - 64996: 	Static reward 78.125
+	Block 64997 - 70037: 	Static reward 39.0625
+	Block 70038 - 332838: 	static reward 20
+
+	Halving every 262800 blocks
+
+==================================
+
+ + Proof-Of-Stake Mining (POS):  
+
+	Variable interest based on coin age.
+
+==================================
+
+ + Proof-Of-Transaction Mining (POT): 
+
+	Mining by matching address segment to block hash (on tansactions greater than 500 coins), 50% of the block subsidy.
+
+	Increased security on Proof-of-Work blocks though verification of coinbase tx value, size, and destinations of coinbase transactions via Proof-Of-Transaction checking.
+
+====================================================
+

+ 23 - 0
ecoin/doc/TRANSLATIONS.txt

@@ -0,0 +1,23 @@
+
+ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+=========================================================
+# TRANSLATIONS - ECOlogical P2P Crypto-Currency (ECOin) #
+=========================================================
+
+       ---------------------------------------------------
+	NAME	 		LANGUAGE
+       --------------------------------------------------
+	 en 			 English
+	 ru 		         Russian
+	 ca			 Catalan
+	 de			 German
+         es			 Spanish
+	 es_EU			 Basque
+         fr			 French
+         it			 Italian
+         pt			 Portuguese
+         zh_CN			 Chinese
+
+=========================================================
+

+ 87 - 0
ecoin/doc/build-linux.txt

@@ -0,0 +1,87 @@
+
+ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+======================================
+# SOURCES for ECOin (Unix/GNU-Linux) #
+======================================
+
+All of the commands should be executed in a shell.
+
+------------------------------
+
+(0.) Clone the github tree to get the source code:
+
+  + Official:
+
+	git clone http://code.03c8.net:3000/epsylon/ecoin
+
+  + Mirror:
+
+	git clone https://github.com/epsylon/ecoin
+
+------------------------------
+
+==============================================
+# Daemon -ecoind- for ECOin (Unix/GNU-Linux) #
+==============================================
+
+(1.) Install dependencies:
+
+ Library       Purpose           Description
+ -------       -------           -----------
+ libssl1.0-dev SSL Support       Secure communications
+ libdb5.3      Berkeley DB       Blockchain & wallet storage
+ libboost      Boost             C++ Library
+ miniupnpc     UPnP Support      Optional firewall-jumping support
+ libqrencode   QRCode generation Optional QRCode generation
+
+    + From Debian/Ubuntu:
+  
+        sudo apt-get install build-essential libssl1.0-dev libssl1.0.2 libdb5.3-dev libdb5.3++-dev libboost-all-dev miniupnpc libminiupnpc-dev
+
+        + Optionally install qrencode (and set USE_QRCODE=1):
+
+       	    sudo apt-get install libqrencode-dev
+
+(2.) Now you should be able to build ecoind:
+
+	cd src/
+	make -f makefile.linux
+	strip ecoind
+
+     An executable named 'ecoind' will be built.
+
+------------------------------
+
+======================================
+# Qt4 GUI for ECOin (Unix/GNU-Linux) #
+======================================
+
+(1.) First, make sure that the required packages for Qt4 development of your distribution are installed, for Debian and Ubuntu these are:
+
+        sudo apt-get install qt4-qmake libqt4-dev build-essential libboost-dev libboost-system-dev miniupnpc libminiupnpc-dev \
+             libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev libssl1.0-dev libssl1.0.2 libdb5.3++-dev
+
+(2.) Then execute the following:
+
+        qmake
+        make
+
+     An executable named 'ecoin-qt' will be built.
+
+======================================
+
+For a list of command-line options:
+
+  ./ecoind --help
+
+To start the ECOin daemon:
+
+  ./ecoind -daemon
+
+For ECOin-QT Wallet
+
+  ./ecoin-qt
+
+======================================
+

+ 85 - 0
ecoin/doc/build-osx.txt

@@ -0,0 +1,85 @@
+
+ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+===============================
+# SOURCES for ECOin (MacOS X) #
+===============================
+
+All of the commands should be executed in Terminal.app
+
+------------------------------
+
+(0.) Clone the github tree to get the source code:
+
+  + Official:
+
+	git clone http://code.03c8.net:3000/epsylon/ecoin
+
+  + Mirror:
+
+	git clone https://github.com/epsylon/ecoin
+
+------------------------------
+
+=======================================
+# DAEMON -ecoind- for ECOin (MacOS X) #
+=======================================
+
+(1.) Download and install MacPorts from: http://www.macports.org/
+
+(2.) Install dependencies:
+
+ Library     Purpose           Description
+ -------     -------           -----------
+ libssl      SSL Support       Secure communications
+ libdb5.3    Berkeley DB       Blockchain & wallet storage
+ libboost    Boost             C++ Library
+ miniupnpc   UPnP Support      Optional firewall-jumping support
+ libqrencode QRCode generation Optional QRCode generation
+
+    + From MacPorts:
+	
+ 	sudo port install boost db53 openssl miniupnpc
+
+	+ Optionally install qrencode (and set USE_QRCODE=1):
+
+             sudo port install qrencode
+
+(3.) Now you should be able to build ecoind:
+
+	cd ecoin/src
+	make -f makefile.osx
+
+     An executable named 'ecoind' will be built.
+
+===============================
+# Qt4 GUI for ECOin (MacOS X) #
+===============================
+
+(1.) Download and install MacPorts from: http://www.macports.org/
+
+(2.) Execute the following commands in a terminal to get the dependencies:
+
+        sudo port selfupdate
+        sudo port install qt4-mac qt4-creator-mac boost db53 miniupnpc
+
+(3.) Open the .pro file in Qt Creator (with Desktop kit) and build as normal (cmd-B)
+
+	An executable named 'ecoin-qt' will be built.
+
+===============================
+
+For a list of command-line options:
+
+  ./ecoind --help
+
+To start the ECOin daemon:
+
+  ./ecoind -daemon
+
+For ECOin-QT Wallet
+
+  ./ecoin-qt
+
+===============================
+

+ 51 - 0
ecoin/doc/build-win32.txt

@@ -0,0 +1,51 @@
+
+ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+=============================
+# SOURCES for ECOin (Win32) #
+=============================
+
+------------------------------
+
+(0.) Clone the github tree to get the source code:
+
+  + Official:
+
+	git clone http://code.03c8.net:3000/epsylon/ecoin
+
+  + Mirror:
+
+	git clone https://github.com/epsylon/ecoin
+
+------------------------------
+
+=============================
+# Qt4 GUI for ECOin (Win32) #
+=============================
+
+(1.) Download the 'QT Windows SDK'_ and install it. You don't need the Symbian stuff, just the desktop Qt.
+
+(2.) Download and extract the 'dependencies archive'_  [#]_, or compile openssl, boost and dbcxx yourself.
+
+(3.) Copy the contents of the folder "deps" to "X:\\QtSDK\\mingw", replace X:\\ with the location where you installed the Qt SDK. 
+
+(4.) Open the .pro file in QT creator (with Desktop kit) and build as normal (ctrl-B)
+
+	An executable named 'ecoin-qt.exe' will be built.
+
+=============================
+
+For a list of command-line options:
+
+  ecoind.exe --help
+
+To start the ECOin daemon:
+
+  ecoind.exe -daemon
+
+For ECOin-QT Wallet
+
+  ecoin-qt.exe
+
+=============================
+

+ 21 - 0
ecoin/doc/qr-codes.txt

@@ -0,0 +1,21 @@
+
+ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+=====================================================
+# QR-Codes - ECOlogical P2P Crypto-Currency (ECOin) #
+=====================================================
+
+  + libqrencode may be used to generate QRCode images for payment requests.
+
+       It can be downloaded from: https://fukuchi.org/works/qrencode/index.html.en (or installed via your package manager). 
+
+       Pass the USE_QRCODE flag to qmake to control this:
+
+	+--------------+--------------------------------------------------------------------------+
+	| USE_QRCODE=0 | (the default) No QRCode support - libarcode not required                 |
+	+--------------+--------------------------------------------------------------------------+
+	| USE_QRCODE=1 | QRCode support enabled                                                   |
+	+--------------+--------------------------------------------------------------------------+
+
+=====================================================
+

+ 427 - 0
ecoin/ecoin-qt.pro

@@ -0,0 +1,427 @@
+
+# ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+TEMPLATE = app
+TARGET = ecoin-qt
+VERSION = 0.0.2
+INCLUDEPATH += src src/json src/qt
+DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
+CONFIG += no_include_pwd
+CONFIG += thread
+OBJECTS_DIR = build
+MOC_DIR = build
+UI_DIR = build
+
+# use: qmake "RELEASE=1"
+contains(RELEASE, 1) {
+    # Mac: compile for maximum compatibility (10.5, 32-bit)
+    macx:QMAKE_CXXFLAGS += -mmacosx-version-min=10.5 -arch x86_64 -isysroot /Developer/SDKs/MacOSX10.5.sdk
+
+    !windows:!macx {
+        # Linux: static link
+        LIBS += -Wl,-Bstatic
+    }
+}
+
+!win32 {
+# for extra security against potential buffer overflows: enable GCCs Stack Smashing Protection
+QMAKE_CXXFLAGS *= -fstack-protector-all --param ssp-buffer-size=1
+QMAKE_LFLAGS *= -fstack-protector-all --param ssp-buffer-size=1
+# We need to exclude this for Windows cross compile with MinGW 4.2.x, as it will result in a non-working executable!
+# This can be enabled for Windows, when we switch to MinGW >= 4.4.x.
+}
+# for extra security on Windows: enable ASLR and DEP via GCC linker flags
+win32:QMAKE_LFLAGS *= -Wl,--dynamicbase -Wl,--nxcompat
+win32:QMAKE_LFLAGS += -static-libgcc -static-libstdc++
+
+# use: qmake "USE_QRCODE=1"
+# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support
+contains(USE_QRCODE, 1) {
+    message(Building with QRCode support)
+    DEFINES += USE_QRCODE
+    LIBS += -lqrencode
+}
+
+# use: qmake "USE_UPNP=1" ( enabled by default; default)
+#  or: qmake "USE_UPNP=0" (disabled by default)
+#  or: qmake "USE_UPNP=-" (not supported)
+# miniupnpc (http://miniupnp.free.fr/files/) must be installed for support
+contains(USE_UPNP, -) {
+    message(Building without UPNP support)
+} else {
+    message(Building with UPNP support)
+    count(USE_UPNP, 0) {
+        USE_UPNP=1
+    }
+    DEFINES += USE_UPNP=$$USE_UPNP STATICLIB
+    INCLUDEPATH += $$MINIUPNPC_INCLUDE_PATH
+    LIBS += $$join(MINIUPNPC_LIB_PATH,,-L,) -lminiupnpc
+    win32:LIBS += -liphlpapi
+}
+
+# use: qmake "USE_DBUS=1"
+contains(USE_DBUS, 1) {
+    message(Building with DBUS (Freedesktop notifications) support)
+    DEFINES += USE_DBUS
+    QT += dbus
+}
+
+# use: qmake "USE_IPV6=1" ( enabled by default; default)
+#  or: qmake "USE_IPV6=0" (disabled by default)
+#  or: qmake "USE_IPV6=-" (not supported)
+contains(USE_IPV6, -) {
+    message(Building without IPv6 support)
+} else {
+    count(USE_IPV6, 0) {
+        USE_IPV6=1
+    }
+    DEFINES += USE_IPV6=$$USE_IPV6
+}
+
+contains(ECOIN_NEED_QT_PLUGINS, 1) {
+    DEFINES += ECOIN_NEED_QT_PLUGINS
+    QTPLUGIN += qcncodecs qjpcodecs qtwcodecs qkrcodecs qtaccessiblewidgets
+}
+
+INCLUDEPATH += src/leveldb/include src/leveldb/helpers
+LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a
+SOURCES += src/txdb-leveldb.cpp
+!win32 {
+    # we use QMAKE_CXXFLAGS_RELEASE even without RELEASE=1 because we use RELEASE to indicate linking preferences not -O preferences
+    genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a
+} else {
+    # make an educated guess about what the ranlib command is called
+    isEmpty(QMAKE_RANLIB) {
+        QMAKE_RANLIB = $$replace(QMAKE_STRIP, strip, ranlib)
+    }
+    LIBS += -lshlwapi
+    genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libleveldb.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libmemenv.a
+}
+genleveldb.target = $$PWD/src/leveldb/libleveldb.a
+genleveldb.depends = FORCE
+PRE_TARGETDEPS += $$PWD/src/leveldb/libleveldb.a
+QMAKE_EXTRA_TARGETS += genleveldb
+# Gross ugly hack that depends on qmake internals, unfortunately there is no other way to do it.
+QMAKE_CLEAN += $$PWD/src/leveldb/libleveldb.a; cd $$PWD/src/leveldb ; $(MAKE) clean
+
+# regenerate src/build.h
+!windows|contains(USE_BUILD_INFO, 1) {
+    genbuild.depends = FORCE
+    genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OUT_PWD/build/build.h
+    genbuild.target = $$OUT_PWD/build/build.h
+    PRE_TARGETDEPS += $$OUT_PWD/build/build.h
+    QMAKE_EXTRA_TARGETS += genbuild
+    DEFINES += HAVE_BUILD_INFO
+}
+
+contains(USE_O3, 1) {
+    message(Building O3 optimization flag)
+    QMAKE_CXXFLAGS_RELEASE -= -O2
+    QMAKE_CFLAGS_RELEASE -= -O2
+    QMAKE_CXXFLAGS += -O3
+    QMAKE_CFLAGS += -O3
+}
+
+*-g++-32 {
+    message("32 platform, adding -msse2 flag")
+
+    QMAKE_CXXFLAGS += -msse2
+    QMAKE_CFLAGS += -msse2
+}
+
+QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter -Wstack-protector
+
+# Input
+DEPENDPATH += src src/json src/qt
+HEADERS += src/qt/ecoingui.h \
+    src/qt/transactiontablemodel.h \
+    src/qt/addresstablemodel.h \
+    src/qt/optionsdialog.h \
+    src/qt/coincontroldialog.h \
+    src/qt/coincontroltreewidget.h \
+    src/qt/sendcoinsdialog.h \
+    src/qt/addressbookpage.h \
+    src/qt/signverifymessagedialog.h \
+    src/qt/aboutdialog.h \
+    src/qt/editaddressdialog.h \
+    src/qt/ecoinaddressvalidator.h \
+    src/alert.h \
+    src/addrman.h \
+    src/base58.h \
+    src/bignum.h \
+    src/checkpoints.h \
+    src/compat.h \
+    src/coincontrol.h \
+    src/sync.h \
+    src/util.h \
+    src/uint256.h \
+    src/kernel.h \
+    src/scrypt.h \
+    src/pbkdf2.h \
+    src/zerocoin/Accumulator.h \
+    src/zerocoin/AccumulatorProofOfKnowledge.h \
+    src/zerocoin/Coin.h \
+    src/zerocoin/CoinSpend.h \
+    src/zerocoin/Commitment.h \
+    src/zerocoin/ParamGeneration.h \
+    src/zerocoin/Params.h \
+    src/zerocoin/SerialNumberSignatureOfKnowledge.h \
+    src/zerocoin/SpendMetaData.h \
+    src/zerocoin/ZeroTest.h \
+    src/zerocoin/Zerocoin.h \
+    src/serialize.h \
+    src/strlcpy.h \
+    src/main.h \
+    src/miner.h \
+    src/net.h \
+    src/key.h \
+    src/db.h \
+    src/txdb.h \
+    src/walletdb.h \
+    src/script.h \
+    src/init.h \
+    src/irc.h \
+    src/mruset.h \
+    src/json/json_spirit_writer_template.h \
+    src/json/json_spirit_writer.h \
+    src/json/json_spirit_value.h \
+    src/json/json_spirit_utils.h \
+    src/json/json_spirit_stream_reader.h \
+    src/json/json_spirit_reader_template.h \
+    src/json/json_spirit_reader.h \
+    src/json/json_spirit_error_position.h \
+    src/json/json_spirit.h \
+    src/qt/clientmodel.h \
+    src/qt/guiutil.h \
+    src/qt/transactionrecord.h \
+    src/qt/guiconstants.h \
+    src/qt/optionsmodel.h \
+    src/qt/monitoreddatamapper.h \
+    src/qt/transactiondesc.h \
+    src/qt/transactiondescdialog.h \
+    src/qt/ecoinamountfield.h \
+    src/wallet.h \
+    src/keystore.h \
+    src/qt/transactionfilterproxy.h \
+    src/qt/transactionview.h \
+    src/qt/walletmodel.h \
+    src/ecoinrpc.h \
+    src/qt/overviewpage.h \
+    src/qt/csvmodelwriter.h \
+    src/crypter.h \
+    src/qt/sendcoinsentry.h \
+    src/qt/qvalidatedlineedit.h \
+    src/qt/ecoinunits.h \
+    src/qt/qvaluecombobox.h \
+    src/qt/askpassphrasedialog.h \
+    src/protocol.h \
+    src/qt/notificator.h \
+    src/qt/qtipcserver.h \
+    src/allocators.h \
+    src/ui_interface.h \
+    src/qt/rpcconsole.h \
+    src/version.h \
+    src/netbase.h \
+    src/clientversion.h
+
+SOURCES += src/qt/ecoin.cpp src/qt/ecoingui.cpp \
+    src/qt/transactiontablemodel.cpp \
+    src/qt/addresstablemodel.cpp \
+    src/qt/optionsdialog.cpp \
+    src/qt/sendcoinsdialog.cpp \
+    src/qt/coincontroldialog.cpp \
+    src/qt/coincontroltreewidget.cpp \
+    src/qt/addressbookpage.cpp \
+    src/qt/signverifymessagedialog.cpp \
+    src/qt/aboutdialog.cpp \
+    src/qt/editaddressdialog.cpp \
+    src/qt/ecoinaddressvalidator.cpp \
+    src/alert.cpp \
+    src/version.cpp \
+    src/sync.cpp \
+    src/util.cpp \
+    src/netbase.cpp \
+    src/key.cpp \
+    src/script.cpp \
+    src/main.cpp \
+    src/miner.cpp \
+    src/init.cpp \
+    src/net.cpp \
+    src/irc.cpp \
+    src/checkpoints.cpp \
+    src/addrman.cpp \
+    src/db.cpp \
+    src/walletdb.cpp \
+    src/qt/clientmodel.cpp \
+    src/qt/guiutil.cpp \
+    src/qt/transactionrecord.cpp \
+    src/qt/optionsmodel.cpp \
+    src/qt/monitoreddatamapper.cpp \
+    src/qt/transactiondesc.cpp \
+    src/qt/transactiondescdialog.cpp \
+    src/qt/ecoinstrings.cpp \
+    src/qt/ecoinamountfield.cpp \
+    src/wallet.cpp \
+    src/keystore.cpp \
+    src/qt/transactionfilterproxy.cpp \
+    src/qt/transactionview.cpp \
+    src/qt/walletmodel.cpp \
+    src/ecoinrpc.cpp \
+    src/rpcdump.cpp \
+    src/rpcnet.cpp \
+    src/rpcmining.cpp \
+    src/rpcwallet.cpp \
+    src/rpcblockchain.cpp \
+    src/rpcrawtransaction.cpp \
+    src/qt/overviewpage.cpp \
+    src/qt/csvmodelwriter.cpp \
+    src/crypter.cpp \
+    src/qt/sendcoinsentry.cpp \
+    src/qt/qvalidatedlineedit.cpp \
+    src/qt/ecoinunits.cpp \
+    src/qt/qvaluecombobox.cpp \
+    src/qt/askpassphrasedialog.cpp \
+    src/protocol.cpp \
+    src/qt/notificator.cpp \
+    src/qt/qtipcserver.cpp \
+    src/qt/rpcconsole.cpp \
+    src/noui.cpp \
+    src/kernel.cpp \
+    src/scrypt-arm.S \
+    src/scrypt-x86.S \
+    src/scrypt-x86_64.S \
+    src/scrypt.cpp \
+    src/pbkdf2.cpp \
+    src/zerocoin/Accumulator.cpp \
+    src/zerocoin/AccumulatorProofOfKnowledge.cpp \
+    src/zerocoin/Coin.cpp \
+    src/zerocoin/CoinSpend.cpp \
+    src/zerocoin/Commitment.cpp \
+    src/zerocoin/ParamGeneration.cpp \
+    src/zerocoin/Params.cpp \
+    src/zerocoin/SerialNumberSignatureOfKnowledge.cpp \
+    src/zerocoin/SpendMetaData.cpp \
+    src/zerocoin/ZeroTest.cpp
+
+RESOURCES += \
+    src/qt/ecoin.qrc
+
+FORMS += \
+    src/qt/forms/coincontroldialog.ui \
+    src/qt/forms/sendcoinsdialog.ui \
+    src/qt/forms/addressbookpage.ui \
+    src/qt/forms/signverifymessagedialog.ui \
+    src/qt/forms/aboutdialog.ui \
+    src/qt/forms/editaddressdialog.ui \
+    src/qt/forms/transactiondescdialog.ui \
+    src/qt/forms/overviewpage.ui \
+    src/qt/forms/sendcoinsentry.ui \
+    src/qt/forms/askpassphrasedialog.ui \
+    src/qt/forms/rpcconsole.ui \
+    src/qt/forms/optionsdialog.ui
+
+contains(USE_QRCODE, 1) {
+HEADERS += src/qt/qrcodedialog.h
+SOURCES += src/qt/qrcodedialog.cpp
+FORMS += src/qt/forms/qrcodedialog.ui
+}
+
+CODECFORTR = UTF-8
+
+# for lrelease/lupdate
+# also add new translations to src/qt/ecoin.qrc under translations/
+TRANSLATIONS = $$files(src/qt/locale/ecoin_*.ts)
+
+isEmpty(QMAKE_LRELEASE) {
+    win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
+    else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
+}
+isEmpty(QM_DIR):QM_DIR = $$PWD/src/qt/locale
+# automatically build translations, so they can be included in resource file
+TSQM.name = lrelease ${QMAKE_FILE_IN}
+TSQM.input = TRANSLATIONS
+TSQM.output = $$QM_DIR/${QMAKE_FILE_BASE}.qm
+TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT}
+TSQM.CONFIG = no_link
+QMAKE_EXTRA_COMPILERS += TSQM
+
+# "Other files" to show in Qt Creator
+OTHER_FILES += \
+    doc/*.rst doc/*.txt doc/README README.md res/ecoin-qt.rc
+
+# platform specific defaults, if not overridden on command line
+isEmpty(BOOST_LIB_SUFFIX) {
+    macx:BOOST_LIB_SUFFIX = -mt
+    windows:BOOST_LIB_SUFFIX = -mgw44-mt-1_53
+}
+
+isEmpty(BOOST_THREAD_LIB_SUFFIX) {
+    BOOST_THREAD_LIB_SUFFIX = $$BOOST_LIB_SUFFIX
+}
+
+isEmpty(BDB_LIB_PATH) {
+    macx:BDB_LIB_PATH = /opt/local/lib/db48
+}
+
+isEmpty(BDB_LIB_SUFFIX) {
+    macx:BDB_LIB_SUFFIX = -4.8
+}
+
+isEmpty(BDB_INCLUDE_PATH) {
+    macx:BDB_INCLUDE_PATH = /opt/local/include/db48
+}
+
+isEmpty(BOOST_LIB_PATH) {
+    macx:BOOST_LIB_PATH = /opt/local/lib
+}
+
+isEmpty(BOOST_INCLUDE_PATH) {
+    macx:BOOST_INCLUDE_PATH = /opt/local/include
+}
+
+windows:DEFINES += WIN32
+windows:RC_FILE = src/qt/res/ecoin-qt.rc
+
+windows:!contains(MINGW_THREAD_BUGFIX, 0) {
+    # At least qmake's win32-g++-cross profile is missing the -lmingwthrd
+    # thread-safety flag. GCC has -mthreads to enable this, but it doesn't
+    # work with static linking. -lmingwthrd must come BEFORE -lmingw, so
+    # it is prepended to QMAKE_LIBS_QT_ENTRY.
+    # It can be turned off with MINGW_THREAD_BUGFIX=0, just in case it causes
+    # any problems on some untested qmake profile now or in the future.
+    DEFINES += _MT BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
+    QMAKE_LIBS_QT_ENTRY = -lmingwthrd $$QMAKE_LIBS_QT_ENTRY
+}
+
+!windows:!macx {
+    DEFINES += LINUX
+    LIBS += -lrt
+}
+
+macx:HEADERS += src/qt/macdockiconhandler.h
+macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm
+macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
+macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0
+macx:ICON = src/qt/res/icons/ecoin.icns
+macx:TARGET = "Ecoin-Qt"
+macx:QMAKE_CFLAGS_THREAD += -pthread
+macx:QMAKE_LFLAGS_THREAD += -pthread
+macx:QMAKE_CXXFLAGS_THREAD += -pthread
+
+# Set libraries and includes at end, to use platform-defined defaults if not overridden
+INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH $$QRENCODE_INCLUDE_PATH
+LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,) $$join(QRENCODE_LIB_PATH,,-L,)
+LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX
+# -lgdi32 has to happen after -lcrypto (see  #681)
+windows:LIBS += -lws2_32 -lshlwapi -lmswsock -lole32 -loleaut32 -luuid -lgdi32
+LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_filesystem$$BOOST_LIB_SUFFIX -lboost_program_options$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_THREAD_LIB_SUFFIX
+windows:LIBS += -lboost_chrono$$BOOST_LIB_SUFFIX
+
+contains(RELEASE, 1) {
+    !windows:!macx {
+        # Linux: turn dynamic linking back on for c/c++ runtime libraries
+        LIBS += -Wl,-Bdynamic
+    }
+}
+
+system($$QMAKE_LRELEASE -silent $$_PRO_FILE_)

+ 30 - 0
ecoin/share/genbuild.sh

@@ -0,0 +1,30 @@
+#!/bin/sh
+# ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+if [ $# -gt 0 ]; then
+    FILE="$1"
+    shift
+    if [ -f "$FILE" ]; then
+        INFO="$(head -n 1 "$FILE")"
+    fi
+else
+    echo "Usage: $0 <filename>"
+    exit 1
+fi
+
+if [ -e "$(which git)" ]; then
+    git diff >/dev/null 2>/dev/null 
+    DESC="$(git describe --dirty 2>/dev/null)"
+    TIME="$(git log -n 1 --format="%ci")"
+fi
+
+if [ -n "$DESC" ]; then
+    NEWINFO="#define BUILD_DESC \"$DESC\""
+else
+    NEWINFO="// No build information available"
+fi
+
+if [ "$INFO" != "$NEWINFO" ]; then
+    echo "$NEWINFO" >"$FILE"
+    echo "#define BUILD_DATE \"$TIME\"" >>"$FILE"
+fi

BIN
ecoin/share/pixmaps/addressbook16.bmp


BIN
ecoin/share/pixmaps/addressbook16mask.bmp


BIN
ecoin/share/pixmaps/addressbook20.bmp


BIN
ecoin/share/pixmaps/addressbook20mask.bmp


BIN
ecoin/share/pixmaps/check.ico


BIN
ecoin/share/pixmaps/ecoin.ico


+ 608 - 0
ecoin/share/pixmaps/ecoin32.xpm

@@ -0,0 +1,608 @@
+/* XPM */
+static char * ecoin32_xpm[] = {
+"32 32 573 2",
+"  	c None",
+". 	c #171717",
+"+ 	c #171716",
+"@ 	c #161617",
+"# 	c #161616",
+"$ 	c #161715",
+"% 	c #151517",
+"& 	c #141616",
+"* 	c #141414",
+"= 	c #151515",
+"- 	c #161615",
+"; 	c #171615",
+"> 	c #171617",
+", 	c #0D0F13",
+"' 	c #101015",
+") 	c #332F15",
+"! 	c #5B4D1A",
+"~ 	c #665A1A",
+"{ 	c #685D1C",
+"] 	c #5E5119",
+"^ 	c #3F3717",
+"/ 	c #161515",
+"( 	c #0D0E15",
+"_ 	c #161717",
+": 	c #171616",
+"< 	c #0E0F14",
+"[ 	c #413A18",
+"} 	c #A99320",
+"| 	c #EAC725",
+"1 	c #FCD925",
+"2 	c #FFD623",
+"3 	c #FFD423",
+"4 	c #FFD422",
+"5 	c #FFD522",
+"6 	c #F4CB24",
+"7 	c #BB9F1E",
+"8 	c #5B4F18",
+"9 	c #111113",
+"0 	c #141516",
+"a 	c #101116",
+"b 	c #373118",
+"c 	c #CBAE1F",
+"d 	c #FFD824",
+"e 	c #FCD324",
+"f 	c #FBCC20",
+"g 	c #F5BD1C",
+"h 	c #F4B619",
+"i 	c #F4B316",
+"j 	c #F4B417",
+"k 	c #F5B617",
+"l 	c #F4BA18",
+"m 	c #FBC61F",
+"n 	c #FCCE1F",
+"o 	c #FFD220",
+"p 	c #E6BF1E",
+"q 	c #584C18",
+"r 	c #171718",
+"s 	c #0E0F12",
+"t 	c #7E6E1C",
+"u 	c #FED624",
+"v 	c #FDD123",
+"w 	c #F8C21E",
+"x 	c #F0AC14",
+"y 	c #F2AD13",
+"z 	c #F8BE1C",
+"A 	c #FBCE20",
+"B 	c #FCCE20",
+"C 	c #FECD1F",
+"D 	c #FCCC21",
+"E 	c #F9C31C",
+"F 	c #F2B116",
+"G 	c #F2AD17",
+"H 	c #F7BB1A",
+"I 	c #FCCB1E",
+"J 	c #FFD11E",
+"K 	c #AD911B",
+"L 	c #0F1014",
+"M 	c #A68E1D",
+"N 	c #FFD321",
+"O 	c #FBCD22",
+"P 	c #F1A711",
+"Q 	c #F5B819",
+"R 	c #FCC91C",
+"S 	c #FEC418",
+"T 	c #FCC015",
+"U 	c #FDBF14",
+"V 	c #65521C",
+"W 	c #63511E",
+"X 	c #FDBF15",
+"Y 	c #FCC115",
+"Z 	c #FDC418",
+"` 	c #FDC91A",
+" .	c #F9BE1B",
+"..	c #F1AD17",
+"+.	c #FBC41D",
+"@.	c #FEC91C",
+"#.	c #D4AE1B",
+"$.	c #191914",
+"%.	c #161816",
+"&.	c #0D0F14",
+"*.	c #9C861E",
+"=.	c #FFD123",
+"-.	c #F9C71E",
+";.	c #EEA411",
+">.	c #FBC91D",
+",.	c #FCC116",
+"'.	c #FDBE14",
+").	c #DDA716",
+"!.	c #8A6C1A",
+"~.	c #352A0D",
+"{.	c #2E250D",
+"].	c #FCBE14",
+"^.	c #91721D",
+"/.	c #DFA813",
+"(.	c #FDC016",
+"_.	c #FCC519",
+":.	c #F5B31B",
+"<.	c #F8BE19",
+"[.	c #FEC71D",
+"}.	c #D2AA19",
+"|.	c #161516",
+"1.	c #161716",
+"2.	c #151415",
+"3.	c #60551A",
+"4.	c #FFD221",
+"5.	c #FAC91E",
+"6.	c #FABE15",
+"7.	c #F9BB13",
+"8.	c #7E641C",
+"9.	c #010101",
+"0.	c #806419",
+"a.	c #33290B",
+"b.	c #2C230C",
+"c.	c #866919",
+"d.	c #000000",
+"e.	c #715919",
+"f.	c #FABC15",
+"g.	c #F5B71C",
+"h.	c #FEC618",
+"i.	c #A08316",
+"j.	c #0F1115",
+"k.	c #1E1D13",
+"l.	c #F3CA20",
+"m.	c #EEA410",
+"n.	c #FCC91D",
+"o.	c #886B1D",
+"p.	c #664E0D",
+"q.	c #FBBD16",
+"r.	c #6B5417",
+"s.	c #020200",
+"t.	c #010100",
+"u.	c #695215",
+"v.	c #FCBD14",
+"w.	c #53410E",
+"x.	c #7E631B",
+"y.	c #FBC217",
+"z.	c #F5B521",
+"A.	c #FAC117",
+"B.	c #FFCA18",
+"C.	c #443814",
+"D.	c #8E791A",
+"E.	c #FECC1D",
+"F.	c #F2B015",
+"G.	c #F0BC1C",
+"H.	c #CC9E1C",
+"I.	c #4B3B10",
+"J.	c #130F05",
+"K.	c #F6BA16",
+"L.	c #FDBE15",
+"M.	c #735A17",
+"N.	c #715916",
+"O.	c #F5B815",
+"P.	c #070705",
+"Q.	c #3E300C",
+"R.	c #F8BB14",
+"S.	c #C6981A",
+"T.	c #F8BE18",
+"U.	c #F5B621",
+"V.	c #FDC214",
+"W.	c #CFA415",
+"X.	c #0D0E14",
+"Y.	c #161613",
+"Z.	c #F1C31E",
+"`.	c #FCCA1C",
+" +	c #F1A912",
+".+	c #AB891D",
+"++	c #020202",
+"@+	c #58430C",
+"#+	c #8A6B18",
+"$+	c #030303",
+"%+	c #D09F1B",
+"&+	c #FCBD13",
+"*+	c #2B220C",
+"=+	c #29210C",
+"-+	c #DBA515",
+";+	c #92731F",
+">+	c #5B460E",
+",+	c #040402",
+"'+	c #AE881E",
+")+	c #F9BD1E",
+"!+	c #FBBC19",
+"~+	c #FFC515",
+"{+	c #3D3313",
+"]+	c #171715",
+"^+	c #4B4016",
+"/+	c #FFCE1B",
+"(+	c #F4B213",
+"_+	c #F8BC18",
+":+	c #EAB419",
+"<+	c #735912",
+"[+	c #0C0A04",
+"}+	c #060503",
+"|+	c #8E6F1B",
+"1+	c #FBBC14",
+"2+	c #372B0D",
+"3+	c #90711D",
+"4+	c #070604",
+"5+	c #0D0B04",
+"6+	c #715812",
+"7+	c #E4AB14",
+"8+	c #FCC214",
+"9+	c #F8BA21",
+"0+	c #FDBF12",
+"a+	c #947716",
+"b+	c #111215",
+"c+	c #131315",
+"d+	c #957C18",
+"e+	c #FDC81C",
+"f+	c #F2A911",
+"g+	c #FCC71B",
+"h+	c #F5BB19",
+"i+	c #C09112",
+"j+	c #67531C",
+"k+	c #030200",
+"l+	c #171205",
+"m+	c #A67F17",
+"n+	c #F4B815",
+"o+	c #362B0D",
+"p+	c #F3B715",
+"q+	c #A67F14",
+"r+	c #181307",
+"s+	c #6A5621",
+"t+	c #BD8F12",
+"u+	c #F3B716",
+"v+	c #FDBE13",
+"w+	c #F9BC28",
+"x+	c #FCBB0E",
+"y+	c #CA9B11",
+"z+	c #0D0F16",
+"A+	c #BD9818",
+"B+	c #FEC619",
+"C+	c #F2A70E",
+"D+	c #806315",
+"E+	c #050503",
+"F+	c #141003",
+"G+	c #3E310E",
+"H+	c #644D0E",
+"I+	c #3D300C",
+"J+	c #030302",
+"K+	c #473911",
+"L+	c #CB9A18",
+"M+	c #33280B",
+"N+	c #2B220B",
+"O+	c #CB9A16",
+"P+	c #483912",
+"Q+	c #3A2E0C",
+"R+	c #3E310F",
+"S+	c #161105",
+"T+	c #644E12",
+"U+	c #FCBE11",
+"V+	c #F8BD26",
+"W+	c #FDBA12",
+"X+	c #F3B70E",
+"Y+	c #111214",
+"Z+	c #171618",
+"`+	c #0C0D16",
+" @	c #CDA518",
+".@	c #FCC416",
+"+@	c #F2A50F",
+"@@	c #D8A620",
+"#@	c #B48A1A",
+"$@	c #E5AD17",
+"%@	c #9B7817",
+"&@	c #161103",
+"*@	c #0B0902",
+"=@	c #060502",
+"-@	c #181304",
+";@	c #9E7A19",
+">@	c #E7B01A",
+",@	c #BA8F1D",
+"'@	c #DEAA1D",
+")@	c #FABE22",
+"!@	c #FAB915",
+"~@	c #FFBF0E",
+"{@	c #1D1B13",
+"]@	c #0B0D15",
+"^@	c #D1A717",
+"/@	c #FCC215",
+"(@	c #F3A40E",
+"_@	c #FDC317",
+":@	c #D7A419",
+"<@	c #1F1B0E",
+"[@	c #181408",
+"}@	c #D6A218",
+"|@	c #FDBD13",
+"1@	c #FCBD12",
+"2@	c #FBBC13",
+"3@	c #FBBE21",
+"4@	c #FBB915",
+"5@	c #FFC00C",
+"6@	c #201D14",
+"7@	c #171816",
+"8@	c #0C0E16",
+"9@	c #C69C15",
+"0@	c #FCC113",
+"a@	c #F1A60D",
+"b@	c #FEC216",
+"c@	c #D5A31B",
+"d@	c #C89815",
+"e@	c #E4AC16",
+"f@	c #EDB214",
+"g@	c #F5B813",
+"h@	c #EEB314",
+"i@	c #B18717",
+"j@	c #2B220A",
+"k@	c #0F0C02",
+"l@	c #060501",
+"m@	c #040301",
+"n@	c #100D03",
+"o@	c #282009",
+"p@	c #AF8617",
+"q@	c #EEB315",
+"r@	c #E5AD16",
+"s@	c #CF9D15",
+"t@	c #D8A214",
+"u@	c #FCBC0F",
+"v@	c #FABF25",
+"w@	c #FCB612",
+"x@	c #FFBA0C",
+"y@	c #171613",
+"z@	c #181717",
+"A@	c #101217",
+"B@	c #A88713",
+"C@	c #FDC014",
+"D@	c #F3A80F",
+"E@	c #FDC315",
+"F@	c #856817",
+"G@	c #050401",
+"H@	c #2F2711",
+"I@	c #4B3A0E",
+"J@	c #88670E",
+"K@	c #4D3C0E",
+"L@	c #382C0B",
+"M@	c #B68B18",
+"N@	c #34290C",
+"O@	c #BA8E18",
+"P@	c #392D0B",
+"Q@	c #87660F",
+"R@	c #4B3B0F",
+"S@	c #312913",
+"T@	c #070601",
+"U@	c #6E5515",
+"V@	c #FCBA0D",
+"W@	c #FBC12F",
+"X@	c #FBB209",
+"Y@	c #DCA40C",
+"Z@	c #0E0F15",
+"`@	c #151617",
+" #	c #725D14",
+".#	c #FFC214",
+"+#	c #FBBB13",
+"@#	c #EAB117",
+"##	c #9F7B19",
+"$#	c #4F3F14",
+"%#	c #0D0B03",
+"&#	c #8E6D14",
+"*#	c #FCBE17",
+"=#	c #8D6C13",
+"-#	c #544418",
+";#	c #9E7918",
+">#	c #E8AC13",
+",#	c #FCB80A",
+"'#	c #F9BF2B",
+")#	c #FBB105",
+"!#	c #AE800D",
+"~#	c #252115",
+"{#	c #FDBF11",
+"]#	c #FBB70F",
+"^#	c #F6AF11",
+"/#	c #957113",
+"(#	c #271F09",
+"_#	c #0E0B02",
+":#	c #8A6C19",
+"<#	c #91721F",
+"[#	c #0F0C03",
+"}#	c #2C230A",
+"|#	c #987313",
+"1#	c #F0B010",
+"2#	c #FABA16",
+"3#	c #FBBB22",
+"4#	c #FFB704",
+"5#	c #675010",
+"6#	c #C89A10",
+"7#	c #FDBB0E",
+"8#	c #F2A210",
+"9#	c #A47F18",
+"0#	c #070602",
+"a#	c #4A390C",
+"b#	c #7B5F17",
+"c#	c #D19F1A",
+"d#	c #F7BA17",
+"e#	c #2C230B",
+"f#	c #271F0B",
+"g#	c #DCA615",
+"h#	c #7B611C",
+"i#	c #47360B",
+"j#	c #0A0802",
+"k#	c #AA7E17",
+"l#	c #FCC430",
+"m#	c #FCAE04",
+"n#	c #EDAB08",
+"o#	c #443714",
+"p#	c #FFBF0C",
+"q#	c #FBB50E",
+"r#	c #ECA614",
+"s#	c #B48815",
+"t#	c #FDBC11",
+"u#	c #554211",
+"v#	c #151105",
+"w#	c #F7BA16",
+"x#	c #8B6C18",
+"y#	c #020201",
+"z#	c #836617",
+"A#	c #F2B616",
+"B#	c #090804",
+"C#	c #4F3E10",
+"D#	c #AD7F10",
+"E#	c #FCBB1D",
+"F#	c #FAB81E",
+"G#	c #FFB106",
+"H#	c #85630C",
+"I#	c #121315",
+"J#	c #0F1116",
+"K#	c #AC8410",
+"L#	c #FEB70B",
+"M#	c #F8AD0F",
+"N#	c #F7B312",
+"O#	c #FDBA0F",
+"P#	c #705714",
+"Q#	c #624B0F",
+"R#	c #EEB416",
+"S#	c #816517",
+"T#	c #7D6219",
+"U#	c #ECB215",
+"V#	c #FCBD15",
+"W#	c #4E3D0E",
+"X#	c #FCB60C",
+"Y#	c #FBB70E",
+"Z#	c #FCC132",
+"`#	c #FBAC03",
+" $	c #E5A108",
+".$	c #141614",
+"+$	c #191915",
+"@$	c #E5AA0B",
+"#$	c #FCB409",
+"$$	c #F7AB11",
+"%$	c #F9B214",
+"&$	c #FCB80E",
+"*$	c #F7B611",
+"=$	c #FDBB11",
+"-$	c #9D7819",
+";$	c #6E5614",
+">$	c #32270B",
+",$	c #28200B",
+"'$	c #725915",
+")$	c #94731A",
+"!$	c #F5B713",
+"~$	c #FBB80E",
+"{$	c #FBB710",
+"]$	c #FAC133",
+"^$	c #FBAB03",
+"/$	c #FCAF06",
+"($	c #3D3111",
+"_$	c #151616",
+":$	c #2D2513",
+"<$	c #F1AF0A",
+"[$	c #FDB206",
+"}$	c #F9AE10",
+"|$	c #F7AF19",
+"1$	c #FCB70C",
+"2$	c #FDB70C",
+"3$	c #C6900D",
+"4$	c #765811",
+"5$	c #785D16",
+"6$	c #C79615",
+"7$	c #FCB90F",
+"8$	c #FCB40A",
+"9$	c #FBBD21",
+"0$	c #FBBD2D",
+"a$	c #FBAA01",
+"b$	c #FFB004",
+"c$	c #5D470E",
+"d$	c #121317",
+"e$	c #2A2413",
+"f$	c #E4A50A",
+"g$	c #FCB106",
+"h$	c #FCB008",
+"i$	c #F7AE1B",
+"j$	c #F9B41B",
+"k$	c #FDB50B",
+"l$	c #FCB507",
+"m$	c #FCB60B",
+"n$	c #634E16",
+"o$	c #604C17",
+"p$	c #FDB90E",
+"q$	c #FCB50A",
+"r$	c #FCB509",
+"s$	c #FBBC1B",
+"t$	c #FABF32",
+"u$	c #FBB114",
+"v$	c #FCA901",
+"w$	c #FAAC04",
+"x$	c #573E10",
+"y$	c #111316",
+"z$	c #A77A0D",
+"A$	c #FFB405",
+"B$	c #FDAE04",
+"C$	c #FCAD07",
+"D$	c #F9B01A",
+"E$	c #F8B525",
+"F$	c #FAB61F",
+"G$	c #FBB81D",
+"H$	c #FBB91D",
+"I$	c #FBB921",
+"J$	c #FABD2B",
+"K$	c #FCBA2A",
+"L$	c #FCAE0F",
+"M$	c #FCA701",
+"N$	c #FFAF01",
+"O$	c #CC8F07",
+"P$	c #2A2213",
+"Q$	c #121617",
+"R$	c #3B2F10",
+"S$	c #B8820B",
+"T$	c #FCAF04",
+"U$	c #FFAF03",
+"V$	c #FDAB01",
+"W$	c #FCAA03",
+"X$	c #FBAA03",
+"Y$	c #FDA904",
+"Z$	c #FAA803",
+"`$	c #FDA900",
+" %	c #FFAC01",
+".%	c #FFAD01",
+"+%	c #D18F07",
+"@%	c #5A430E",
+"#%	c #0E1016",
+"$%	c #0D1016",
+"%%	c #231E13",
+"&%	c #5F4511",
+"*%	c #9A7008",
+"=%	c #CE8E07",
+"-%	c #DB9A03",
+";%	c #DD9A04",
+">%	c #D49106",
+",%	c #AA7808",
+"'%	c #6C4D0D",
+")%	c #312812",
+"!%	c #0A0F17",
+"~%	c #0E1215",
+"{%	c #0F1117",
+"]%	c #0F1316",
+"^%	c #151516",
+". . . . . . . . . . . . . + . . . . . . . . . . . . . . . . . . ",
+". . . . . . . . . . . @ # $ % & * = - ; # . + . . . . . . . . . ",
+". . . . . . . . @ > . , ' ) ! ~ { ] ^ / ( _ _ : + . . . . . . . ",
+". . . . . . + # ; < [ } | 1 2 3 3 4 5 6 7 8 9 0 # . . . . . . . ",
+". . . . # # + a b c d e f g h i j k l m n o p q < r : . . . . . ",
+". . . . # > s t u v w x y z A B C D E F G H I J K = > . . . . . ",
+". . . > $ L M N O P Q R S T U V W X Y Z `  ...+.@.#.$.%.# . . . ",
+". . + # &.*.=.-.;.>.,.'.).!.'.~.{.].^./.'.(._.:.<.[.}.|.: 1.. . ",
+". + % 2.3.4.5.;.I 6.7.'.8.9.0.a.b.c.d.e.'.7.f.Z g. .h.i.j.# : . ",
+". # - k.l.f m.n.(.o.p.'.q.r.d.s.t.d.u.'.v.w.x.v.y.z.A.B.C._ @ . ",
+". > j.D.E.F.G.H.'.I.J.K.'.L.M.9.9.N.'.'.O.P.Q.R.S.T.U.V.W.X.# 1.",
+". ; Y.Z.`. +.+++@+#+$+%+'.&+'.*+=+&+'.'.-+d.;+>+,+'+)+!+~+{+]+# ",
+"# - ^+/+(+_+:+<+[+}+d.|+1+'.'.2+{.'.'.1+3+d.4+5+6+7+8+9+0+a+b+@ ",
+"- c+d+e+f+g+h+i+j+d.k+l+m+n+&+o+{.'.p+q+r+k+9.s+t+u+v+w+x+y+( @ ",
+"# z+A+B+C+B+D+E+F+G+H+I+J+K+L+M+N+O+P+9.Q+H+R+S+E+T+U+V+W+X+Y+Z+",
+"# `+ @.@+@Z @@#@$@].'.'.%@&@$+*@=@++-@;@'.'.'.>@,@'@].)@!@~@{@. ",
+"+ ]@^@/@(@_@'.'.'.].'.'.'.:@<@d.d.[@}@'.'.'.'.'.|@1@2@3@4@5@6@7@",
+"# 8@9@0@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@g@f@r@s@t@u@v@w@x@y@z@",
+". A@B@C@D@E@F@G@H@I@J@K@9.L@M@N@b.O@P@J+K@Q@R@S@T@U@V@W@X@Y@Z@. ",
+"`@0  #.#D@+#@###$#d.9.%#&#L.'.o+{.'.*#=#5+9.d.-#;#>#,#'#)#!#Z@# ",
+"_ . ~#{#]#^#h@/#(#_#d.:#'.'.'.o+{.'.'.'.<#d.[#}#|#1#2#3#4#5## # ",
+"_ `@&.6#7#8#9#0#a#b#9.c#'.'.d#e#f#d#'.'.g#d.h#i#j#k#l#m#n#/ # + ",
+". # # o#p#q#r#s#t#u#v#w#'.u+x#9.y#z#A#'.K.B#C#t#D#E#F#G#H#I## . ",
+". # = J#K#L#M#N#O#P#Q#&+R#S#9.l@m@++T#U#V#W#Q#X#Y#Z#`# $.$: # . ",
+". # 1.: +$@$#$$$%$&$*$=$-$++;$>$,$'$$+)$|@!$~${$]$^$/$($_$+ . . ",
+". . @ # # :$<$[$}$|$1$2$3$4$t#o+{.&+5$6$7$8$9$0$a$b$c$d$@ @ . . ",
+". . . # @ = e$f$g$h$i$j$k$l$m$n$o$p$q$r$s$t$u$v$w$x$y$> . . . . ",
+". . . . : _ = = z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$Q$1.. . . . . ",
+". . . . . 1.1.; J#R$S$T$U$V$W$X$Y$Z$`$ %.%+%@%#%# > . . . . . . ",
+". . . . . . # # # _ $%%%&%*%=%-%;%>%,%'%)%!%# > 1.. . . . . . . ",
+". . . . . . . . . . . + # I#$%~%{%$%]%^%+ + . . . . . . . . . . ",
+". . . . . . . . . . . . # _$# 1._$# @ - # . . . . . . . . . . . "};

File diff suppressed because it is too large
+ 2645 - 0
ecoin/share/pixmaps/ecoin80.xpm


BIN
ecoin/share/pixmaps/favicon.ico


BIN
ecoin/share/pixmaps/nsis-header.bmp


BIN
ecoin/share/pixmaps/nsis-wizard.bmp


BIN
ecoin/share/pixmaps/send16.bmp


BIN
ecoin/share/pixmaps/send16mask.bmp


BIN
ecoin/share/pixmaps/send16masknoshadow.bmp


BIN
ecoin/share/pixmaps/send20.bmp


BIN
ecoin/share/pixmaps/send20mask.bmp


+ 58 - 0
ecoin/share/qt/extract_strings_qt.py

@@ -0,0 +1,58 @@
+#!/usr/bin/python
+# ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+from subprocess import Popen, PIPE
+import glob
+
+OUT_CPP="src/qt/ecoinstrings.cpp"
+EMPTY=['""']
+
+def parse_po(text):
+    messages = []
+    msgid = []
+    msgstr = []
+    in_msgid = False
+    in_msgstr = False
+    for line in text.split('\n'):
+        line = line.rstrip('\r')
+        if line.startswith('msgid '):
+            if in_msgstr:
+                messages.append((msgid, msgstr))
+                in_msgstr = False
+            in_msgid = True
+            msgid = [line[6:]]
+        elif line.startswith('msgstr '):
+            in_msgid = False
+            in_msgstr = True
+            msgstr = [line[7:]]
+        elif line.startswith('"'):
+            if in_msgid:
+                msgid.append(line)
+            if in_msgstr:
+                msgstr.append(line)
+    if in_msgstr:
+        messages.append((msgid, msgstr))
+    return messages
+
+files = glob.glob('src/*.cpp') + glob.glob('src/*.h') 
+
+child = Popen(['xgettext','--output=-','-n','--keyword=_'] + files, stdout=PIPE)
+(out, err) = child.communicate()
+
+messages = parse_po(out) 
+
+f = open(OUT_CPP, 'w')
+f.write("""#include <QtGlobal>
+// Automatically generated by extract_strings.py
+#ifdef __GNUC__
+#define UNUSED __attribute__((unused))
+#else
+#define UNUSED
+#endif
+""")
+f.write('static const char UNUSED *ecoin_strings[] = {')
+for (msgid, msgstr) in messages:
+    if msgid != EMPTY:
+        f.write('QT_TRANSLATE_NOOP("ecoin-core", %s),\n' % ('\n'.join(msgid)))
+f.write('};')
+f.close()

BIN
ecoin/share/qt/img/reload.xcf


+ 42 - 0
ecoin/share/qt/make_spinner.py

@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+# Requires imagemagick 6.7+
+from __future__ import division
+from os import path
+from PIL import Image
+from subprocess import Popen
+
+SRC='img/reload_scaled.png'
+DST='../../src/qt/res/movies/update_spinner.mng'
+TMPDIR='/tmp'
+TMPNAME='tmp-%03i.png'
+NUMFRAMES=35
+FRAMERATE=10.0
+CONVERT='convert'
+CLOCKWISE=True
+DSIZE=(16,16)
+
+im_src = Image.open(SRC)
+
+if CLOCKWISE:
+    im_src = im_src.transpose(Image.FLIP_LEFT_RIGHT)
+
+def frame_to_filename(frame):
+    return path.join(TMPDIR, TMPNAME % frame)
+
+frame_files = []
+for frame in xrange(NUMFRAMES):
+    rotation = (frame + 0.5) / NUMFRAMES * 360.0
+    if CLOCKWISE:
+        rotation = -rotation
+    im_new = im_src.rotate(rotation, Image.BICUBIC)
+    im_new.thumbnail(DSIZE, Image.ANTIALIAS)
+    outfile = frame_to_filename(frame)
+    im_new.save(outfile, 'png')
+    frame_files.append(outfile)
+
+p = Popen([CONVERT, "-delay", str(FRAMERATE), "-dispose", "2"] + frame_files + [DST])
+p.communicate()
+
+
+

+ 5 - 0
ecoin/share/qt/make_windows_icon.sh

@@ -0,0 +1,5 @@
+#!/bin/bash
+# ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+# Create multiresolution windows icon
+ICON_DST=../../src/qt/res/icons/ecoin.ico
+convert ../../src/qt/res/icons/ecoin-16.png ../../src/qt/res/icons/ecoin-32.png ../../src/qt/res/icons/ecoin-48.png ${ICON_DST}

+ 157 - 0
ecoin/share/setup.nsi

@@ -0,0 +1,157 @@
+
+# ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+Name Ecoin
+
+RequestExecutionLevel highest
+SetCompressor /SOLID lzma
+
+# General Symbol Definitions
+!define REGKEY "SOFTWARE\$(^Name)"
+!define VERSION 0.0.2
+!define COMPANY "Ecoin project"
+!define URL https://03c8.net
+
+# MUI Symbol Definitions
+!define MUI_ICON "../share/pixmaps/ecoin.ico"
+!define MUI_WELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp"
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_RIGHT
+!define MUI_HEADERIMAGE_BITMAP "../share/pixmaps/nsis-header.bmp"
+!define MUI_FINISHPAGE_NOAUTOCLOSE
+!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
+!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY}
+!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup
+!define MUI_STARTMENUPAGE_DEFAULTFOLDER Ecoin
+#!define MUI_FINISHPAGE_RUN $INSTDIR\ecoin-qt.exe
+!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
+!define MUI_UNWELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp"
+!define MUI_UNFINISHPAGE_NOAUTOCLOSE
+
+# Included files
+!include Sections.nsh
+!include MUI2.nsh
+
+# Variables
+Var StartMenuGroup
+
+# Installer pages
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro MUI_PAGE_DIRECTORY
+!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_PAGE_FINISH
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_INSTFILES
+
+# Installer languages
+!insertmacro MUI_LANGUAGE English
+
+# Installer attributes
+OutFile ecoin-0.0.2-win32-setup.exe
+InstallDir $PROGRAMFILES\Ecoin
+CRCCheck on
+XPStyle on
+BrandingText " "
+ShowInstDetails show
+VIProductVersion 0.0.2.1
+VIAddVersionKey ProductName Ecoin
+VIAddVersionKey ProductVersion "${VERSION}"
+VIAddVersionKey CompanyName "${COMPANY}"
+VIAddVersionKey CompanyWebsite "${URL}"
+VIAddVersionKey FileVersion "${VERSION}"
+VIAddVersionKey FileDescription ""
+VIAddVersionKey LegalCopyright ""
+InstallDirRegKey HKCU "${REGKEY}" Path
+ShowUninstDetails show
+
+# Installer sections
+Section -Main SEC0000
+    SetOutPath $INSTDIR
+    SetOverwrite on
+    #File ../release/ecoin-qt.exe
+    File /oname=license.txt ../COPYING
+    File /oname=readme.txt ../doc/README_windows.txt
+    SetOutPath $INSTDIR\daemon
+    File ../src/ecoind.exe
+    SetOutPath $INSTDIR\src
+    File /r /x *.exe /x *.o ../src\*.*
+    SetOutPath $INSTDIR
+    WriteRegStr HKCU "${REGKEY}\Components" Main 1
+
+    # Remove old wxwidgets-based-bitcoin executable and locales:
+    #Delete /REBOOTOK $INSTDIR\ecoin.exe
+    #RMDir /r /REBOOTOK $INSTDIR\locale
+SectionEnd
+
+Section -post SEC0001
+    WriteRegStr HKCU "${REGKEY}" Path $INSTDIR
+    SetOutPath $INSTDIR
+    WriteUninstaller $INSTDIR\uninstall.exe
+    !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+    CreateDirectory $SMPROGRAMS\$StartMenuGroup
+    CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall Ecoin.lnk" $INSTDIR\uninstall.exe
+    !insertmacro MUI_STARTMENU_WRITE_END
+    WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
+    WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}"
+    WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}"
+    WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}"
+    WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe
+    WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe
+    WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1
+    WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1
+SectionEnd
+
+# Macro for selecting uninstaller sections
+!macro SELECT_UNSECTION SECTION_NAME UNSECTION_ID
+    Push $R0
+    ReadRegStr $R0 HKCU "${REGKEY}\Components" "${SECTION_NAME}"
+    StrCmp $R0 1 0 next${UNSECTION_ID}
+    !insertmacro SelectSection "${UNSECTION_ID}"
+    GoTo done${UNSECTION_ID}
+next${UNSECTION_ID}:
+    !insertmacro UnselectSection "${UNSECTION_ID}"
+done${UNSECTION_ID}:
+    Pop $R0
+!macroend
+
+# Uninstaller sections
+Section /o -un.Main UNSEC0000
+    Delete /REBOOTOK $INSTDIR\license.txt
+    Delete /REBOOTOK $INSTDIR\readme.txt
+    RMDir /r /REBOOTOK $INSTDIR\daemon
+    RMDir /r /REBOOTOK $INSTDIR\src
+    DeleteRegValue HKCU "${REGKEY}\Components" Main
+SectionEnd
+
+Section -un.post UNSEC0001
+    DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)"
+    Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall Ecoin.lnk"
+    Delete /REBOOTOK $INSTDIR\uninstall.exe
+    Delete /REBOOTOK $INSTDIR\debug.log
+    Delete /REBOOTOK $INSTDIR\db.log
+    DeleteRegValue HKCU "${REGKEY}" StartMenuGroup
+    DeleteRegValue HKCU "${REGKEY}" Path
+    DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components"
+    DeleteRegKey /IfEmpty HKCU "${REGKEY}"
+    DeleteRegKey HKCR "ecoin"
+    RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup
+    RmDir /REBOOTOK $INSTDIR
+    Push $R0
+    StrCpy $R0 $StartMenuGroup 1
+    StrCmp $R0 ">" no_smgroup
+no_smgroup:
+    Pop $R0
+SectionEnd
+
+# Installer functions
+Function .onInit
+    InitPluginsDir
+FunctionEnd
+
+# Uninstaller functions
+Function un.onInit
+    ReadRegStr $INSTDIR HKCU "${REGKEY}" Path
+    !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup
+    !insertmacro SELECT_UNSECTION Main ${UNSEC0000}
+FunctionEnd

+ 18 - 0
ecoin/share/ui.rc

@@ -0,0 +1,18 @@
+
+// ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+ecoin                 ICON    "pixmaps/ecoin.ico"
+
+#include "wx/msw/wx.rc"
+
+check                 ICON    "pixmaps/check.ico"
+send16                BITMAP  "pixmaps/send16.bmp"
+send16mask            BITMAP  "pixmaps/send16mask.bmp"
+send16masknoshadow    BITMAP  "pixmaps/send16masknoshadow.bmp"
+send20                BITMAP  "pixmaps/send20.bmp"
+send20mask            BITMAP  "pixmaps/send20mask.bmp"
+addressbook16         BITMAP  "pixmaps/addressbook16.bmp"
+addressbook16mask     BITMAP  "pixmaps/addressbook16mask.bmp"
+addressbook20         BITMAP  "pixmaps/addressbook20.bmp"
+addressbook20mask     BITMAP  "pixmaps/addressbook20mask.bmp"
+favicon               ICON    "pixmaps/favicon.ico"

+ 525 - 0
ecoin/src/addrman.cpp

@@ -0,0 +1,525 @@
+// ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+#include "addrman.h"
+
+using namespace std;
+
+int CAddrInfo::GetTriedBucket(const std::vector<unsigned char> &nKey) const
+{
+    CDataStream ss1(SER_GETHASH, 0);
+    std::vector<unsigned char> vchKey = GetKey();
+    ss1 << nKey << vchKey;
+    uint64 hash1 = Hash(ss1.begin(), ss1.end()).Get64();
+
+    CDataStream ss2(SER_GETHASH, 0);
+    std::vector<unsigned char> vchGroupKey = GetGroup();
+    ss2 << nKey << vchGroupKey << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP);
+    uint64 hash2 = Hash(ss2.begin(), ss2.end()).Get64();
+    return hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
+}
+
+int CAddrInfo::GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const
+{
+    CDataStream ss1(SER_GETHASH, 0);
+    std::vector<unsigned char> vchGroupKey = GetGroup();
+    std::vector<unsigned char> vchSourceGroupKey = src.GetGroup();
+    ss1 << nKey << vchGroupKey << vchSourceGroupKey;
+    uint64 hash1 = Hash(ss1.begin(), ss1.end()).Get64();
+
+    CDataStream ss2(SER_GETHASH, 0);
+    ss2 << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP);
+    uint64 hash2 = Hash(ss2.begin(), ss2.end()).Get64();
+    return hash2 % ADDRMAN_NEW_BUCKET_COUNT;
+}
+
+bool CAddrInfo::IsTerrible(int64 nNow) const
+{
+    if (nLastTry && nLastTry >= nNow-60) // never remove things tried the last minute
+        return false;
+
+    if (nTime > nNow + 10*60) // came in a flying DeLorean
+        return true;
+
+    if (nTime==0 || nNow-nTime > ADDRMAN_HORIZON_DAYS*86400) // not seen in over a month
+        return true;
+
+    if (nLastSuccess==0 && nAttempts>=ADDRMAN_RETRIES) // tried three times and never a success
+        return true;
+
+    if (nNow-nLastSuccess > ADDRMAN_MIN_FAIL_DAYS*86400 && nAttempts>=ADDRMAN_MAX_FAILURES) // 10 successive failures in the last week
+        return true;
+
+    return false;
+}
+
+double CAddrInfo::GetChance(int64 nNow) const
+{
+    double fChance = 1.0;
+
+    int64 nSinceLastSeen = nNow - nTime;
+    int64 nSinceLastTry = nNow - nLastTry;
+
+    if (nSinceLastSeen < 0) nSinceLastSeen = 0;
+    if (nSinceLastTry < 0) nSinceLastTry = 0;
+
+    fChance *= 600.0 / (600.0 + nSinceLastSeen);
+
+    // deprioritize very recent attempts away
+    if (nSinceLastTry < 60*10)
+        fChance *= 0.01;
+
+    // deprioritize 50% after each failed attempt
+    for (int n=0; n<nAttempts; n++)
+        fChance /= 1.5;
+
+    return fChance;
+}
+
+CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int *pnId)
+{
+    std::map<CNetAddr, int>::iterator it = mapAddr.find(addr);
+    if (it == mapAddr.end())
+        return NULL;
+    if (pnId)
+        *pnId = (*it).second;
+    std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
+    if (it2 != mapInfo.end())
+        return &(*it2).second;
+    return NULL;
+}
+
+CAddrInfo* CAddrMan::Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId)
+{
+    int nId = nIdCount++;
+    mapInfo[nId] = CAddrInfo(addr, addrSource);
+    mapAddr[addr] = nId;
+    mapInfo[nId].nRandomPos = vRandom.size();
+    vRandom.push_back(nId);
+    if (pnId)
+        *pnId = nId;
+    return &mapInfo[nId];
+}
+
+void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
+{
+    if (nRndPos1 == nRndPos2)
+        return;
+
+    assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
+
+    int nId1 = vRandom[nRndPos1];
+    int nId2 = vRandom[nRndPos2];
+
+    assert(mapInfo.count(nId1) == 1);
+    assert(mapInfo.count(nId2) == 1);
+
+    mapInfo[nId1].nRandomPos = nRndPos2;
+    mapInfo[nId2].nRandomPos = nRndPos1;
+
+    vRandom[nRndPos1] = nId2;
+    vRandom[nRndPos2] = nId1;
+}
+
+int CAddrMan::SelectTried(int nKBucket)
+{
+    std::vector<int> &vTried = vvTried[nKBucket];
+
+    // random shuffle the first few elements (using the entire list)
+    // find the least recently tried among them
+    int64 nOldest = -1;
+    int nOldestPos = -1;
+    for (unsigned int i = 0; i < ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT && i < vTried.size(); i++)
+    {
+        int nPos = GetRandInt(vTried.size() - i) + i;
+        int nTemp = vTried[nPos];
+        vTried[nPos] = vTried[i];
+        vTried[i] = nTemp;
+        assert(nOldest == -1 || mapInfo.count(nTemp) == 1);
+        if (nOldest == -1 || mapInfo[nTemp].nLastSuccess < mapInfo[nOldest].nLastSuccess) {
+           nOldest = nTemp;
+           nOldestPos = nPos;
+        }
+    }
+
+    return nOldestPos;
+}
+
+int CAddrMan::ShrinkNew(int nUBucket)
+{
+    assert(nUBucket >= 0 && (unsigned int)nUBucket < vvNew.size());
+    std::set<int> &vNew = vvNew[nUBucket];
+
+    // first look for deletable items
+    for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
+    {
+        assert(mapInfo.count(*it));
+        CAddrInfo &info = mapInfo[*it];
+        if (info.IsTerrible())
+        {
+            if (--info.nRefCount == 0)
+            {
+                SwapRandom(info.nRandomPos, vRandom.size()-1);
+                vRandom.pop_back();
+                mapAddr.erase(info);
+                mapInfo.erase(*it);
+                nNew--;
+            }
+            vNew.erase(it);
+            return 0;
+        }
+    }
+
+    // otherwise, select four randomly, and pick the oldest of those to replace
+    int n[4] = {GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size()), GetRandInt(vNew.size())};
+    int nI = 0;
+    int nOldest = -1;
+    for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
+    {
+        if (nI == n[0] || nI == n[1] || nI == n[2] || nI == n[3])
+        {
+            assert(nOldest == -1 || mapInfo.count(*it) == 1);
+            if (nOldest == -1 || mapInfo[*it].nTime < mapInfo[nOldest].nTime)
+                nOldest = *it;
+        }
+        nI++;
+    }
+    assert(mapInfo.count(nOldest) == 1);
+    CAddrInfo &info = mapInfo[nOldest];
+    if (--info.nRefCount == 0)
+    {
+        SwapRandom(info.nRandomPos, vRandom.size()-1);
+        vRandom.pop_back();
+        mapAddr.erase(info);
+        mapInfo.erase(nOldest);
+        nNew--;
+    }
+    vNew.erase(nOldest);
+
+    return 1;
+}
+
+void CAddrMan::MakeTried(CAddrInfo& info, int nId, int nOrigin)
+{
+    assert(vvNew[nOrigin].count(nId) == 1);
+
+    // remove the entry from all new buckets
+    for (std::vector<std::set<int> >::iterator it = vvNew.begin(); it != vvNew.end(); it++)
+    {
+        if ((*it).erase(nId))
+            info.nRefCount--;
+    }
+    nNew--;
+
+    assert(info.nRefCount == 0);
+
+    // what tried bucket to move the entry to
+    int nKBucket = info.GetTriedBucket(nKey);
+    std::vector<int> &vTried = vvTried[nKBucket];
+
+    // first check whether there is place to just add it
+    if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE)
+    {
+        vTried.push_back(nId);
+        nTried++;
+        info.fInTried = true;
+        return;
+    }
+
+    // otherwise, find an item to evict
+    int nPos = SelectTried(nKBucket);
+
+    // find which new bucket it belongs to
+    assert(mapInfo.count(vTried[nPos]) == 1);
+    int nUBucket = mapInfo[vTried[nPos]].GetNewBucket(nKey);
+    std::set<int> &vNew = vvNew[nUBucket];
+
+    // remove the to-be-replaced tried entry from the tried set
+    CAddrInfo& infoOld = mapInfo[vTried[nPos]];
+    infoOld.fInTried = false;
+    infoOld.nRefCount = 1;
+    // do not update nTried, as we are going to move something else there immediately
+
+    // check whether there is place in that one,
+    if (vNew.size() < ADDRMAN_NEW_BUCKET_SIZE)
+    {
+        // if so, move it back there
+        vNew.insert(vTried[nPos]);
+    } else {
+        // otherwise, move it to the new bucket nId came from (there is certainly place there)
+        vvNew[nOrigin].insert(vTried[nPos]);
+    }
+    nNew++;
+
+    vTried[nPos] = nId;
+    // we just overwrote an entry in vTried; no need to update nTried
+    info.fInTried = true;
+    return;
+}
+
+void CAddrMan::Good_(const CService &addr, int64 nTime)
+{
+//    printf("Good: addr=%s\n", addr.ToString().c_str());
+
+    int nId;
+    CAddrInfo *pinfo = Find(addr, &nId);
+
+    // if not found, bail out
+    if (!pinfo)
+        return;
+
+    CAddrInfo &info = *pinfo;
+
+    // check whether we are talking about the exact same CService (including same port)
+    if (info != addr)
+        return;
+
+    // update info
+    info.nLastSuccess = nTime;
+    info.nLastTry = nTime;
+    info.nTime = nTime;
+    info.nAttempts = 0;
+
+    // if it is already in the tried set, don't do anything else
+    if (info.fInTried)
+        return;
+
+    // find a bucket it is in now
+    int nRnd = GetRandInt(vvNew.size());
+    int nUBucket = -1;
+    for (unsigned int n = 0; n < vvNew.size(); n++)
+    {
+        int nB = (n+nRnd) % vvNew.size();
+        std::set<int> &vNew = vvNew[nB];
+        if (vNew.count(nId))
+        {
+            nUBucket = nB;
+            break;
+        }
+    }
+
+    // if no bucket is found, something bad happened;
+    // TODO: maybe re-add the node, but for now, just bail out
+    if (nUBucket == -1) return;
+
+    printf("Moving %s to tried\n", addr.ToString().c_str());
+
+    // move nId to the tried tables
+    MakeTried(info, nId, nUBucket);
+}
+
+bool CAddrMan::Add_(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty)
+{
+    if (!addr.IsRoutable())
+        return false;
+
+    bool fNew = false;
+    int nId;
+    CAddrInfo *pinfo = Find(addr, &nId);
+
+    if (pinfo)
+    {
+        // periodically update nTime
+        bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
+        int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
+        if (addr.nTime && (!pinfo->nTime || pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty))
+            pinfo->nTime = max((int64)0, addr.nTime - nTimePenalty);
+
+        // add services
+        pinfo->nServices |= addr.nServices;
+
+        // do not update if no new information is present
+        if (!addr.nTime || (pinfo->nTime && addr.nTime <= pinfo->nTime))
+            return false;
+
+        // do not update if the entry was already in the "tried" table
+        if (pinfo->fInTried)
+            return false;
+
+        // do not update if the max reference count is reached
+        if (pinfo->nRefCount == ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
+            return false;
+
+        // stochastic test: previous nRefCount == N: 2^N times harder to increase it
+        int nFactor = 1;
+        for (int n=0; n<pinfo->nRefCount; n++)
+            nFactor *= 2;
+        if (nFactor > 1 && (GetRandInt(nFactor) != 0))
+            return false;
+    } else {
+        pinfo = Create(addr, source, &nId);
+        pinfo->nTime = max((int64)0, (int64)pinfo->nTime - nTimePenalty);
+//        printf("Added %s [nTime=%fhr]\n", pinfo->ToString().c_str(), (GetAdjustedTime() - pinfo->nTime) / 3600.0);
+        nNew++;
+        fNew = true;
+    }
+
+    int nUBucket = pinfo->GetNewBucket(nKey, source);
+    std::set<int> &vNew = vvNew[nUBucket];
+    if (!vNew.count(nId))
+    {
+        pinfo->nRefCount++;
+        if (vNew.size() == ADDRMAN_NEW_BUCKET_SIZE)
+            ShrinkNew(nUBucket);
+        vvNew[nUBucket].insert(nId);
+    }
+    return fNew;
+}
+
+void CAddrMan::Attempt_(const CService &addr, int64 nTime)
+{
+    CAddrInfo *pinfo = Find(addr);
+
+    // if not found, bail out
+    if (!pinfo)
+        return;
+
+    CAddrInfo &info = *pinfo;
+
+    // check whether we are talking about the exact same CService (including same port)
+    if (info != addr)
+        return;
+
+    // update info
+    info.nLastTry = nTime;
+    info.nAttempts++;
+}
+
+CAddress CAddrMan::Select_(int nUnkBias)
+{
+    if (size() == 0)
+        return CAddress();
+
+    double nCorTried = sqrt(nTried) * (100.0 - nUnkBias);
+    double nCorNew = sqrt(nNew) * nUnkBias;
+    if ((nCorTried + nCorNew)*GetRandInt(1<<30)/(1<<30) < nCorTried)
+    {
+        // use a tried node
+        double fChanceFactor = 1.0;
+        while(1)
+        {
+            int nKBucket = GetRandInt(vvTried.size());
+            std::vector<int> &vTried = vvTried[nKBucket];
+            if (vTried.size() == 0) continue;
+            int nPos = GetRandInt(vTried.size());
+            assert(mapInfo.count(vTried[nPos]) == 1);
+            CAddrInfo &info = mapInfo[vTried[nPos]];
+            if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
+                return info;
+            fChanceFactor *= 1.2;
+        }
+    } else {
+        // use a new node
+        double fChanceFactor = 1.0;
+        while(1)
+        {
+            int nUBucket = GetRandInt(vvNew.size());
+            std::set<int> &vNew = vvNew[nUBucket];
+            if (vNew.size() == 0) continue;
+            int nPos = GetRandInt(vNew.size());
+            std::set<int>::iterator it = vNew.begin();
+            while (nPos--)
+                it++;
+            assert(mapInfo.count(*it) == 1);
+            CAddrInfo &info = mapInfo[*it];
+            if (GetRandInt(1<<30) < fChanceFactor*info.GetChance()*(1<<30))
+                return info;
+            fChanceFactor *= 1.2;
+        }
+    }
+}
+
+#ifdef DEBUG_ADDRMAN
+int CAddrMan::Check_()
+{
+    std::set<int> setTried;
+    std::map<int, int> mapNew;
+
+    if (vRandom.size() != nTried + nNew) return -7;
+
+    for (std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++)
+    {
+        int n = (*it).first;
+        CAddrInfo &info = (*it).second;
+        if (info.fInTried)
+        {
+
+            if (!info.nLastSuccess) return -1;
+            if (info.nRefCount) return -2;
+            setTried.insert(n);
+        } else {
+            if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS) return -3;
+            if (!info.nRefCount) return -4;
+            mapNew[n] = info.nRefCount;
+        }
+        if (mapAddr[info] != n) return -5;
+        if (info.nRandomPos<0 || info.nRandomPos>=vRandom.size() || vRandom[info.nRandomPos] != n) return -14;
+        if (info.nLastTry < 0) return -6;
+        if (info.nLastSuccess < 0) return -8;
+    }
+
+    if (setTried.size() != nTried) return -9;
+    if (mapNew.size() != nNew) return -10;
+
+    for (int n=0; n<vvTried.size(); n++)
+    {
+        std::vector<int> &vTried = vvTried[n];
+        for (std::vector<int>::iterator it = vTried.begin(); it != vTried.end(); it++)
+        {
+            if (!setTried.count(*it)) return -11;
+            setTried.erase(*it);
+        }
+    }
+
+    for (int n=0; n<vvNew.size(); n++)
+    {
+        std::set<int> &vNew = vvNew[n];
+        for (std::set<int>::iterator it = vNew.begin(); it != vNew.end(); it++)
+        {
+            if (!mapNew.count(*it)) return -12;
+            if (--mapNew[*it] == 0)
+                mapNew.erase(*it);
+        }
+    }
+
+    if (setTried.size()) return -13;
+    if (mapNew.size()) return -15;
+
+    return 0;
+}
+#endif
+
+void CAddrMan::GetAddr_(std::vector<CAddress> &vAddr)
+{
+    int nNodes = ADDRMAN_GETADDR_MAX_PCT*vRandom.size()/100;
+    if (nNodes > ADDRMAN_GETADDR_MAX)
+        nNodes = ADDRMAN_GETADDR_MAX;
+
+    // perform a random shuffle over the first nNodes elements of vRandom (selecting from all)
+    for (int n = 0; n<nNodes; n++)
+    {
+        int nRndPos = GetRandInt(vRandom.size() - n) + n;
+        SwapRandom(n, nRndPos);
+        assert(mapInfo.count(vRandom[n]) == 1);
+        vAddr.push_back(mapInfo[vRandom[n]]);
+    }
+}
+
+void CAddrMan::Connected_(const CService &addr, int64 nTime)
+{
+    CAddrInfo *pinfo = Find(addr);
+
+    // if not found, bail out
+    if (!pinfo)
+        return;
+
+    CAddrInfo &info = *pinfo;
+
+    // check whether we are talking about the exact same CService (including same port)
+    if (info != addr)
+        return;
+
+    // update info
+    int64 nUpdateInterval = 20 * 60;
+    if (nTime - info.nTime > nUpdateInterval)
+        info.nTime = nTime;
+}

+ 449 - 0
ecoin/src/addrman.h

@@ -0,0 +1,449 @@
+// ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+#ifndef _ECOIN_ADDRMAN
+#define _ECOIN_ADDRMAN 1
+
+#include "netbase.h"
+#include "protocol.h"
+#include "util.h"
+#include "sync.h"
+#include <map>
+#include <vector>
+#include <openssl/rand.h>
+
+/** Extended statistics about a CAddress */
+class CAddrInfo : public CAddress
+{
+private:
+    // where knowledge about this address first came from
+    CNetAddr source;
+
+    // last successful connection by us
+    int64 nLastSuccess;
+
+    // last try whatsoever by us:
+    // int64 CAddress::nLastTry
+
+    // connection attempts since last successful attempt
+    int nAttempts;
+
+    // reference count in new sets (memory only)
+    int nRefCount;
+
+    // in tried set? (memory only)
+    bool fInTried;
+
+    // position in vRandom
+    int nRandomPos;
+
+    friend class CAddrMan;
+
+public:
+
+    IMPLEMENT_SERIALIZE(
+        CAddress* pthis = (CAddress*)(this);
+        READWRITE(*pthis);
+        READWRITE(source);
+        READWRITE(nLastSuccess);
+        READWRITE(nAttempts);
+    )
+
+    void Init()
+    {
+        nLastSuccess = 0;
+        nLastTry = 0;
+        nAttempts = 0;
+        nRefCount = 0;
+        fInTried = false;
+        nRandomPos = -1;
+    }
+
+    CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
+    {
+        Init();
+    }
+
+    CAddrInfo() : CAddress(), source()
+    {
+        Init();
+    }
+
+    // Calculate in which "tried" bucket this entry belongs
+    int GetTriedBucket(const std::vector<unsigned char> &nKey) const;
+
+    // Calculate in which "new" bucket this entry belongs, given a certain source
+    int GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const;
+
+    // Calculate in which "new" bucket this entry belongs, using its default source
+    int GetNewBucket(const std::vector<unsigned char> &nKey) const
+    {
+        return GetNewBucket(nKey, source);
+    }
+
+    // Determine whether the statistics about this entry are bad enough so that it can just be deleted
+    bool IsTerrible(int64 nNow = GetAdjustedTime()) const;
+
+    // Calculate the relative chance this entry should be given when selecting nodes to connect to
+    double GetChance(int64 nNow = GetAdjustedTime()) const;
+
+};
+
+// total number of buckets for tried addresses
+#define ADDRMAN_TRIED_BUCKET_COUNT 64
+
+// maximum allowed number of entries in buckets for tried addresses
+#define ADDRMAN_TRIED_BUCKET_SIZE 64
+
+// total number of buckets for new addresses
+#define ADDRMAN_NEW_BUCKET_COUNT 256
+
+// maximum allowed number of entries in buckets for new addresses
+#define ADDRMAN_NEW_BUCKET_SIZE 64
+
+// over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread
+#define ADDRMAN_TRIED_BUCKETS_PER_GROUP 4
+
+// over how many buckets entries with new addresses originating from a single group are spread
+#define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 32
+
+// in how many buckets for entries with new addresses a single address may occur
+#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 4
+
+// how many entries in a bucket with tried addresses are inspected, when selecting one to replace
+#define ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT 4
+
+// how old addresses can maximally be
+#define ADDRMAN_HORIZON_DAYS 30
+
+// after how many failed attempts we give up on a new node
+#define ADDRMAN_RETRIES 3
+
+// how many successive failures are allowed ...
+#define ADDRMAN_MAX_FAILURES 10
+
+// ... in at least this many days
+#define ADDRMAN_MIN_FAIL_DAYS 7
+
+// the maximum percentage of nodes to return in a getaddr call
+#define ADDRMAN_GETADDR_MAX_PCT 23
+
+// the maximum number of nodes to return in a getaddr call
+#define ADDRMAN_GETADDR_MAX 2500
+
+/** Stochastical (IP) address manager */
+class CAddrMan
+{
+private:
+    // critical section to protect the inner data structures
+    mutable CCriticalSection cs;
+
+    // secret key to randomize bucket select with
+    std::vector<unsigned char> nKey;
+
+    // last used nId
+    int nIdCount;
+
+    // table with information about all nIds
+    std::map<int, CAddrInfo> mapInfo;
+
+    // find an nId based on its network address
+    std::map<CNetAddr, int> mapAddr;
+
+    // randomly-ordered vector of all nIds
+    std::vector<int> vRandom;
+
+    // number of "tried" entries
+    int nTried;
+
+    // list of "tried" buckets
+    std::vector<std::vector<int> > vvTried;
+
+    // number of (unique) "new" entries
+    int nNew;
+
+    // list of "new" buckets
+    std::vector<std::set<int> > vvNew;
+
+protected:
+    // Find an entry.
+    CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL);
+
+    // find an entry, creating it if necessary.
+    // nTime and nServices of found node is updated, if necessary.
+    CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = NULL);
+
+    // Swap two elements in vRandom.
+    void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2);
+
+    // Return position in given bucket to replace.
+    int SelectTried(int nKBucket);
+
+    // Remove an element from a "new" bucket.
+    // This is the only place where actual deletes occur.
+    // They are never deleted while in the "tried" table, only possibly evicted back to the "new" table.
+    int ShrinkNew(int nUBucket);
+
+    // Move an entry from the "new" table(s) to the "tried" table
+    // @pre vvUnkown[nOrigin].count(nId) != 0
+    void MakeTried(CAddrInfo& info, int nId, int nOrigin);
+
+    // Mark an entry "good", possibly moving it from "new" to "tried".
+    void Good_(const CService &addr, int64 nTime);
+
+    // Add an entry to the "new" table.
+    bool Add_(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty);
+
+    // Mark an entry as attempted to connect.
+    void Attempt_(const CService &addr, int64 nTime);
+
+    // Select an address to connect to.
+    // nUnkBias determines how much to favor new addresses over tried ones (min=0, max=100)
+    CAddress Select_(int nUnkBias);
+
+#ifdef DEBUG_ADDRMAN
+    // Perform consistency check. Returns an error code or zero.
+    int Check_();
+#endif
+
+    // Select several addresses at once.
+    void GetAddr_(std::vector<CAddress> &vAddr);
+
+    // Mark an entry as currently-connected-to.
+    void Connected_(const CService &addr, int64 nTime);
+
+public:
+    IMPLEMENT_SERIALIZE
+    (({
+        {
+            LOCK(cs);
+            unsigned char nVersion = 0;
+            READWRITE(nVersion);
+            READWRITE(nKey);
+            READWRITE(nNew);
+            READWRITE(nTried);
+
+            CAddrMan *am = const_cast<CAddrMan*>(this);
+            if (fWrite)
+            {
+                int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT;
+                READWRITE(nUBuckets);
+                std::map<int, int> mapUnkIds;
+                int nIds = 0;
+                for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
+                {
+                    if (nIds == nNew) break; // this means nNew was wrong, oh ow
+                    mapUnkIds[(*it).first] = nIds;
+                    CAddrInfo &info = (*it).second;
+                    if (info.nRefCount)
+                    {
+                        READWRITE(info);
+                        nIds++;
+                    }
+                }
+                nIds = 0;
+                for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
+                {
+                    if (nIds == nTried) break; // this means nTried was wrong, oh ow
+                    CAddrInfo &info = (*it).second;
+                    if (info.fInTried)
+                    {
+                        READWRITE(info);
+                        nIds++;
+                    }
+                }
+                for (std::vector<std::set<int> >::iterator it = am->vvNew.begin(); it != am->vvNew.end(); it++)
+                {
+                    const std::set<int> &vNew = (*it);
+                    int nSize = vNew.size();
+                    READWRITE(nSize);
+                    for (std::set<int>::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++)
+                    {
+                        int nIndex = mapUnkIds[*it2];
+                        READWRITE(nIndex);
+                    }
+                }
+            } else {
+                int nUBuckets = 0;
+                READWRITE(nUBuckets);
+                am->nIdCount = 0;
+                am->mapInfo.clear();
+                am->mapAddr.clear();
+                am->vRandom.clear();
+                am->vvTried = std::vector<std::vector<int> >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0));
+                am->vvNew = std::vector<std::set<int> >(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>());
+                for (int n = 0; n < am->nNew; n++)
+                {
+                    CAddrInfo &info = am->mapInfo[n];
+                    READWRITE(info);
+                    am->mapAddr[info] = n;
+                    info.nRandomPos = vRandom.size();
+                    am->vRandom.push_back(n);
+                    if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
+                    {
+                        am->vvNew[info.GetNewBucket(am->nKey)].insert(n);
+                        info.nRefCount++;
+                    }
+                }
+                am->nIdCount = am->nNew;
+                int nLost = 0;
+                for (int n = 0; n < am->nTried; n++)
+                {
+                    CAddrInfo info;
+                    READWRITE(info);
+                    std::vector<int> &vTried = am->vvTried[info.GetTriedBucket(am->nKey)];
+                    if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE)
+                    {
+                        info.nRandomPos = vRandom.size();
+                        info.fInTried = true;
+                        am->vRandom.push_back(am->nIdCount);
+                        am->mapInfo[am->nIdCount] = info;
+                        am->mapAddr[info] = am->nIdCount;
+                        vTried.push_back(am->nIdCount);
+                        am->nIdCount++;
+                    } else {
+                        nLost++;
+                    }
+                }
+                am->nTried -= nLost;
+                for (int b = 0; b < nUBuckets; b++)
+                {
+                    std::set<int> &vNew = am->vvNew[b];
+                    int nSize = 0;
+                    READWRITE(nSize);
+                    for (int n = 0; n < nSize; n++)
+                    {
+                        int nIndex = 0;
+                        READWRITE(nIndex);
+                        CAddrInfo &info = am->mapInfo[nIndex];
+                        if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
+                        {
+                            info.nRefCount++;
+                            vNew.insert(nIndex);
+                        }
+                    }
+                }
+            }
+        }
+    });)
+
+    CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>())
+    {
+         nKey.resize(32);
+         RAND_bytes(&nKey[0], 32);
+
+         nIdCount = 0;
+         nTried = 0;
+         nNew = 0;
+    }
+
+    // Return the number of (unique) addresses in all tables.
+    int size()
+    {
+        return vRandom.size();
+    }
+
+    // Consistency check
+    void Check()
+    {
+#ifdef DEBUG_ADDRMAN
+        {
+            LOCK(cs);
+            int err;
+            if ((err=Check_()))
+                printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
+        }
+#endif
+    }
+
+    // Add a single address.
+    bool Add(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty = 0)
+    {
+        bool fRet = false;
+        {
+            LOCK(cs);
+            Check();
+            fRet |= Add_(addr, source, nTimePenalty);
+            Check();
+        }
+        if (fRet)
+            printf("Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString().c_str(), nTried, nNew);
+        return fRet;
+    }
+
+    // Add multiple addresses.
+    bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64 nTimePenalty = 0)
+    {
+        int nAdd = 0;
+        {
+            LOCK(cs);
+            Check();
+            for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
+                nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
+            Check();
+        }
+        if (nAdd)
+            printf("Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString().c_str(), nTried, nNew);
+        return nAdd > 0;
+    }
+
+    // Mark an entry as accessible.
+    void Good(const CService &addr, int64 nTime = GetAdjustedTime())
+    {
+        {
+            LOCK(cs);
+            Check();
+            Good_(addr, nTime);
+            Check();
+        }
+    }
+
+    // Mark an entry as connection attempted to.
+    void Attempt(const CService &addr, int64 nTime = GetAdjustedTime())
+    {
+        {
+            LOCK(cs);
+            Check();
+            Attempt_(addr, nTime);
+            Check();
+        }
+    }
+
+    // Choose an address to connect to.
+    // nUnkBias determines how much "new" entries are favored over "tried" ones (0-100).
+    CAddress Select(int nUnkBias = 50)
+    {
+        CAddress addrRet;
+        {
+            LOCK(cs);
+            Check();
+            addrRet = Select_(nUnkBias);
+            Check();
+        }
+        return addrRet;
+    }
+
+    // Return a bunch of addresses, selected at random.
+    std::vector<CAddress> GetAddr()
+    {
+        Check();
+        std::vector<CAddress> vAddr;
+        {
+            LOCK(cs);
+            GetAddr_(vAddr);
+        }
+        Check();
+        return vAddr;
+    }
+
+    // Mark an entry as currently-connected-to.
+    void Connected(const CService &addr, int64 nTime = GetAdjustedTime())
+    {
+        {
+            LOCK(cs);
+            Check();
+            Connected_(addr, nTime);
+            Check();
+        }
+    }
+};
+
+#endif

+ 228 - 0
ecoin/src/alert.cpp

@@ -0,0 +1,228 @@
+// ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
+
+#include <boost/foreach.hpp>
+#include <map>
+#include "alert.h"