├── .gitignore ├── LICENSE ├── README.md ├── backtest-mt ├── backtest-mt.pro ├── main.cpp ├── simulationthread.cpp ├── simulationthread.h ├── tester.cpp └── tester.h ├── blake2b ├── COPYING ├── README.md └── sse │ ├── blake2-config.h │ ├── blake2-impl.h │ ├── blake2.h │ ├── blake2b-load-sse2.h │ ├── blake2b-round.h │ └── blake2b.c ├── candlestick-puller ├── README.md ├── candlestick-puller.pro ├── main.cpp ├── puller.cpp └── puller.h ├── cli ├── commandcaller.cpp ├── commandcaller.h ├── main.cpp └── trader-cli.pro ├── daemon ├── alphatracker.cpp ├── alphatracker.h ├── baserest.cpp ├── baserest.h ├── bncrest.cpp ├── bncrest.h ├── build-config.h ├── coinamount.cpp ├── coinamount.h ├── coinamount_test.cpp ├── coinamount_test.h ├── commandlistener.cpp ├── commandlistener.h ├── commandrunner.cpp ├── commandrunner.h ├── diffusionphaseman.cpp ├── diffusionphaseman.h ├── diffusionphaseman_test.cpp ├── diffusionphaseman_test.h ├── engine.cpp ├── engine.h ├── engine_test.cpp ├── engine_test.h ├── enginemap.h ├── enginesettings.h ├── fallbacklistener.cpp ├── fallbacklistener.h ├── global.h ├── keydefs.h.example ├── keystore.h ├── main.cpp ├── market.cpp ├── market.h ├── misctypes.h ├── polorest.cpp ├── polorest.h ├── position.cpp ├── position.h ├── positiondata.h ├── positionman.cpp ├── positionman.h ├── priceaggregator.cpp ├── priceaggregator.h ├── pricesignal.cpp ├── pricesignal.h ├── pricesignal_test.cpp ├── pricesignal_test.h ├── spruceoverseer.cpp ├── spruceoverseer.h ├── spruceoverseer_test.cpp ├── spruceoverseer_test.h ├── sprucev2.cpp ├── sprucev2.h ├── ssl_policy.h ├── trader.cpp ├── trader.h ├── traderd.pro ├── trexrest.cpp ├── trexrest.h ├── wavesaccount.cpp ├── wavesaccount.h ├── wavesaccount_test.cpp ├── wavesaccount_test.h ├── wavesrest.cpp ├── wavesrest.h ├── wavesutil.cpp ├── wavesutil.h ├── wavesutil_test.cpp └── wavesutil_test.h ├── doc └── commands.md ├── generate_keys.py ├── gettotallines.sh ├── libbase58 ├── AUTHORS ├── COPYING ├── README.md ├── base58.c └── libbase58.h ├── libcurve25519-donna ├── additions │ ├── compare.c │ ├── compare.h │ ├── crypto_additions.h │ ├── crypto_hash_sha512.h │ ├── curve_sigs.c │ ├── curve_sigs.h │ ├── fe_montx_to_edy.c │ ├── ge_p3_to_montx.c │ ├── keygen.c │ ├── keygen.h │ ├── open_modified.c │ ├── sign_modified.c │ ├── zeroize.c │ └── zeroize.h ├── base.h ├── base2.h ├── d.h ├── d2.h ├── fe.h ├── fe_0.c ├── fe_1.c ├── fe_add.c ├── fe_cmov.c ├── fe_copy.c ├── fe_frombytes.c ├── fe_invert.c ├── fe_isnegative.c ├── fe_isnonzero.c ├── fe_mul.c ├── fe_neg.c ├── fe_pow22523.c ├── fe_sq.c ├── fe_sq2.c ├── fe_sub.c ├── fe_tobytes.c ├── ge.h ├── ge_add.c ├── ge_add.h ├── ge_double_scalarmult.c ├── ge_frombytes.c ├── ge_madd.c ├── ge_madd.h ├── ge_msub.c ├── ge_msub.h ├── ge_p1p1_to_p2.c ├── ge_p1p1_to_p3.c ├── ge_p2_0.c ├── ge_p2_dbl.c ├── ge_p2_dbl.h ├── ge_p3_0.c ├── ge_p3_dbl.c ├── ge_p3_to_cached.c ├── ge_p3_to_p2.c ├── ge_p3_tobytes.c ├── ge_precomp_0.c ├── ge_scalarmult_base.c ├── ge_sub.c ├── ge_sub.h ├── ge_tobytes.c ├── nacl_includes │ ├── crypto_int32.h │ ├── crypto_int64.h │ ├── crypto_sign.h │ ├── crypto_sign_edwards25519sha512batch.h │ ├── crypto_uint32.h │ ├── crypto_uint64.h │ └── crypto_verify_32.h ├── nacl_sha512 │ ├── blocks.c │ └── hash.c ├── pow22523.h ├── pow225521.h ├── sc.h ├── sc_muladd.c ├── sc_reduce.c └── sqrtm1.h ├── qbase58 ├── qbase58.cpp ├── qbase58.h ├── qbase58_test.cpp └── qbase58_test.h └── trader.pro /.gitignore: -------------------------------------------------------------------------------- 1 | traderd 2 | trader-cli 3 | 4 | Makefile* 5 | .qmake.stash 6 | *.pro.user 7 | 8 | build-tmp/ 9 | daemon/traderd_plugin_import.cpp 10 | cli/trader-cli_plugin_import.cpp 11 | 12 | daemon/keydefs.h 13 | daemon/keydefs_mine.h 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright © 2019 tryphe 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /backtest-mt/backtest-mt.pro: -------------------------------------------------------------------------------- 1 | QT = core network 2 | 3 | QMAKE_CXXFLAGS = -O3 4 | QMAKE_CFLAGS = -O3 5 | 6 | CONFIG += c++14 c++17 7 | CONFIG += release 8 | #CONFIG += debug 9 | 10 | LIBS += -lgmp 11 | 12 | TARGET = backtest-mt 13 | TEMPLATE = app 14 | 15 | SOURCES += main.cpp \ 16 | ../daemon/alphatracker.cpp \ 17 | ../daemon/coinamount.cpp \ 18 | ../daemon/coinamount_test.cpp \ 19 | ../daemon/market.cpp \ 20 | ../daemon/position.cpp \ 21 | ../daemon/pricesignal.cpp \ 22 | ../daemon/pricesignal_test.cpp \ 23 | ../daemon/sprucev2.cpp \ 24 | ../daemon/priceaggregator.cpp \ 25 | ../libbase58/base58.c \ 26 | ../qbase58/qbase58.cpp \ 27 | ../qbase58/qbase58_test.cpp \ 28 | simulationthread.cpp \ 29 | tester.cpp 30 | 31 | HEADERS += \ 32 | ../daemon/build-config.h \ 33 | ../daemon/global.h \ 34 | ../daemon/alphatracker.h \ 35 | ../daemon/coinamount.h \ 36 | ../daemon/coinamount_test.h \ 37 | ../daemon/market.h \ 38 | ../daemon/position.h \ 39 | ../daemon/pricesignal.h \ 40 | ../daemon/pricesignal_test.h \ 41 | ../daemon/sprucev2.h \ 42 | ../daemon/priceaggregator.h \ 43 | ../daemon/misctypes.h \ 44 | ../libbase58/libbase58.h \ 45 | ../qbase58/qbase58.h \ 46 | ../qbase58/qbase58_test.h \ 47 | simulationthread.h \ 48 | tester.h 49 | -------------------------------------------------------------------------------- /backtest-mt/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tester.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | //qInstallMessageHandler( messageOutput ); 8 | QCoreApplication a(argc, argv); 9 | 10 | Tester *t = new Tester(); Q_UNUSED( t ) 11 | 12 | return a.exec(); 13 | } 14 | -------------------------------------------------------------------------------- /backtest-mt/simulationthread.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMULATIONTHREAD_H 2 | #define SIMULATIONTHREAD_H 3 | 4 | #include "../daemon/coinamount.h" 5 | #include "../daemon/market.h" 6 | #include "../daemon/misctypes.h" 7 | #include "../daemon/priceaggregator.h" 8 | #include "../daemon/pricesignal.h" 9 | #include "../daemon/sprucev2.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | struct SignalContainer 20 | { 21 | ~SignalContainer() { } 22 | 23 | void initSignals( const int signal_count ); 24 | bool isStrategyInitialized(); 25 | 26 | PriceSignal price_signal; 27 | QVector price_signal_cache; 28 | QVector strategy_signals; 29 | qint64 current_idx{ 0 }; 30 | }; 31 | 32 | struct StrategyArgs 33 | { 34 | StrategyArgs() {} 35 | StrategyArgs( const PriceSignalType _type, const int _fast, const int _slow, const Coin &_weight ) 36 | : type( _type ), 37 | length_fast( _fast ), 38 | length_slow( _slow ), 39 | weight( _weight ) 40 | {} 41 | 42 | PriceSignalType type{ SMA }; 43 | 44 | quint16 length_fast{ 0 }, length_slow{ 0 }; 45 | Coin weight{ CoinAmount::COIN }; 46 | 47 | bool isEqualExcludingWeights( const StrategyArgs &other ) const 48 | { 49 | return length_fast == other.length_fast && 50 | length_slow == other.length_slow && 51 | type == other.type; 52 | } 53 | 54 | bool operator == ( const StrategyArgs &other ) const 55 | { 56 | return length_fast == other.length_fast && 57 | length_slow == other.length_slow && 58 | type == other.type && 59 | weight == other.weight; 60 | } 61 | 62 | operator QString() const { return QString( "%1/%2/%3/%4" ) 63 | .arg( type ) 64 | .arg( length_fast ) 65 | .arg( length_slow ) 66 | .arg( weight.toCompact() ); } 67 | }; 68 | 69 | struct SimulationTask 70 | { 71 | QByteArray &getUniqueID(); 72 | 73 | void addStrategyArgs( const StrategyArgs &new_args ) { m_strategy_args += new_args; } 74 | 75 | // general options 76 | QVector> m_markets_tested; 77 | 78 | QVector m_strategy_args; 79 | quint8 m_allocation_func{ 0 }; 80 | 81 | // results 82 | QString m_simulation_result; 83 | QString m_alpha_readout; 84 | QVector m_scores; 85 | 86 | // cached raw bytes of the options, for getRaw() 87 | QByteArray m_unique_id; 88 | }; 89 | 90 | class SimulationThread : public QThread 91 | { 92 | Q_OBJECT 93 | 94 | public: 95 | explicit SimulationThread( const int id = 0 ); 96 | ~SimulationThread(); 97 | 98 | int m_id; 99 | 100 | // price data pointers 101 | QVector*> m_price_data; 102 | 103 | // current task 104 | SimulationTask *m_work; 105 | 106 | // external pointers 107 | QMutex *ext_mutex{ nullptr }; 108 | QVector *ext_threads; 109 | QVector *ext_work_done{ nullptr }, *ext_work_queued{ nullptr }; 110 | int *ext_work_count_total, *ext_work_count_done, *ext_work_count_started; 111 | 112 | private: 113 | void run() override; 114 | void runSimulation( const QMap *const &price_data ); 115 | 116 | QString m_signals_str; 117 | QVector m_signals; 118 | PriceSignal m_base_capital_sma0; 119 | SpruceV2 sp; 120 | Coin initial_btc_value, highest_btc_value, simulation_cutoff_value, total_volume; 121 | qint64 m_latest_ts, m_latest_ts_price_cache; 122 | }; 123 | 124 | #endif // SIMULATIONTHREAD_H 125 | -------------------------------------------------------------------------------- /backtest-mt/tester.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTER_H 2 | #define TESTER_H 3 | 4 | #include "../daemon/coinamount.h" 5 | #include "../daemon/market.h" 6 | #include "../daemon/priceaggregator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | class QTimer; 16 | class SimulationThread; 17 | class SimulationTask; 18 | 19 | class Tester : public QObject 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | //#define OUTPUT_BASE_CAPITAL 25 | //#define OUTPUT_SIMULATION_TIME 26 | //#define OUTPUT_TOTAL_RUNTIME 27 | //#define OUTPUT_SIMULATION_CUTOFF_WARNING 28 | //#define PRICE_SIGNAL_CACHED_DEF 29 | //#define REPAIR_INDEX_FRAGMENTATION 30 | 31 | static const bool USE_CANDLES_FROM_THIS_DIRECTORY = false; // note: true for realtime, false for backtest 32 | static const bool OUTPUT_QTY_TARGETS = false; // note: true for realtime, false for backtest 33 | 34 | static const int MAX_WORKERS = 7; 35 | static const int MARKET_VARIATIONS = 1; 36 | static const bool USE_SAVED_WORK = true; 37 | static const int BASE_INTERVAL = 100; // note: when base interval is 100, signal interval is 1, and vice versa 38 | static const int CANDLE_INTERVAL_SECS = 300; 39 | static const int ACTUAL_CANDLE_INTERVAL_SECS = CANDLE_INTERVAL_SECS * BASE_INTERVAL; 40 | static const int RELATIVE_SATS_TRADED_PER_BASE_INTERVAL = 50000; // note: 50000 for both 41 | static const int PRICE_SIGNAL_LENGTH = 15; // note: 1 for realtime, 15 for backtest 42 | static const int PRICE_SIGNAL_BIAS = 5; // note: -1 for realtime, 5 for backtest 43 | static const int FEE_DIV = 10000; // every ~2 trades, incur a penalty of base_capital/FEE_DIV on our position 44 | 45 | static const bool WORK_RANDOM = true; 46 | static const int WORK_RANDOM_TRIES_MAX = 1000000; 47 | static const bool WORK_INFINITE = true; // regenerate work each RESULTS_OUTPUT_INTERVAL_SECS 48 | static const int WORK_UNITS_BUFFER = 20000; 49 | static const int WORK_SAMPLES_START_OFFSET = 0; 50 | static const bool WORK_SAMPLES_BASE_LEVELER = true; // level the base samples so our latest 5min candle is always used in the current getSignal 51 | static const bool WORK_PREVENT_RETRY = true; // false = save ram, true = use ram to prevent retry 52 | 53 | static const int RESULTS_HIGH_SCORE_COUNT = 50; // print x best results 54 | static const int RESULTS_OUTPUT_INTERVAL_SECS = 300; // print and process results every x ms 55 | static const int RESULTS_OUTPUT_THREAD_SECS = 30; // 0 = print per-thread message every work unit start, >0 = output only every n secs 56 | static const bool RESULTS_OUTPUT_NEWLY_FINISHED = false; 57 | static const bool RESULTS_EVICT_ZERO_SCORE = true; // if any score is zero, evict from results map to save resources 58 | static const bool RESULTS_EVICT_NON_HIGH_SCORE = true; // evict result if not a high score, saves disk/ram 59 | 60 | explicit Tester(); 61 | ~Tester(); 62 | 63 | void loadPriceDataSingle( const QString &file_name, const Market &market ); 64 | void loadPriceData(); 65 | void reindexPriceData( PriceData &data, const int interval ); 66 | 67 | void fillRandomWorkQueue(); 68 | void generateWork(); 69 | void generateRandomWork(); 70 | void generateWorkFromResultString( const QString &construct ); 71 | void startWork(); 72 | void processFinishedWork(); 73 | 74 | void printHighScores( const QMultiMap &scores, QTextStream &out, QString description, const int print_count = RESULTS_HIGH_SCORE_COUNT ); 75 | void trimHighScores( QMultiMap &scores, QMap &scores_by_result ); 76 | 77 | void saveFinishedWork(); 78 | void loadFinishedWork(); 79 | 80 | public Q_SLOTS: 81 | void onWorkTimer(); 82 | void onThreadFinished(); 83 | 84 | private: 85 | QMap> m_highscores_by_score; // for each score type, store kv 86 | QMap> m_highscores_by_result; // for each score type, store kv 87 | 88 | // price data 89 | QVector> m_price_data_0;//, m_price_data_1; 90 | 91 | // work data 92 | QMutex m_work_mutex; 93 | int m_work_count_total{ 0 }, m_work_count_done{ 0 }, m_work_count_started{ 0 }; 94 | QVector m_work_queued, m_work_done; 95 | QTimer *m_work_timer{ nullptr }; 96 | 97 | // threads 98 | QVector m_threads; 99 | 100 | // work data, but not accessed by threads 101 | QSet m_work_ids_generated_or_done; 102 | QMap m_work_results_unsaved; 103 | 104 | // stats 105 | int m_work_skipped_duplicate{ 0 }; 106 | qint64 m_start_time{ 0 }; 107 | }; 108 | 109 | #endif // TESTER_H 110 | -------------------------------------------------------------------------------- /blake2b/README.md: -------------------------------------------------------------------------------- 1 | # BLAKE2 2 | 3 | This is the reference source code package of BLAKE2, which includes 4 | 5 | * `ref/`: C implementations of BLAKE2b, BLAKE2bp, BLAKE2s, BLAKE2sp, 6 | aimed at portability and simplicity. 7 | 8 | * `sse/`: C implementations of BLAKE2b, BLAKE2bp, BLAKE2s, BLAKE2sp, 9 | optimized for speed on CPUs supporting SSE2, SSSE3, SSE4.1, AVX, or 10 | XOP. 11 | 12 | * `csharp/`: C# implementation of BLAKE2b. 13 | 14 | * `b2sum/`: Command line utility to hash files, based on the `sse/` 15 | implementations. 16 | 17 | * `bench/`: Benchmark tool to measure cycles-per-byte speeds and produce 18 | graphs copyright. 19 | 20 | All code is triple-licensed under the [CC0](http://creativecommons.org/publicdomain/zero/1.0), the [OpenSSL Licence](https://www.openssl.org/source/license.html), or the [Apache Public License 2.0](http://www.apache.org/licenses/LICENSE-2.0), 21 | at your choosing. 22 | 23 | More: [https://blake2.net](https://blake2.net). 24 | 25 | Contact: contact@blake2.net 26 | -------------------------------------------------------------------------------- /blake2b/sse/blake2-config.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #ifndef BLAKE2_CONFIG_H 16 | #define BLAKE2_CONFIG_H 17 | 18 | /* These don't work everywhere */ 19 | #if defined(__SSE2__) || defined(__x86_64__) || defined(__amd64__) 20 | #define HAVE_SSE2 21 | #endif 22 | 23 | #if defined(__SSSE3__) 24 | #define HAVE_SSSE3 25 | #endif 26 | 27 | #if defined(__SSE4_1__) 28 | #define HAVE_SSE41 29 | #endif 30 | 31 | #if defined(__AVX__) 32 | #define HAVE_AVX 33 | #endif 34 | 35 | #if defined(__XOP__) 36 | #define HAVE_XOP 37 | #endif 38 | 39 | 40 | #ifdef HAVE_AVX2 41 | #ifndef HAVE_AVX 42 | #define HAVE_AVX 43 | #endif 44 | #endif 45 | 46 | #ifdef HAVE_XOP 47 | #ifndef HAVE_AVX 48 | #define HAVE_AVX 49 | #endif 50 | #endif 51 | 52 | #ifdef HAVE_AVX 53 | #ifndef HAVE_SSE41 54 | #define HAVE_SSE41 55 | #endif 56 | #endif 57 | 58 | #ifdef HAVE_SSE41 59 | #ifndef HAVE_SSSE3 60 | #define HAVE_SSSE3 61 | #endif 62 | #endif 63 | 64 | #ifdef HAVE_SSSE3 65 | #define HAVE_SSE2 66 | #endif 67 | 68 | #if !defined(HAVE_SSE2) 69 | #error "This code requires at least SSE2." 70 | #endif 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /blake2b/sse/blake2-impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - reference C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #ifndef BLAKE2_IMPL_H 16 | #define BLAKE2_IMPL_H 17 | 18 | #include 19 | #include 20 | 21 | #if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) 22 | #if defined(_MSC_VER) 23 | #define BLAKE2_INLINE __inline 24 | #elif defined(__GNUC__) 25 | #define BLAKE2_INLINE __inline__ 26 | #else 27 | #define BLAKE2_INLINE 28 | #endif 29 | #else 30 | #define BLAKE2_INLINE inline 31 | #endif 32 | 33 | static BLAKE2_INLINE uint32_t load32( const void *src ) 34 | { 35 | #if defined(NATIVE_LITTLE_ENDIAN) 36 | uint32_t w; 37 | memcpy(&w, src, sizeof w); 38 | return w; 39 | #else 40 | const uint8_t *p = ( const uint8_t * )src; 41 | return (( uint32_t )( p[0] ) << 0) | 42 | (( uint32_t )( p[1] ) << 8) | 43 | (( uint32_t )( p[2] ) << 16) | 44 | (( uint32_t )( p[3] ) << 24) ; 45 | #endif 46 | } 47 | 48 | static BLAKE2_INLINE uint64_t load64( const void *src ) 49 | { 50 | #if defined(NATIVE_LITTLE_ENDIAN) 51 | uint64_t w; 52 | memcpy(&w, src, sizeof w); 53 | return w; 54 | #else 55 | const uint8_t *p = ( const uint8_t * )src; 56 | return (( uint64_t )( p[0] ) << 0) | 57 | (( uint64_t )( p[1] ) << 8) | 58 | (( uint64_t )( p[2] ) << 16) | 59 | (( uint64_t )( p[3] ) << 24) | 60 | (( uint64_t )( p[4] ) << 32) | 61 | (( uint64_t )( p[5] ) << 40) | 62 | (( uint64_t )( p[6] ) << 48) | 63 | (( uint64_t )( p[7] ) << 56) ; 64 | #endif 65 | } 66 | 67 | static BLAKE2_INLINE uint16_t load16( const void *src ) 68 | { 69 | #if defined(NATIVE_LITTLE_ENDIAN) 70 | uint16_t w; 71 | memcpy(&w, src, sizeof w); 72 | return w; 73 | #else 74 | const uint8_t *p = ( const uint8_t * )src; 75 | return (( uint16_t )( p[0] ) << 0) | 76 | (( uint16_t )( p[1] ) << 8) ; 77 | #endif 78 | } 79 | 80 | static BLAKE2_INLINE void store16( void *dst, uint16_t w ) 81 | { 82 | #if defined(NATIVE_LITTLE_ENDIAN) 83 | memcpy(dst, &w, sizeof w); 84 | #else 85 | uint8_t *p = ( uint8_t * )dst; 86 | *p++ = ( uint8_t )w; w >>= 8; 87 | *p++ = ( uint8_t )w; 88 | #endif 89 | } 90 | 91 | static BLAKE2_INLINE void store32( void *dst, uint32_t w ) 92 | { 93 | #if defined(NATIVE_LITTLE_ENDIAN) 94 | memcpy(dst, &w, sizeof w); 95 | #else 96 | uint8_t *p = ( uint8_t * )dst; 97 | p[0] = (uint8_t)(w >> 0); 98 | p[1] = (uint8_t)(w >> 8); 99 | p[2] = (uint8_t)(w >> 16); 100 | p[3] = (uint8_t)(w >> 24); 101 | #endif 102 | } 103 | 104 | static BLAKE2_INLINE void store64( void *dst, uint64_t w ) 105 | { 106 | #if defined(NATIVE_LITTLE_ENDIAN) 107 | memcpy(dst, &w, sizeof w); 108 | #else 109 | uint8_t *p = ( uint8_t * )dst; 110 | p[0] = (uint8_t)(w >> 0); 111 | p[1] = (uint8_t)(w >> 8); 112 | p[2] = (uint8_t)(w >> 16); 113 | p[3] = (uint8_t)(w >> 24); 114 | p[4] = (uint8_t)(w >> 32); 115 | p[5] = (uint8_t)(w >> 40); 116 | p[6] = (uint8_t)(w >> 48); 117 | p[7] = (uint8_t)(w >> 56); 118 | #endif 119 | } 120 | 121 | static BLAKE2_INLINE uint64_t load48( const void *src ) 122 | { 123 | const uint8_t *p = ( const uint8_t * )src; 124 | return (( uint64_t )( p[0] ) << 0) | 125 | (( uint64_t )( p[1] ) << 8) | 126 | (( uint64_t )( p[2] ) << 16) | 127 | (( uint64_t )( p[3] ) << 24) | 128 | (( uint64_t )( p[4] ) << 32) | 129 | (( uint64_t )( p[5] ) << 40) ; 130 | } 131 | 132 | static BLAKE2_INLINE void store48( void *dst, uint64_t w ) 133 | { 134 | uint8_t *p = ( uint8_t * )dst; 135 | p[0] = (uint8_t)(w >> 0); 136 | p[1] = (uint8_t)(w >> 8); 137 | p[2] = (uint8_t)(w >> 16); 138 | p[3] = (uint8_t)(w >> 24); 139 | p[4] = (uint8_t)(w >> 32); 140 | p[5] = (uint8_t)(w >> 40); 141 | } 142 | 143 | static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) 144 | { 145 | return ( w >> c ) | ( w << ( 32 - c ) ); 146 | } 147 | 148 | static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) 149 | { 150 | return ( w >> c ) | ( w << ( 64 - c ) ); 151 | } 152 | 153 | /* prevents compiler optimizing out memset() */ 154 | static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) 155 | { 156 | static void *(*const volatile memset_v)(void *, int, size_t) = &memset; 157 | memset_v(v, 0, n); 158 | } 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /blake2b/sse/blake2b-load-sse2.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #ifndef BLAKE2B_LOAD_SSE2_H 16 | #define BLAKE2B_LOAD_SSE2_H 17 | 18 | #define LOAD_MSG_0_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4) 19 | #define LOAD_MSG_0_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5) 20 | #define LOAD_MSG_0_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12) 21 | #define LOAD_MSG_0_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13) 22 | #define LOAD_MSG_1_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9) 23 | #define LOAD_MSG_1_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15) 24 | #define LOAD_MSG_1_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11) 25 | #define LOAD_MSG_1_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7) 26 | #define LOAD_MSG_2_1(b0, b1) b0 = _mm_set_epi64x(m12, m11); b1 = _mm_set_epi64x(m15, m5) 27 | #define LOAD_MSG_2_2(b0, b1) b0 = _mm_set_epi64x(m0, m8); b1 = _mm_set_epi64x(m13, m2) 28 | #define LOAD_MSG_2_3(b0, b1) b0 = _mm_set_epi64x(m3, m10); b1 = _mm_set_epi64x(m9, m7) 29 | #define LOAD_MSG_2_4(b0, b1) b0 = _mm_set_epi64x(m6, m14); b1 = _mm_set_epi64x(m4, m1) 30 | #define LOAD_MSG_3_1(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m13) 31 | #define LOAD_MSG_3_2(b0, b1) b0 = _mm_set_epi64x(m1, m9); b1 = _mm_set_epi64x(m14, m12) 32 | #define LOAD_MSG_3_3(b0, b1) b0 = _mm_set_epi64x(m5, m2); b1 = _mm_set_epi64x(m15, m4) 33 | #define LOAD_MSG_3_4(b0, b1) b0 = _mm_set_epi64x(m10, m6); b1 = _mm_set_epi64x(m8, m0) 34 | #define LOAD_MSG_4_1(b0, b1) b0 = _mm_set_epi64x(m5, m9); b1 = _mm_set_epi64x(m10, m2) 35 | #define LOAD_MSG_4_2(b0, b1) b0 = _mm_set_epi64x(m7, m0); b1 = _mm_set_epi64x(m15, m4) 36 | #define LOAD_MSG_4_3(b0, b1) b0 = _mm_set_epi64x(m11, m14); b1 = _mm_set_epi64x(m3, m6) 37 | #define LOAD_MSG_4_4(b0, b1) b0 = _mm_set_epi64x(m12, m1); b1 = _mm_set_epi64x(m13, m8) 38 | #define LOAD_MSG_5_1(b0, b1) b0 = _mm_set_epi64x(m6, m2); b1 = _mm_set_epi64x(m8, m0) 39 | #define LOAD_MSG_5_2(b0, b1) b0 = _mm_set_epi64x(m10, m12); b1 = _mm_set_epi64x(m3, m11) 40 | #define LOAD_MSG_5_3(b0, b1) b0 = _mm_set_epi64x(m7, m4); b1 = _mm_set_epi64x(m1, m15) 41 | #define LOAD_MSG_5_4(b0, b1) b0 = _mm_set_epi64x(m5, m13); b1 = _mm_set_epi64x(m9, m14) 42 | #define LOAD_MSG_6_1(b0, b1) b0 = _mm_set_epi64x(m1, m12); b1 = _mm_set_epi64x(m4, m14) 43 | #define LOAD_MSG_6_2(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m10, m13) 44 | #define LOAD_MSG_6_3(b0, b1) b0 = _mm_set_epi64x(m6, m0); b1 = _mm_set_epi64x(m8, m9) 45 | #define LOAD_MSG_6_4(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m2) 46 | #define LOAD_MSG_7_1(b0, b1) b0 = _mm_set_epi64x(m7, m13); b1 = _mm_set_epi64x(m3, m12) 47 | #define LOAD_MSG_7_2(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m9, m1) 48 | #define LOAD_MSG_7_3(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m2, m8) 49 | #define LOAD_MSG_7_4(b0, b1) b0 = _mm_set_epi64x(m4, m0); b1 = _mm_set_epi64x(m10, m6) 50 | #define LOAD_MSG_8_1(b0, b1) b0 = _mm_set_epi64x(m14, m6); b1 = _mm_set_epi64x(m0, m11) 51 | #define LOAD_MSG_8_2(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m8, m3) 52 | #define LOAD_MSG_8_3(b0, b1) b0 = _mm_set_epi64x(m13, m12); b1 = _mm_set_epi64x(m10, m1) 53 | #define LOAD_MSG_8_4(b0, b1) b0 = _mm_set_epi64x(m7, m2); b1 = _mm_set_epi64x(m5, m4) 54 | #define LOAD_MSG_9_1(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m1, m7) 55 | #define LOAD_MSG_9_2(b0, b1) b0 = _mm_set_epi64x(m4, m2); b1 = _mm_set_epi64x(m5, m6) 56 | #define LOAD_MSG_9_3(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m13, m3) 57 | #define LOAD_MSG_9_4(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m0, m12) 58 | #define LOAD_MSG_10_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4) 59 | #define LOAD_MSG_10_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5) 60 | #define LOAD_MSG_10_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12) 61 | #define LOAD_MSG_10_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13) 62 | #define LOAD_MSG_11_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9) 63 | #define LOAD_MSG_11_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15) 64 | #define LOAD_MSG_11_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11) 65 | #define LOAD_MSG_11_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7) 66 | 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /blake2b/sse/blake2b-round.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #ifndef BLAKE2B_ROUND_H 16 | #define BLAKE2B_ROUND_H 17 | 18 | #define LOADU(p) _mm_loadu_si128( (const __m128i *)(p) ) 19 | #define STOREU(p,r) _mm_storeu_si128((__m128i *)(p), r) 20 | 21 | #define TOF(reg) _mm_castsi128_ps((reg)) 22 | #define TOI(reg) _mm_castps_si128((reg)) 23 | 24 | #define LIKELY(x) __builtin_expect((x),1) 25 | 26 | 27 | /* Microarchitecture-specific macros */ 28 | #ifndef HAVE_XOP 29 | #ifdef HAVE_SSSE3 30 | #define _mm_roti_epi64(x, c) \ 31 | (-(c) == 32) ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2,3,0,1)) \ 32 | : (-(c) == 24) ? _mm_shuffle_epi8((x), r24) \ 33 | : (-(c) == 16) ? _mm_shuffle_epi8((x), r16) \ 34 | : (-(c) == 63) ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_add_epi64((x), (x))) \ 35 | : _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_slli_epi64((x), 64-(-(c)))) 36 | #else 37 | #define _mm_roti_epi64(r, c) _mm_xor_si128(_mm_srli_epi64( (r), -(c) ),_mm_slli_epi64( (r), 64-(-(c)) )) 38 | #endif 39 | #else 40 | /* ... */ 41 | #endif 42 | 43 | 44 | 45 | #define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ 46 | row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \ 47 | row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \ 48 | \ 49 | row4l = _mm_xor_si128(row4l, row1l); \ 50 | row4h = _mm_xor_si128(row4h, row1h); \ 51 | \ 52 | row4l = _mm_roti_epi64(row4l, -32); \ 53 | row4h = _mm_roti_epi64(row4h, -32); \ 54 | \ 55 | row3l = _mm_add_epi64(row3l, row4l); \ 56 | row3h = _mm_add_epi64(row3h, row4h); \ 57 | \ 58 | row2l = _mm_xor_si128(row2l, row3l); \ 59 | row2h = _mm_xor_si128(row2h, row3h); \ 60 | \ 61 | row2l = _mm_roti_epi64(row2l, -24); \ 62 | row2h = _mm_roti_epi64(row2h, -24); \ 63 | 64 | #define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ 65 | row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \ 66 | row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \ 67 | \ 68 | row4l = _mm_xor_si128(row4l, row1l); \ 69 | row4h = _mm_xor_si128(row4h, row1h); \ 70 | \ 71 | row4l = _mm_roti_epi64(row4l, -16); \ 72 | row4h = _mm_roti_epi64(row4h, -16); \ 73 | \ 74 | row3l = _mm_add_epi64(row3l, row4l); \ 75 | row3h = _mm_add_epi64(row3h, row4h); \ 76 | \ 77 | row2l = _mm_xor_si128(row2l, row3l); \ 78 | row2h = _mm_xor_si128(row2h, row3h); \ 79 | \ 80 | row2l = _mm_roti_epi64(row2l, -63); \ 81 | row2h = _mm_roti_epi64(row2h, -63); \ 82 | 83 | #if defined(HAVE_SSSE3) 84 | #define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 85 | t0 = _mm_alignr_epi8(row2h, row2l, 8); \ 86 | t1 = _mm_alignr_epi8(row2l, row2h, 8); \ 87 | row2l = t0; \ 88 | row2h = t1; \ 89 | \ 90 | t0 = row3l; \ 91 | row3l = row3h; \ 92 | row3h = t0; \ 93 | \ 94 | t0 = _mm_alignr_epi8(row4h, row4l, 8); \ 95 | t1 = _mm_alignr_epi8(row4l, row4h, 8); \ 96 | row4l = t1; \ 97 | row4h = t0; 98 | 99 | #define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 100 | t0 = _mm_alignr_epi8(row2l, row2h, 8); \ 101 | t1 = _mm_alignr_epi8(row2h, row2l, 8); \ 102 | row2l = t0; \ 103 | row2h = t1; \ 104 | \ 105 | t0 = row3l; \ 106 | row3l = row3h; \ 107 | row3h = t0; \ 108 | \ 109 | t0 = _mm_alignr_epi8(row4l, row4h, 8); \ 110 | t1 = _mm_alignr_epi8(row4h, row4l, 8); \ 111 | row4l = t1; \ 112 | row4h = t0; 113 | #else 114 | 115 | #define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 116 | t0 = row4l;\ 117 | t1 = row2l;\ 118 | row4l = row3l;\ 119 | row3l = row3h;\ 120 | row3h = row4l;\ 121 | row4l = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t0, t0)); \ 122 | row4h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row4h, row4h)); \ 123 | row2l = _mm_unpackhi_epi64(row2l, _mm_unpacklo_epi64(row2h, row2h)); \ 124 | row2h = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(t1, t1)) 125 | 126 | #define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 127 | t0 = row3l;\ 128 | row3l = row3h;\ 129 | row3h = t0;\ 130 | t0 = row2l;\ 131 | t1 = row4l;\ 132 | row2l = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(row2l, row2l)); \ 133 | row2h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row2h, row2h)); \ 134 | row4l = _mm_unpackhi_epi64(row4l, _mm_unpacklo_epi64(row4h, row4h)); \ 135 | row4h = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t1, t1)) 136 | 137 | #endif 138 | 139 | #if defined(HAVE_SSE41) 140 | #include "blake2b-load-sse41.h" 141 | #else 142 | #include "blake2b-load-sse2.h" 143 | #endif 144 | 145 | #define ROUND(r) \ 146 | LOAD_MSG_ ##r ##_1(b0, b1); \ 147 | G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 148 | LOAD_MSG_ ##r ##_2(b0, b1); \ 149 | G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 150 | DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ 151 | LOAD_MSG_ ##r ##_3(b0, b1); \ 152 | G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 153 | LOAD_MSG_ ##r ##_4(b0, b1); \ 154 | G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 155 | UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); 156 | 157 | #endif 158 | -------------------------------------------------------------------------------- /candlestick-puller/README.md: -------------------------------------------------------------------------------- 1 | # candlestick-puller 2 | 3 | Rudimentary candlestick puller. Downloads and saves candles. Currently only supports Bittrex, but can be modified to support more exchanges. 4 | 5 | Dumps the candlesticks in OHLC4 `(open+high+low+close)/4` format, space delimited text, prepended by the epoch timestamp of the first candle, and a marker `p`: 6 | 7 | `p ...` 8 | 9 | ### Market format 10 | The market format on Bittrex is backwards from most exchanges. Where `LTC-BTC` is for quantities of `LTC` priced in `BTC`, some other exchanges will format this as `BTC_LTC`. Arguments are taken in the former format, but the file name will be saved in the latter format. 11 | 12 | ### Exchange rate limits 13 | Bittrex allows 1 command per second. Pulling candles for many markets may take hours, but at least you won't get banned. In order to support multiple pullers running and be nice to the API, it only sends a request after it gets a response. 14 | 15 | ### Usage 16 | 17 | `./candlestick-puller [invert flag]` 18 | 19 | Pull the `LTC-BTC` market: 20 | 21 | `./candlestick-puller LTC-BTC M3d7y2014` 22 | 23 | Where `M3d7y2014` is month 3, day 7, year 2014, the date `LTC` became tradeable. 24 | This will pull the candles and save to the file `BITTREX.BTC_LTC.5` when finished. 25 | 26 | If you don't know exactly where the data starts, you can specify `?` at the end of an earlier date, and it will scan until it finds populated data: 27 | 28 | `./candlestick-puller LTC-BTC M2d1y2014?` 29 | 30 | If you want to invert the price of a market, for example `BTC-USDT`, but you want the price in `BTC` and not `USDT`, you can invert it: 31 | 32 | `./candlestick-puller BTC-USDT M12d12y2015 invert` 33 | Will save to the file `BITTREX.BTC_USDT.5` when finished. 34 | 35 | ### Updating existing candles 36 | To update a market, supply `update` for the date: 37 | 38 | `./candlestick-puller LTC-BTC update` 39 | 40 | ### Candlestick intervals 41 | 42 | Currently, only 5 minute candles are supported. Please fork the code if you would like to change it. 43 | -------------------------------------------------------------------------------- /candlestick-puller/candlestick-puller.pro: -------------------------------------------------------------------------------- 1 | QT = core network 2 | 3 | TARGET = candlestick-puller 4 | TEMPLATE = app 5 | 6 | CONFIG += c++14 c++17 7 | CONFIG += release 8 | 9 | LIBS += -lgmp 10 | 11 | SOURCES += \ 12 | ../daemon/coinamount.cpp \ 13 | ../daemon/market.cpp \ 14 | ../daemon/priceaggregator.cpp \ 15 | ../daemon/pricesignal.cpp \ 16 | main.cpp \ 17 | puller.cpp 18 | 19 | HEADERS += \ 20 | ../daemon/ssl_policy.h \ 21 | ../daemon/coinamount.h \ 22 | ../daemon/market.h \ 23 | ../daemon/priceaggregator.h \ 24 | ../daemon/pricesignal.h \ 25 | puller.h 26 | 27 | DISTFILES += \ 28 | README.md 29 | -------------------------------------------------------------------------------- /candlestick-puller/main.cpp: -------------------------------------------------------------------------------- 1 | #include "puller.h" 2 | 3 | #include "../daemon/ssl_policy.h" 4 | 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QCoreApplication a( argc, argv ); 10 | SslPolicy::enableSecureSsl(); 11 | Puller *p = new Puller(); Q_UNUSED( p ); 12 | 13 | return a.exec(); 14 | } 15 | -------------------------------------------------------------------------------- /candlestick-puller/puller.h: -------------------------------------------------------------------------------- 1 | #ifndef PULLER_H 2 | #define PULLER_H 3 | 4 | #include "../daemon/coinamount.h" 5 | #include "../daemon/priceaggregator.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class QNetworkAccessManager; 14 | class QNetworkReply; 15 | class QNetworkRequest; 16 | class TickerRequest; 17 | 18 | struct CandleRequest 19 | { 20 | QNetworkRequest request; 21 | QString id; 22 | }; 23 | 24 | class Puller : public QObject 25 | { 26 | Q_OBJECT 27 | 28 | public: 29 | explicit Puller(); 30 | ~Puller(); 31 | 32 | void sendCandleRequest(); 33 | 34 | void sendRequest( QString url, QString query, QString id ); 35 | 36 | public Q_SLOTS: 37 | void onSendNameQueue(); 38 | void onCheckFinished(); 39 | void onNamReply( QNetworkReply *reply ); 40 | 41 | private: 42 | QNetworkAccessManager *nam; 43 | 44 | QMap nam_queue_sent; 45 | QVector nam_queue; 46 | 47 | bool waiting_for_final_reply{ false }; // tracks if we are done 48 | bool invert_price{ false }; 49 | bool continue_on_empty_data{ false }; 50 | bool updating_candles{ false }; 51 | 52 | qint64 last_sample_secs{ 0 }; 53 | qint64 requests_made{ 0 }; 54 | qint64 requests_parsed{ 0 }; 55 | qint64 replies_empty{ 0 }; 56 | 57 | qint64 application_end_secs{ 0 }; 58 | 59 | PriceAggregatorConfig price_data; 60 | QDateTime current_date; 61 | QString current_market; 62 | QString filename; 63 | }; 64 | 65 | #endif // PULLER_H 66 | -------------------------------------------------------------------------------- /cli/commandcaller.cpp: -------------------------------------------------------------------------------- 1 | #include "commandcaller.h" 2 | #include "../daemon/global.h" 3 | 4 | #include 5 | 6 | CommandCaller::CommandCaller( const QByteArray &command, QObject *parent ) 7 | : QLocalSocket( parent ) 8 | { 9 | // open ipc 10 | const QString ipc_path = Global::getIPCPath(); 11 | QLocalSocket::connectToServer( ipc_path ); 12 | QLocalSocket::waitForConnected(); 13 | 14 | // send command 15 | if ( state() == QLocalSocket::ConnectedState ) 16 | { 17 | QLocalSocket::write( command ); 18 | QLocalSocket::flush(); 19 | QLocalSocket::close(); 20 | } 21 | else // abort if we didn't connect 22 | { 23 | qDebug() << "error: failed to send command:" << QLocalSocket::errorString(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /cli/commandcaller.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMANDCALLER_H 2 | #define COMMANDCALLER_H 3 | 4 | #include 5 | #include 6 | 7 | class CommandCaller : public QLocalSocket 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | explicit CommandCaller( const QByteArray &command, QObject *parent = nullptr ); 13 | }; 14 | 15 | #endif // COMMANDCALLER_H 16 | -------------------------------------------------------------------------------- /cli/main.cpp: -------------------------------------------------------------------------------- 1 | #include "commandcaller.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int main( int argc, char *argv[] ) 8 | { 9 | QCoreApplication a( argc, argv ); 10 | 11 | // read args 12 | QStringList args = QCoreApplication::arguments(); 13 | 14 | // strip binary name 15 | args.removeFirst(); 16 | 17 | // form arguments for command caller 18 | QString joined = args.join( QChar( ' ' ) ); 19 | 20 | CommandCaller c( joined.toLocal8Bit() ); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /cli/trader-cli.pro: -------------------------------------------------------------------------------- 1 | QT = core network 2 | 3 | TARGET = trader-cli 4 | DESTDIR = ../ 5 | 6 | MOC_DIR = ../build-tmp/cli 7 | OBJECTS_DIR = ../build-tmp/cli 8 | 9 | CONFIG += c++14 c++17 10 | CONFIG += RELEASE 11 | 12 | SOURCES += commandcaller.cpp \ 13 | main.cpp 14 | 15 | HEADERS += \ 16 | commandcaller.h 17 | 18 | -------------------------------------------------------------------------------- /daemon/alphatracker.h: -------------------------------------------------------------------------------- 1 | #ifndef ALPHATRACKER_H 2 | #define ALPHATRACKER_H 3 | 4 | #include "coinamount.h" 5 | #include 6 | 7 | class Position; 8 | 9 | struct AlphaData 10 | { 11 | Coin v, vp; 12 | quint64 trades{ 0 }; 13 | }; 14 | 15 | class AlphaTracker 16 | { 17 | public: 18 | AlphaTracker(); 19 | 20 | void reset(); 21 | 22 | // "alpha" 23 | Coin getAlpha( const QString &market ) const; 24 | Coin getAlphaSignificanceFactor( const QString &market ) const; 25 | Coin getVolume( const QString &market ) const; 26 | Coin getVolume( const quint8 side, const QString &market ) const; 27 | Coin getVolumePerTrade( const QString &market ) const; 28 | Coin getAvgPrice( const QString &market, quint8 side ) const; 29 | quint64 getTrades( const QString &market ) const; 30 | void addAlpha( const QString &market, const quint8 side, const Coin &amount, const Coin &price ); 31 | Coin getEstimatedPL( const bool conservative = true ) const; 32 | // 33 | 34 | // "daily volume" 35 | void addDailyVolume( const qint64 epoch_time_secs, const Coin &volume ); 36 | // 37 | 38 | QString getAlphaReadout() const; 39 | void printDailyVolume() const; 40 | 41 | QString getSaveState() const; 42 | void readSaveState( const QString &state ); 43 | 44 | QList getMarkets() const; 45 | 46 | private: 47 | // "alpha" data 48 | QMap buys, sells; 49 | 50 | // "daily volume" data 51 | qint64 daily_volume_epoch_secs{ 0 }; // the date we started recording volume 52 | QMap daily_volume; 53 | }; 54 | 55 | #endif // ALPHATRACKER_H 56 | -------------------------------------------------------------------------------- /daemon/baserest.h: -------------------------------------------------------------------------------- 1 | #ifndef BASEREST_H 2 | #define BASEREST_H 3 | 4 | #include "global.h" 5 | #include "misctypes.h" 6 | #include "keystore.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class QNetworkAccessManager; 15 | class QNetworkReply; 16 | class Request; 17 | class Stats; 18 | class Engine; 19 | class QTimer; 20 | class Position; 21 | 22 | struct BaseREST : public QObject 23 | { 24 | explicit BaseREST( Engine *_engine ); 25 | ~BaseREST(); 26 | 27 | virtual void init() {} 28 | 29 | bool yieldToFlowControlQueue() const; 30 | bool yieldToFlowControlSent() const; 31 | bool isTickerStale() const; 32 | 33 | void sendRequest( QString api_command, QString body = QLatin1String(), Position *pos = nullptr, quint16 weight = 0 ); 34 | 35 | bool isKeyOrSecretUnset() const; 36 | bool isCommandQueued( const QString &api_command_prefix ) const; 37 | // bool isCommandSent( const QString &api_command_prefix, qint32 min_times = 1 ) const; 38 | void removeRequest( const QString &api_command, const QString &body ); 39 | void deleteReply( QNetworkReply *const &reply, Request *const &request ); 40 | 41 | QString getExchangeStr() const { return exchange_string; } 42 | QString getExchangeFancyStr() const { return QString( "[REST %1]" ).arg( exchange_string ); } 43 | 44 | public Q_SLOTS: 45 | void onCheckSentTimeouts(); 46 | 47 | public: 48 | 49 | QQueue nam_queue; // queue for requests so we can load balance timestamp/hmac generation 50 | QHash nam_queue_sent; // request tracking queue 51 | 52 | KeyStore keystore; 53 | AvgResponseTime avg_response_time; 54 | QString exchange_string; 55 | 56 | qint64 request_nonce{ 0 }; // nonce (except for trex which uses time atm) 57 | qint64 last_request_sent_ms{ 0 }; // last nam request time 58 | 59 | qint64 orderbook_update_time{ 0 }; // most recent trade time 60 | qint64 orderbook_update_request_time{ 0 }; 61 | qint64 ticker_update_time{ 0 }; 62 | qint64 ticker_update_request_time{ 0 }; 63 | qint32 limit_commands_queued{ 20 }; // stop checks if we are over this many commands queued 64 | qint32 limit_commands_queued_dc_check{ 10 }; // skip dc check if we are over this many commands queued 65 | qint32 limit_commands_sent{ 100 }; // stop checks if we are over this many commands sent 66 | qint32 limit_timeout_yield{ 5 }; 67 | qint32 market_cancel_thresh{ 300 }; // limit for market order total for weighting cancels to be sent first 68 | 69 | qint64 slippage_stale_time{ 500 }; // quiet time before we allow an order to be included in slippage price calculations 70 | qint64 orderbook_stale_tolerance{ 10000 }; // only accept orderbooks sent within this time 71 | qint64 orders_stale_trip_count{ 0 }; 72 | qint64 books_stale_trip_count{ 0 }; 73 | 74 | QTimer *send_timer{ nullptr }; 75 | QTimer *orderbook_timer{ nullptr }; 76 | QTimer *ticker_timer{ nullptr }; 77 | QTimer *timeout_timer{ nullptr }; 78 | QTimer *diverge_converge_timer{ nullptr }; 79 | 80 | QNetworkAccessManager *nam{ nullptr }; 81 | Engine *engine{ nullptr }; 82 | }; 83 | 84 | #endif // BASEREST_H 85 | -------------------------------------------------------------------------------- /daemon/bncrest.h: -------------------------------------------------------------------------------- 1 | #ifndef BNCREST_H 2 | #define BNCREST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "global.h" 10 | #include "position.h" 11 | #include "keystore.h" 12 | #include "baserest.h" 13 | 14 | class QNetworkReply; 15 | class QTimer; 16 | class QWebSocket; 17 | 18 | class BncREST : public BaseREST 19 | { 20 | Q_OBJECT 21 | 22 | friend class CommandRunner; 23 | 24 | public: 25 | explicit BncREST( Engine *_engine, QNetworkAccessManager *_nam ); 26 | ~BncREST(); 27 | 28 | void init(); 29 | 30 | bool yieldToLag() const; 31 | 32 | void sendNamRequest( Request *const &request ); 33 | void sendBuySell( Position *const &pos, bool quiet = true ); 34 | void sendCancel( const QString &_order_id, Position *const &pos = nullptr ); 35 | void sendGetOrder( const QString &_order_id, Position *const &pos = nullptr ); 36 | void parseBuySell( Request *const &request, const QJsonObject &response ); 37 | void parseCancelOrder( Request *const &request, const QJsonObject &response ); 38 | void parseOpenOrders( const QJsonArray &markets, qint64 request_time_sent_ms ); 39 | void parseReturnBalances( const QJsonObject &obj ); 40 | void parseTicker( const QJsonArray &info, qint64 request_time_sent_ms ); 41 | void parseExchangeInfo( const QJsonObject &obj ); 42 | void wssSendJsonObj( const QJsonObject &obj ); 43 | 44 | void checkBotOrders( bool ignore_flow_control = false ); 45 | 46 | public Q_SLOTS: 47 | void sendNamQueue(); 48 | void onNamReply( QNetworkReply *const &reply ); 49 | 50 | void onCheckRateLimit(); 51 | void onCheckBotOrders(); 52 | void onCheckTicker(); 53 | void onCheckExchangeInfo(); 54 | 55 | void wssConnected(); 56 | void wssCheckConnection(); 57 | void wssTextMessageReceived( const QString &msg ); 58 | void wssSendSubscriptions(); 59 | 60 | private: 61 | QMap market_aliases; 62 | QMap daily_orders; // track daily orders sent 63 | 64 | qint64 wss_connect_try_time{ 0 }, 65 | wss_heartbeat_time{ 0 }, 66 | wss_account_feed_update_time{ 0 }, 67 | wss_safety_delay_time{ 2000 }; // only detect a wss filled order after this amount of time - for possible wss lag 68 | 69 | bool wss_1000_state{ false }, // account subscription 70 | wss_1002_state{ false }; // ticker subscription 71 | 72 | // rate limit stuff 73 | qint32 binance_weight{ 0 }, // current weight 74 | ratelimit_second{ 10 }, // orders limit 75 | ratelimit_minute{ 600 }, // weight limit 76 | ratelimit_day{ 100000 }; // orders limit 77 | 78 | QTimer *exchangeinfo_timer{ nullptr }; 79 | QTimer *ratelimit_timer{ nullptr }; 80 | }; 81 | 82 | #endif // BNCREST_H 83 | -------------------------------------------------------------------------------- /daemon/build-config.h: -------------------------------------------------------------------------------- 1 | #ifndef BUILDCONFIG_H 2 | #define BUILDCONFIG_H 3 | 4 | #define BUILD_VERSION "1.84k" 5 | 6 | /// select your exchanges 7 | //#define BITTREX_ENABLED 8 | #define BINANCE_ENABLED 9 | #define POLONIEX_ENABLED 10 | #define WAVES_ENABLED 11 | 12 | /// universal exchange options 13 | //#define BITTREX_TICKER_ONLY 14 | #define BINANCE_TICKER_ONLY 15 | #define POLONIEX_TICKER_ONLY 16 | //#define WAVES_TICKER_ONLY 17 | 18 | /// where to print logs 19 | #define PRINT_LOGS_TO_CONSOLE 20 | //#define PRINT_LOGS_TO_FILE 21 | #define PRINT_LOGS_TO_FILE_COLOR 22 | 23 | /// to make trades with the strategy, comment this out 24 | //#define PAPER_TRADE 25 | 26 | /// what to log 27 | //#define PRINT_LOGS_WITH_FUNCTION_NAMES 28 | #define PRINT_ENABLED_SSL_CIPHERS 29 | //#define PRINT_DISABLED_SSL_CIPHERS 30 | 31 | /// spread expansion on fill 32 | #define SPREAD_EXPAND_FULL // expand to trade price 33 | //#define SPREAD_EXPAND_HALF // expand between trade price and current ticker price 34 | 35 | /// spread contraction on aggressive spread 36 | #define SPREAD_CONTRACT_RATIO "0.5" 37 | 38 | /// coin options 39 | #define COIN_CATCH_DIV0 40 | #define COIN_CATCH_INF 41 | 42 | #endif // BUILDCONFIG_H 43 | -------------------------------------------------------------------------------- /daemon/coinamount_test.h: -------------------------------------------------------------------------------- 1 | #ifndef COINAMOUNT_TEST_H 2 | #define COINAMOUNT_TEST_H 3 | 4 | struct CoinAmountTest 5 | { 6 | void test(); 7 | 8 | void testUnit(); 9 | void testDoubleFailure(); 10 | void testPractical(); 11 | void testRandom(); 12 | }; 13 | 14 | #endif // COINAMOUNT_TEST_H 15 | -------------------------------------------------------------------------------- /daemon/commandlistener.cpp: -------------------------------------------------------------------------------- 1 | #include "commandlistener.h" 2 | #include "global.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | CommandListener::CommandListener( QObject *parent ) 9 | : QLocalServer( parent ) 10 | { 11 | QString path = Global::getIPCPath(); 12 | 13 | // remove socket path if it exists 14 | if ( QFile::exists( path ) ) 15 | { 16 | QFile f( path ); 17 | f.remove(); 18 | } 19 | 20 | // ensure we can listen 21 | if ( !QLocalServer::listen( path ) ) 22 | { 23 | kDebug() << "[CommandListener] failed to listen at" << path; 24 | return; 25 | } 26 | 27 | connect( this, &QLocalServer::newConnection, this, &CommandListener::handleNewConnection ); 28 | kDebug() << "[CommandListener] listening at" << path; 29 | } 30 | 31 | CommandListener::~CommandListener() 32 | { 33 | QLocalServer::close(); 34 | 35 | QList list = m_users.values(); 36 | while ( !list.isEmpty() ) 37 | delete list.takeFirst(); //->deleteLater(); 38 | } 39 | 40 | void CommandListener::handleNewConnection() 41 | { 42 | LocalClient *next = new LocalClient( QLocalServer::nextPendingConnection() ); 43 | m_users += next; 44 | 45 | connect( next, &LocalClient::disconnected, this, &CommandListener::handleDisconnect ); 46 | connect( next, &LocalClient::readyRead, this, &CommandListener::handleReadyRead ); 47 | //kDebug() << "[CommandListener] socket connected"; 48 | } 49 | 50 | void CommandListener::handleDisconnect( LocalClient *sck ) 51 | { 52 | m_users.remove( sck ); 53 | sck->deleteLater(); 54 | //kDebug() << "[CommandListener] socket disconnected"; 55 | } 56 | 57 | void CommandListener::handleReadyRead( LocalClient *sck ) 58 | { 59 | QString data = sck->getSocketData(); 60 | emit gotDataChunk( data ); 61 | //kDebug() << "[CommandListener] " << data; 62 | } 63 | 64 | 65 | LocalClient::LocalClient( QLocalSocket *sck, QObject *parent ) 66 | : QObject( parent ), 67 | m_sck( sck ) 68 | { 69 | connect( m_sck, &QLocalSocket::disconnected, this, &LocalClient::handleDisconnected ); 70 | connect( m_sck, &QLocalSocket::readyRead, this, &LocalClient::handleReadyRead ); 71 | //kDebug() << "[LocalClient()]"; 72 | } 73 | 74 | LocalClient::~LocalClient() 75 | { 76 | m_sck->deleteLater(); 77 | } 78 | 79 | QByteArray LocalClient::getSocketData() const 80 | { 81 | return m_sck->readAll(); 82 | } 83 | 84 | void LocalClient::handleDisconnected() 85 | { 86 | emit disconnected( this ); 87 | } 88 | 89 | void LocalClient::handleReadyRead() 90 | { 91 | emit readyRead( this ); 92 | } 93 | -------------------------------------------------------------------------------- /daemon/commandlistener.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMANDLISTENER_H 2 | #define COMMANDLISTENER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class QLocalSocket; 11 | 12 | // 13 | // LocalClient, a signal wrapper around QLocalSocket 14 | // 15 | class LocalClient : public QObject 16 | { 17 | Q_OBJECT 18 | public: 19 | explicit LocalClient( QLocalSocket *sck, QObject *parent = nullptr );\ 20 | ~LocalClient(); 21 | 22 | QByteArray getSocketData() const; 23 | 24 | signals: 25 | void disconnected( LocalClient *sck ); 26 | void readyRead( LocalClient *sck ); 27 | 28 | public slots: 29 | void handleDisconnected(); 30 | void handleReadyRead(); 31 | 32 | private: 33 | QLocalSocket *m_sck; 34 | }; 35 | 36 | // 37 | // CommandListener, an IPC server to listen for commands 38 | // 39 | class CommandListener : public QLocalServer 40 | { 41 | Q_OBJECT 42 | public: 43 | explicit CommandListener( QObject *parent = nullptr ); 44 | ~CommandListener(); 45 | 46 | signals: 47 | void gotDataChunk( QString &s ); 48 | 49 | public slots: 50 | void handleNewConnection(); 51 | void handleDisconnect( LocalClient *sck ); 52 | void handleReadyRead( LocalClient *sck ); 53 | 54 | private: 55 | QSet m_users; 56 | }; 57 | 58 | #endif // COMMANDLISTENER_H 59 | -------------------------------------------------------------------------------- /daemon/diffusionphaseman.cpp: -------------------------------------------------------------------------------- 1 | #include "diffusionphaseman.h" 2 | #include "global.h" 3 | 4 | #include 5 | #include 6 | 7 | DiffusionPhaseMan::DiffusionPhaseMan() {} 8 | 9 | DiffusionPhaseMan::DiffusionPhaseMan( QVector _markets ) 10 | { 11 | setMarkets( _markets ); 12 | } 13 | 14 | void DiffusionPhaseMan::addPhase( const DiffusionPhaseFluxType &_phase ) 15 | { 16 | m_phases += _phase; 17 | } 18 | 19 | DiffusionPhaseFluxType DiffusionPhaseMan::getCurrentPhase() const 20 | { 21 | return m_phases.value( m_phase_selected, NO_FLUX ); 22 | } 23 | 24 | QVector DiffusionPhaseMan::getCurrentPhaseMarkets() 25 | { 26 | if ( getCurrentPhase() == NO_FLUX ) 27 | return m_markets; 28 | 29 | QVector ret; 30 | ret += m_markets.value( m_market_selected ); 31 | return ret; 32 | } 33 | 34 | void DiffusionPhaseMan::setMarkets( const QVector &_markets ) 35 | { 36 | m_markets = _markets; 37 | } 38 | 39 | QVector &DiffusionPhaseMan::getMarkets() 40 | { 41 | return m_markets; 42 | } 43 | 44 | int DiffusionPhaseMan::getMarketCount() const 45 | { 46 | return m_markets.size(); 47 | } 48 | 49 | void DiffusionPhaseMan::begin() 50 | { 51 | m_phase_selected = 0; 52 | m_market_selected = 0; 53 | m_side_selected = SIDE_BUY; 54 | } 55 | 56 | void DiffusionPhaseMan::next() 57 | { 58 | // if buy, flip to sell 59 | if ( m_side_selected == SIDE_BUY ) 60 | { 61 | m_side_selected = SIDE_SELL; 62 | } 63 | // if sell, flip back to buy if we have more markets 64 | else if ( getCurrentPhase() == FLUX_PER_MARKET && m_market_selected < m_markets.size() -1 ) 65 | { 66 | m_market_selected++; 67 | m_side_selected = SIDE_BUY; 68 | } 69 | // if we ran out of markets, switch to next phase 70 | else 71 | { 72 | m_phase_selected++; 73 | m_market_selected = 0; 74 | m_side_selected = SIDE_BUY; 75 | } 76 | } 77 | 78 | bool DiffusionPhaseMan::atEnd() const 79 | { 80 | return m_phase_selected >= m_phases.size() || m_phase_selected < 0; // TODO: remove second condition when we use size_type 81 | } 82 | -------------------------------------------------------------------------------- /daemon/diffusionphaseman.h: -------------------------------------------------------------------------------- 1 | #ifndef DIFFUSIONPHASEMAN_H 2 | #define DIFFUSIONPHASEMAN_H 3 | 4 | #include "global.h" 5 | 6 | #include 7 | #include 8 | 9 | enum DiffusionPhaseFluxType 10 | { 11 | NO_FLUX, 12 | FLUX_PER_MARKET 13 | }; 14 | 15 | class DiffusionPhaseMan final 16 | { 17 | public: 18 | DiffusionPhaseMan(); 19 | DiffusionPhaseMan( QVector _markets ); 20 | 21 | void addPhase( const DiffusionPhaseFluxType &_phase ); 22 | DiffusionPhaseFluxType getCurrentPhase() const; 23 | QVector getCurrentPhaseMarkets(); 24 | quint8 getCurrentPhaseSide() const { return m_side_selected; } 25 | 26 | void setMarkets( const QVector &_markets ); 27 | QVector &getMarkets(); 28 | int getMarketCount() const; 29 | 30 | void begin(); 31 | void next(); 32 | bool atEnd() const; 33 | 34 | private: 35 | QVector m_phases; 36 | QVector m_markets; 37 | int m_phase_selected{ 0 }; 38 | int m_market_selected{ 0 }; 39 | quint8 m_side_selected{ SIDE_BUY }; 40 | }; 41 | 42 | #endif // DIFFUSIONPHASEMAN_H 43 | -------------------------------------------------------------------------------- /daemon/diffusionphaseman_test.cpp: -------------------------------------------------------------------------------- 1 | #include "diffusionphaseman_test.h" 2 | #include "diffusionphaseman.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void DiffusionPhaseManTest::test() 9 | { 10 | QVector markets; 11 | markets += "BTC_TEST0"; 12 | markets += "BTC_TEST1"; 13 | markets += "BTC_TEST2"; 14 | markets += "BTC_TEST3"; 15 | markets += "BTC_TEST4"; 16 | 17 | DiffusionPhaseMan pm( markets ); 18 | pm.addPhase( NO_FLUX ); 19 | pm.addPhase( FLUX_PER_MARKET ); 20 | 21 | int buy_count = 0; 22 | int sell_count = 0; 23 | int flux_count = 0; 24 | int noflux_count = 0; 25 | QMap flux_markets_accounted_for; 26 | 27 | for ( pm.begin(); !pm.atEnd(); pm.next() ) 28 | { 29 | const quint8 side = pm.getCurrentPhaseSide(); 30 | const bool is_flux_phase = ( pm.getCurrentPhase() == FLUX_PER_MARKET ); 31 | 32 | // count iterations of different phase types 33 | if ( is_flux_phase ) 34 | flux_count++; 35 | else 36 | noflux_count++; 37 | 38 | // count phases per size 39 | if ( side == SIDE_BUY ) 40 | buy_count++; 41 | else 42 | sell_count++; 43 | 44 | // make sure the execution market matches the correct market count 45 | if ( is_flux_phase ) 46 | { 47 | const QString ¤t_active_market = pm.getCurrentPhaseMarkets().value( 0 ); 48 | flux_markets_accounted_for[ current_active_market ]++; 49 | 50 | assert( pm.getCurrentPhaseMarkets().size() == 1 ); // make sure it's a single market 51 | assert( ( side == SIDE_BUY && flux_markets_accounted_for.value( current_active_market ) == 1 ) || 52 | ( side == SIDE_SELL && flux_markets_accounted_for.value( current_active_market ) == 2 ) ); // ensure market is fluxed once on each side 53 | } 54 | else 55 | assert( pm.getCurrentPhaseMarkets() == markets ); 56 | } 57 | 58 | assert( flux_markets_accounted_for.size() == markets.size() ); // verify we fluxed as many markets as supplied 59 | assert( flux_count == markets.size() *2 ); // one buy/sell flux phase for each market 60 | assert( noflux_count == 2 ); // noflux always has 1 buy/sell phase 61 | assert( buy_count == sell_count ); 62 | assert( buy_count == markets.size() +1 ); // buy/sell count == 1+1m, 1 for noflux phase and 1m for each market 63 | } 64 | -------------------------------------------------------------------------------- /daemon/diffusionphaseman_test.h: -------------------------------------------------------------------------------- 1 | #ifndef DIFFUSIONPHASEMAN_TEST_H 2 | #define DIFFUSIONPHASEMAN_TEST_H 3 | 4 | struct DiffusionPhaseManTest 5 | { 6 | void test(); 7 | }; 8 | 9 | #endif // DIFFUSIONPHASEMAN_TEST_H 10 | -------------------------------------------------------------------------------- /daemon/engine_test.h: -------------------------------------------------------------------------------- 1 | #ifndef ENGINE_TEST_H 2 | #define ENGINE_TEST_H 3 | 4 | class Engine; 5 | 6 | struct EngineTest 7 | { 8 | void test( Engine *e ); 9 | }; 10 | 11 | #endif // ENGINE_TEST_H 12 | -------------------------------------------------------------------------------- /daemon/enginemap.h: -------------------------------------------------------------------------------- 1 | #ifndef ENGINEMAP_H 2 | #define ENGINEMAP_H 3 | 4 | #include 5 | 6 | class Engine; 7 | 8 | class EngineMap : public QMap 9 | { 10 | public: 11 | explicit EngineMap() {} 12 | }; 13 | 14 | #endif // ENGINEMAP_H 15 | -------------------------------------------------------------------------------- /daemon/enginesettings.h: -------------------------------------------------------------------------------- 1 | #ifndef ENGINESETTINGS_H 2 | #define ENGINESETTINGS_H 3 | 4 | #include "global.h" 5 | #include "coinamount.h" 6 | 7 | struct EngineSettings 8 | { 9 | explicit EngineSettings( const quint8 _engine_type ) 10 | { 11 | if ( _engine_type == ENGINE_BITTREX ) 12 | { 13 | fee = BITTREX_DEFAULT_FEERATE; 14 | safety_delay_time = BITTREX_SAFETY_DELAY; 15 | ticker_safety_delay_time = BITTREX_SAFETY_DELAY; 16 | } 17 | else if ( _engine_type == ENGINE_BINANCE ) 18 | { 19 | fee = BINANCE_DEFAULT_FEERATE; 20 | safety_delay_time = BINANCE_SAFETY_DELAY; 21 | ticker_safety_delay_time = BINANCE_SAFETY_DELAY; 22 | } 23 | else if ( _engine_type == ENGINE_POLONIEX ) 24 | { 25 | fee = POLONIEX_DEFAULT_FEERATE; 26 | safety_delay_time = POLONIEX_SAFETY_DELAY; 27 | ticker_safety_delay_time = POLONIEX_SAFETY_DELAY; 28 | } 29 | else if ( _engine_type == ENGINE_WAVES ) 30 | { 31 | safety_delay_time = 5000; 32 | ticker_safety_delay_time = 5000; 33 | } 34 | } 35 | ~EngineSettings() {} 36 | 37 | Coin fee; 38 | 39 | // global settings (probably shouldn't be modified) 40 | #if defined(PAPER_TRADE) 41 | bool should_clear_stray_orders{ false }; // auto cancels orders that aren't ours 42 | bool should_clear_stray_orders_all{ false }; // cancel orders in markets we don't have orders in 43 | #else 44 | bool should_clear_stray_orders{ true }; // auto cancels orders that aren't ours 45 | bool should_clear_stray_orders_all{ true }; // cancel orders in markets we don't have orders in 46 | #endif 47 | bool is_chatty{ false }; 48 | bool should_slippage_be_calculated{ true }; // calculated/additive preference of slippage 49 | bool should_adjust_hibuy_losell{ true }; // adjust hi_buy/lo_sell maps based on post-only price errors 50 | bool should_adjust_hibuy_losell_debugmsgs_ticker{ false }; // enable chatty messages for hi/lo bounds adjust for wss-ticker 51 | bool should_mitigate_blank_orderbook_flash{ true }; 52 | bool should_dc_slippage_orders{ false }; 53 | qint64 order_timeout{ 3 * 60000 }; // how long before we resend most requests 54 | qint64 cancel_timeout{ 5 * 60000 }; // how long before we resend a cancel request 55 | qint64 stray_grace_time_limit{ 10000 }; // how long before we cancel stray orders, if enabled 56 | qint64 safety_delay_time; // safety delay, should be more than your ping by a second or two 57 | qint64 ticker_safety_delay_time; // ^ 58 | qint64 orderbook_stale_time{ 2 * 60000 }; // after this amount of time, orderbooks are considered stale and new orders are not set 59 | }; 60 | 61 | #endif // ENGINESETTINGS_H 62 | -------------------------------------------------------------------------------- /daemon/fallbacklistener.cpp: -------------------------------------------------------------------------------- 1 | #include "fallbacklistener.h" 2 | #include "global.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | FallbackListener::FallbackListener(QObject *parent) 11 | : QObject( parent ), 12 | input_file( nullptr ), 13 | input_timer( nullptr ) 14 | { 15 | openInputFile(); 16 | 17 | // init input timer to read commands from in.txt 18 | input_timer = new QTimer( this ); 19 | connect( input_timer, &QTimer::timeout, this, &FallbackListener::parseInputFile ); 20 | input_timer->setTimerType( Qt::VeryCoarseTimer ); 21 | input_timer->start( 1000 ); 22 | } 23 | 24 | FallbackListener::~FallbackListener() 25 | { 26 | input_file->close(); 27 | input_timer->stop(); 28 | 29 | delete input_file; 30 | delete input_timer; 31 | } 32 | 33 | bool FallbackListener::openInputFile() 34 | { 35 | // the file is open and ready, exit 36 | if ( input_file != nullptr && input_file->isReadable() && input_file->isWritable() ) 37 | return true; 38 | 39 | QString input_file_path = Global::getTraderPath() + QDir::separator() + "in.txt"; 40 | 41 | // if the file is open but stale, dispose of it 42 | if ( input_file && ( !input_file->isReadable() || !input_file->exists() ) ) 43 | { 44 | input_file->deleteLater(); 45 | input_file = nullptr; 46 | } 47 | 48 | // initialize input file if needed 49 | if ( input_file == nullptr ) 50 | { 51 | input_file = new QFile( input_file_path ); 52 | if ( !input_file->open( QIODevice::ReadWrite | QIODevice::Text ) ) 53 | { 54 | // delete the file handle 55 | input_file->deleteLater(); 56 | input_file = nullptr; 57 | 58 | kDebug() << "[FallbackListener] local error: failed to open input file for read/write:" << input_file->fileName(); 59 | return false; 60 | } 61 | 62 | kDebug() << "[FallbackListener] opened fallback input file" << input_file->fileName(); 63 | } 64 | 65 | return true; 66 | } 67 | 68 | void FallbackListener::parseInputFile() 69 | { 70 | // check/try to open file, and check for bytes available 71 | if ( !openInputFile() || input_file->bytesAvailable() == 0 ) 72 | return; 73 | 74 | // check for new lines 75 | QString data = input_file->readAll(); 76 | 77 | // truncate the file before we parse the commands, incase we run 'exit', otherwise they'll run next time 78 | // NOTE: this causes problems, as we can't bombard the text file with frequent edits. use IPC sockets instead, except for bulk calls. 79 | if ( !data.isEmpty() ) 80 | { 81 | input_file->resize( 0 ); 82 | } 83 | 84 | emit gotDataChunk( data ); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /daemon/fallbacklistener.h: -------------------------------------------------------------------------------- 1 | #ifndef FALLBACKLISTENER_H 2 | #define FALLBACKLISTENER_H 3 | 4 | #include 5 | 6 | class QFile; 7 | class QTimer; 8 | 9 | class FallbackListener : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit FallbackListener( QObject *parent = nullptr ); 14 | ~FallbackListener(); 15 | 16 | signals: 17 | void gotDataChunk( QString &s ); 18 | 19 | public slots: 20 | void parseInputFile(); 21 | 22 | private: 23 | bool openInputFile(); 24 | 25 | QFile *input_file; 26 | QTimer *input_timer; 27 | }; 28 | 29 | #endif // FALLBACKLISTENER_H 30 | -------------------------------------------------------------------------------- /daemon/keydefs.h.example: -------------------------------------------------------------------------------- 1 | #ifndef KEYDEFS_H 2 | #define KEYDEFS_H 3 | 4 | // put your poloniex key/secret here 5 | #define POLONIEX_KEY "POLONIEX-KEY-12345" 6 | #define POLONIEX_SECRET "227ac44a..." 7 | 8 | // put your bittrex key/secret here 9 | #define BITTREX_KEY "88a25c45..." 10 | #define BITTREX_SECRET "a47b25..." 11 | 12 | // put your binance key/secret here 13 | #define BINANCE_KEY "AJSDF45abc123..." 14 | #define BINANCE_SECRET "AJSD56abc123..." 15 | 16 | // put your waves private key here 17 | #define WAVES_SECRET "base58key" 18 | 19 | #endif // KEYDEFS_H 20 | 21 | -------------------------------------------------------------------------------- /daemon/keystore.h: -------------------------------------------------------------------------------- 1 | #ifndef KEYSTORE_H 2 | #define KEYSTORE_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class KeyStore 12 | { 13 | public: 14 | static const int pad_size = 32; // pad_size must be divisible by 4 15 | static const int junk_factor = 12; // set greater than 1 16 | static const int sane_minimum_size = 32*2; 17 | static const int pad_size_final = std::max( sane_minimum_size, std::min( pad_size * ( junk_factor ), std::numeric_limits::max() - ( pad_size * junk_factor ) ) ); 18 | 19 | static_assert( pad_size % 4 == 0 ); 20 | static_assert( pad_size > 0 ); 21 | static_assert( junk_factor > 1 ); 22 | 23 | explicit KeyStore() { test(); } 24 | void setKeys( const QByteArray &key, const QByteArray &secret ) 25 | { 26 | // setKeys() essentially refreshes our store 27 | clear(); 28 | 29 | // generate pad 30 | for ( int i = 0; i < pad_size_final; i += 4 ) 31 | { 32 | quint32 rand = QRandomGenerator::system()->generate(); 33 | m_pad += quint8( rand >> 24 ); 34 | m_pad += quint8( rand >> 16 ); 35 | m_pad += quint8( rand >> 8 ); 36 | m_pad += quint8( rand ); 37 | } 38 | //qDebug() << m_pad.toHex(); 39 | assert( m_pad.size() == pad_size_final ); 40 | 41 | // generate offset to read from 42 | m_offset = QRandomGenerator::system()->generate() % ( pad_size * junk_factor ); 43 | 44 | const QByteArray &pad_to_use = m_getPad(); 45 | m_key = xorDecodeEncode( key, pad_to_use ); 46 | m_secret = xorDecodeEncode( secret, pad_to_use ); 47 | } 48 | 49 | void test() 50 | { 51 | const QByteArray test_key = QByteArray::fromHex("07D1"); 52 | const QByteArray test_secret = QByteArray::fromHex("F877"); 53 | 54 | setKeys( test_key, test_secret ); 55 | 56 | assert( getKey() == test_key ); 57 | assert( getSecret() == test_secret ); 58 | } 59 | 60 | void clear() 61 | { 62 | m_pad.clear(); 63 | m_key.clear(); 64 | m_secret.clear(); 65 | m_offset = 0; 66 | } 67 | 68 | static QByteArray xorDecodeEncode( const QByteArray &m /*msg*/, const QByteArray &k /*key*/ ) 69 | { 70 | if ( k.isEmpty() || m.isEmpty() ) 71 | return QByteArray(); 72 | 73 | QByteArray ret; 74 | const int k_size = k.size(); 75 | for ( int i = 0; i < m.size(); i++ ) 76 | ret += m[ i ] ^ k.at( i % k_size ); 77 | 78 | assert( ret.size() == m.size() ); 79 | return ret; 80 | } 81 | 82 | bool isKeyOrSecretEmpty() const { return m_key.isEmpty() || m_secret.isEmpty(); } 83 | QByteArray getKey() const { return xorDecodeEncode( m_key, m_getPad() ); } 84 | QByteArray getSecret() const { return xorDecodeEncode( m_secret, m_getPad() ); } 85 | 86 | private: 87 | const QByteArray m_getPad() const { return m_pad.mid( m_offset, pad_size ); } 88 | 89 | QByteArray m_key, m_secret, m_pad; 90 | quint16 m_offset; 91 | }; 92 | 93 | #endif // KEYSTORE_H 94 | -------------------------------------------------------------------------------- /daemon/main.cpp: -------------------------------------------------------------------------------- 1 | #include "global.h" 2 | #include "trader.h" 3 | 4 | #include 5 | #include 6 | 7 | int main( qint32 argc, char *argv[] ) 8 | { 9 | // set message handler 10 | qInstallMessageHandler( Global::messageOutput ); 11 | 12 | // start qapp 13 | QCoreApplication a( argc, argv ); 14 | 15 | // start trader 16 | Trader *trader = new Trader(); Q_UNUSED( trader ) 17 | 18 | int ret = a.exec(); 19 | 20 | kDebug() << QString( "main() done, code %1.").arg( ret ); 21 | 22 | return ret; 23 | } 24 | -------------------------------------------------------------------------------- /daemon/market.cpp: -------------------------------------------------------------------------------- 1 | #include "market.h" 2 | 3 | Market::Market() 4 | { 5 | } 6 | 7 | Market::Market( const QString &market ) 8 | { 9 | // find separator index 10 | int sep_idx = market.indexOf( QChar( '_' ) ); 11 | if ( sep_idx < 0 ) 12 | sep_idx = market.indexOf( QChar( '-' ) ); 13 | 14 | // check for separator 15 | if ( sep_idx < 0 ) 16 | return; 17 | 18 | base = market.left( sep_idx ); 19 | quote = market.mid( sep_idx +1, market.size() - sep_idx -1 ); 20 | } 21 | 22 | Market::Market( const QString &_base, const QString &_quote ) 23 | : base( _base ), 24 | quote( _quote ) 25 | { 26 | } 27 | 28 | bool Market::isValid() const 29 | { 30 | return !( base.isEmpty() || quote.isEmpty() ); 31 | } 32 | 33 | bool Market::operator ==( const QString &other ) const 34 | { 35 | return operator QString() == other; 36 | } 37 | 38 | bool Market::operator !=( const QString &other ) const 39 | { 40 | return !operator ==( other ); 41 | } 42 | 43 | Market::operator QString() const 44 | { 45 | return !isValid() ? QString() : 46 | QString( DEFAULT_MARKET_STRING_TEMPLATE ) 47 | .arg( base ) 48 | .arg( quote ); 49 | } 50 | 51 | QString Market::toExchangeString( const quint8 engine_type ) const 52 | { 53 | return QString( engine_type == ENGINE_BITTREX ? BITTREX_MARKET_STRING_TEMPLATE : 54 | engine_type == ENGINE_BINANCE ? BINANCE_MARKET_STRING_TEMPLATE : 55 | engine_type == ENGINE_POLONIEX ? POLONIEX_MARKET_STRING_TEMPLATE : 56 | QString() ) 57 | .arg( base ) 58 | .arg( quote ); 59 | } 60 | -------------------------------------------------------------------------------- /daemon/market.h: -------------------------------------------------------------------------------- 1 | #ifndef MARKET_H 2 | #define MARKET_H 3 | 4 | #include "global.h" 5 | #include "positiondata.h" 6 | #include "coinamount.h" 7 | #include "misctypes.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | class Market 14 | { 15 | public: 16 | Market(); 17 | Market( const QString &market ); 18 | Market( const QString &_base, const QString &_quote ); 19 | bool isValid() const; 20 | 21 | bool operator <( const Market &other ) const { return this->operator QString() < other.operator QString(); } 22 | bool operator ==( const QString &other ) const; 23 | bool operator !=( const QString &other ) const; 24 | operator QString() const; // obtain universal string 25 | QString toExchangeString( const quint8 engine_type ) const; // obtain exchange-specific string 26 | 27 | const QString &getBase() const { return base; } 28 | const QString &getQuote() const { return quote; } 29 | 30 | Market getInverse() const { return Market( getQuote(), getBase() ); } 31 | 32 | private: 33 | QString base, quote; 34 | }; 35 | 36 | struct MarketInfo 37 | { 38 | explicit MarketInfo() 39 | { 40 | } 41 | 42 | operator QString() const { return QString( "bid %1 ask %2 tradeable %3 price_tick %4 matcher_tick %5 qty_tick %6 order_min %7 order_max %8 order_dc %9 order_dc_nice %10 order_landmark_thresh %11 order_landmark_start %12 slippage_timeout %13 market_offset %14 market_sentiment %15" ) 43 | .arg( spread.bid, -16 ) 44 | .arg( spread.ask, -16 ) 45 | .arg( is_tradeable ) 46 | .arg( price_ticksize ) 47 | .arg( quantity_ticksize ) 48 | .arg( matcher_ticksize ) 49 | .arg( order_min, -2 ) 50 | .arg( order_max, -2 ) 51 | .arg( order_dc, -2 ) 52 | .arg( order_dc_nice, -2 ) 53 | .arg( order_landmark_thresh, -2 ) 54 | .arg( order_landmark_start, -2 ) 55 | .arg( slippage_timeout, -6 ) 56 | .arg( market_offset, -6 ) 57 | .arg( market_sentiment ); } // TODO: fill in this string for binance stuff 58 | 59 | // void jsonifyTicker( QJsonArray &arr, const QString &market ) const 60 | // { 61 | // arr += "t"; 62 | // arr += market; 63 | // arr += Coin( spread.bid ).toAmountString(); 64 | // arr += Coin( spread.ask ).toAmountString(); 65 | // } 66 | // void jsonifyBid( QJsonArray &arr, const QString &market ) const 67 | // { 68 | // arr += "b"; 69 | // arr += market; 70 | // arr += spread.bid.toAmountString(); 71 | // } 72 | // void jsonifyAsk( QJsonArray &arr, const QString &market ) const 73 | // { 74 | // arr += "a"; 75 | // arr += market; 76 | // arr += spread.ask.toAmountString(); 77 | // } 78 | 79 | // prices for this market 80 | QVector order_prices; 81 | 82 | // internal ticker 83 | Spread spread; 84 | 85 | // ping-pong settings 86 | QVector /*position_index*/ position_index; 87 | qint32 /*order count limit*/ order_min{ 5 }; 88 | qint32 /*order count limit*/ order_max{ 10 }; 89 | qint32 /*order count combine*/ order_dc{ 1 }; 90 | qint32 /*nice value*/ order_dc_nice{ 0 }; 91 | qint32 /*n*/ order_landmark_thresh{ 0 }; 92 | qint32 /*n*/ order_landmark_start{ 0 }; 93 | qint32 /*timeout secs*/ slippage_timeout{ 2 * 60000 }; 94 | qreal /*offset scalar*/ market_offset{ 0. }; 95 | bool /*bullish*/ market_sentiment{ false }; 96 | 97 | // per-market settings 98 | Coin price_ticksize{ CoinAmount::SATOSHI }; // used to find new prices and pass binance filter PRICE_FILTER "tickSize" 99 | 100 | // Binance only - used to pass filter PERCENT_PRICE 101 | Coin price_min_mul{ 0.2 }; 102 | Coin price_max_mul{ 5.0 }; 103 | Coin quantity_ticksize{ CoinAmount::SATOSHI }; // used to pass filter LOT_SIZE "stepSize" 104 | 105 | // waves exchange 106 | Coin matcher_ticksize{ CoinAmount::SATOSHI }; 107 | 108 | // inverse market tags 109 | bool is_tradeable{ false }; 110 | }; 111 | 112 | #endif // MARKET_H 113 | -------------------------------------------------------------------------------- /daemon/misctypes.h: -------------------------------------------------------------------------------- 1 | #ifndef MISCTYPES_H 2 | #define MISCTYPES_H 3 | 4 | #include "coinamount.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class Position; 12 | 13 | struct Request 14 | { 15 | explicit Request() {} 16 | 17 | QString api_command; 18 | QString body; 19 | qint64 time_sent_ms{ 0 }; // track timeouts 20 | quint16 weight{ 0 }; // for binance, command weight 21 | Position *pos{ nullptr }; 22 | }; 23 | 24 | struct OrderInfo 25 | { 26 | explicit OrderInfo( const QString &_order_number, 27 | const quint8 &_side, 28 | const QString &_price, 29 | const QString &_amount ) 30 | { 31 | order_number = _order_number; 32 | side = _side; 33 | price = _price; 34 | amount = _amount; 35 | } 36 | 37 | QString order_number; 38 | quint8 side; 39 | QString price; 40 | QString amount; 41 | }; 42 | 43 | struct Spread 44 | { 45 | explicit Spread() {} 46 | explicit Spread( const Coin &_bid_price, 47 | const Coin &_ask_price ) 48 | { 49 | bid = _bid_price; 50 | ask = _ask_price; 51 | } 52 | 53 | operator QString() const { return QString( "bid: %1 ask: %2" ) 54 | .arg( bid ) 55 | .arg( ask ); } 56 | 57 | bool isValid() const { return bid.isGreaterThanZero() && ask.isGreaterThanZero(); } 58 | Coin getMidPrice() const { return ( ask + bid ) / 2; } 59 | 60 | Coin bid; 61 | Coin ask; 62 | }; 63 | 64 | class AvgResponseTime 65 | { 66 | public: 67 | explicit AvgResponseTime() {} 68 | 69 | void addResponseTime( quint64 time ) 70 | { 71 | total += time; 72 | iterations++; 73 | } 74 | quint64 avgResponseTime() const { return iterations == 0 ? 0 : total / iterations; } 75 | 76 | private: 77 | quint64 total{ 0 }, 78 | iterations{ 0 }; 79 | }; 80 | 81 | class CoinAverage 82 | { 83 | public: 84 | explicit CoinAverage() {} 85 | 86 | void addSample( const Coin &sample ) 87 | { 88 | total += sample; 89 | iterations++; 90 | } 91 | Coin getSignal() const { return iterations == 0 ? CoinAmount::ZERO : total / iterations; } 92 | 93 | private: 94 | Coin total; 95 | quint64 iterations{ 0 }; 96 | }; 97 | 98 | #endif // MISCTYPES_H 99 | -------------------------------------------------------------------------------- /daemon/polorest.h: -------------------------------------------------------------------------------- 1 | #ifndef POLOREST_H 2 | #define POLOREST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "global.h" 10 | #include "position.h" 11 | #include "keystore.h" 12 | #include "baserest.h" 13 | 14 | 15 | class QNetworkReply; 16 | class QTimer; 17 | class QWebSocket; 18 | 19 | class PoloREST : public BaseREST 20 | { 21 | Q_OBJECT 22 | 23 | friend class CommandRunner; 24 | 25 | public: 26 | explicit PoloREST( Engine *_engine, QNetworkAccessManager *_nam ); 27 | ~PoloREST(); 28 | 29 | void init(); 30 | 31 | bool yieldToLag() const; 32 | 33 | void sendNamRequest( Request *const &request ); 34 | void sendBuySell( Position *const &pos, bool quiet = true ); 35 | void sendCancel( const QString &order_id, Position *const &pos = nullptr ); 36 | 37 | void parseBuySell( Request *const &request, const QJsonObject &response ); 38 | void parseCancelOrder( Request *const &request, const QJsonObject &response ); 39 | void parseOpenOrders( const QJsonObject &markets, qint64 request_time_sent_ms ); 40 | void parseReturnBalances( const QJsonObject &balances ); 41 | void parseFeeInfo( const QJsonObject &info ); 42 | void parseOrderBook( const QJsonObject &info, qint64 request_time_sent_ms ); 43 | 44 | void wssSendJsonObj( const QJsonObject &obj ); 45 | void setupCurrencyMap( QMap &m ); 46 | 47 | bool getWSS1000State() const { return wss_1000_state; } 48 | qreal getSlippageMul( const QString &market ) const { return slippage_multiplier.value( market, 0.005 ); } 49 | 50 | void checkBotOrders( bool ignore_flow_control = false ); 51 | 52 | public Q_SLOTS: 53 | // timer slots 54 | void sendNamQueue(); 55 | void onCheckBotOrders(); 56 | void onCheckTicker(); 57 | void onCheckFee(); 58 | 59 | // nam slots 60 | void onNamReply( QNetworkReply *const &reply ); 61 | 62 | // websockets slots 63 | void wssConnected(); 64 | void wssCheckConnection(); 65 | void wssTextMessageReceived( const QString &msg ); 66 | void wssSendSubscriptions(); 67 | 68 | private: 69 | QMap currency_name_by_id; // currency ids for websocket feed 70 | QMap slippage_multiplier; 71 | 72 | bool wss_1000_state{ false }, // account subscription 73 | wss_1002_state{ false }; // ticker subscription 74 | 75 | qint64 wss_connect_try_time{ 0 }, 76 | wss_heartbeat_time{ 0 }, 77 | wss_1000_subscribe_try_time{ 0 }, 78 | wss_1002_subscribe_try_time{ 0 }, 79 | wss_account_feed_update_time{ 0 }; 80 | 81 | qint64 poloniex_throttle_time{ 0 }; // when we should wait until to sent the next request 82 | 83 | QTimer *fee_timer{ nullptr }; 84 | QTimer *wss_timer{ nullptr }; 85 | QWebSocket *wss{ nullptr }; 86 | }; 87 | 88 | #endif // POLOREST_H 89 | -------------------------------------------------------------------------------- /daemon/position.h: -------------------------------------------------------------------------------- 1 | #ifndef POSITION_H 2 | #define POSITION_H 3 | 4 | #include "global.h" 5 | #include "coinamount.h" 6 | #include "market.h" 7 | 8 | #include 9 | 10 | class Engine; 11 | 12 | class Position 13 | { 14 | public: 15 | explicit Position( QString _market, quint8 _side, QString _buy_price, QString _sell_price, 16 | QString _order_size, QString _strategy_tag = QLatin1String(), 17 | QVector _market_indices = QVector(), 18 | bool _landmark = false, Engine *_engine = nullptr ); 19 | ~Position(); 20 | 21 | void calculateQuantity(); 22 | void flip(); 23 | QString getFlippedPrice() { return side == SIDE_BUY ? sell_price_original : buy_price_original; } 24 | bool applyPriceSide(); 25 | void applyOffset(); 26 | void applyOffset( qreal offset, bool sentiment = true ); 27 | void jsonifyPositionFill( QJsonArray &arr ); 28 | void jsonifyPositionSet( QJsonArray &arr ); 29 | void jsonifyPositionCancel( QJsonArray &arr ); 30 | QString stringifyOrder(); 31 | QString stringifyOrderWithoutOrderID(); 32 | QString stringifyNewPosition(); 33 | QString stringifyPositionChange(); 34 | QString sideStr() const { return side == SIDE_BUY ? QString( BUY ) : 35 | QString( SELL ); } 36 | qint32 getLowestMarketIndex() const; 37 | qint32 getHighestMarketIndex() const; 38 | 39 | // exchange data 40 | Market market; // BTC_CLAM... 41 | QString order_number; 42 | 43 | Coin quantity; 44 | 45 | quint8 side; // buy = 1, sell = 2 46 | quint8 cancel_reason; 47 | 48 | qint64 order_set_time; // 0 when not set 49 | qint64 order_request_time; // 0 when not requested 50 | qint64 order_cancel_time; // 0 when not cancelling 51 | qint64 order_getorder_time; // 0 or last getorder time 52 | 53 | // our position data 54 | QString indices_str; 55 | Coin price, buy_price, sell_price; 56 | Coin buy_price_original, sell_price_original; 57 | Coin original_size, amount, per_trade_profit, profit_margin, btc_commission; 58 | quint32 price_reset_count; 59 | qint64 max_age_epoch; // epoch time of when we should cancel the order 60 | QString strategy_tag; // tag for short/long 61 | 62 | // track indices for market map 63 | QVector market_indices; 64 | 65 | bool is_cancelling, 66 | is_landmark, 67 | is_slippage, // order has slippage 68 | is_new_hilo_order, 69 | is_onetime, // is a one-time order, ping-pong disabled 70 | is_taker; // is taker, post-only disabled 71 | 72 | private: 73 | Engine *engine; 74 | }; 75 | 76 | 77 | #endif // POSITION_H 78 | -------------------------------------------------------------------------------- /daemon/positiondata.h: -------------------------------------------------------------------------------- 1 | #ifndef POSITIONDATA_H 2 | #define POSITIONDATA_H 3 | 4 | #include 5 | 6 | struct PositionData 7 | { 8 | explicit PositionData() {} 9 | explicit PositionData( QString _buy_price, QString _sell_price, QString _order_size, QString _alternate_size ) 10 | { 11 | buy_price = _buy_price; 12 | sell_price = _sell_price; 13 | order_size = _order_size; 14 | alternate_size = _alternate_size; 15 | fill_count = 0; 16 | } 17 | 18 | void iterateFillCount() 19 | { 20 | fill_count++; 21 | if ( !alternate_size.isEmpty() ) 22 | { 23 | order_size = alternate_size; 24 | alternate_size.clear(); 25 | } 26 | } 27 | 28 | QString buy_price, sell_price, order_size, alternate_size; 29 | quint32 fill_count; 30 | }; 31 | 32 | #endif // POSITIONDATA_H 33 | -------------------------------------------------------------------------------- /daemon/positionman.h: -------------------------------------------------------------------------------- 1 | #ifndef POSITIONMAN_H 2 | #define POSITIONMAN_H 3 | 4 | #include "global.h" 5 | #include "coinamount.h" 6 | #include "market.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | class Position; 16 | class Engine; 17 | 18 | // 19 | // PositionMan, helps Engine manage the positions 20 | // 21 | class PositionMan : public QObject 22 | { 23 | Q_OBJECT 24 | 25 | friend class EngineTest; 26 | 27 | public: 28 | explicit PositionMan( Engine *_engine, QObject *parent = nullptr ); 29 | ~PositionMan(); 30 | 31 | QSet &active() { return positions_active; } 32 | QSet &queued() { return positions_queued; } 33 | QSet &all() { return positions_all; } 34 | QVector activeBySetTime() const; 35 | 36 | bool hasActivePositions() const; 37 | bool hasQueuedPositions() const; 38 | bool isActive( Position *const &pos ) const; 39 | bool isQueued( Position *const &pos ) const; 40 | bool isValid( Position *const &pos ) const; 41 | bool isValidOrderID( const QString &order_id ) const; 42 | 43 | Position *getByOrderID( const QString &order_id ) const; 44 | Position *getByIndex( const QString &market, const qint32 idx ) const; 45 | Position *getHighestBuyAll( const QString &market ) const; 46 | Position *getLowestSellAll( const QString &market ) const; 47 | Position *getHighestBuyByIndex( const QString &market ) const; 48 | Position *getHighestSellByIndex( const QString &market ) const; 49 | Position *getLowestSellByIndex( const QString &market ) const; 50 | Position *getLowestBuyByIndex( const QString &market ) const; 51 | Position *getHighestBuyByPrice( const QString &market ) const; 52 | Position *getLowestSellByPrice( const QString &market ) const; 53 | Position *getLowestPingPong( const QString &market ) const; 54 | Position *getHighestPingPong( const QString &market ) const; 55 | Position *getHighestSpruceBuy( const QString &market ) const; 56 | Position *getLowestSpruceSell( const QString &market ) const; 57 | Position *getRandomSprucePosition( const QString &market, const quint8 side ); 58 | 59 | qint32 getLowestPingPongIndex( const QString &market ) const; 60 | qint32 getHighestPingPongIndex( const QString &market ) const; 61 | qint32 getMarketOrderTotal( const QString &market, bool onetime_only = false ) const; 62 | qint32 getTotalOrdersForSide( const Market &market, const quint8 side, const QString &strategy_filter = QLatin1String() ) const; 63 | 64 | void flipHiBuyPrice( const QString &market, QString tag ); 65 | void flipHiBuyIndex( const QString &market, QString tag ); 66 | void flipLoSellPrice( const QString &market, QString tag ); 67 | void flipLoSellIndex( const QString &market, QString tag ); 68 | 69 | Coin getLoSell( const QString &market ) const; 70 | Coin getHiBuy( const QString &market ) const; 71 | Coin getHiBuyFlipPrice( const QString &market ) const; 72 | Coin getLoSellFlipPrice( const QString &market ) const; 73 | 74 | Coin getActiveSpruceEquityTotal( const Market &market, const QString &strategy, quint8 side, const Coin &price_threshold ); 75 | 76 | void add( Position *const &pos ); 77 | void activate( Position *const &pos, const QString &order_number ); 78 | void remove( Position *const &pos ); 79 | 80 | // ping-pong routines 81 | void checkBuySellCount(); 82 | 83 | // cancel commands 84 | void cancel( Position *const &pos, bool quiet = false, quint8 cancel_reason = 0 ); 85 | void cancelAll( QString market ); 86 | void cancelLocal( QString market = "" ); 87 | void cancelHighest( const QString &market ); 88 | void cancelLowest( const QString &market ); 89 | void cancelStrategy( const QString &strategy ); 90 | void cancelFluxOrders( const QString ¤cy, const Coin &required, const QString &available, const qint64 ban_secs = 0 ); 91 | 92 | void divergeConverge(); 93 | bool isDivergingConverging( const QString &market, const qint32 index ) const; 94 | int getDCCount() { return diverge_converge.size(); } 95 | QMap,QPair>> &getDCMap() { return diverge_converge; } 96 | QMap> &getDCPending() { return diverging_converging; } 97 | 98 | void setRunningCancelAll( bool b ) { is_running_cancelall = b; } 99 | bool isRunningCancelAll() const { return is_running_cancelall; } 100 | const QString &getCancelMarketFilter() const { return cancel_market_filter; } 101 | 102 | private: 103 | void setNextLowest( const QString &market, quint8 side = SIDE_BUY, bool landmark = false ); 104 | void setNextHighest( const QString &market, quint8 side = SIDE_SELL, bool landmark = false ); 105 | void removeFromDC( Position *const &pos ); 106 | 107 | void converge( QMap> &market_map, quint8 side ); 108 | void diverge( QMap> &market_map ); 109 | 110 | // maintain a map of queued positions and set positions 111 | QHash positions_by_number; 112 | QSet positions_active; // ptr list of active positions 113 | QSet positions_queued; // ptr list of queued positions 114 | QSet positions_all; // active and queued 115 | 116 | // internal dc stuff 117 | QMap/*waiting for cancel*/, QPair/*indices*/>> diverge_converge; 118 | QMap/*reserved idxs*/> diverging_converging; // store a vector of converging/diverging indices 119 | 120 | // cancelall command state 121 | QString cancel_market_filter; 122 | bool is_running_cancelall{ false }; 123 | 124 | Engine *engine; 125 | }; 126 | 127 | #endif // POSITIONMAN_H 128 | -------------------------------------------------------------------------------- /daemon/priceaggregator.h: -------------------------------------------------------------------------------- 1 | #ifndef PRICEAGGREGATOR_H 2 | #define PRICEAGGREGATOR_H 3 | 4 | #include "coinamount.h" 5 | #include "misctypes.h" 6 | #include "pricesignal.h" 7 | #include "global.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | class EngineMap; 16 | class QTimer; 17 | 18 | /* 19 | * PriceData 20 | * 21 | * Data for each MA in the config 22 | * 23 | */ 24 | struct PriceData 25 | { 26 | PriceData() {} 27 | ~PriceData() {} 28 | 29 | qint64 data_start_secs{ 0 }; 30 | QVector data; 31 | }; 32 | 33 | /* PriceAggregatorConfig 34 | * 35 | * Holds data for each market in the PriceAggregator config. 36 | * 37 | */ 38 | struct PriceAggregatorConfig 39 | { 40 | PriceAggregatorConfig(); 41 | PriceAggregatorConfig( const QString &_market, 42 | const int _base_interval_secs, 43 | const int _base_len, 44 | const int _strategy_length, 45 | const int _strategy_length_internal_option0, 46 | const int _interval_counter = 0, 47 | const Coin jumpstart_price = Coin() ); 48 | 49 | void jumpstart( const Coin &price ); 50 | 51 | // data in the config file 52 | QString market; 53 | 54 | int base_interval_secs{ 0 }; // record new sample for price every x secs 55 | int base_length{ 0 }; 56 | int strategy_length{ 0 }; 57 | 58 | // TODO: these should be a stack and interval/lengths should be in PriceData 59 | // data in the small_ma file 60 | PriceData base_data; 61 | 62 | // data in the signal ma file 63 | PriceSignal signal_base, signal_strategy; 64 | }; 65 | 66 | /* PriceAggregator 67 | * 68 | * Aggregates prices from the engines. 69 | * Saves/loads price history. 70 | * Maintains a config of markets to commit to disk. 71 | * Computes averages, etc. from price history according to config. 72 | * 73 | */ 74 | class PriceAggregator : public QObject 75 | { 76 | Q_OBJECT 77 | 78 | public: 79 | explicit PriceAggregator( EngineMap *_engine_map ); 80 | ~PriceAggregator(); 81 | 82 | static QString getSettingsPath(); 83 | static QString getSamplesPath( const QString &market, const qint64 interval_secs ); 84 | 85 | static void savePriceSamples(const PriceAggregatorConfig &config , const QString filename_override = QString() ); 86 | static bool loadPriceSamples( PriceData &data, const QString &path ); 87 | 88 | Spread getSpread( const QString &market ) const; 89 | Coin getStrategySignal( const QString &market ); 90 | 91 | void addPersistentMarket( const PriceAggregatorConfig &config ); 92 | 93 | void saveMaybe(); 94 | void save(); 95 | void saveConfig(); 96 | void savePrices(); 97 | void load(); 98 | void loadConfig(); 99 | void loadPrices(); 100 | 101 | signals: 102 | void gotUserCommandChunk( QString &s ); 103 | 104 | public Q_SLOTS: 105 | void onTimerUp(); 106 | 107 | private: 108 | void nextPriceSample(); 109 | 110 | QMap m_config; 111 | QVector m_currencies; 112 | QVector m_markets; 113 | 114 | qint64 m_last_save_secs{ 0 }; 115 | qint64 m_save_interval_secs{ 3600 }; // save config/samples every x seconds 116 | EngineMap *m_engine_map{ nullptr }; 117 | QTimer *m_timer{ nullptr }; 118 | }; 119 | 120 | #endif // PRICEAGGREGATOR_H 121 | -------------------------------------------------------------------------------- /daemon/pricesignal.h: -------------------------------------------------------------------------------- 1 | #ifndef PRICESIGNAL_H 2 | #define PRICESIGNAL_H 3 | 4 | #include "coinamount.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | enum PriceSignalType 13 | { 14 | SMA, // 0 15 | WMA, // 1 16 | EMA, // 2 17 | RSI, // 3 18 | SMARatio, // 4 19 | WMARatio, // 5 20 | EMARatio, // 6 21 | RSIRatio, // 7 22 | HMA // 8 23 | // GMA // 9 24 | }; 25 | 26 | class PriceSignal 27 | { 28 | public: 29 | 30 | PriceSignal( const PriceSignalType _type = SMA, const int _fast_length = 0, const int _slow_length = 0, const Coin &_weight = CoinAmount::COIN ); 31 | ~PriceSignal(); 32 | 33 | void setSignalArgs( const PriceSignalType _type, const int _fast_length = 0, const int _slow_length = 0, const Coin &_weight = CoinAmount::COIN ); 34 | // PriceSignalType getType() const { return type; } 35 | 36 | inline void applyWeight( Coin &signal ) const; 37 | 38 | void setMaxSamples( const int max ); 39 | int getMaxSamples() const { return samples_max; } 40 | int getCurrentSamples() const { return samples.size(); } 41 | void removeExcessSamples(); 42 | 43 | void clear(); 44 | 45 | const Coin &getSignal(); 46 | const Coin &getSignalSMA(); 47 | const Coin &getSignalSMAR(); 48 | const Coin &getSignalRSI(); 49 | const Coin &getSignalRSIR(); 50 | const Coin &getSignalRSIRES(); 51 | const Coin &getSignalEMA(); 52 | const Coin &getSignalEMAR(); 53 | const Coin &getSignalWMA(); 54 | const Coin &getSignalWMAR(); 55 | const Coin &getSignalHMA(); 56 | // const Coin &getSignalGMA(); 57 | 58 | void addSample( const Coin &sample ); 59 | void addSampleSMASMAR( const Coin &sample ); 60 | void addSampleRSIRISRRSIRES( const Coin &sample ); 61 | void addSampleWMAEMAWMAREMAR( const Coin &sample ); 62 | void addSampleHMA( const Coin &sample ); 63 | // void addSampleGMA( const Coin &sample ); 64 | 65 | bool hasSignal() const; 66 | 67 | // void setCounterMax( int max ) { counter_max = std::max( 0, max ); } 68 | // void iterateCounter() { counter++; } 69 | // void resetCounter() { counter = 0; } 70 | // bool shouldUpdateSignal() const { }; 71 | 72 | private: 73 | QVector> getsignal_internal; 74 | QVector> addsample_internal; 75 | Coin getsignal_result; 76 | 77 | PriceSignalType type{ SMA }; 78 | Coin weight{ CoinAmount::COIN }; 79 | // int counter{ 0 }, counter_max{ 0 }; 80 | 81 | // sma/wma/ema 82 | int samples_max{ 0 }; 83 | QQueue samples; 84 | 85 | // sma only 86 | Coin sum; 87 | 88 | // rsi 89 | QQueue gain_loss; 90 | Coin current_avg_gain, current_avg_loss; 91 | 92 | // ma types 93 | int i; 94 | Coin wt, s, w; 95 | 96 | // for ratioized PriceSignals 97 | int fast_length{ 0 }, slow_length{ 0 }; 98 | PriceSignal *embedded_signal{ nullptr }; 99 | }; 100 | 101 | #endif // PRICESIGNAL_H 102 | -------------------------------------------------------------------------------- /daemon/pricesignal_test.h: -------------------------------------------------------------------------------- 1 | #ifndef PRICESIGNAL_TEST_H 2 | #define PRICESIGNAL_TEST_H 3 | 4 | struct PriceSignalTest 5 | { 6 | void test(); 7 | }; 8 | 9 | 10 | #endif // PRICESIGNAL_TEST_H 11 | -------------------------------------------------------------------------------- /daemon/spruceoverseer.h: -------------------------------------------------------------------------------- 1 | #ifndef SPRUCEOVERSEER_H 2 | #define SPRUCEOVERSEER_H 3 | 4 | #include "global.h" 5 | #include "market.h" 6 | #include "coinamount.h" 7 | #include "misctypes.h" 8 | #include "diffusionphaseman.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class AlphaTracker; 18 | class PriceAggregator; 19 | class SpruceV2; 20 | class EngineMap; 21 | class Engine; 22 | class QTimer; 23 | 24 | class SpruceOverseer : public QObject 25 | { 26 | Q_OBJECT 27 | 28 | friend class SpruceOverseerTest; 29 | 30 | public: 31 | explicit SpruceOverseer( EngineMap *_engine_map, PriceAggregator *_price_aggregator, SpruceV2 *_spruce ); 32 | ~SpruceOverseer(); 33 | 34 | static QString getSettingsPath() { return Global::getTraderPath() + QDir::separator() + "spruce.settings"; } 35 | void loadSettings(); 36 | void saveSettings(); 37 | void loadStats(); 38 | void saveStats(); 39 | 40 | const QString &getLastMidspreadPhaseOutput() const { return m_last_midspread_output; } 41 | 42 | EngineMap *engine_map{ nullptr }; 43 | AlphaTracker *alpha{ nullptr }; 44 | PriceAggregator *price_aggregator{ nullptr }; 45 | SpruceV2 *spruce{ nullptr }; 46 | QTimer *spruce_timer{ nullptr }; 47 | 48 | signals: 49 | void gotUserCommandChunk( QString &s ); // loaded settings file 50 | 51 | public Q_SLOTS: 52 | void onSpruceUp(); 53 | void onBackupAndSave(); 54 | 55 | private: 56 | void runCancellors( Engine *engine, const QString &market, const quint8 side, const QString &strategy, const Coin &flux_price ); 57 | 58 | void adjustSpread( Spread &spread, Coin limit, quint8 side, Coin &default_ticksize, bool expand = true ); 59 | void adjustTicksizeToSpread( Coin &ticksize, Spread &spread, const Coin &ticksize_minimum ); 60 | Spread getSpreadLimit( const QString &market, bool order_duplicity = false ); 61 | Spread getSpreadForSide( const QString &market, quint8 side, bool order_duplicity = false, bool taker_mode = false, bool include_greed_random = false, bool is_randomized = false, Coin greed_reduce = Coin() ); 62 | Coin getPriceTicksizeForMarket( const Market &market ) const; 63 | 64 | QMap m_last_spread_distance_buys; 65 | QMap m_last_spread_distance_sells; 66 | QString m_last_midspread_output; 67 | 68 | DiffusionPhaseMan m_phase_man; 69 | 70 | QTimer *autosave_timer{ nullptr }; 71 | }; 72 | 73 | #endif // SPRUCEOVERSEER_H 74 | -------------------------------------------------------------------------------- /daemon/spruceoverseer_test.h: -------------------------------------------------------------------------------- 1 | #ifndef SPRUCEOVERSEER_TEST_H 2 | #define SPRUCEOVERSEER_TEST_H 3 | 4 | class SpruceOverseer; 5 | class Engine; 6 | 7 | struct SpruceOverseerTest 8 | { 9 | void test( SpruceOverseer *o , Engine *engine ); 10 | }; 11 | 12 | #endif // SPRUCEOVERSEER_TEST_H 13 | -------------------------------------------------------------------------------- /daemon/ssl_policy.h: -------------------------------------------------------------------------------- 1 | #ifndef SSLPOLICY_H 2 | #define SSLPOLICY_H 3 | 4 | #include 5 | #include "global.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | namespace SslPolicy 14 | { 15 | 16 | static inline void enableSecureSsl() 17 | { 18 | // disable chatty messages for disabled ssl stuff (might suppress problems with ssl in the future) 19 | //QLoggingCategory::setFilterRules( "qt.network.ssl.warning=false" ); 20 | 21 | // get default config 22 | QSslConfiguration ssl_config = QSslConfiguration::defaultConfiguration(); 23 | 24 | // enforce tls minimum version 25 | ssl_config.setProtocol( QSsl::TlsV1_2OrLater ); 26 | 27 | // enable ocsp (don't do this, it breaks things) 28 | //ssl_config.setOcspStaplingEnabled( true ); 29 | 30 | // disable legacy reneg 31 | ssl_config.setSslOption( QSsl::SslOptionDisableLegacyRenegotiation, true ); 32 | 33 | // disable compression 34 | ssl_config.setSslOption( QSsl::SslOptionDisableCompression, true ); 35 | 36 | QList cipher_list = ssl_config.supportedCiphers(); 37 | QList chosen_ciphers; 38 | 39 | QSet bad_ciphers; 40 | // old/weak 41 | bad_ciphers += "DHE-DSS-AES256-SHA256"; 42 | bad_ciphers += "DHE-DSS-AES128-SHA256"; 43 | bad_ciphers += "AES128-GCM-SHA256"; 44 | bad_ciphers += "AES256-GCM-SHA384"; 45 | bad_ciphers += "AES256-SHA256"; 46 | bad_ciphers += "AES128-SHA256"; 47 | bad_ciphers += "RSA-PSK-AES128-GCM-SHA256"; 48 | bad_ciphers += "RSA-PSK-AES256-GCM-SHA384"; 49 | bad_ciphers += "RSA-PSK-CHACHA20-POLY1305"; 50 | bad_ciphers += "DHE-RSA-AES128-SHA256"; 51 | bad_ciphers += "DHE-RSA-AES256-SHA256"; 52 | bad_ciphers += "ECDH-RSA-AES128-SHA256"; 53 | bad_ciphers += "ECDH-RSA-AES256-SHA384"; 54 | bad_ciphers += "ECDH-ECDSA-AES256-SHA384"; 55 | bad_ciphers += "ECDH-ECDSA-AES128-SHA256"; 56 | bad_ciphers += "ECDHE-RSA-AES128-SHA256"; 57 | bad_ciphers += "ECDHE-RSA-AES256-SHA256"; 58 | bad_ciphers += "ECDHE-ECDSA-AES128-SHA256"; 59 | bad_ciphers += "ECDHE-ECDSA-AES256-SHA384"; 60 | bad_ciphers += "ECDHE-RSA-AES256-SHA384"; 61 | 62 | // no forward secrecy 63 | bad_ciphers += "DHE-RSA-AES128-GCM-SHA256"; 64 | bad_ciphers += "DHE-PSK-AES128-GCM-SHA256"; 65 | bad_ciphers += "DHE-PSK-AES256-GCM-SHA384"; 66 | bad_ciphers += "DHE-PSK-CHACHA20-POLY1305"; 67 | bad_ciphers += "ECDHE-PSK-CHACHA20-POLY1305"; 68 | bad_ciphers += "PSK-AES128-GCM-SHA256"; 69 | bad_ciphers += "PSK-AES256-GCM-SHA384"; 70 | bad_ciphers += "PSK-CHACHA20-POLY1305"; 71 | 72 | // choose ciphers 73 | for ( int i = 0; i < cipher_list.size(); i++ ) 74 | { 75 | const QSslCipher &cipher = cipher_list.at( i ); 76 | const QString &cipher_str = cipher.name(); 77 | const QString &proto_str = cipher.protocolString(); 78 | 79 | // remove shit ciphers and protocols 80 | if ( proto_str == "TLSv1" || // for some reason setProtocol does not remove v1 proto ciphers 81 | cipher_str.contains( "MD5-" ) || // any md5 82 | cipher_str.contains( "RC4-" ) || // any rc4 83 | cipher_str.contains( "DES-" ) || // any des/3des 84 | cipher_str.endsWith( "-SHA" ) || // any counter mode with sha1 85 | bad_ciphers.contains( cipher_str ) ) 86 | { 87 | #if defined(PRINT_DISABLED_SSL_CIPHERS) 88 | kDebug() << "[SSL] disabled" << proto_str << cipher_str; 89 | #endif 90 | continue; 91 | } 92 | 93 | #if defined(PRINT_ENABLED_SSL_CIPHERS) 94 | kDebug() << "[SSL] enabled" << proto_str << cipher_str; 95 | #endif 96 | 97 | chosen_ciphers.append( cipher ); 98 | } 99 | 100 | // check for ciphers 101 | if ( chosen_ciphers.isEmpty() ) 102 | { 103 | kDebug() << "[SSL] local error: no secure ciphers found"; 104 | exit( 11 ); 105 | } 106 | 107 | // set ciphers as default config for this application 108 | ssl_config.setCiphers( chosen_ciphers ); 109 | QSslConfiguration::setDefaultConfiguration( ssl_config ); 110 | assert( QSslConfiguration::defaultConfiguration().ciphers() == chosen_ciphers ); 111 | } 112 | 113 | } 114 | 115 | #endif // SSLPOLICY_H 116 | -------------------------------------------------------------------------------- /daemon/trader.h: -------------------------------------------------------------------------------- 1 | #ifndef TREXTRADER_H 2 | #define TREXTRADER_H 3 | 4 | #include 5 | 6 | class QNetworkAccessManager; 7 | class CommandListener; 8 | class CommandRunner; 9 | class AlphaTracker; 10 | class PriceAggregator; 11 | class SpruceV2; 12 | class SpruceOverseer; 13 | class EngineMap; 14 | class Engine; 15 | class TrexREST; 16 | class BncREST; 17 | class PoloREST; 18 | class WavesREST; 19 | 20 | class Trader : public QObject 21 | { 22 | Q_OBJECT 23 | 24 | public: 25 | explicit Trader( QObject *parent = nullptr ); 26 | ~Trader(); 27 | 28 | public slots: 29 | void handleCommand( QString &s ); 30 | void handleExitSignal(); 31 | 32 | private: 33 | QNetworkAccessManager *nam; 34 | 35 | CommandListener *command_listener{ nullptr }; 36 | CommandRunner *command_runner_trex{ nullptr }; 37 | CommandRunner *command_runner_bnc{ nullptr }; 38 | CommandRunner *command_runner_polo{ nullptr }; 39 | CommandRunner *command_runner_waves{ nullptr }; 40 | 41 | AlphaTracker *alpha{ nullptr }; 42 | PriceAggregator *price_aggregator{ nullptr }; 43 | SpruceV2 *spruce{ nullptr }; 44 | SpruceOverseer *spruce_overseer{ nullptr }; 45 | 46 | EngineMap *engine_map{ nullptr }; 47 | Engine *engine_trex{ nullptr }; 48 | Engine *engine_bnc{ nullptr }; 49 | Engine *engine_polo{ nullptr }; 50 | Engine *engine_waves{ nullptr }; 51 | 52 | TrexREST *rest_trex{ nullptr }; 53 | BncREST *rest_bnc{ nullptr }; 54 | PoloREST *rest_polo{ nullptr }; 55 | WavesREST *rest_waves{ nullptr }; 56 | }; 57 | 58 | #endif // TREXTRADER_H 59 | -------------------------------------------------------------------------------- /daemon/traderd.pro: -------------------------------------------------------------------------------- 1 | QT = core network websockets 2 | 3 | TARGET = traderd 4 | DESTDIR = ../ 5 | 6 | MOC_DIR = ../build-tmp/daemon 7 | OBJECTS_DIR = ../build-tmp/daemon 8 | 9 | CONFIG += c++14 c++17 10 | CONFIG += RELEASE 11 | #CONFIG += DEBUG 12 | 13 | # enables stack symbols on release build for QMessageLogContext function and line output 14 | #DEFINES -= QT_MESSAGELOGCONTEXT 15 | 16 | LIBS += -lgmp 17 | 18 | QMAKE_CXXFLAGS = -Wall -ansi -pedantic -fstack-protector-strong -fstack-reuse=none -D_FORTIFY_SOURCE=2 -pie -fPIE -O3 19 | QMAKE_CFLAGS = -Wall -ansi -pedantic -fstack-protector-strong -fstack-reuse=none -D_FORTIFY_SOURCE=2 -pie -fPIE -O3 20 | QMAKE_LFLAGS += "-z noexecstack -z relro -z now" 21 | 22 | SOURCES += main.cpp \ 23 | alphatracker.cpp \ 24 | commandlistener.cpp \ 25 | commandrunner.cpp \ 26 | diffusionphaseman.cpp \ 27 | diffusionphaseman_test.cpp \ 28 | fallbacklistener.cpp \ 29 | market.cpp \ 30 | position.cpp \ 31 | engine.cpp \ 32 | positionman.cpp \ 33 | pricesignal.cpp \ 34 | pricesignal_test.cpp \ 35 | priceaggregator.cpp \ 36 | spruceoverseer.cpp \ 37 | spruceoverseer_test.cpp \ 38 | sprucev2.cpp \ 39 | trader.cpp \ 40 | trexrest.cpp \ 41 | bncrest.cpp \ 42 | polorest.cpp \ 43 | wavesrest.cpp \ 44 | baserest.cpp \ 45 | engine_test.cpp \ 46 | coinamount.cpp \ 47 | coinamount_test.cpp \ 48 | wavesutil.cpp \ 49 | wavesutil_test.cpp \ 50 | wavesaccount.cpp \ 51 | wavesaccount_test.cpp \ 52 | ../libbase58/base58.c \ 53 | ../qbase58/qbase58.cpp \ 54 | ../qbase58/qbase58_test.cpp \ 55 | ../blake2b/sse/blake2b.c \ 56 | ../libcurve25519-donna/nacl_sha512/hash.c \ 57 | ../libcurve25519-donna/nacl_sha512/blocks.c \ 58 | ../libcurve25519-donna/additions/keygen.c \ 59 | ../libcurve25519-donna/additions/curve_sigs.c \ 60 | ../libcurve25519-donna/additions/compare.c \ 61 | ../libcurve25519-donna/additions/fe_montx_to_edy.c \ 62 | ../libcurve25519-donna/additions/open_modified.c \ 63 | ../libcurve25519-donna/additions/sign_modified.c \ 64 | ../libcurve25519-donna/additions/ge_p3_to_montx.c \ 65 | ../libcurve25519-donna/additions/zeroize.c \ 66 | ../libcurve25519-donna/ge_scalarmult_base.c \ 67 | ../libcurve25519-donna/fe_0.c \ 68 | ../libcurve25519-donna/fe_1.c \ 69 | ../libcurve25519-donna/fe_add.c \ 70 | ../libcurve25519-donna/fe_invert.c \ 71 | ../libcurve25519-donna/fe_isnegative.c \ 72 | ../libcurve25519-donna/fe_isnonzero.c \ 73 | ../libcurve25519-donna/fe_sub.c \ 74 | ../libcurve25519-donna/fe_sq.c \ 75 | ../libcurve25519-donna/fe_sq2.c \ 76 | ../libcurve25519-donna/fe_frombytes.c \ 77 | ../libcurve25519-donna/fe_pow22523.c \ 78 | ../libcurve25519-donna/fe_mul.c \ 79 | ../libcurve25519-donna/fe_tobytes.c \ 80 | ../libcurve25519-donna/fe_cmov.c \ 81 | ../libcurve25519-donna/fe_copy.c \ 82 | ../libcurve25519-donna/fe_neg.c \ 83 | ../libcurve25519-donna/ge_add.c \ 84 | ../libcurve25519-donna/ge_p3_0.c \ 85 | ../libcurve25519-donna/ge_frombytes.c \ 86 | ../libcurve25519-donna/ge_tobytes.c \ 87 | ../libcurve25519-donna/ge_p3_tobytes.c \ 88 | ../libcurve25519-donna/ge_precomp_0.c \ 89 | ../libcurve25519-donna/ge_p2_dbl.c \ 90 | ../libcurve25519-donna/ge_p3_dbl.c \ 91 | ../libcurve25519-donna/ge_p2_0.c \ 92 | ../libcurve25519-donna/ge_p1p1_to_p2.c \ 93 | ../libcurve25519-donna/ge_p1p1_to_p3.c \ 94 | ../libcurve25519-donna/ge_p3_to_p2.c \ 95 | ../libcurve25519-donna/ge_p3_to_cached.c \ 96 | ../libcurve25519-donna/ge_double_scalarmult.c \ 97 | ../libcurve25519-donna/ge_madd.c \ 98 | ../libcurve25519-donna/ge_msub.c \ 99 | ../libcurve25519-donna/ge_sub.c \ 100 | ../libcurve25519-donna/sc_reduce.c \ 101 | ../libcurve25519-donna/sc_muladd.c 102 | 103 | HEADERS += build-config.h \ 104 | alphatracker.h \ 105 | commandlistener.h \ 106 | commandrunner.h \ 107 | diffusionphaseman.h \ 108 | diffusionphaseman_test.h \ 109 | enginemap.h \ 110 | enginesettings.h \ 111 | fallbacklistener.h \ 112 | global.h \ 113 | coinamount.h \ 114 | keydefs.h \ 115 | market.h \ 116 | position.h \ 117 | engine.h \ 118 | positiondata.h \ 119 | positionman.h \ 120 | pricesignal.h \ 121 | pricesignal_test.h \ 122 | priceaggregator.h \ 123 | spruceoverseer.h \ 124 | spruceoverseer_test.h \ 125 | sprucev2.h \ 126 | trader.h \ 127 | trexrest.h \ 128 | bncrest.h \ 129 | wavesrest.h \ 130 | polorest.h \ 131 | keystore.h \ 132 | engine_test.h \ 133 | baserest.h \ 134 | misctypes.h \ 135 | ssl_policy.h \ 136 | coinamount_test.h \ 137 | wavesutil.h \ 138 | wavesutil_test.h \ 139 | wavesaccount.h \ 140 | wavesaccount_test.h \ 141 | ../libbase58/libbase58.h \ 142 | ../qbase58/qbase58.h \ 143 | ../qbase58/qbase58_test.h \ 144 | ../blake2b/sse/blake2.h \ 145 | ../libcurve25519-donna/nacl_includes/crypto_uint32.h \ 146 | ../libcurve25519-donna/nacl_includes/crypto_int32.h \ 147 | ../libcurve25519-donna/fe.h \ 148 | ../libcurve25519-donna/ge.h \ 149 | ../libcurve25519-donna/additions/crypto_additions.h \ 150 | ../libcurve25519-donna/additions/keygen.h \ 151 | ../libcurve25519-donna/additions/curve_sigs.h 152 | -------------------------------------------------------------------------------- /daemon/trexrest.h: -------------------------------------------------------------------------------- 1 | #ifndef TREXREST_H 2 | #define TREXREST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "global.h" 10 | #include "position.h" 11 | #include "keystore.h" 12 | #include "baserest.h" 13 | 14 | class QNetworkReply; 15 | class QTimer; 16 | class QWebSocket; 17 | 18 | class TrexREST : public BaseREST 19 | { 20 | Q_OBJECT 21 | 22 | friend class CommandRunner; 23 | 24 | public: 25 | explicit TrexREST( Engine *_engine, QNetworkAccessManager *_nam ); 26 | ~TrexREST(); 27 | 28 | void init(); 29 | 30 | bool yieldToLag() const; 31 | 32 | void sendNamRequest( Request *const &request ); 33 | void sendBuySell( Position *const &pos, bool quiet = true ); 34 | void sendCancel( const QString &order_id, Position *const &pos = nullptr ); 35 | void parseBuySell( Request *const &request, const QJsonObject &response ); 36 | void parseCancelOrder( Request *const &request, const QJsonObject &response ); 37 | void parseOpenOrders(const QJsonArray &orders, qint64 request_time_sent_ms ); 38 | void parseReturnBalances( const QJsonArray &balances ); 39 | void parseGetOrder( const QJsonObject &order ); 40 | void parseOrderBook( const QJsonArray &info, qint64 request_time_sent_ms ); 41 | void parseOrderHistory( const QJsonObject &obj ); 42 | 43 | void wssSendJsonObj( const QJsonObject &obj ); 44 | 45 | void checkBotOrders( bool ignore_flow_control = false ); 46 | 47 | public Q_SLOTS: 48 | void sendNamQueue(); 49 | void onNamReply( QNetworkReply *const &reply ); 50 | 51 | void onCheckBotOrders(); 52 | void onCheckOrderHistory(); 53 | void onCheckTicker(); 54 | 55 | void wssConnected(); 56 | void wssCheckConnection(); 57 | void wssTextMessageReceived( const QString &msg ); 58 | 59 | private: 60 | qint64 order_history_update_time{ 0 }; 61 | 62 | QTimer *order_history_timer{ nullptr }; 63 | }; 64 | 65 | #endif // TREXREST_H 66 | -------------------------------------------------------------------------------- /daemon/wavesaccount.h: -------------------------------------------------------------------------------- 1 | #ifndef WAVESACCOUNT_H 2 | #define WAVESACCOUNT_H 3 | 4 | #include "../qbase58/qbase58.h" 5 | #include "coinamount.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | class Position; 12 | class WavesREST; 13 | 14 | class WavesAccount 15 | { 16 | public: 17 | static const uint8_t MAINNET = 'W'; 18 | static const uint8_t TESTNET = 'T'; 19 | 20 | WavesAccount(); 21 | 22 | /// crypto stuff 23 | void setPrivateKey( const QByteArray &new_private_key ); 24 | void setPrivateKeyB58( const QByteArray &new_private_key_b58 ); 25 | void setMatcherPublicKeyB58( const QByteArray &new_matcher_public_key_b58 ) { matcher_public_key = QBase58::decode( new_matcher_public_key_b58 ); } 26 | 27 | QByteArray privateKey() const { return private_key; } 28 | QByteArray privateKeyB58() const { return QBase58::encode( private_key ); } 29 | QByteArray publicKey() const { return public_key; } 30 | QByteArray publicKeyB58() const { return QBase58::encode( public_key ); } 31 | QByteArray address( const uint8_t network = MAINNET ) const; 32 | 33 | bool sign( const QByteArray &message, QByteArray &signature, bool add_random_bytes = true ) const; 34 | bool verify( const QByteArray &message, const QByteArray &signature ) const; 35 | 36 | /// order stuff 37 | void initAssetMaps(); 38 | 39 | QString getAliasByAsset( const QString &asset ) const { return alias_by_asset.value( asset ); } 40 | QString getAssetByAlias( const QString &asset ) const { return asset_by_alias.value( asset ); } 41 | const QStringList &getPriceAssets() const { return price_assets; } 42 | 43 | QByteArray createCancelBytes( const QByteArray &order_id_b58 ) const; 44 | QByteArray createCancelBody( const QByteArray &order_id_b58, bool random_sign_bytes = true ) const; 45 | 46 | QByteArray createOrderBytes( Position *const &pos, const Coin &price_ticksize, const Coin &qty_ticksize, const qint64 epoch_now, const qint64 epoch_expiration ) const; 47 | QByteArray createOrderId( const QByteArray &order_bytes ) const; 48 | QByteArray createOrderBody( Position *const &pos, const Coin &price_ticksize, const Coin &qty_ticksize, const qint64 epoch_now, const qint64 epoch_expiration, bool random_sign_bytes = true ) const; 49 | 50 | QByteArray createGetOrdersBytes( const qint64 epoch_now ); 51 | 52 | private: 53 | QByteArray private_key, public_key, matcher_public_key; 54 | 55 | // asset mappings 56 | QMap asset_by_alias, alias_by_asset; 57 | QStringList price_assets; 58 | }; 59 | 60 | #endif // WAVESACCOUNT_H 61 | -------------------------------------------------------------------------------- /daemon/wavesaccount_test.cpp: -------------------------------------------------------------------------------- 1 | #include "wavesaccount_test.h" 2 | #include "wavesaccount.h" 3 | #include "position.h" 4 | 5 | #include 6 | 7 | void WavesAccountTest::test() 8 | { 9 | /// test private_key -> public_key -> address 10 | const QByteArray private_key_b58 = "CMLwxbMZJMztyTJ6Zkos66cgU7DybfFJfyJtTVpme54t"; 11 | const QByteArray public_key_b58 = "8LbAU5BSrGkpk5wbjLMNjrbc9VzN9KBBYv9X8wGpmAJT"; 12 | const QByteArray testnet_addr_b58 = "3MzZCGFyuxgC4ZmtKRS7vpJTs75ZXdkbp1K"; 13 | 14 | WavesAccount acc; 15 | acc.setPrivateKeyB58( private_key_b58 ); 16 | 17 | assert( acc.privateKeyB58() == private_key_b58 ); 18 | assert( acc.publicKeyB58() == public_key_b58 ); 19 | assert( acc.address( WavesAccount::TESTNET ) == testnet_addr_b58 ); 20 | 21 | acc.setPrivateKey( QByteArray::fromHex( "88727a03377bfba1b3655c5ecb978da171e024aad722ee49fff9214a747e7061" ) ); 22 | 23 | /// test sign and verify 24 | const QByteArray message = QByteArray::fromHex( "0102030405" ); 25 | 26 | /// generate signature 27 | QByteArray signature; 28 | bool sign_result = acc.sign( message, signature ); 29 | 30 | assert( sign_result ); 31 | assert( !signature.isEmpty() ); 32 | 33 | /// verify our message signed with a random signature 34 | bool verify_result = acc.verify( message, signature ); 35 | 36 | assert( verify_result ); 37 | 38 | /// verify our message signed with a non-random signature 39 | sign_result = acc.sign( message, signature, false ); 40 | 41 | assert( sign_result ); 42 | assert( QBase58::encode( signature ) == "5HRwSL8XGhSEbtLuBfZT1AkfKaybYA67aKTUpg3v47aTZfCLiBMDLj1P9PmoirWcNCVFCoja4gmv5nkjDnYAULus" ); 43 | 44 | /// verify that it's false with the wrong message but the correct signature 45 | QByteArray wrong_message = message + "1"; 46 | verify_result = acc.verify( wrong_message, signature ); 47 | 48 | assert( !verify_result ); 49 | 50 | /// verify that it's false with the correct message but the wrong signature 51 | QByteArray wrong_signature = signature; 52 | wrong_signature[ 0 ] = 0x00; 53 | verify_result = acc.verify( message, wrong_signature ); 54 | 55 | assert( !verify_result ); 56 | 57 | /// test cancel order bytes without random signature bytes 58 | QByteArray order_id_b58 = "H93RaJ6D9YxEWNJiiMsej23NVHLrxu6kMyFb7CgX2DZW"; 59 | acc.setPrivateKeyB58( "CrppxhgtZZNd5wcVMwsudWJ78ZKLqETR8AmhtjeKDFZU" ); 60 | 61 | QByteArray cancel_order_bytes = acc.createCancelBytes( order_id_b58 ); 62 | 63 | sign_result = acc.sign( cancel_order_bytes, signature, false ); 64 | 65 | assert( QBase58::encode( cancel_order_bytes ) == "4W1eSfcBttw6kiyZhhe52DamKjdcQgqGapg1VFVp5pNqgyomPVMi6NRAr6cLiCi1dAQoUni7eQETMBsjMu1fNLbn" ); 66 | 67 | /// test cancel order body without random signature bytes 68 | order_id_b58 = "6j1ccV4SV2FtNUUUKGwYJVEVvH5L8iXKiawrmoWCtqV2"; 69 | acc.setPrivateKeyB58( "7V7gbGjXBiLGJf8aUNUP4Vzm5kuMNHd3Gt5THRTmYMfd" ); 70 | 71 | assert( acc.createCancelBody( order_id_b58, false ) == "{\"orderId\":\"6j1ccV4SV2FtNUUUKGwYJVEVvH5L8iXKiawrmoWCtqV2\",\"proofs\":[\"3AP6y9ye9eaDzFP7LaAdxkDYf6YXFBHVFJ9Dqy4PLBQPNdvwyJMGUFs3xLx1JFxNext8xhonPKhdyZQ6GLYCdZhD\"],\"sender\":\"27YM9icwd6TwfZD3KEJpYsj7rLwPAShJdYXrCt8QRo6L\",\"senderPublicKey\":\"27YM9icwd6TwfZD3KEJpYsj7rLwPAShJdYXrCt8QRo6L\",\"signature\":\"3AP6y9ye9eaDzFP7LaAdxkDYf6YXFBHVFJ9Dqy4PLBQPNdvwyJMGUFs3xLx1JFxNext8xhonPKhdyZQ6GLYCdZhD\"}" ); 72 | 73 | /// test creating an order id v2 with the above keys 74 | acc.initAssetMaps(); // init asset aliases 75 | acc.setMatcherPublicKeyB58( "9cpfKN9suPNvfeUNphzxXMjcnn974eme8ZhWUjaktzU5" ); 76 | 77 | Position pos = Position( "BTC_WAVES", SIDE_SELL, "", "0.01000000", "0.00097" ); 78 | 79 | QByteArray order_bytes_v2 = acc.createOrderBytes( &pos, CoinAmount::SATOSHI, CoinAmount::SATOSHI, quint64( 1580472938469 ), quint64( 1582978538468 ) ); 80 | 81 | assert( acc.createOrderId( order_bytes_v2 ) == "DH2Uyfdoj2pj1t1EEbLPYJMVRcWYqw6kBgQkVZjNiE2o" ); 82 | 83 | /// test creating order body from the order byes above 84 | assert( acc.createOrderBody( &pos, CoinAmount::SATOSHI, CoinAmount::SATOSHI, quint64( 1580472938469 ), quint64( 1582978538468 ) , false ) == "{\"amount\":9700000,\"assetPair\":{\"amountAsset\":\"WAVES\",\"priceAsset\":\"8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS\"},\"expiration\":1582978538468,\"id\":\"DH2Uyfdoj2pj1t1EEbLPYJMVRcWYqw6kBgQkVZjNiE2o\",\"matcherFee\":300000,\"matcherPublicKey\":\"9cpfKN9suPNvfeUNphzxXMjcnn974eme8ZhWUjaktzU5\",\"orderType\":\"sell\",\"price\":1000000,\"proofs\":[\"DCKsiyJu1avWRDe3Zr5Wxt2T1A352T1TosxwUiaQEaTDqYoNC7D9N3fa6fDjGLL3QRbxKnovKchrMCJb6fv1d5y\"],\"senderPublicKey\":\"27YM9icwd6TwfZD3KEJpYsj7rLwPAShJdYXrCt8QRo6L\",\"timestamp\":1580472938469,\"version\":2}" ); 85 | 86 | /// test creating get orders bytes 87 | QByteArray get_orders_bytes = acc.createGetOrdersBytes( qint64( 0 ) ); 88 | 89 | assert( get_orders_bytes == QByteArray::fromHex( "10889dcdbba87fac60ac658f4c8b4add9e7aafecc3fff1fafb599d833b38307d0000000000000000" ) ); 90 | 91 | /// test alias->asset 92 | assert( acc.getAssetByAlias( "8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS" ) == "BTC" ); 93 | assert( acc.getAssetByAlias( "WAVES" ) == "WAVES" ); 94 | 95 | /// test asset->alias 96 | assert( acc.getAliasByAsset( "BTC" ) == "8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS" ); 97 | assert( acc.getAliasByAsset( "WAVES" ) == "WAVES" ); 98 | } 99 | -------------------------------------------------------------------------------- /daemon/wavesaccount_test.h: -------------------------------------------------------------------------------- 1 | #ifndef WAVESACCOUNT_TEST_H 2 | #define WAVESACCOUNT_TEST_H 3 | 4 | struct WavesAccountTest 5 | { 6 | void test(); 7 | }; 8 | 9 | #endif // WAVESACCOUNT_TEST_H 10 | -------------------------------------------------------------------------------- /daemon/wavesrest.h: -------------------------------------------------------------------------------- 1 | #ifndef WAVESREST_H 2 | #define WAVESREST_H 3 | 4 | #include 5 | 6 | #include "global.h" 7 | #include "position.h" 8 | #include "keystore.h" 9 | #include "baserest.h" 10 | #include "wavesaccount.h" 11 | 12 | class QNetworkReply; 13 | class QTimer; 14 | 15 | class WavesREST : public BaseREST 16 | { 17 | Q_OBJECT 18 | 19 | friend class CommandRunner; 20 | 21 | public: 22 | explicit WavesREST( Engine *_engine, QNetworkAccessManager *_nam ); 23 | ~WavesREST(); 24 | 25 | void init(); 26 | 27 | void sendNamRequest( Request *const &request ); 28 | 29 | void getOrderStatus( Position *const &pos ); 30 | 31 | void sendCancel( const QString &order_id, Position *const &pos , const Market &market ); 32 | void sendCancelNonLocal( const QString &order_id , const QString &amount_asset_alias, const QString &price_asset_alias ); 33 | void sendBuySell( Position *const &pos, bool quiet = true ); 34 | 35 | void checkTicker( bool ignore_flow_control = false ); 36 | void checkBotOrders( bool ignore_flow_control = false ); 37 | 38 | public Q_SLOTS: 39 | void sendNamQueue(); 40 | void onNamReply( QNetworkReply *const &reply ); 41 | 42 | void onCheckMarketData(); 43 | void onCheckTicker(); 44 | void onCheckBotOrders(); 45 | void onCheckCancellingOrders(); 46 | 47 | private: 48 | void parseMarketData( const QJsonObject &info ); 49 | void parseMarketStatus( const QJsonObject &info, Request *const &request ); 50 | void parseOrderStatus( const QJsonObject &info, Request *const &request ); 51 | void parseCancelOrder( const QJsonObject &info, Request *const &request ); 52 | void parseNewOrder( const QJsonObject &info, Request *const &request ); 53 | void parseMyOrders( const QJsonArray &orders, qint64 request_time_sent_ms ); 54 | 55 | WavesAccount account; 56 | 57 | QStringList tracked_markets; 58 | 59 | QVector cancelling_orders_to_query; 60 | 61 | bool initial_ticker_update_done{ false }; 62 | qint32 next_ticker_index_to_query{ 0 }; 63 | qint32 last_cancelling_index_checked{ 0 }; 64 | QTimer *market_data_timer{ nullptr }; 65 | }; 66 | 67 | #endif // WAVESREST_H 68 | -------------------------------------------------------------------------------- /daemon/wavesutil.cpp: -------------------------------------------------------------------------------- 1 | #include "wavesutil.h" 2 | #include "../blake2b/sse/blake2.h" 3 | #include "../qbase58/qbase58.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | QByteArray WavesUtil::hashBlake2b( const QByteArray &in ) 10 | { 11 | QByteArray blake_out; 12 | blake_out.resize( 32 ); 13 | 14 | blake2b_state S[1]; 15 | 16 | blake2b_init( S, 32 ); 17 | blake2b_update( S, in.data(), in.length() ); 18 | blake2b_final( S, blake_out.data(), 32 ); 19 | 20 | return blake_out; 21 | } 22 | 23 | QByteArray WavesUtil::hashWaves( const QByteArray &in ) 24 | { 25 | return QCryptographicHash::hash( hashBlake2b( in ), QCryptographicHash::Keccak_256 ); 26 | } 27 | 28 | void WavesUtil::clampPrivateKey( QByteArray &key ) 29 | { 30 | assert( key.size() > 31 ); 31 | 32 | key[ 0 ] = key[ 0 ] & uint8_t( 248 ); 33 | key[ 31 ] = key[ 31 ] & uint8_t( 127 ); 34 | key[ 31 ] = key[ 31 ] | uint8_t( 64 ); 35 | } 36 | 37 | QByteArray WavesUtil::getAssetBytes( const QString &asset ) 38 | { 39 | QByteArray ret; 40 | 41 | if ( asset == QLatin1String( "WAVES" ) ) 42 | { 43 | ret += '\x00'; 44 | assert( ret.size() == 1 ); 45 | } 46 | else 47 | { 48 | ret += '\x01'; 49 | ret += QBase58::decode( asset.toLocal8Bit() ); 50 | assert( ret.size() == 33 ); 51 | } 52 | 53 | return ret; 54 | } 55 | -------------------------------------------------------------------------------- /daemon/wavesutil.h: -------------------------------------------------------------------------------- 1 | #ifndef WAVESUTIL_H 2 | #define WAVESUTIL_H 3 | 4 | #include 5 | 6 | namespace WavesUtil 7 | { 8 | const uint8_t BUY = 0; 9 | const uint8_t SELL = 1; 10 | 11 | QByteArray hashBlake2b( const QByteArray &in ); 12 | QByteArray hashWaves( const QByteArray &in ); 13 | 14 | void clampPrivateKey( QByteArray &key ); 15 | 16 | QByteArray getAssetBytes( const QString &asset ); 17 | } 18 | 19 | #endif // WAVESUTIL_H 20 | -------------------------------------------------------------------------------- /daemon/wavesutil_test.cpp: -------------------------------------------------------------------------------- 1 | #include "wavesutil_test.h" 2 | #include "wavesutil.h" 3 | #include "../qbase58/qbase58.h" 4 | 5 | #include 6 | #include 7 | 8 | void WavesUtilTest::test() 9 | { 10 | /// test private key clamp on zeroed out key 11 | QByteArray pkey; 12 | pkey.resize( 32 ); 13 | pkey.fill( 0x00 ); 14 | 15 | WavesUtil::clampPrivateKey( pkey ); 16 | assert( QBase58::encode( pkey ) == "111111111111111111111111111111127" ); 17 | 18 | /// test blake2b hash 19 | assert( WavesUtil::hashBlake2b( QByteArray() ).toHex() == "0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8" ); 20 | assert( WavesUtil::hashBlake2b( QByteArray( "Hello World!\n") ).toHex() == "f497a36252fe0182836a19a75de5d75996a0f0a4e19f81fe749aa9e809a1150c" ); 21 | 22 | /// test waves hash 23 | assert( WavesUtil::hashWaves( QByteArray( "A nice, long test to make the day great! :-)" ) ).toHex() == "5df3cf20205d75e09ae46d13a8d99a16174d71c84ffcc00387fec3d81e39dcbe" ); 24 | 25 | /// test binary serialization of assets 26 | assert( WavesUtil::getAssetBytes( "WAVES" ) == QByteArray::fromHex( "00" ) ); 27 | assert( WavesUtil::getAssetBytes( "8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS" ) == QByteArray::fromHex( "01" ) + QBase58::decode( "8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS" ) ); 28 | } 29 | -------------------------------------------------------------------------------- /daemon/wavesutil_test.h: -------------------------------------------------------------------------------- 1 | #ifndef WAVESUTIL_TEST_H 2 | #define WAVESUTIL_TEST_H 3 | 4 | struct WavesUtilTest 5 | { 6 | void test(); 7 | }; 8 | 9 | #endif // WAVESUTIL_TEST_H 10 | -------------------------------------------------------------------------------- /generate_keys.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os.path 3 | 4 | def add_quotes(a): 5 | return '"{0}"'.format(a) 6 | 7 | MSG = "(press enter to leave blank for later, or CTRL-C to abort):" 8 | KEYDEFS_FILE = "daemon/keydefs.h" 9 | 10 | if not os.path.exists( KEYDEFS_FILE ): 11 | print( "NOTE: If you don't want to hardcode these values, leave them blank and you can use 'setkeyandsecret ' in the bot upon startup. Alternately, if you don't want to use this script, but still want to hardcode your keys, CTRL-C and 'cp daemon/keydefs.h.example daemon/keydefs.h' and paste your keys in there." ) 12 | print( "Generating keydefs.h..." ) 13 | 14 | polo_key = add_quotes( raw_input( "Enter Poloniex API Key" + MSG ) ) 15 | polo_secret = add_quotes( raw_input( "Enter Poloniex API Secret" + MSG ) ) 16 | trex_key = add_quotes( raw_input( "Enter Bittrex API Key" + MSG ) ) 17 | trex_secret = add_quotes( raw_input( "Enter Bittrex API Secret" + MSG ) ) 18 | bnc_key = add_quotes( raw_input( "Enter Binance API Key" + MSG ) ) 19 | bnc_secret = add_quotes( raw_input( "Enter Binance API Secret" + MSG ) ) 20 | waves_secret = add_quotes( raw_input( "Enter Waves API Secret (Base58)" + MSG ) ) 21 | 22 | file = open( KEYDEFS_FILE, "w" ) 23 | file.write( "#ifndef KEYDEFS_H\n" ) 24 | file.write( "#define KEYDEFS_H\n\n" ) 25 | 26 | file.write( "#define POLONIEX_KEY " + polo_key + "\n" ) 27 | file.write( "#define POLONIEX_SECRET " + polo_secret + "\n" ) 28 | file.write( "#define BITTREX_KEY " + trex_key + "\n" ) 29 | file.write( "#define BITTREX_SECRET " + trex_secret + "\n" ) 30 | file.write( "#define BINANCE_KEY " + bnc_key + "\n" ) 31 | file.write( "#define BINANCE_SECRET " + bnc_secret + "\n" ) 32 | file.write( "#define WAVES_SECRET " + waves_secret + "\n\n" ) 33 | 34 | 35 | file.write( "#endif // KEYDEFS_H\n" ) 36 | file.close(); 37 | 38 | else: 39 | print( "keydefs.h already exists, exiting.. (if you meant to overwrite it, remove/move the file and re-run this script.)" ) 40 | -------------------------------------------------------------------------------- /gettotallines.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | wc -l daemon/*.cpp daemon/*.h cli/*.cpp cli/*.h backtest-mt/*.cpp backtest-mt/*.h candlestick-puller/*.cpp candlestick-puller/*.h 3 | -------------------------------------------------------------------------------- /libbase58/AUTHORS: -------------------------------------------------------------------------------- 1 | Luke Dashjr 2 | Huang Le <4tarhl@gmail.com> 3 | -------------------------------------------------------------------------------- /libbase58/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Luke Dashjr 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /libbase58/README.md: -------------------------------------------------------------------------------- 1 | Initialisation 2 | -------------- 3 | 4 | Before you can use libbase58 for base58check, you must provide a SHA256 5 | function. The required function signature is: 6 | 7 | bool my_sha256(void *digest, const void *data, size_t datasz) 8 | 9 | Simply assign your function to b58_sha256_impl: 10 | 11 | b58_sha256_impl = my_sha256; 12 | 13 | This is only required if base58check is used. Raw base58 does not need SHA256. 14 | 15 | 16 | Decoding Base58 17 | --------------- 18 | 19 | Simply allocate a buffer to store the binary data in, and set a variable with 20 | the buffer size, and call the b58tobin function: 21 | 22 | bool b58tobin(void *bin, size_t *binsz, const char *b58, size_t b58sz) 23 | 24 | The "canonical" base58 byte length will be assigned to binsz on success, which 25 | may be larger than the actual buffer if the input has many leading zeros. 26 | Regardless of the canonical byte length, the full binary buffer will be used. 27 | If b58sz is zero, it will be initialised with strlen(b58); note that a true 28 | zero-length base58 string is not supported here. 29 | 30 | 31 | Validating Base58Check 32 | ---------------------- 33 | 34 | After calling b58tobin, you can validate base58check data using the b58check 35 | function: 36 | 37 | int b58check(const void *bin, size_t binsz, const char *b58, size_t b58sz) 38 | 39 | Call it with the same buffers used for b58tobin. If the return value is 40 | negative, an error occurred. Otherwise, the return value is the base58check 41 | "version" byte from the decoded data. 42 | 43 | 44 | Encoding Base58 45 | --------------- 46 | 47 | Allocate a string to store the base58 content, create a size_t variable with the 48 | size of that allocation, and call: 49 | 50 | bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) 51 | 52 | Note that you must pass a pointer to the string size variable, not the size 53 | itself. When b58enc returns, the variable will be modified to contain the actual 54 | number of bytes used (including the null terminator). If encoding fails for any 55 | reason, or if the string buffer is not large enough for the result, b58enc will 56 | return false. Otherwise, it returns true to indicate success. 57 | 58 | 59 | Encoding Base58Check 60 | -------------------- 61 | 62 | Targeting base58check is done similarly to raw base58 encoding, but you must 63 | also provide a version byte: 64 | 65 | bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, 66 | const void *data, size_t datasz) 67 | -------------------------------------------------------------------------------- /libbase58/libbase58.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBBASE58_H 2 | #define LIBBASE58_H 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | extern bool (*b58_sha256_impl)(void *, const void *, size_t); 12 | 13 | extern bool b58tobin(void *bin, size_t *binsz, const char *b58, size_t b58sz); 14 | extern int b58check(const void *bin, const size_t binsz, const char *b58); 15 | 16 | extern bool b58enc(char *b58, size_t *b58sz, const void *bin, const size_t binsz); 17 | extern bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, const size_t datasz); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/compare.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "compare.h" 3 | 4 | /* Const-time comparison from SUPERCOP, but here it's only used for 5 | signature verification, so doesn't need to be const-time. But 6 | copied the nacl version anyways. */ 7 | int crypto_verify_32_ref(const unsigned char *x, const unsigned char *y) 8 | { 9 | unsigned int differentbits = 0; 10 | #define F(i) differentbits |= x[i] ^ y[i]; 11 | F(0) 12 | F(1) 13 | F(2) 14 | F(3) 15 | F(4) 16 | F(5) 17 | F(6) 18 | F(7) 19 | F(8) 20 | F(9) 21 | F(10) 22 | F(11) 23 | F(12) 24 | F(13) 25 | F(14) 26 | F(15) 27 | F(16) 28 | F(17) 29 | F(18) 30 | F(19) 31 | F(20) 32 | F(21) 33 | F(22) 34 | F(23) 35 | F(24) 36 | F(25) 37 | F(26) 38 | F(27) 39 | F(28) 40 | F(29) 41 | F(30) 42 | F(31) 43 | return (1 & ((differentbits - 1) >> 8)) - 1; 44 | } 45 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/compare.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMPARE_H__ 2 | #define __COMPARE_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int crypto_verify_32_ref(const unsigned char *b1, const unsigned char *b2); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/crypto_additions.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CRYPTO_ADDITIONS__ 3 | #define __CRYPTO_ADDITIONS__ 4 | 5 | #include "../nacl_includes/crypto_uint32.h" 6 | #include "../fe.h" 7 | #include "../ge.h" 8 | 9 | #include 10 | 11 | #define MAX_MSG_LEN 256 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | void sc_neg(unsigned char *b, const unsigned char *a); 18 | void sc_cmov(unsigned char* f, const unsigned char* g, unsigned char b); 19 | 20 | int fe_isequal(const fe f, const fe g); 21 | int fe_isreduced(const unsigned char* s); 22 | void fe_mont_rhs(fe v2, const fe u); 23 | void fe_montx_to_edy(fe y, const fe u); 24 | void fe_sqrt(fe b, const fe a); 25 | 26 | int ge_isneutral(const ge_p3* q); 27 | void ge_neg(ge_p3* r, const ge_p3 *p); 28 | void ge_montx_to_p3(ge_p3* p, const fe u, const unsigned char ed_sign_bit); 29 | void ge_p3_to_montx(fe u, const ge_p3 *p); 30 | void ge_scalarmult(ge_p3 *h, const unsigned char *a, const ge_p3 *A); 31 | void ge_scalarmult_cofactor(ge_p3 *q, const ge_p3 *p); 32 | 33 | void elligator(fe u, const fe r); 34 | void hash_to_point(ge_p3* p, const unsigned char* msg, const uint32_t in_len); 35 | 36 | int crypto_sign_modified( 37 | unsigned char *sm, 38 | const unsigned char *m,uint64_t mlen, 39 | const unsigned char *sk, /* Curve/Ed25519 private key */ 40 | const unsigned char *pk, /* Ed25519 public key */ 41 | const unsigned char *random /* 64 bytes random to hash into nonce */ 42 | ); 43 | 44 | int crypto_sign_open_modified( 45 | unsigned char *m, 46 | const unsigned char *sm,uint64_t smlen, 47 | const unsigned char *pk 48 | ); 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/crypto_hash_sha512.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_hash_sha512_H 2 | #define crypto_hash_sha512_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | extern int crypto_hash_sha512(unsigned char *,const unsigned char *,uint64_t); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/curve_sigs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../ge.h" 4 | #include "curve_sigs.h" 5 | #include "../nacl_includes/crypto_sign.h" 6 | #include "crypto_additions.h" 7 | 8 | int curve25519_sign(unsigned char* signature_out, 9 | const unsigned char* curve25519_privkey, 10 | const unsigned char* msg, const unsigned long msg_len, 11 | const unsigned char* random) 12 | { 13 | ge_p3 ed_pubkey_point; /* Ed25519 pubkey point */ 14 | unsigned char ed_pubkey[32]; /* Ed25519 encoded pubkey */ 15 | unsigned char *sigbuf; /* working buffer */ 16 | unsigned char sign_bit = 0; 17 | 18 | if ((sigbuf = malloc(msg_len + 128)) == 0) { 19 | memset(signature_out, 0, 64); 20 | return -1; 21 | } 22 | 23 | /* Convert the Curve25519 privkey to an Ed25519 public key */ 24 | ge_scalarmult_base(&ed_pubkey_point, curve25519_privkey); 25 | ge_p3_tobytes(ed_pubkey, &ed_pubkey_point); 26 | sign_bit = ed_pubkey[31] & 0x80; 27 | 28 | /* Perform an Ed25519 signature with explicit private key */ 29 | crypto_sign_modified(sigbuf, msg, msg_len, curve25519_privkey, 30 | ed_pubkey, random); 31 | memmove(signature_out, sigbuf, 64); 32 | 33 | /* Encode the sign bit into signature (in unused high bit of S) */ 34 | signature_out[63] &= 0x7F; /* bit should be zero already, but just in case */ 35 | signature_out[63] |= sign_bit; 36 | 37 | free(sigbuf); 38 | return 0; 39 | } 40 | 41 | int curve25519_verify(const unsigned char* signature, 42 | const unsigned char* curve25519_pubkey, 43 | const unsigned char* msg, const unsigned long msg_len) 44 | { 45 | fe u; 46 | fe y; 47 | unsigned char ed_pubkey[32]; 48 | unsigned char *verifybuf = NULL; /* working buffer */ 49 | unsigned char *verifybuf2 = NULL; /* working buffer #2 */ 50 | int result; 51 | 52 | if ((verifybuf = malloc(msg_len + 64)) == 0) { 53 | result = -1; 54 | goto err; 55 | } 56 | 57 | if ((verifybuf2 = malloc(msg_len + 64)) == 0) { 58 | result = -1; 59 | goto err; 60 | } 61 | 62 | /* Convert the Curve25519 public key into an Ed25519 public key. In 63 | particular, convert Curve25519's "montgomery" x-coordinate (u) into an 64 | Ed25519 "edwards" y-coordinate: 65 | 66 | y = (u - 1) / (u + 1) 67 | 68 | NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp 69 | 70 | Then move the sign bit into the pubkey from the signature. 71 | */ 72 | fe_frombytes(u, curve25519_pubkey); 73 | fe_montx_to_edy(y, u); 74 | fe_tobytes(ed_pubkey, y); 75 | 76 | /* Copy the sign bit, and remove it from signature */ 77 | ed_pubkey[31] &= 0x7F; /* bit should be zero already, but just in case */ 78 | ed_pubkey[31] |= (signature[63] & 0x80); 79 | memmove(verifybuf, signature, 64); 80 | verifybuf[63] &= 0x7F; 81 | 82 | memmove(verifybuf+64, msg, msg_len); 83 | 84 | /* Then perform a normal Ed25519 verification, return 0 on success */ 85 | /* The below call has a strange API: */ 86 | /* verifybuf = R || S || message */ 87 | /* verifybuf2 = internal to next call gets a copy of verifybuf, S gets 88 | replaced with pubkey for hashing */ 89 | result = crypto_sign_open_modified(verifybuf2, verifybuf, 64 + msg_len, ed_pubkey); 90 | 91 | err: 92 | 93 | if (verifybuf != NULL) { 94 | free(verifybuf); 95 | } 96 | 97 | if (verifybuf2 != NULL) { 98 | free(verifybuf2); 99 | } 100 | 101 | return result; 102 | } 103 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/curve_sigs.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CURVE_SIGS_H__ 3 | #define __CURVE_SIGS_H__ 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | /* returns 0 on success */ 10 | int curve25519_sign(unsigned char* signature_out, /* 64 bytes */ 11 | const unsigned char* curve25519_privkey, /* 32 bytes */ 12 | const unsigned char* msg, const unsigned long msg_len, /* <= 256 bytes */ 13 | const unsigned char* random); /* 64 bytes */ 14 | 15 | /* returns 0 on success */ 16 | int curve25519_verify(const unsigned char* signature, /* 64 bytes */ 17 | const unsigned char* curve25519_pubkey, /* 32 bytes */ 18 | const unsigned char* msg, const unsigned long msg_len); /* <= 256 bytes */ 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/fe_montx_to_edy.c: -------------------------------------------------------------------------------- 1 | 2 | #include "../fe.h" 3 | #include "crypto_additions.h" 4 | 5 | void fe_montx_to_edy(fe y, const fe u) 6 | { 7 | /* 8 | y = (u - 1) / (u + 1) 9 | 10 | NOTE: u=-1 is converted to y=0 since fe_invert is mod-exp 11 | */ 12 | fe one, um1, up1; 13 | 14 | fe_1(one); 15 | fe_sub(um1, u, one); 16 | fe_add(up1, u, one); 17 | fe_invert(up1, up1); 18 | fe_mul(y, um1, up1); 19 | } 20 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/ge_p3_to_montx.c: -------------------------------------------------------------------------------- 1 | #include "../fe.h" 2 | #include "crypto_additions.h" 3 | 4 | void ge_p3_to_montx(fe u, const ge_p3 *ed) 5 | { 6 | /* 7 | u = (y + 1) / (1 - y) 8 | or 9 | u = (y + z) / (z - y) 10 | 11 | NOTE: y=1 is converted to u=0 since fe_invert is mod-exp 12 | */ 13 | 14 | fe y_plus_one, one_minus_y, inv_one_minus_y; 15 | 16 | fe_add(y_plus_one, ed->Y, ed->Z); 17 | fe_sub(one_minus_y, ed->Z, ed->Y); 18 | fe_invert(inv_one_minus_y, one_minus_y); 19 | fe_mul(u, y_plus_one, inv_one_minus_y); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/keygen.c: -------------------------------------------------------------------------------- 1 | #include "keygen.h" 2 | #include "crypto_additions.h" 3 | 4 | void curve25519_keygen(unsigned char* curve25519_pubkey_out, 5 | const unsigned char* curve25519_privkey_in) 6 | { 7 | /* Perform a fixed-base multiplication of the Edwards base point, 8 | (which is efficient due to precalculated tables), then convert 9 | to the Curve25519 montgomery-format public key. 10 | 11 | NOTE: y=1 is converted to u=0 since fe_invert is mod-exp 12 | */ 13 | 14 | ge_p3 ed; /* Ed25519 pubkey point */ 15 | fe u; 16 | 17 | ge_scalarmult_base(&ed, curve25519_privkey_in); 18 | ge_p3_to_montx(u, &ed); 19 | fe_tobytes(curve25519_pubkey_out, u); 20 | } 21 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/keygen.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __KEYGEN_H__ 3 | #define __KEYGEN_H__ 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | /* Sets and clears bits to make a random 32 bytes into a private key */ 10 | void sc_clamp(unsigned char* a); 11 | 12 | /* The private key should be 32 random bytes "clamped" by sc_clamp() */ 13 | void curve25519_keygen(unsigned char* curve25519_pubkey_out, /* 32 bytes */ 14 | const unsigned char* curve25519_privkey_in); /* 32 bytes */ 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/open_modified.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../nacl_includes/crypto_sign.h" 3 | #include "crypto_hash_sha512.h" 4 | #include "../nacl_includes/crypto_verify_32.h" 5 | #include "../ge.h" 6 | #include "../sc.h" 7 | #include "crypto_additions.h" 8 | 9 | int crypto_sign_open_modified(unsigned char *m, 10 | const unsigned char *sm, uint64_t smlen, 11 | const unsigned char *pk 12 | ) 13 | { 14 | unsigned char pkcopy[32]; 15 | unsigned char rcopy[32]; 16 | unsigned char scopy[32]; 17 | unsigned char h[64]; 18 | unsigned char rcheck[32]; 19 | ge_p3 A; 20 | ge_p2 R; 21 | 22 | if (smlen < 64) goto badsig; 23 | if (sm[63] & 224) goto badsig; /* strict parsing of s */ 24 | if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig; 25 | 26 | memmove(pkcopy,pk,32); 27 | memmove(rcopy,sm,32); 28 | memmove(scopy,sm + 32,32); 29 | 30 | memmove(m,sm,smlen); 31 | memmove(m + 32,pkcopy,32); 32 | crypto_hash_sha512(h,m,smlen); 33 | sc_reduce(h); 34 | 35 | ge_double_scalarmult_vartime(&R,h,&A,scopy); 36 | ge_tobytes(rcheck,&R); 37 | 38 | if (crypto_verify_32(rcheck,rcopy) == 0) { 39 | return 0; 40 | } 41 | 42 | badsig: 43 | return -1; 44 | } 45 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/sign_modified.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../nacl_includes/crypto_sign.h" 3 | #include "crypto_hash_sha512.h" 4 | #include "../ge.h" 5 | #include "../sc.h" 6 | #include "zeroize.h" 7 | #include "crypto_additions.h" 8 | 9 | /* NEW: Compare to pristine crypto_sign() 10 | Uses explicit private key for nonce derivation and as scalar, 11 | instead of deriving both from a master key. 12 | */ 13 | int crypto_sign_modified( 14 | unsigned char *sm, 15 | const unsigned char *m,uint64_t mlen, 16 | const unsigned char *sk, const unsigned char* pk, 17 | const unsigned char* random 18 | ) 19 | { 20 | unsigned char nonce[64]; 21 | unsigned char hram[64]; 22 | ge_p3 R; 23 | int count=0; 24 | 25 | memmove(sm + 64,m,mlen); 26 | memmove(sm + 32,sk,32); /* NEW: Use privkey directly for nonce derivation */ 27 | 28 | /* NEW : add prefix to separate hash uses - see .h */ 29 | sm[0] = 0xFE; 30 | for (count = 1; count < 32; count++) 31 | sm[count] = 0xFF; 32 | 33 | /* NEW: add suffix of random data */ 34 | memmove(sm + mlen + 64, random, 64); 35 | 36 | crypto_hash_sha512(nonce,sm,mlen + 128); 37 | memmove(sm + 32,pk,32); 38 | 39 | sc_reduce(nonce); 40 | 41 | ge_scalarmult_base(&R,nonce); 42 | ge_p3_tobytes(sm,&R); 43 | 44 | crypto_hash_sha512(hram,sm,mlen + 64); 45 | sc_reduce(hram); 46 | sc_muladd(sm + 32,hram,sk,nonce); /* NEW: Use privkey directly */ 47 | 48 | /* Erase any traces of private scalar or 49 | nonce left in the stack from sc_muladd */ 50 | zeroize_stack(); 51 | zeroize(nonce, 64); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/zeroize.c: -------------------------------------------------------------------------------- 1 | #include "zeroize.h" 2 | 3 | void zeroize(unsigned char* b, size_t len) 4 | { 5 | size_t count = 0; 6 | volatile unsigned char *p = b; 7 | 8 | for (count = 0; count < len; count++) 9 | p[count] = 0; 10 | } 11 | 12 | void zeroize_stack() 13 | { 14 | unsigned char m[ZEROIZE_STACK_SIZE]; 15 | zeroize(m, ZEROIZE_STACK_SIZE); 16 | } 17 | -------------------------------------------------------------------------------- /libcurve25519-donna/additions/zeroize.h: -------------------------------------------------------------------------------- 1 | #ifndef __ZEROIZE_H__ 2 | #define __ZEROIZE_H__ 3 | 4 | #include 5 | 6 | #define ZEROIZE_STACK_SIZE 1024 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | void zeroize(unsigned char* b, size_t len); 13 | 14 | void zeroize_stack(); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /libcurve25519-donna/base2.h: -------------------------------------------------------------------------------- 1 | { 2 | { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, 3 | { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 }, 4 | { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 }, 5 | }, 6 | { 7 | { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 }, 8 | { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 }, 9 | { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 }, 10 | }, 11 | { 12 | { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 }, 13 | { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 }, 14 | { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 }, 15 | }, 16 | { 17 | { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 }, 18 | { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 }, 19 | { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 }, 20 | }, 21 | { 22 | { -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 }, 23 | { -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 }, 24 | { 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 }, 25 | }, 26 | { 27 | { -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 }, 28 | { 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 }, 29 | { 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 }, 30 | }, 31 | { 32 | { -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 }, 33 | { -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 }, 34 | { -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 }, 35 | }, 36 | { 37 | { -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 }, 38 | { -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 }, 39 | { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 }, 40 | }, 41 | -------------------------------------------------------------------------------- /libcurve25519-donna/d.h: -------------------------------------------------------------------------------- 1 | -10913610,13857413,-15372611,6949391,114729,-8787816,-6275908,-3247719,-18696448,-12055116 2 | -------------------------------------------------------------------------------- /libcurve25519-donna/d2.h: -------------------------------------------------------------------------------- 1 | -21827239,-5839606,-30745221,13898782,229458,15978800,-12551817,-6495438,29715968,9444199 2 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe.h: -------------------------------------------------------------------------------- 1 | #ifndef FE_H 2 | #define FE_H 3 | 4 | #include "nacl_includes/crypto_int32.h" 5 | 6 | typedef crypto_int32 fe[10]; 7 | 8 | /* 9 | fe means field element. 10 | Here the field is \Z/(2^255-19). 11 | An element t, entries t[0]...t[9], represents the integer 12 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. 13 | Bounds on each t[i] vary depending on context. 14 | */ 15 | 16 | #define fe_frombytes crypto_sign_ed25519_ref10_fe_frombytes 17 | #define fe_tobytes crypto_sign_ed25519_ref10_fe_tobytes 18 | #define fe_copy crypto_sign_ed25519_ref10_fe_copy 19 | #define fe_isnonzero crypto_sign_ed25519_ref10_fe_isnonzero 20 | #define fe_isnegative crypto_sign_ed25519_ref10_fe_isnegative 21 | #define fe_0 crypto_sign_ed25519_ref10_fe_0 22 | #define fe_1 crypto_sign_ed25519_ref10_fe_1 23 | #define fe_cswap crypto_sign_ed25519_ref10_fe_cswap 24 | #define fe_cmov crypto_sign_ed25519_ref10_fe_cmov 25 | #define fe_add crypto_sign_ed25519_ref10_fe_add 26 | #define fe_sub crypto_sign_ed25519_ref10_fe_sub 27 | #define fe_neg crypto_sign_ed25519_ref10_fe_neg 28 | #define fe_mul crypto_sign_ed25519_ref10_fe_mul 29 | #define fe_sq crypto_sign_ed25519_ref10_fe_sq 30 | #define fe_sq2 crypto_sign_ed25519_ref10_fe_sq2 31 | #define fe_mul121666 crypto_sign_ed25519_ref10_fe_mul121666 32 | #define fe_invert crypto_sign_ed25519_ref10_fe_invert 33 | #define fe_pow22523 crypto_sign_ed25519_ref10_fe_pow22523 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | extern void fe_frombytes(fe,const unsigned char *); 40 | extern void fe_tobytes(unsigned char *,const fe); 41 | 42 | extern void fe_copy(fe,const fe); 43 | extern int fe_isnonzero(const fe); 44 | extern int fe_isnegative(const fe); 45 | extern void fe_0(fe); 46 | extern void fe_1(fe); 47 | extern void fe_cswap(fe,fe,unsigned int); 48 | extern void fe_cmov(fe,const fe,unsigned int); 49 | 50 | extern void fe_add(fe,const fe,const fe); 51 | extern void fe_sub(fe,const fe,const fe); 52 | extern void fe_neg(fe,const fe); 53 | extern void fe_mul(fe,const fe,const fe); 54 | extern void fe_sq(fe,const fe); 55 | extern void fe_sq2(fe,const fe); 56 | extern void fe_mul121666(fe,const fe); 57 | extern void fe_invert(fe,const fe); 58 | extern void fe_pow22523(fe,const fe); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_0.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = 0 5 | */ 6 | 7 | void fe_0(fe h) 8 | { 9 | h[0] = 0; 10 | h[1] = 0; 11 | h[2] = 0; 12 | h[3] = 0; 13 | h[4] = 0; 14 | h[5] = 0; 15 | h[6] = 0; 16 | h[7] = 0; 17 | h[8] = 0; 18 | h[9] = 0; 19 | } 20 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_1.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = 1 5 | */ 6 | 7 | void fe_1(fe h) 8 | { 9 | h[0] = 1; 10 | h[1] = 0; 11 | h[2] = 0; 12 | h[3] = 0; 13 | h[4] = 0; 14 | h[5] = 0; 15 | h[6] = 0; 16 | h[7] = 0; 17 | h[8] = 0; 18 | h[9] = 0; 19 | } 20 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_add.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = f + g 5 | Can overlap h with f or g. 6 | 7 | Preconditions: 8 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 9 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 10 | 11 | Postconditions: 12 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 13 | */ 14 | 15 | void fe_add(fe h,const fe f,const fe g) 16 | { 17 | crypto_int32 f0 = f[0]; 18 | crypto_int32 f1 = f[1]; 19 | crypto_int32 f2 = f[2]; 20 | crypto_int32 f3 = f[3]; 21 | crypto_int32 f4 = f[4]; 22 | crypto_int32 f5 = f[5]; 23 | crypto_int32 f6 = f[6]; 24 | crypto_int32 f7 = f[7]; 25 | crypto_int32 f8 = f[8]; 26 | crypto_int32 f9 = f[9]; 27 | crypto_int32 g0 = g[0]; 28 | crypto_int32 g1 = g[1]; 29 | crypto_int32 g2 = g[2]; 30 | crypto_int32 g3 = g[3]; 31 | crypto_int32 g4 = g[4]; 32 | crypto_int32 g5 = g[5]; 33 | crypto_int32 g6 = g[6]; 34 | crypto_int32 g7 = g[7]; 35 | crypto_int32 g8 = g[8]; 36 | crypto_int32 g9 = g[9]; 37 | crypto_int32 h0 = f0 + g0; 38 | crypto_int32 h1 = f1 + g1; 39 | crypto_int32 h2 = f2 + g2; 40 | crypto_int32 h3 = f3 + g3; 41 | crypto_int32 h4 = f4 + g4; 42 | crypto_int32 h5 = f5 + g5; 43 | crypto_int32 h6 = f6 + g6; 44 | crypto_int32 h7 = f7 + g7; 45 | crypto_int32 h8 = f8 + g8; 46 | crypto_int32 h9 = f9 + g9; 47 | h[0] = h0; 48 | h[1] = h1; 49 | h[2] = h2; 50 | h[3] = h3; 51 | h[4] = h4; 52 | h[5] = h5; 53 | h[6] = h6; 54 | h[7] = h7; 55 | h[8] = h8; 56 | h[9] = h9; 57 | } 58 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_cmov.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | Replace (f,g) with (g,g) if b == 1; 5 | replace (f,g) with (f,g) if b == 0. 6 | 7 | Preconditions: b in {0,1}. 8 | */ 9 | 10 | void fe_cmov(fe f,const fe g,unsigned int b) 11 | { 12 | crypto_int32 f0 = f[0]; 13 | crypto_int32 f1 = f[1]; 14 | crypto_int32 f2 = f[2]; 15 | crypto_int32 f3 = f[3]; 16 | crypto_int32 f4 = f[4]; 17 | crypto_int32 f5 = f[5]; 18 | crypto_int32 f6 = f[6]; 19 | crypto_int32 f7 = f[7]; 20 | crypto_int32 f8 = f[8]; 21 | crypto_int32 f9 = f[9]; 22 | crypto_int32 g0 = g[0]; 23 | crypto_int32 g1 = g[1]; 24 | crypto_int32 g2 = g[2]; 25 | crypto_int32 g3 = g[3]; 26 | crypto_int32 g4 = g[4]; 27 | crypto_int32 g5 = g[5]; 28 | crypto_int32 g6 = g[6]; 29 | crypto_int32 g7 = g[7]; 30 | crypto_int32 g8 = g[8]; 31 | crypto_int32 g9 = g[9]; 32 | crypto_int32 x0 = f0 ^ g0; 33 | crypto_int32 x1 = f1 ^ g1; 34 | crypto_int32 x2 = f2 ^ g2; 35 | crypto_int32 x3 = f3 ^ g3; 36 | crypto_int32 x4 = f4 ^ g4; 37 | crypto_int32 x5 = f5 ^ g5; 38 | crypto_int32 x6 = f6 ^ g6; 39 | crypto_int32 x7 = f7 ^ g7; 40 | crypto_int32 x8 = f8 ^ g8; 41 | crypto_int32 x9 = f9 ^ g9; 42 | b = -b; 43 | x0 &= b; 44 | x1 &= b; 45 | x2 &= b; 46 | x3 &= b; 47 | x4 &= b; 48 | x5 &= b; 49 | x6 &= b; 50 | x7 &= b; 51 | x8 &= b; 52 | x9 &= b; 53 | f[0] = f0 ^ x0; 54 | f[1] = f1 ^ x1; 55 | f[2] = f2 ^ x2; 56 | f[3] = f3 ^ x3; 57 | f[4] = f4 ^ x4; 58 | f[5] = f5 ^ x5; 59 | f[6] = f6 ^ x6; 60 | f[7] = f7 ^ x7; 61 | f[8] = f8 ^ x8; 62 | f[9] = f9 ^ x9; 63 | } 64 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_copy.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = f 5 | */ 6 | 7 | void fe_copy(fe h,const fe f) 8 | { 9 | crypto_int32 f0 = f[0]; 10 | crypto_int32 f1 = f[1]; 11 | crypto_int32 f2 = f[2]; 12 | crypto_int32 f3 = f[3]; 13 | crypto_int32 f4 = f[4]; 14 | crypto_int32 f5 = f[5]; 15 | crypto_int32 f6 = f[6]; 16 | crypto_int32 f7 = f[7]; 17 | crypto_int32 f8 = f[8]; 18 | crypto_int32 f9 = f[9]; 19 | h[0] = f0; 20 | h[1] = f1; 21 | h[2] = f2; 22 | h[3] = f3; 23 | h[4] = f4; 24 | h[5] = f5; 25 | h[6] = f6; 26 | h[7] = f7; 27 | h[8] = f8; 28 | h[9] = f9; 29 | } 30 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_frombytes.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "nacl_includes/crypto_int64.h" 3 | #include "nacl_includes/crypto_uint64.h" 4 | 5 | static crypto_uint64 load_3(const unsigned char *in) 6 | { 7 | crypto_uint64 result; 8 | result = (crypto_uint64) in[0]; 9 | result |= ((crypto_uint64) in[1]) << 8; 10 | result |= ((crypto_uint64) in[2]) << 16; 11 | return result; 12 | } 13 | 14 | static crypto_uint64 load_4(const unsigned char *in) 15 | { 16 | crypto_uint64 result; 17 | result = (crypto_uint64) in[0]; 18 | result |= ((crypto_uint64) in[1]) << 8; 19 | result |= ((crypto_uint64) in[2]) << 16; 20 | result |= ((crypto_uint64) in[3]) << 24; 21 | return result; 22 | } 23 | 24 | /* 25 | Ignores top bit of h. 26 | */ 27 | 28 | void fe_frombytes(fe h,const unsigned char *s) 29 | { 30 | crypto_int64 h0 = load_4(s); 31 | crypto_int64 h1 = load_3(s + 4) << 6; 32 | crypto_int64 h2 = load_3(s + 7) << 5; 33 | crypto_int64 h3 = load_3(s + 10) << 3; 34 | crypto_int64 h4 = load_3(s + 13) << 2; 35 | crypto_int64 h5 = load_4(s + 16); 36 | crypto_int64 h6 = load_3(s + 20) << 7; 37 | crypto_int64 h7 = load_3(s + 23) << 5; 38 | crypto_int64 h8 = load_3(s + 26) << 4; 39 | crypto_int64 h9 = (load_3(s + 29) & 8388607) << 2; 40 | crypto_int64 carry0; 41 | crypto_int64 carry1; 42 | crypto_int64 carry2; 43 | crypto_int64 carry3; 44 | crypto_int64 carry4; 45 | crypto_int64 carry5; 46 | crypto_int64 carry6; 47 | crypto_int64 carry7; 48 | crypto_int64 carry8; 49 | crypto_int64 carry9; 50 | 51 | carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; 52 | carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; 53 | carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; 54 | carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; 55 | carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; 56 | 57 | carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; 58 | carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; 59 | carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; 60 | carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; 61 | carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; 62 | 63 | h[0] = h0; 64 | h[1] = h1; 65 | h[2] = h2; 66 | h[3] = h3; 67 | h[4] = h4; 68 | h[5] = h5; 69 | h[6] = h6; 70 | h[7] = h7; 71 | h[8] = h8; 72 | h[9] = h9; 73 | } 74 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_invert.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | void fe_invert(fe out,const fe z) 4 | { 5 | fe t0; 6 | fe t1; 7 | fe t2; 8 | fe t3; 9 | int i; 10 | 11 | #include "pow225521.h" 12 | 13 | return; 14 | } 15 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_isnegative.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | return 1 if f is in {1,3,5,...,q-2} 5 | return 0 if f is in {0,2,4,...,q-1} 6 | 7 | Preconditions: 8 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 9 | */ 10 | 11 | int fe_isnegative(const fe f) 12 | { 13 | unsigned char s[32]; 14 | fe_tobytes(s,f); 15 | return s[0] & 1; 16 | } 17 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_isnonzero.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | #include "nacl_includes/crypto_verify_32.h" 3 | 4 | /* 5 | return nonzero if f == 0 6 | return 0 if f != 0 7 | 8 | Preconditions: 9 | |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 10 | */ 11 | 12 | /* TREVOR'S COMMENT 13 | * 14 | * I think the above comment is wrong. Instead: 15 | * 16 | * return 0 if f == 0 17 | * return -1 if f != 0 18 | * 19 | * */ 20 | 21 | static const unsigned char zero[32]; 22 | 23 | int fe_isnonzero(const fe f) 24 | { 25 | unsigned char s[32]; 26 | fe_tobytes(s,f); 27 | return crypto_verify_32(s,zero); 28 | } 29 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_neg.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = -f 5 | 6 | Preconditions: 7 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 8 | 9 | Postconditions: 10 | |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 11 | */ 12 | 13 | void fe_neg(fe h,const fe f) 14 | { 15 | crypto_int32 f0 = f[0]; 16 | crypto_int32 f1 = f[1]; 17 | crypto_int32 f2 = f[2]; 18 | crypto_int32 f3 = f[3]; 19 | crypto_int32 f4 = f[4]; 20 | crypto_int32 f5 = f[5]; 21 | crypto_int32 f6 = f[6]; 22 | crypto_int32 f7 = f[7]; 23 | crypto_int32 f8 = f[8]; 24 | crypto_int32 f9 = f[9]; 25 | crypto_int32 h0 = -f0; 26 | crypto_int32 h1 = -f1; 27 | crypto_int32 h2 = -f2; 28 | crypto_int32 h3 = -f3; 29 | crypto_int32 h4 = -f4; 30 | crypto_int32 h5 = -f5; 31 | crypto_int32 h6 = -f6; 32 | crypto_int32 h7 = -f7; 33 | crypto_int32 h8 = -f8; 34 | crypto_int32 h9 = -f9; 35 | h[0] = h0; 36 | h[1] = h1; 37 | h[2] = h2; 38 | h[3] = h3; 39 | h[4] = h4; 40 | h[5] = h5; 41 | h[6] = h6; 42 | h[7] = h7; 43 | h[8] = h8; 44 | h[9] = h9; 45 | } 46 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_pow22523.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | void fe_pow22523(fe out,const fe z) 4 | { 5 | fe t0; 6 | fe t1; 7 | fe t2; 8 | int i; 9 | 10 | #include "pow22523.h" 11 | 12 | return; 13 | } 14 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_sub.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | h = f - g 5 | Can overlap h with f or g. 6 | 7 | Preconditions: 8 | |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 9 | |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. 10 | 11 | Postconditions: 12 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 13 | */ 14 | 15 | void fe_sub(fe h,const fe f,const fe g) 16 | { 17 | crypto_int32 f0 = f[0]; 18 | crypto_int32 f1 = f[1]; 19 | crypto_int32 f2 = f[2]; 20 | crypto_int32 f3 = f[3]; 21 | crypto_int32 f4 = f[4]; 22 | crypto_int32 f5 = f[5]; 23 | crypto_int32 f6 = f[6]; 24 | crypto_int32 f7 = f[7]; 25 | crypto_int32 f8 = f[8]; 26 | crypto_int32 f9 = f[9]; 27 | crypto_int32 g0 = g[0]; 28 | crypto_int32 g1 = g[1]; 29 | crypto_int32 g2 = g[2]; 30 | crypto_int32 g3 = g[3]; 31 | crypto_int32 g4 = g[4]; 32 | crypto_int32 g5 = g[5]; 33 | crypto_int32 g6 = g[6]; 34 | crypto_int32 g7 = g[7]; 35 | crypto_int32 g8 = g[8]; 36 | crypto_int32 g9 = g[9]; 37 | crypto_int32 h0 = f0 - g0; 38 | crypto_int32 h1 = f1 - g1; 39 | crypto_int32 h2 = f2 - g2; 40 | crypto_int32 h3 = f3 - g3; 41 | crypto_int32 h4 = f4 - g4; 42 | crypto_int32 h5 = f5 - g5; 43 | crypto_int32 h6 = f6 - g6; 44 | crypto_int32 h7 = f7 - g7; 45 | crypto_int32 h8 = f8 - g8; 46 | crypto_int32 h9 = f9 - g9; 47 | h[0] = h0; 48 | h[1] = h1; 49 | h[2] = h2; 50 | h[3] = h3; 51 | h[4] = h4; 52 | h[5] = h5; 53 | h[6] = h6; 54 | h[7] = h7; 55 | h[8] = h8; 56 | h[9] = h9; 57 | } 58 | -------------------------------------------------------------------------------- /libcurve25519-donna/fe_tobytes.c: -------------------------------------------------------------------------------- 1 | #include "fe.h" 2 | 3 | /* 4 | Preconditions: 5 | |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. 6 | 7 | Write p=2^255-19; q=floor(h/p). 8 | Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). 9 | 10 | Proof: 11 | Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. 12 | Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. 13 | 14 | Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). 15 | Then 0> 25; 53 | q = (h0 + q) >> 26; 54 | q = (h1 + q) >> 25; 55 | q = (h2 + q) >> 26; 56 | q = (h3 + q) >> 25; 57 | q = (h4 + q) >> 26; 58 | q = (h5 + q) >> 25; 59 | q = (h6 + q) >> 26; 60 | q = (h7 + q) >> 25; 61 | q = (h8 + q) >> 26; 62 | q = (h9 + q) >> 25; 63 | 64 | /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ 65 | h0 += 19 * q; 66 | /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ 67 | 68 | carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; 69 | carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; 70 | carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; 71 | carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; 72 | carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; 73 | carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; 74 | carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; 75 | carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; 76 | carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; 77 | carry9 = h9 >> 25; h9 -= carry9 << 25; 78 | /* h10 = carry9 */ 79 | 80 | /* 81 | Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. 82 | Have h0+...+2^230 h9 between 0 and 2^255-1; 83 | evidently 2^255 h10-2^255 q = 0. 84 | Goal: Output h0+...+2^230 h9. 85 | */ 86 | 87 | s[0] = h0 >> 0; 88 | s[1] = h0 >> 8; 89 | s[2] = h0 >> 16; 90 | s[3] = (h0 >> 24) | (h1 << 2); 91 | s[4] = h1 >> 6; 92 | s[5] = h1 >> 14; 93 | s[6] = (h1 >> 22) | (h2 << 3); 94 | s[7] = h2 >> 5; 95 | s[8] = h2 >> 13; 96 | s[9] = (h2 >> 21) | (h3 << 5); 97 | s[10] = h3 >> 3; 98 | s[11] = h3 >> 11; 99 | s[12] = (h3 >> 19) | (h4 << 6); 100 | s[13] = h4 >> 2; 101 | s[14] = h4 >> 10; 102 | s[15] = h4 >> 18; 103 | s[16] = h5 >> 0; 104 | s[17] = h5 >> 8; 105 | s[18] = h5 >> 16; 106 | s[19] = (h5 >> 24) | (h6 << 1); 107 | s[20] = h6 >> 7; 108 | s[21] = h6 >> 15; 109 | s[22] = (h6 >> 23) | (h7 << 3); 110 | s[23] = h7 >> 5; 111 | s[24] = h7 >> 13; 112 | s[25] = (h7 >> 21) | (h8 << 4); 113 | s[26] = h8 >> 4; 114 | s[27] = h8 >> 12; 115 | s[28] = (h8 >> 20) | (h9 << 6); 116 | s[29] = h9 >> 2; 117 | s[30] = h9 >> 10; 118 | s[31] = h9 >> 18; 119 | } 120 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge.h: -------------------------------------------------------------------------------- 1 | #ifndef GE_H 2 | #define GE_H 3 | 4 | /* 5 | ge means group element. 6 | 7 | Here the group is the set of pairs (x,y) of field elements (see fe.h) 8 | satisfying -x^2 + y^2 = 1 + d x^2y^2 9 | where d = -121665/121666. 10 | 11 | Representations: 12 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z 13 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT 14 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T 15 | ge_precomp (Duif): (y+x,y-x,2dxy) 16 | */ 17 | 18 | #include "fe.h" 19 | 20 | typedef struct { 21 | fe X; 22 | fe Y; 23 | fe Z; 24 | } ge_p2; 25 | 26 | typedef struct { 27 | fe X; 28 | fe Y; 29 | fe Z; 30 | fe T; 31 | } ge_p3; 32 | 33 | typedef struct { 34 | fe X; 35 | fe Y; 36 | fe Z; 37 | fe T; 38 | } ge_p1p1; 39 | 40 | typedef struct { 41 | fe yplusx; 42 | fe yminusx; 43 | fe xy2d; 44 | } ge_precomp; 45 | 46 | typedef struct { 47 | fe YplusX; 48 | fe YminusX; 49 | fe Z; 50 | fe T2d; 51 | } ge_cached; 52 | 53 | #define ge_frombytes_negate_vartime crypto_sign_ed25519_ref10_ge_frombytes_negate_vartime 54 | #define ge_tobytes crypto_sign_ed25519_ref10_ge_tobytes 55 | #define ge_p3_tobytes crypto_sign_ed25519_ref10_ge_p3_tobytes 56 | 57 | #define ge_p2_0 crypto_sign_ed25519_ref10_ge_p2_0 58 | #define ge_p3_0 crypto_sign_ed25519_ref10_ge_p3_0 59 | #define ge_precomp_0 crypto_sign_ed25519_ref10_ge_precomp_0 60 | #define ge_p3_to_p2 crypto_sign_ed25519_ref10_ge_p3_to_p2 61 | #define ge_p3_to_cached crypto_sign_ed25519_ref10_ge_p3_to_cached 62 | #define ge_p1p1_to_p2 crypto_sign_ed25519_ref10_ge_p1p1_to_p2 63 | #define ge_p1p1_to_p3 crypto_sign_ed25519_ref10_ge_p1p1_to_p3 64 | #define ge_p2_dbl crypto_sign_ed25519_ref10_ge_p2_dbl 65 | #define ge_p3_dbl crypto_sign_ed25519_ref10_ge_p3_dbl 66 | 67 | #define ge_madd crypto_sign_ed25519_ref10_ge_madd 68 | #define ge_msub crypto_sign_ed25519_ref10_ge_msub 69 | #define ge_add crypto_sign_ed25519_ref10_ge_add 70 | #define ge_sub crypto_sign_ed25519_ref10_ge_sub 71 | #define ge_scalarmult_base crypto_sign_ed25519_ref10_ge_scalarmult_base 72 | #define ge_double_scalarmult_vartime crypto_sign_ed25519_ref10_ge_double_scalarmult_vartime 73 | 74 | #ifdef __cplusplus 75 | extern "C" { 76 | #endif 77 | 78 | extern void ge_tobytes(unsigned char *,const ge_p2 *); 79 | extern void ge_p3_tobytes(unsigned char *,const ge_p3 *); 80 | extern int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *); 81 | 82 | extern void ge_p2_0(ge_p2 *); 83 | extern void ge_p3_0(ge_p3 *); 84 | extern void ge_precomp_0(ge_precomp *); 85 | extern void ge_p3_to_p2(ge_p2 *,const ge_p3 *); 86 | extern void ge_p3_to_cached(ge_cached *,const ge_p3 *); 87 | extern void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *); 88 | extern void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *); 89 | extern void ge_p2_dbl(ge_p1p1 *,const ge_p2 *); 90 | extern void ge_p3_dbl(ge_p1p1 *,const ge_p3 *); 91 | 92 | extern void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *); 93 | extern void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *); 94 | extern void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *); 95 | extern void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *); 96 | extern void ge_scalarmult_base(ge_p3 *,const unsigned char *); 97 | extern void ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,const ge_p3 *,const unsigned char *); 98 | 99 | #ifdef __cplusplus 100 | } 101 | #endif 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_add.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p + q 5 | */ 6 | 7 | void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) 8 | { 9 | fe t0; 10 | #include "ge_add.h" 11 | } 12 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_add.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_add */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe Z2 */ 11 | 12 | /* qhasm: fe T1 */ 13 | 14 | /* qhasm: fe ZZ */ 15 | 16 | /* qhasm: fe YpX2 */ 17 | 18 | /* qhasm: fe YmX2 */ 19 | 20 | /* qhasm: fe T2d2 */ 21 | 22 | /* qhasm: fe X3 */ 23 | 24 | /* qhasm: fe Y3 */ 25 | 26 | /* qhasm: fe Z3 */ 27 | 28 | /* qhasm: fe T3 */ 29 | 30 | /* qhasm: fe YpX1 */ 31 | 32 | /* qhasm: fe YmX1 */ 33 | 34 | /* qhasm: fe A */ 35 | 36 | /* qhasm: fe B */ 37 | 38 | /* qhasm: fe C */ 39 | 40 | /* qhasm: fe D */ 41 | 42 | /* qhasm: YpX1 = Y1+X1 */ 43 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 45 | fe_add(r->X,p->Y,p->X); 46 | 47 | /* qhasm: YmX1 = Y1-X1 */ 48 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 50 | fe_sub(r->Y,p->Y,p->X); 51 | 52 | /* qhasm: A = YpX1*YpX2 */ 53 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YplusX); */ 55 | fe_mul(r->Z,r->X,q->YplusX); 56 | 57 | /* qhasm: B = YmX1*YmX2 */ 58 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YminusX); */ 60 | fe_mul(r->Y,r->Y,q->YminusX); 61 | 62 | /* qhasm: C = T2d2*T1 */ 63 | /* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */ 65 | fe_mul(r->T,q->T2d,p->T); 66 | 67 | /* qhasm: ZZ = Z1*Z2 */ 68 | /* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */ 70 | fe_mul(r->X,p->Z,q->Z); 71 | 72 | /* qhasm: D = 2*ZZ */ 73 | /* asm 1: fe_add(>D=fe#5,D=t0,X,X); */ 75 | fe_add(t0,r->X,r->X); 76 | 77 | /* qhasm: X3 = A-B */ 78 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 80 | fe_sub(r->X,r->Z,r->Y); 81 | 82 | /* qhasm: Y3 = A+B */ 83 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 85 | fe_add(r->Y,r->Z,r->Y); 86 | 87 | /* qhasm: Z3 = D+C */ 88 | /* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */ 90 | fe_add(r->Z,t0,r->T); 91 | 92 | /* qhasm: T3 = D-C */ 93 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */ 95 | fe_sub(r->T,t0,r->T); 96 | 97 | /* qhasm: return */ 98 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_double_scalarmult.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | static void slide(signed char *r,const unsigned char *a) 4 | { 5 | int i; 6 | int b; 7 | int k; 8 | 9 | for (i = 0;i < 256;++i) 10 | r[i] = 1 & (a[i >> 3] >> (i & 7)); 11 | 12 | for (i = 0;i < 256;++i) 13 | if (r[i]) { 14 | for (b = 1;b <= 6 && i + b < 256;++b) { 15 | if (r[i + b]) { 16 | if (r[i] + (r[i + b] << b) <= 15) { 17 | r[i] += r[i + b] << b; r[i + b] = 0; 18 | } else if (r[i] - (r[i + b] << b) >= -15) { 19 | r[i] -= r[i + b] << b; 20 | for (k = i + b;k < 256;++k) { 21 | if (!r[k]) { 22 | r[k] = 1; 23 | break; 24 | } 25 | r[k] = 0; 26 | } 27 | } else 28 | break; 29 | } 30 | } 31 | } 32 | 33 | } 34 | 35 | static ge_precomp Bi[8] = { 36 | #include "base2.h" 37 | } ; 38 | 39 | /* 40 | r = a * A + b * B 41 | where a = a[0]+256*a[1]+...+256^31 a[31]. 42 | and b = b[0]+256*b[1]+...+256^31 b[31]. 43 | B is the Ed25519 base point (x,4/5) with x positive. 44 | */ 45 | 46 | void ge_double_scalarmult_vartime(ge_p2 *r,const unsigned char *a,const ge_p3 *A,const unsigned char *b) 47 | { 48 | signed char aslide[256]; 49 | signed char bslide[256]; 50 | ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ 51 | ge_p1p1 t; 52 | ge_p3 u; 53 | ge_p3 A2; 54 | int i; 55 | 56 | slide(aslide,a); 57 | slide(bslide,b); 58 | 59 | ge_p3_to_cached(&Ai[0],A); 60 | ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t); 61 | ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u); 62 | ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u); 63 | ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u); 64 | ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u); 65 | ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u); 66 | ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u); 67 | ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u); 68 | 69 | ge_p2_0(r); 70 | 71 | for (i = 255;i >= 0;--i) { 72 | if (aslide[i] || bslide[i]) break; 73 | } 74 | 75 | for (;i >= 0;--i) { 76 | ge_p2_dbl(&t,r); 77 | 78 | if (aslide[i] > 0) { 79 | ge_p1p1_to_p3(&u,&t); 80 | ge_add(&t,&u,&Ai[aslide[i]/2]); 81 | } else if (aslide[i] < 0) { 82 | ge_p1p1_to_p3(&u,&t); 83 | ge_sub(&t,&u,&Ai[(-aslide[i])/2]); 84 | } 85 | 86 | if (bslide[i] > 0) { 87 | ge_p1p1_to_p3(&u,&t); 88 | ge_madd(&t,&u,&Bi[bslide[i]/2]); 89 | } else if (bslide[i] < 0) { 90 | ge_p1p1_to_p3(&u,&t); 91 | ge_msub(&t,&u,&Bi[(-bslide[i])/2]); 92 | } 93 | 94 | ge_p1p1_to_p2(r,&t); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_frombytes.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | static const fe d = { 4 | #include "d.h" 5 | } ; 6 | 7 | static const fe sqrtm1 = { 8 | #include "sqrtm1.h" 9 | } ; 10 | 11 | int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) 12 | { 13 | fe u; 14 | fe v; 15 | fe v3; 16 | fe vxx; 17 | fe check; 18 | 19 | fe_frombytes(h->Y,s); 20 | fe_1(h->Z); 21 | fe_sq(u,h->Y); 22 | fe_mul(v,u,d); 23 | fe_sub(u,u,h->Z); /* u = y^2-1 */ 24 | fe_add(v,v,h->Z); /* v = dy^2+1 */ 25 | 26 | fe_sq(v3,v); 27 | fe_mul(v3,v3,v); /* v3 = v^3 */ 28 | fe_sq(h->X,v3); 29 | fe_mul(h->X,h->X,v); 30 | fe_mul(h->X,h->X,u); /* x = uv^7 */ 31 | 32 | fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ 33 | fe_mul(h->X,h->X,v3); 34 | fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ 35 | 36 | fe_sq(vxx,h->X); 37 | fe_mul(vxx,vxx,v); 38 | fe_sub(check,vxx,u); /* vx^2-u */ 39 | if (fe_isnonzero(check)) { 40 | fe_add(check,vxx,u); /* vx^2+u */ 41 | if (fe_isnonzero(check)) return -1; 42 | fe_mul(h->X,h->X,sqrtm1); 43 | } 44 | 45 | if (fe_isnegative(h->X) == (s[31] >> 7)) 46 | fe_neg(h->X,h->X); 47 | 48 | fe_mul(h->T,h->X,h->Y); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_madd.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p + q 5 | */ 6 | 7 | void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) 8 | { 9 | fe t0; 10 | #include "ge_madd.h" 11 | } 12 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_madd.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_madd */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe T1 */ 11 | 12 | /* qhasm: fe ypx2 */ 13 | 14 | /* qhasm: fe ymx2 */ 15 | 16 | /* qhasm: fe xy2d2 */ 17 | 18 | /* qhasm: fe X3 */ 19 | 20 | /* qhasm: fe Y3 */ 21 | 22 | /* qhasm: fe Z3 */ 23 | 24 | /* qhasm: fe T3 */ 25 | 26 | /* qhasm: fe YpX1 */ 27 | 28 | /* qhasm: fe YmX1 */ 29 | 30 | /* qhasm: fe A */ 31 | 32 | /* qhasm: fe B */ 33 | 34 | /* qhasm: fe C */ 35 | 36 | /* qhasm: fe D */ 37 | 38 | /* qhasm: YpX1 = Y1+X1 */ 39 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 41 | fe_add(r->X,p->Y,p->X); 42 | 43 | /* qhasm: YmX1 = Y1-X1 */ 44 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 46 | fe_sub(r->Y,p->Y,p->X); 47 | 48 | /* qhasm: A = YpX1*ypx2 */ 49 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yplusx); */ 51 | fe_mul(r->Z,r->X,q->yplusx); 52 | 53 | /* qhasm: B = YmX1*ymx2 */ 54 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yminusx); */ 56 | fe_mul(r->Y,r->Y,q->yminusx); 57 | 58 | /* qhasm: C = xy2d2*T1 */ 59 | /* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */ 61 | fe_mul(r->T,q->xy2d,p->T); 62 | 63 | /* qhasm: D = 2*Z1 */ 64 | /* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */ 66 | fe_add(t0,p->Z,p->Z); 67 | 68 | /* qhasm: X3 = A-B */ 69 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 71 | fe_sub(r->X,r->Z,r->Y); 72 | 73 | /* qhasm: Y3 = A+B */ 74 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 76 | fe_add(r->Y,r->Z,r->Y); 77 | 78 | /* qhasm: Z3 = D+C */ 79 | /* asm 1: fe_add(>Z3=fe#3,Z3=r->Z,T); */ 81 | fe_add(r->Z,t0,r->T); 82 | 83 | /* qhasm: T3 = D-C */ 84 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T); */ 86 | fe_sub(r->T,t0,r->T); 87 | 88 | /* qhasm: return */ 89 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_msub.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p - q 5 | */ 6 | 7 | void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) 8 | { 9 | fe t0; 10 | #include "ge_msub.h" 11 | } 12 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_msub.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_msub */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe T1 */ 11 | 12 | /* qhasm: fe ypx2 */ 13 | 14 | /* qhasm: fe ymx2 */ 15 | 16 | /* qhasm: fe xy2d2 */ 17 | 18 | /* qhasm: fe X3 */ 19 | 20 | /* qhasm: fe Y3 */ 21 | 22 | /* qhasm: fe Z3 */ 23 | 24 | /* qhasm: fe T3 */ 25 | 26 | /* qhasm: fe YpX1 */ 27 | 28 | /* qhasm: fe YmX1 */ 29 | 30 | /* qhasm: fe A */ 31 | 32 | /* qhasm: fe B */ 33 | 34 | /* qhasm: fe C */ 35 | 36 | /* qhasm: fe D */ 37 | 38 | /* qhasm: YpX1 = Y1+X1 */ 39 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 41 | fe_add(r->X,p->Y,p->X); 42 | 43 | /* qhasm: YmX1 = Y1-X1 */ 44 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 46 | fe_sub(r->Y,p->Y,p->X); 47 | 48 | /* qhasm: A = YpX1*ymx2 */ 49 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,yminusx); */ 51 | fe_mul(r->Z,r->X,q->yminusx); 52 | 53 | /* qhasm: B = YmX1*ypx2 */ 54 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,yplusx); */ 56 | fe_mul(r->Y,r->Y,q->yplusx); 57 | 58 | /* qhasm: C = xy2d2*T1 */ 59 | /* asm 1: fe_mul(>C=fe#4,C=r->T,xy2d,T); */ 61 | fe_mul(r->T,q->xy2d,p->T); 62 | 63 | /* qhasm: D = 2*Z1 */ 64 | /* asm 1: fe_add(>D=fe#5,D=t0,Z,Z); */ 66 | fe_add(t0,p->Z,p->Z); 67 | 68 | /* qhasm: X3 = A-B */ 69 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 71 | fe_sub(r->X,r->Z,r->Y); 72 | 73 | /* qhasm: Y3 = A+B */ 74 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 76 | fe_add(r->Y,r->Z,r->Y); 77 | 78 | /* qhasm: Z3 = D-C */ 79 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */ 81 | fe_sub(r->Z,t0,r->T); 82 | 83 | /* qhasm: T3 = D+C */ 84 | /* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */ 86 | fe_add(r->T,t0,r->T); 87 | 88 | /* qhasm: return */ 89 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p1p1_to_p2.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) 8 | { 9 | fe_mul(r->X,p->X,p->T); 10 | fe_mul(r->Y,p->Y,p->Z); 11 | fe_mul(r->Z,p->Z,p->T); 12 | } 13 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p1p1_to_p3.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | extern void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) 8 | { 9 | fe_mul(r->X,p->X,p->T); 10 | fe_mul(r->Y,p->Y,p->Z); 11 | fe_mul(r->Z,p->Z,p->T); 12 | fe_mul(r->T,p->X,p->Y); 13 | } 14 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p2_0.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_p2_0(ge_p2 *h) 4 | { 5 | fe_0(h->X); 6 | fe_1(h->Y); 7 | fe_1(h->Z); 8 | } 9 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p2_dbl.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = 2 * p 5 | */ 6 | 7 | void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) 8 | { 9 | fe t0; 10 | #include "ge_p2_dbl.h" 11 | } 12 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p2_dbl.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_p2_dbl */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe A */ 11 | 12 | /* qhasm: fe AA */ 13 | 14 | /* qhasm: fe XX */ 15 | 16 | /* qhasm: fe YY */ 17 | 18 | /* qhasm: fe B */ 19 | 20 | /* qhasm: fe X3 */ 21 | 22 | /* qhasm: fe Y3 */ 23 | 24 | /* qhasm: fe Z3 */ 25 | 26 | /* qhasm: fe T3 */ 27 | 28 | /* qhasm: XX=X1^2 */ 29 | /* asm 1: fe_sq(>XX=fe#1,XX=r->X,X); */ 31 | fe_sq(r->X,p->X); 32 | 33 | /* qhasm: YY=Y1^2 */ 34 | /* asm 1: fe_sq(>YY=fe#3,YY=r->Z,Y); */ 36 | fe_sq(r->Z,p->Y); 37 | 38 | /* qhasm: B=2*Z1^2 */ 39 | /* asm 1: fe_sq2(>B=fe#4,B=r->T,Z); */ 41 | fe_sq2(r->T,p->Z); 42 | 43 | /* qhasm: A=X1+Y1 */ 44 | /* asm 1: fe_add(>A=fe#2,A=r->Y,X,Y); */ 46 | fe_add(r->Y,p->X,p->Y); 47 | 48 | /* qhasm: AA=A^2 */ 49 | /* asm 1: fe_sq(>AA=fe#5,AA=t0,Y); */ 51 | fe_sq(t0,r->Y); 52 | 53 | /* qhasm: Y3=YY+XX */ 54 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,X); */ 56 | fe_add(r->Y,r->Z,r->X); 57 | 58 | /* qhasm: Z3=YY-XX */ 59 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,Z,X); */ 61 | fe_sub(r->Z,r->Z,r->X); 62 | 63 | /* qhasm: X3=AA-Y3 */ 64 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Y); */ 66 | fe_sub(r->X,t0,r->Y); 67 | 68 | /* qhasm: T3=B-Z3 */ 69 | /* asm 1: fe_sub(>T3=fe#4,T3=r->T,T,Z); */ 71 | fe_sub(r->T,r->T,r->Z); 72 | 73 | /* qhasm: return */ 74 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p3_0.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_p3_0(ge_p3 *h) 4 | { 5 | fe_0(h->X); 6 | fe_1(h->Y); 7 | fe_1(h->Z); 8 | fe_0(h->T); 9 | } 10 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p3_dbl.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = 2 * p 5 | */ 6 | 7 | void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) 8 | { 9 | ge_p2 q; 10 | ge_p3_to_p2(&q,p); 11 | ge_p2_dbl(r,&q); 12 | } 13 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p3_to_cached.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | static const fe d2 = { 8 | #include "d2.h" 9 | } ; 10 | 11 | extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) 12 | { 13 | fe_add(r->YplusX,p->Y,p->X); 14 | fe_sub(r->YminusX,p->Y,p->X); 15 | fe_copy(r->Z,p->Z); 16 | fe_mul(r->T2d,p->T,d2); 17 | } 18 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p3_to_p2.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p 5 | */ 6 | 7 | extern void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) 8 | { 9 | fe_copy(r->X,p->X); 10 | fe_copy(r->Y,p->Y); 11 | fe_copy(r->Z,p->Z); 12 | } 13 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_p3_tobytes.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) 4 | { 5 | fe recip; 6 | fe x; 7 | fe y; 8 | 9 | fe_invert(recip,h->Z); 10 | fe_mul(x,h->X,recip); 11 | fe_mul(y,h->Y,recip); 12 | fe_tobytes(s,y); 13 | s[31] ^= fe_isnegative(x) << 7; 14 | } 15 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_precomp_0.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_precomp_0(ge_precomp *h) 4 | { 5 | fe_1(h->yplusx); 6 | fe_1(h->yminusx); 7 | fe_0(h->xy2d); 8 | } 9 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_scalarmult_base.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | #include "nacl_includes/crypto_uint32.h" 3 | 4 | #include 5 | 6 | static unsigned char equal(signed char b,signed char c) 7 | { 8 | unsigned char ub = b; 9 | unsigned char uc = c; 10 | unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ 11 | crypto_uint32 y = x; /* 0: yes; 1..255: no */ 12 | y -= 1; /* 4294967295: yes; 0..254: no */ 13 | y >>= 31; /* 1: yes; 0: no */ 14 | return y; 15 | } 16 | 17 | static unsigned char negative(signed char b) 18 | { 19 | uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ 20 | x >>= 63; /* 1: yes; 0: no */ 21 | return x; 22 | } 23 | 24 | static void cmov(ge_precomp *t,ge_precomp *u,unsigned char b) 25 | { 26 | fe_cmov(t->yplusx,u->yplusx,b); 27 | fe_cmov(t->yminusx,u->yminusx,b); 28 | fe_cmov(t->xy2d,u->xy2d,b); 29 | } 30 | 31 | /* base[i][j] = (j+1)*256^i*B */ 32 | static ge_precomp base[32][8] = { 33 | #include "base.h" 34 | } ; 35 | 36 | static void select(ge_precomp *t,int pos,signed char b) 37 | { 38 | ge_precomp minust; 39 | unsigned char bnegative = negative(b); 40 | unsigned char babs = b - (((-bnegative) & b) << 1); 41 | 42 | ge_precomp_0(t); 43 | cmov(t,&base[pos][0],equal(babs,1)); 44 | cmov(t,&base[pos][1],equal(babs,2)); 45 | cmov(t,&base[pos][2],equal(babs,3)); 46 | cmov(t,&base[pos][3],equal(babs,4)); 47 | cmov(t,&base[pos][4],equal(babs,5)); 48 | cmov(t,&base[pos][5],equal(babs,6)); 49 | cmov(t,&base[pos][6],equal(babs,7)); 50 | cmov(t,&base[pos][7],equal(babs,8)); 51 | fe_copy(minust.yplusx,t->yminusx); 52 | fe_copy(minust.yminusx,t->yplusx); 53 | fe_neg(minust.xy2d,t->xy2d); 54 | cmov(t,&minust,bnegative); 55 | } 56 | 57 | /* 58 | h = a * B 59 | where a = a[0]+256*a[1]+...+256^31 a[31] 60 | B is the Ed25519 base point (x,4/5) with x positive. 61 | 62 | Preconditions: 63 | a[31] <= 127 64 | */ 65 | 66 | void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) 67 | { 68 | signed char e[64]; 69 | signed char carry; 70 | ge_p1p1 r; 71 | ge_p2 s; 72 | ge_precomp t; 73 | int i; 74 | 75 | for (i = 0;i < 32;++i) { 76 | e[2 * i + 0] = (a[i] >> 0) & 15; 77 | e[2 * i + 1] = (a[i] >> 4) & 15; 78 | } 79 | /* each e[i] is between 0 and 15 */ 80 | /* e[63] is between 0 and 7 */ 81 | 82 | carry = 0; 83 | for (i = 0;i < 63;++i) { 84 | e[i] += carry; 85 | carry = e[i] + 8; 86 | carry >>= 4; 87 | e[i] -= carry << 4; 88 | } 89 | e[63] += carry; 90 | /* each e[i] is between -8 and 8 */ 91 | 92 | ge_p3_0(h); 93 | for (i = 1;i < 64;i += 2) { 94 | select(&t,i / 2,e[i]); 95 | ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); 96 | } 97 | 98 | ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r); 99 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); 100 | ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); 101 | ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r); 102 | 103 | for (i = 0;i < 64;i += 2) { 104 | select(&t,i / 2,e[i]); 105 | ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_sub.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | /* 4 | r = p - q 5 | */ 6 | 7 | void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) 8 | { 9 | fe t0; 10 | #include "ge_sub.h" 11 | } 12 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_sub.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: enter ge_sub */ 3 | 4 | /* qhasm: fe X1 */ 5 | 6 | /* qhasm: fe Y1 */ 7 | 8 | /* qhasm: fe Z1 */ 9 | 10 | /* qhasm: fe Z2 */ 11 | 12 | /* qhasm: fe T1 */ 13 | 14 | /* qhasm: fe ZZ */ 15 | 16 | /* qhasm: fe YpX2 */ 17 | 18 | /* qhasm: fe YmX2 */ 19 | 20 | /* qhasm: fe T2d2 */ 21 | 22 | /* qhasm: fe X3 */ 23 | 24 | /* qhasm: fe Y3 */ 25 | 26 | /* qhasm: fe Z3 */ 27 | 28 | /* qhasm: fe T3 */ 29 | 30 | /* qhasm: fe YpX1 */ 31 | 32 | /* qhasm: fe YmX1 */ 33 | 34 | /* qhasm: fe A */ 35 | 36 | /* qhasm: fe B */ 37 | 38 | /* qhasm: fe C */ 39 | 40 | /* qhasm: fe D */ 41 | 42 | /* qhasm: YpX1 = Y1+X1 */ 43 | /* asm 1: fe_add(>YpX1=fe#1,YpX1=r->X,Y,X); */ 45 | fe_add(r->X,p->Y,p->X); 46 | 47 | /* qhasm: YmX1 = Y1-X1 */ 48 | /* asm 1: fe_sub(>YmX1=fe#2,YmX1=r->Y,Y,X); */ 50 | fe_sub(r->Y,p->Y,p->X); 51 | 52 | /* qhasm: A = YpX1*YmX2 */ 53 | /* asm 1: fe_mul(>A=fe#3,A=r->Z,X,YminusX); */ 55 | fe_mul(r->Z,r->X,q->YminusX); 56 | 57 | /* qhasm: B = YmX1*YpX2 */ 58 | /* asm 1: fe_mul(>B=fe#2,B=r->Y,Y,YplusX); */ 60 | fe_mul(r->Y,r->Y,q->YplusX); 61 | 62 | /* qhasm: C = T2d2*T1 */ 63 | /* asm 1: fe_mul(>C=fe#4,C=r->T,T2d,T); */ 65 | fe_mul(r->T,q->T2d,p->T); 66 | 67 | /* qhasm: ZZ = Z1*Z2 */ 68 | /* asm 1: fe_mul(>ZZ=fe#1,ZZ=r->X,Z,Z); */ 70 | fe_mul(r->X,p->Z,q->Z); 71 | 72 | /* qhasm: D = 2*ZZ */ 73 | /* asm 1: fe_add(>D=fe#5,D=t0,X,X); */ 75 | fe_add(t0,r->X,r->X); 76 | 77 | /* qhasm: X3 = A-B */ 78 | /* asm 1: fe_sub(>X3=fe#1,X3=r->X,Z,Y); */ 80 | fe_sub(r->X,r->Z,r->Y); 81 | 82 | /* qhasm: Y3 = A+B */ 83 | /* asm 1: fe_add(>Y3=fe#2,Y3=r->Y,Z,Y); */ 85 | fe_add(r->Y,r->Z,r->Y); 86 | 87 | /* qhasm: Z3 = D-C */ 88 | /* asm 1: fe_sub(>Z3=fe#3,Z3=r->Z,T); */ 90 | fe_sub(r->Z,t0,r->T); 91 | 92 | /* qhasm: T3 = D+C */ 93 | /* asm 1: fe_add(>T3=fe#4,T3=r->T,T); */ 95 | fe_add(r->T,t0,r->T); 96 | 97 | /* qhasm: return */ 98 | -------------------------------------------------------------------------------- /libcurve25519-donna/ge_tobytes.c: -------------------------------------------------------------------------------- 1 | #include "ge.h" 2 | 3 | void ge_tobytes(unsigned char *s,const ge_p2 *h) 4 | { 5 | fe recip; 6 | fe x; 7 | fe y; 8 | 9 | fe_invert(recip,h->Z); 10 | fe_mul(x,h->X,recip); 11 | fe_mul(y,h->Y,recip); 12 | fe_tobytes(s,y); 13 | s[31] ^= fe_isnegative(x) << 7; 14 | } 15 | -------------------------------------------------------------------------------- /libcurve25519-donna/nacl_includes/crypto_int32.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_int32_h 2 | #define crypto_int32_h 3 | 4 | typedef int crypto_int32; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /libcurve25519-donna/nacl_includes/crypto_int64.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_int64_h 2 | #define crypto_int64_h 3 | 4 | #include 5 | 6 | typedef int64_t crypto_int64; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /libcurve25519-donna/nacl_includes/crypto_sign.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_sign_H 2 | #define crypto_sign_H 3 | 4 | #include "crypto_sign_edwards25519sha512batch.h" 5 | 6 | #define crypto_sign crypto_sign_edwards25519sha512batch 7 | #define crypto_sign_open crypto_sign_edwards25519sha512batch_open 8 | #define crypto_sign_keypair crypto_sign_edwards25519sha512batch_keypair 9 | #define crypto_sign_BYTES crypto_sign_edwards25519sha512batch_BYTES 10 | #define crypto_sign_PUBLICKEYBYTES crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES 11 | #define crypto_sign_SECRETKEYBYTES crypto_sign_edwards25519sha512batch_SECRETKEYBYTES 12 | #define crypto_sign_PRIMITIVE "edwards25519sha512batch" 13 | #define crypto_sign_IMPLEMENTATION crypto_sign_edwards25519sha512batch_IMPLEMENTATION 14 | #define crypto_sign_VERSION crypto_sign_edwards25519sha512batch_VERSION 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /libcurve25519-donna/nacl_includes/crypto_sign_edwards25519sha512batch.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_sign_edwards25519sha512batch_H 2 | #define crypto_sign_edwards25519sha512batch_H 3 | 4 | #include 5 | 6 | #define crypto_sign_edwards25519sha512batch_ref10_SECRETKEYBYTES 64 7 | #define crypto_sign_edwards25519sha512batch_ref10_PUBLICKEYBYTES 32 8 | #define crypto_sign_edwards25519sha512batch_ref10_BYTES 64 9 | #ifdef __cplusplus 10 | #include 11 | extern std::string crypto_sign_edwards25519sha512batch_ref10(const std::string &,const std::string &); 12 | extern std::string crypto_sign_edwards25519sha512batch_ref10_open(const std::string &,const std::string &); 13 | extern std::string crypto_sign_edwards25519sha512batch_ref10_keypair(std::string *); 14 | extern "C" { 15 | #endif 16 | extern int crypto_sign_edwards25519sha512batch_ref10(unsigned char *,uint64_t *,const unsigned char *,uint64_t,const unsigned char *); 17 | extern int crypto_sign_edwards25519sha512batch_ref10_open(unsigned char *,uint64_t *,const unsigned char *,uint64_t,const unsigned char *); 18 | extern int crypto_sign_edwards25519sha512batch_ref10_keypair(unsigned char *,unsigned char *); 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #define crypto_sign_edwards25519sha512batch crypto_sign_edwards25519sha512batch_ref10 24 | #define crypto_sign_edwards25519sha512batch_open crypto_sign_edwards25519sha512batch_ref10_open 25 | #define crypto_sign_edwards25519sha512batch_keypair crypto_sign_edwards25519sha512batch_ref10_keypair 26 | #define crypto_sign_edwards25519sha512batch_BYTES crypto_sign_edwards25519sha512batch_ref10_BYTES 27 | #define crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES crypto_sign_edwards25519sha512batch_ref10_PUBLICKEYBYTES 28 | #define crypto_sign_edwards25519sha512batch_SECRETKEYBYTES crypto_sign_edwards25519sha512batch_ref10_SECRETKEYBYTES 29 | #define crypto_sign_edwards25519sha512batch_IMPLEMENTATION "crypto_sign/edwards25519sha512batch/ref10" 30 | #ifndef crypto_sign_edwards25519sha512batch_ref10_VERSION 31 | #define crypto_sign_edwards25519sha512batch_ref10_VERSION "-" 32 | #endif 33 | #define crypto_sign_edwards25519sha512batch_VERSION crypto_sign_edwards25519sha512batch_ref10_VERSION 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /libcurve25519-donna/nacl_includes/crypto_uint32.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_uint32_h 2 | #define crypto_uint32_h 3 | 4 | typedef unsigned int crypto_uint32; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /libcurve25519-donna/nacl_includes/crypto_uint64.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_uint64_h 2 | #define crypto_uint64_h 3 | 4 | #include 5 | 6 | typedef uint64_t crypto_uint64; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /libcurve25519-donna/nacl_includes/crypto_verify_32.h: -------------------------------------------------------------------------------- 1 | #ifndef crypto_verify_32_H 2 | #define crypto_verify_32_H 3 | 4 | #define crypto_verify_32_ref_BYTES 32 5 | #ifdef __cplusplus 6 | #include 7 | extern "C" { 8 | #endif 9 | extern int crypto_verify_32_ref(const unsigned char *,const unsigned char *); 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #define crypto_verify_32 crypto_verify_32_ref 15 | #define crypto_verify_32_BYTES crypto_verify_32_ref_BYTES 16 | #define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/ref" 17 | #ifndef crypto_verify_32_ref_VERSION 18 | #define crypto_verify_32_ref_VERSION "-" 19 | #endif 20 | #define crypto_verify_32_VERSION crypto_verify_32_ref_VERSION 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /libcurve25519-donna/nacl_sha512/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | 20080913 3 | D. J. Bernstein 4 | Public domain. 5 | */ 6 | 7 | #include 8 | typedef uint64_t uint64; 9 | 10 | extern int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,uint64_t inlen); 11 | 12 | #define blocks crypto_hashblocks_sha512 13 | 14 | static const unsigned char iv[64] = { 15 | 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, 16 | 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, 17 | 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, 18 | 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, 19 | 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, 20 | 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, 21 | 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, 22 | 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 23 | } ; 24 | 25 | int crypto_hash_sha512(unsigned char *out,const unsigned char *in,uint64_t inlen) 26 | { 27 | unsigned char h[64]; 28 | unsigned char padded[256]; 29 | int i; 30 | uint64_t bytes = inlen; 31 | 32 | for (i = 0;i < 64;++i) h[i] = iv[i]; 33 | 34 | blocks(h,in,inlen); 35 | in += inlen; 36 | inlen &= 127; 37 | in -= inlen; 38 | 39 | for (i = 0; i < (int) inlen;++i) padded[i] = in[i]; 40 | padded[inlen] = 0x80; 41 | 42 | if (inlen < 112) { 43 | for (i = inlen + 1;i < 119;++i) padded[i] = 0; 44 | padded[119] = bytes >> 61; 45 | padded[120] = bytes >> 53; 46 | padded[121] = bytes >> 45; 47 | padded[122] = bytes >> 37; 48 | padded[123] = bytes >> 29; 49 | padded[124] = bytes >> 21; 50 | padded[125] = bytes >> 13; 51 | padded[126] = bytes >> 5; 52 | padded[127] = bytes << 3; 53 | blocks(h,padded,128); 54 | } else { 55 | for (i = inlen + 1;i < 247;++i) padded[i] = 0; 56 | padded[247] = bytes >> 61; 57 | padded[248] = bytes >> 53; 58 | padded[249] = bytes >> 45; 59 | padded[250] = bytes >> 37; 60 | padded[251] = bytes >> 29; 61 | padded[252] = bytes >> 21; 62 | padded[253] = bytes >> 13; 63 | padded[254] = bytes >> 5; 64 | padded[255] = bytes << 3; 65 | blocks(h,padded,256); 66 | } 67 | 68 | for (i = 0;i < 64;++i) out[i] = h[i]; 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /libcurve25519-donna/pow22523.h: -------------------------------------------------------------------------------- 1 | 2 | /* qhasm: fe z1 */ 3 | 4 | /* qhasm: fe z2 */ 5 | 6 | /* qhasm: fe z8 */ 7 | 8 | /* qhasm: fe z9 */ 9 | 10 | /* qhasm: fe z11 */ 11 | 12 | /* qhasm: fe z22 */ 13 | 14 | /* qhasm: fe z_5_0 */ 15 | 16 | /* qhasm: fe z_10_5 */ 17 | 18 | /* qhasm: fe z_10_0 */ 19 | 20 | /* qhasm: fe z_20_10 */ 21 | 22 | /* qhasm: fe z_20_0 */ 23 | 24 | /* qhasm: fe z_40_20 */ 25 | 26 | /* qhasm: fe z_40_0 */ 27 | 28 | /* qhasm: fe z_50_10 */ 29 | 30 | /* qhasm: fe z_50_0 */ 31 | 32 | /* qhasm: fe z_100_50 */ 33 | 34 | /* qhasm: fe z_100_0 */ 35 | 36 | /* qhasm: fe z_200_100 */ 37 | 38 | /* qhasm: fe z_200_0 */ 39 | 40 | /* qhasm: fe z_250_50 */ 41 | 42 | /* qhasm: fe z_250_0 */ 43 | 44 | /* qhasm: fe z_252_2 */ 45 | 46 | /* qhasm: fe z_252_3 */ 47 | 48 | /* qhasm: enter pow22523 */ 49 | 50 | /* qhasm: z2 = z1^2^1 */ 51 | /* asm 1: fe_sq(>z2=fe#1,z2=fe#1,>z2=fe#1); */ 52 | /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ 53 | fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); 54 | 55 | /* qhasm: z8 = z2^2^2 */ 56 | /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ 57 | /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ 58 | fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); 59 | 60 | /* qhasm: z9 = z1*z8 */ 61 | /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#1,z22=fe#1,>z22=fe#1); */ 72 | /* asm 2: fe_sq(>z22=t0,z22=t0,>z22=t0); */ 73 | fe_sq(t0,t0); for (i = 1;i < 1;++i) fe_sq(t0,t0); 74 | 75 | /* qhasm: z_5_0 = z9*z22 */ 76 | /* asm 1: fe_mul(>z_5_0=fe#1,z_5_0=t0,z_10_5=fe#2,z_10_5=fe#2,>z_10_5=fe#2); */ 82 | /* asm 2: fe_sq(>z_10_5=t1,z_10_5=t1,>z_10_5=t1); */ 83 | fe_sq(t1,t0); for (i = 1;i < 5;++i) fe_sq(t1,t1); 84 | 85 | /* qhasm: z_10_0 = z_10_5*z_5_0 */ 86 | /* asm 1: fe_mul(>z_10_0=fe#1,z_10_0=t0,z_20_10=fe#2,z_20_10=fe#2,>z_20_10=fe#2); */ 92 | /* asm 2: fe_sq(>z_20_10=t1,z_20_10=t1,>z_20_10=t1); */ 93 | fe_sq(t1,t0); for (i = 1;i < 10;++i) fe_sq(t1,t1); 94 | 95 | /* qhasm: z_20_0 = z_20_10*z_10_0 */ 96 | /* asm 1: fe_mul(>z_20_0=fe#2,z_20_0=t1,z_40_20=fe#3,z_40_20=fe#3,>z_40_20=fe#3); */ 102 | /* asm 2: fe_sq(>z_40_20=t2,z_40_20=t2,>z_40_20=t2); */ 103 | fe_sq(t2,t1); for (i = 1;i < 20;++i) fe_sq(t2,t2); 104 | 105 | /* qhasm: z_40_0 = z_40_20*z_20_0 */ 106 | /* asm 1: fe_mul(>z_40_0=fe#2,z_40_0=t1,z_50_10=fe#2,z_50_10=fe#2,>z_50_10=fe#2); */ 112 | /* asm 2: fe_sq(>z_50_10=t1,z_50_10=t1,>z_50_10=t1); */ 113 | fe_sq(t1,t1); for (i = 1;i < 10;++i) fe_sq(t1,t1); 114 | 115 | /* qhasm: z_50_0 = z_50_10*z_10_0 */ 116 | /* asm 1: fe_mul(>z_50_0=fe#1,z_50_0=t0,z_100_50=fe#2,z_100_50=fe#2,>z_100_50=fe#2); */ 122 | /* asm 2: fe_sq(>z_100_50=t1,z_100_50=t1,>z_100_50=t1); */ 123 | fe_sq(t1,t0); for (i = 1;i < 50;++i) fe_sq(t1,t1); 124 | 125 | /* qhasm: z_100_0 = z_100_50*z_50_0 */ 126 | /* asm 1: fe_mul(>z_100_0=fe#2,z_100_0=t1,z_200_100=fe#3,z_200_100=fe#3,>z_200_100=fe#3); */ 132 | /* asm 2: fe_sq(>z_200_100=t2,z_200_100=t2,>z_200_100=t2); */ 133 | fe_sq(t2,t1); for (i = 1;i < 100;++i) fe_sq(t2,t2); 134 | 135 | /* qhasm: z_200_0 = z_200_100*z_100_0 */ 136 | /* asm 1: fe_mul(>z_200_0=fe#2,z_200_0=t1,z_250_50=fe#2,z_250_50=fe#2,>z_250_50=fe#2); */ 142 | /* asm 2: fe_sq(>z_250_50=t1,z_250_50=t1,>z_250_50=t1); */ 143 | fe_sq(t1,t1); for (i = 1;i < 50;++i) fe_sq(t1,t1); 144 | 145 | /* qhasm: z_250_0 = z_250_50*z_50_0 */ 146 | /* asm 1: fe_mul(>z_250_0=fe#1,z_250_0=t0,z_252_2=fe#1,z_252_2=fe#1,>z_252_2=fe#1); */ 152 | /* asm 2: fe_sq(>z_252_2=t0,z_252_2=t0,>z_252_2=t0); */ 153 | fe_sq(t0,t0); for (i = 1;i < 2;++i) fe_sq(t0,t0); 154 | 155 | /* qhasm: z_252_3 = z_252_2*z1 */ 156 | /* asm 1: fe_mul(>z_252_3=fe#12,z_252_3=out,z2=fe#1,z2=fe#1,>z2=fe#1); */ 52 | /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ 53 | fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); 54 | 55 | /* qhasm: z8 = z2^2^2 */ 56 | /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ 57 | /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ 58 | fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); 59 | 60 | /* qhasm: z9 = z1*z8 */ 61 | /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#3,z22=fe#3,>z22=fe#3); */ 72 | /* asm 2: fe_sq(>z22=t2,z22=t2,>z22=t2); */ 73 | fe_sq(t2,t0); for (i = 1;i < 1;++i) fe_sq(t2,t2); 74 | 75 | /* qhasm: z_5_0 = z9*z22 */ 76 | /* asm 1: fe_mul(>z_5_0=fe#2,z_5_0=t1,z_10_5=fe#3,z_10_5=fe#3,>z_10_5=fe#3); */ 82 | /* asm 2: fe_sq(>z_10_5=t2,z_10_5=t2,>z_10_5=t2); */ 83 | fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2); 84 | 85 | /* qhasm: z_10_0 = z_10_5*z_5_0 */ 86 | /* asm 1: fe_mul(>z_10_0=fe#2,z_10_0=t1,z_20_10=fe#3,z_20_10=fe#3,>z_20_10=fe#3); */ 92 | /* asm 2: fe_sq(>z_20_10=t2,z_20_10=t2,>z_20_10=t2); */ 93 | fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2); 94 | 95 | /* qhasm: z_20_0 = z_20_10*z_10_0 */ 96 | /* asm 1: fe_mul(>z_20_0=fe#3,z_20_0=t2,z_40_20=fe#4,z_40_20=fe#4,>z_40_20=fe#4); */ 102 | /* asm 2: fe_sq(>z_40_20=t3,z_40_20=t3,>z_40_20=t3); */ 103 | fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3); 104 | 105 | /* qhasm: z_40_0 = z_40_20*z_20_0 */ 106 | /* asm 1: fe_mul(>z_40_0=fe#3,z_40_0=t2,z_50_10=fe#3,z_50_10=fe#3,>z_50_10=fe#3); */ 112 | /* asm 2: fe_sq(>z_50_10=t2,z_50_10=t2,>z_50_10=t2); */ 113 | fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2); 114 | 115 | /* qhasm: z_50_0 = z_50_10*z_10_0 */ 116 | /* asm 1: fe_mul(>z_50_0=fe#2,z_50_0=t1,z_100_50=fe#3,z_100_50=fe#3,>z_100_50=fe#3); */ 122 | /* asm 2: fe_sq(>z_100_50=t2,z_100_50=t2,>z_100_50=t2); */ 123 | fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2); 124 | 125 | /* qhasm: z_100_0 = z_100_50*z_50_0 */ 126 | /* asm 1: fe_mul(>z_100_0=fe#3,z_100_0=t2,z_200_100=fe#4,z_200_100=fe#4,>z_200_100=fe#4); */ 132 | /* asm 2: fe_sq(>z_200_100=t3,z_200_100=t3,>z_200_100=t3); */ 133 | fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3); 134 | 135 | /* qhasm: z_200_0 = z_200_100*z_100_0 */ 136 | /* asm 1: fe_mul(>z_200_0=fe#3,z_200_0=t2,z_250_50=fe#3,z_250_50=fe#3,>z_250_50=fe#3); */ 142 | /* asm 2: fe_sq(>z_250_50=t2,z_250_50=t2,>z_250_50=t2); */ 143 | fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2); 144 | 145 | /* qhasm: z_250_0 = z_250_50*z_50_0 */ 146 | /* asm 1: fe_mul(>z_250_0=fe#2,z_250_0=t1,z_255_5=fe#2,z_255_5=fe#2,>z_255_5=fe#2); */ 152 | /* asm 2: fe_sq(>z_255_5=t1,z_255_5=t1,>z_255_5=t1); */ 153 | fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1); 154 | 155 | /* qhasm: z_255_21 = z_255_5*z11 */ 156 | /* asm 1: fe_mul(>z_255_21=fe#12,z_255_21=out, 6 | #include 7 | 8 | QByteArray QBase58::encode( const QByteArray &in ) 9 | { 10 | QByteArray out; 11 | out.resize( in.size() *2 ); // note: surely there is something better than size*2, but it's better than static 12 | size_t out_size = out.size(); 13 | 14 | const bool result = b58enc( out.data(), &out_size, in.data(), in.size() ); 15 | 16 | if ( !result ) 17 | { 18 | qDebug() << "local error: base58 encoding failed"; 19 | return QByteArray(); 20 | } 21 | 22 | // shrink the buffer to get rid of the trailing bytes and zero byte 23 | if ( (size_t) out.size() > out_size ) 24 | out.resize( out_size -1 ); // -1 for zero byte 25 | 26 | return out; 27 | } 28 | 29 | QByteArray QBase58::decode( const QByteArray &in ) 30 | { 31 | QByteArray out; 32 | out.resize( in.size() *2 ); 33 | size_t out_size = out.size(); 34 | 35 | const bool result = b58tobin( out.data(), &out_size, in.data(), in.size() ); 36 | 37 | if ( !result ) 38 | { 39 | qDebug() << "local error: base58 decoding failed"; 40 | return QByteArray(); 41 | } 42 | 43 | // shrink the buffer to get rid of the preceeding bytes 44 | if ( out_size < (size_t) out.size() ) 45 | out.remove( 0, ( in.size() *2 ) - out_size ); 46 | 47 | return out; 48 | } 49 | -------------------------------------------------------------------------------- /qbase58/qbase58.h: -------------------------------------------------------------------------------- 1 | #ifndef QBASE58_H 2 | #define QBASE58_H 3 | 4 | #include 5 | 6 | namespace QBase58 7 | { 8 | QByteArray encode( const QByteArray &in ); 9 | QByteArray decode( const QByteArray &in ); 10 | } 11 | 12 | #endif // QBASE58_H 13 | -------------------------------------------------------------------------------- /qbase58/qbase58_test.cpp: -------------------------------------------------------------------------------- 1 | #include "qbase58_test.h" 2 | #include "qbase58.h" 3 | 4 | #include 5 | 6 | void QBase58Test::test() 7 | { 8 | const QByteArray encoded = "CMLwxbMZJMztyTJ6Zkos66cgU7DybfFJfyJtTVpme54t"; 9 | const QByteArray decoded = QByteArray::fromHex( "a8a6ba2678d1983ad78cfd1aff049367a91c4274b46674ea51d99fc4a3f3c159" ); 10 | 11 | assert( QBase58::decode( encoded ) == decoded ); 12 | assert( QBase58::encode( decoded ) == encoded ); 13 | 14 | assert( QBase58::encode( "Hello World!" ) == "2NEpo7TZRRrLZSi2U" ); 15 | assert( QBase58::encode( "The quick brown fox jumps over the lazy dog." ) == "USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z" ); 16 | assert( QBase58::encode( QByteArray::fromHex( "0x0000287fb4cd" ) ) == "111233QC4" ); 17 | assert( QBase58::encode( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ) 18 | == "3KkDZnpqFNhbEP9UY6aEka7Y7GeXv5ewVw2aoE3Y3mTG3Rgyu97ZzZwmFyGDc1F4AjwzpVPHqN4pceKnyRTRarHg7K3rP4ny2FvoMcmmR17B1H9Jmr2GQ4AFZAswHjEZDitDq2U2S2jcERKzU3UmbVtfA7Ct3XAExCBoHnNXMPt6t7HsABanmpf6tkfTGzNELUVQ5hPDswWYp5zYnAb45koPVQs2gnrmn925Sgox6Dkb2h6dbK2iBKfeKQsV9umbTLmW8Ddbpfcm657hHB8kCiYCDKFnYFynE38UrWS6qemoqVZhqD1XJyZiWZrp1YquobcAUwh8eZZaCna9Uqz8hktsZD3jnZXEkcLhvqTVQzKTDUsLMtcVTaticcYWR9iYz8wBaAdecXtdjsgREmKfb9mVddt9Uk4VgTwci3xBDV7Qf8TrxAyGouAXadzufsxU6B6U8tSigDoLyhfuNKPe6hRVXNGsRB1JwQrwTZ73GVv7UV74nC71Z4kV7Kv52AgCGjacVPHyaxSa227PH2XxrPFGp27Aq2yH8Y1yddUNUpAFbVkyHhG3wGp74pkayFmRMTZL5UJSFQBCprC99hx3uQs99wa5x67pzv2mbR3rxdMdxSBajwZ5189tpNj4BPHia3j2huwahSobYARcjCu6rg2Q8pLLWYMADHxzvM3dvEPJL49sSZh7HMtKJRphzdsWhf6SSgKrsAEYczmh78adk2ua3z8fhmDu2DFsewc3wUgrNAp8ts8DwQ8N2GTKbkDPJz2GcRupxgwX6Ckb3Q1wCjJiY5ZbQNfLmN3YkudCx3whQFJZzZKBuUHiwwHfmX6pfSmBZyrF8dmvh7XiuXAKxh61bT4u8ctL7eE4eFVsxxHj9ivbGQN5CuyJFNsQJNnDSYeLz62AD38QcE7NaxrXkpuQYhdT63M2BcL8BVbtpPQhenquNTSJNmy3bUhky2qLH9oU5py7rpfwWpggg" ); 19 | } 20 | -------------------------------------------------------------------------------- /qbase58/qbase58_test.h: -------------------------------------------------------------------------------- 1 | #ifndef QBASE58_TEST_H 2 | #define QBASE58_TEST_H 3 | 4 | struct QBase58Test 5 | { 6 | void test(); 7 | }; 8 | 9 | #endif // QBASE58_TEST_H 10 | -------------------------------------------------------------------------------- /trader.pro: -------------------------------------------------------------------------------- 1 | exists( daemon/keydefs.h ) { 2 | TEMPLATE = subdirs 3 | SUBDIRS = cli/trader-cli.pro daemon/traderd.pro 4 | } else { 5 | error( "keydefs.h doesn't exist. You must either: 1) Generate the file with 'python generate_keys.py', or 2) Copy the example file with 'cp daemon/keydefs.h.example daemon/keydefs.h' and manually fill in your keys, or if you don't want hardcoded keys: 3) Copy the example file, leave your keys blank, and use the cli command 'setkeyandsecret' at runtime." ) 6 | } 7 | --------------------------------------------------------------------------------