Browse Source

Merge pull request #25 from jl777/beta

Merge current BETA to mine here
patch-5
blackjok3rtt 6 years ago
committed by GitHub
parent
commit
9eec234922
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .dockerignore
  2. 18
      .github/ISSUE_TEMPLATE/bug_report.md
  3. 8
      .gitignore
  4. 41
      .travis.yml
  5. 9
      Dockerfile.clientnode
  6. 9
      Dockerfile.seednode
  7. 35
      Jenkinsfile
  8. 32
      appveyor.yml
  9. 2
      cpp-ethereum
  10. 1
      crypto777/OS_portable.h
  11. 187
      crypto777/bitcoind_RPC.c
  12. 6
      crypto777/cJSON.c
  13. 41
      docker-compose.yml
  14. 5
      etomic_build/client
  15. 4
      etomic_build/client/buy_BEER_OTHER
  16. 4
      etomic_build/client/client
  17. 7
      etomic_build/client/enable
  18. 1
      etomic_build/client/myipaddr
  19. 1
      etomic_build/client/passphrase
  20. 4
      etomic_build/client/setpassphrase
  21. 2
      etomic_build/client/userpass
  22. 2
      etomic_build/coins
  23. 3
      etomic_build/enable
  24. 1
      etomic_build/passphrase
  25. 5
      etomic_build/run
  26. 7
      etomic_build/seed/enable
  27. 1
      etomic_build/seed/myipaddr
  28. 1
      etomic_build/seed/passphrase
  29. 4
      etomic_build/seed/run
  30. 4
      etomic_build/seed/sell_BEER_OTHER
  31. 4
      etomic_build/seed/setpassphrase
  32. 2
      etomic_build/seed/userpass
  33. 2
      etomic_build/userpass
  34. 1
      iguana/coins/ccl_7776
  35. 2
      iguana/coins/rfox_7776
  36. 2
      iguana/coins/sec_7776
  37. 2
      iguana/coins/vrsc_7776
  38. 1
      iguana/coins/zilla_7776
  39. 6
      iguana/dPoW.h
  40. 14
      iguana/dpow/dpow_fsm.c
  41. 28
      iguana/dpow/dpow_network.c
  42. 30
      iguana/dpow/dpow_rpc.c
  43. 16
      iguana/dpow/dpow_tx.c
  44. 7
      iguana/exchanges/CMakeLists.txt
  45. 23
      iguana/exchanges/LP_bitcoin.c
  46. 22
      iguana/exchanges/LP_coins.c
  47. 107
      iguana/exchanges/LP_commands.c
  48. 214
      iguana/exchanges/LP_etomic.c
  49. 2
      iguana/exchanges/LP_etomic.h
  50. 44
      iguana/exchanges/LP_include.h
  51. 6
      iguana/exchanges/LP_instantdex.c
  52. 6
      iguana/exchanges/LP_mmjson.c
  53. 254
      iguana/exchanges/LP_mpnet.c
  54. 69
      iguana/exchanges/LP_nativeDEX.c
  55. 371
      iguana/exchanges/LP_ordermatch.c
  56. 32
      iguana/exchanges/LP_portfolio.c
  57. 87
      iguana/exchanges/LP_prices.c
  58. 194
      iguana/exchanges/LP_privkey.c
  59. 116
      iguana/exchanges/LP_remember.c
  60. 34
      iguana/exchanges/LP_rpc.c
  61. 7
      iguana/exchanges/LP_scan.c
  62. 58
      iguana/exchanges/LP_signatures.c
  63. 135
      iguana/exchanges/LP_socket.c
  64. 2
      iguana/exchanges/LP_statemachine.c
  65. 86
      iguana/exchanges/LP_swap.c
  66. 2
      iguana/exchanges/LP_tradebots.c
  67. 161
      iguana/exchanges/LP_transaction.c
  68. 49
      iguana/exchanges/LP_utxo.c
  69. 2
      iguana/exchanges/auto_chipsbtc
  70. 2
      iguana/exchanges/auto_chipskmd
  71. 4
      iguana/exchanges/coins
  72. 89
      iguana/exchanges/etomicswap/etomiccurl.c
  73. 9
      iguana/exchanges/etomicswap/etomiccurl.h
  74. 302
      iguana/exchanges/etomicswap/etomiclib.cpp
  75. 49
      iguana/exchanges/etomicswap/etomiclib.h
  76. 3
      iguana/exchanges/gen64addrs
  77. 7
      iguana/exchanges/mm.c
  78. 102
      iguana/exchanges/mm2.md
  79. 2
      iguana/exchanges/mshark
  80. 6
      iguana/exchanges/prices/autoprice
  81. 2
      iguana/exchanges/supernet
  82. 2
      iguana/iguana777.c
  83. 20
      iguana/iguana_notary.c
  84. 2
      iguana/iguana_ramchain.c
  85. 9
      iguana/iguana_wallet.c
  86. 2
      iguana/m_notary
  87. 25
      iguana/m_notary_run
  88. 4
      iguana/m_splitfund
  89. 2
      iguana/mini-gmp.c
  90. 1
      includes/iguana_apideclares.h
  91. 60
      marketmaker_build_depends.cmd
  92. 7
      marketmaker_build_etomic.cmd
  93. 8
      start_BEER_OTHER_trade.sh
  94. 8
      start_BEER_OTHER_trade_inverted.sh
  95. 5
      travis_cmake_linux.sh
  96. 6
      travis_cmake_mac.sh

3
.dockerignore

@ -0,0 +1,3 @@
.git
.vscode
cmake-build-debug

18
.github/ISSUE_TEMPLATE/bug_report.md

@ -0,0 +1,18 @@
---
name: Bug report
about: Marketmaker 1.0 bug report
---
**Describe the bug**
A clear and concise description of what the bug is.
**Please answer following questions and attach requested info - it'll help to solve issue faster**
- What OS do you use?
- What marketmaker version do you run?
- Attach your coins.json config.
- Provide your enable script with response.
- Provide other curl scripts (with responses) which were executed prior to error.
- Attach full marketmaker console logs (start collecting right after marketmaker execution).
- ***Make sure that you don't send your passphrase, userpass and privkeys. Your funds might be stolen if you reveal this info publicly!***
- Provide info for all nodes involved (e.g. if error occurs during atomic swap you should provide info for both Bob and Alice).

8
.gitignore

@ -263,4 +263,12 @@ Release/*
build_win64_release/*
DB/*
.env.client
.env.seed
etomic_build/client/DB
etomic_build/client/stats.log
etomic_build/client/unparsed.txt
etomic_build/seed/DB
etomic_build/seed/stats.log
etomic_build/seed/unparsed.txt
iguana/exchanges/manychains

41
.travis.yml

@ -4,12 +4,6 @@ matrix:
include:
- os: linux
compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
env: OS_NAME=Linux MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- os: osx
compiler: clang
@ -17,14 +11,39 @@ matrix:
osx_image: xcode9.2
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y && sudo apt-get update && sudo apt-get install -y g++-7; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then chmod +x travis_cmake_linux.sh && ./travis_cmake_linux.sh; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then chmod +x travis_cmake_mac.sh && ./travis_cmake_mac.sh; fi
- git submodule update --init --recursive
script:
- export VERSION=`echo "$(git tag -l --points-at HEAD)"`
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export THREAD_COUNT=`echo "$(nproc --all)"`; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export THREAD_COUNT=`echo "$(sysctl -n hw.physicalcpu)"`; fi
- mkdir build && cd build
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then cmake -DCMAKE_C_COMPILER=/usr/bin/gcc-7 -DCMAKE_CXX_COMPILER=/usr/bin/g++-7 ..; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cmake ..; fi
- cmake --build . --target marketmaker-mainnet
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then cmake -DMM_VERSION="$VERSION" -DCMAKE_C_COMPILER=/usr/bin/gcc-7 -DCMAKE_CXX_COMPILER=/usr/bin/g++-7 ..; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then cmake -DMM_VERSION="$VERSION" ..; fi
- echo "cmake --build . --target marketmaker-mainnet -j $THREAD_COUNT"
- cmake --build . --target marketmaker-mainnet -j $THREAD_COUNT
- cmake --build . --target marketmaker-testnet -j $THREAD_COUNT
cache:
directories:
- $HOME/.hunter
apt: true
directories:
- $HOME/.hunter
before_deploy:
- export TAG=`echo "$(git rev-parse --short HEAD)"`
- mkdir deploy
- strip iguana/exchanges/marketmaker-mainnet
- strip iguana/exchanges/marketmaker-testnet
- tar -cvzf deploy/marketmaker-"$TRAVIS_OS_NAME"-"$TAG".tar.gz -C iguana/exchanges marketmaker-mainnet marketmaker-testnet
deploy:
provider: releases
api_key:
secure: "JDwFBGO4WLra9bXr2dsovet8y/ymC0Y+LJNr5/qlUIDt97zVytGbIlUc8BuI2VZFcnAvrtfOGdCs9m/PcLzZd4bMxXSsuaU0AJk/Vj9KzrIIGPJ4uS39KpO1USUpPW+5e0Bisf30JN3N2NypwMbMu42TKjVqaXSbVQfh79Iu6PdnyfiFbbTEfMeiRRrD72c00rwAw7kmndf7Sv9MiMN8WTFe0cQz5eH8GU/BSbnDorSrtClU4r7McR98zXaig/8XVcT543tcqdYW95QO7OqOjAid3XzzA/bPUTjC/nF/AyTJDco26nts0bCrCYeZRXIWdEInFLIeRHhHD7sW7dILRT/I7WlaLWnRtwo8e1L+U1k1yZ84dQMpgBznttdwH3vSj0crwCbFuMaRMMbPeW0H8C1VitLy1mlapw3RDI9yKlcw4V6WjPbz0YKhAoZgT/M/SaGr4ZkoWNCPoV5+Gub78p24Y8Y9BptJgj5t9KAcmDwbJ9wPt006ObWnbXvapo+6N5Dk2zuyQe9seoupzy4CAiNdluzAAVWsV/SjnN2aapjXoxaAaLQC6T8C1l1BpYri9LSKrjerr4QLVl/nw2yovAKNEobLLBVpSwfg4R72fu1BMS65gVsOqtFfs+R47CY+1D1Slev+UmKNMdE51+aXM+1XeC6wDUS5d13mW1NLhOE="
file_glob: true
file: "deploy/*"
on:
tags: true
skip_cleanup: true

9
Dockerfile.clientnode

@ -0,0 +1,9 @@
FROM ubuntu:17.10
USER root
RUN apt-get update && apt-get install -y rinetd curl libcurl3-gnutls
RUN echo "0.0.0.0 10271 10.100.0.1 10271" >> /etc/rinetd.conf
RUN echo "0.0.0.0 8923 10.100.0.1 8923" >> /etc/rinetd.conf
RUN useradd -u 111 jenkins
USER jenkins
WORKDIR /usr/mm/etomic_build/client
CMD /usr/sbin/rinetd && rm -rf DB && ./client

9
Dockerfile.seednode

@ -0,0 +1,9 @@
FROM ubuntu:17.10
USER root
RUN apt-get update && apt-get install -y rinetd curl libcurl3-gnutls
RUN echo "0.0.0.0 10271 10.100.0.1 10271" >> /etc/rinetd.conf
RUN echo "0.0.0.0 8923 10.100.0.1 8923" >> /etc/rinetd.conf
RUN useradd -u 111 jenkins
USER jenkins
WORKDIR /usr/mm/etomic_build/seed
CMD /usr/sbin/rinetd && rm -rf DB && ./run

35
Jenkinsfile

@ -1,11 +1,12 @@
pipeline {
agent {
docker {
image 'artempikulin/cmake-ubuntu'
}
}
agent any
stages {
stage('Prepare') {
steps {
sh '''cp -r /root/.env.client .env.client
cp -r /root/.env.seed .env.seed'''
}
}
stage('Build') {
steps {
sh '''git submodule update --init --recursive
@ -13,7 +14,27 @@ rm -rf build
mkdir build
cd build
cmake ..
cmake --build . --target marketmaker-testnet'''
cmake --build . --target marketmaker-testnet -j 4
cd ../
docker-compose build'''
}
}
stage('Trade BEER/ETH') {
steps {
sh '''docker-compose up -d
./start_BEER_OTHER_trade.sh ETH
timeout 600 grep -q "SWAP completed" <(COMPOSE_HTTP_TIMEOUT=600 docker-compose logs -f clientnode)
timeout 600 grep -q "SWAP completed" <(COMPOSE_HTTP_TIMEOUT=600 docker-compose logs -f seednode)
docker-compose down'''
}
}
stage('Trade ETH/BEER') {
steps {
sh '''docker-compose up -d
./start_BEER_OTHER_trade_inverted.sh ETH
timeout 600 grep -q "SWAP completed" <(COMPOSE_HTTP_TIMEOUT=600 docker-compose logs -f clientnode)
timeout 600 grep -q "SWAP completed" <(COMPOSE_HTTP_TIMEOUT=600 docker-compose logs -f seednode)
docker-compose down'''
}
}
}

32
appveyor.yml

@ -1,6 +1,30 @@
version: 1.0.{build}
branches:
only:
- etomic
build_script:
- cmd: marketmaker_build_etomic.cmd
- cmd: marketmaker_build_etomic.cmd
cache:
- C:\.hunter
- marketmaker_depends
after_build:
- '7z a mm-win.zip
.\build_win64_release\iguana\exchanges\Release\marketmaker-mainnet.exe
.\marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl.dll
.\marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.dll
"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\redist\\x64\\Microsoft.VC140.CRT\\msvcp140.dll"
"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\redist\\x64\\Microsoft.VC140.CRT\\vcruntime140.dll"'
artifacts:
- path: mm-win.zip
name: marketmaker-mainnet
deploy:
release: v$(appveyor_build_version)
provider: GitHub
auth_token:
secure: iabzoz73JgtOIyE/Nmz4a4XefmK+7pIeup+1Hunj4hGKrdfesFN+176DMApgfu8t
artifact: marketmaker-mainnet
draft: false
prerelease: false
on:
branch: master
appveyor_repo_tag: false

2
cpp-ethereum

@ -1 +1 @@
Subproject commit 633c62c08bc73c7c3935c948a8d6c656a3659976
Subproject commit e804e95d9a71e87fc5e3e69a2888448f23bc724f

1
crypto777/OS_portable.h

@ -425,6 +425,7 @@ bits256 bits256_sha256(bits256 data);
void bits256_rmd160(uint8_t rmd160[20],bits256 data);
void bits256_rmd160_sha256(uint8_t rmd160[20],bits256 data);
double get_theoretical(double *avebidp,double *aveaskp,double *highbidp,double *lowaskp,double *CMC_averagep,double changes[3],char *name,char *base,char *rel,double *USD_averagep);
char *bitcoind_RPCnew(void *curl_handle,char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout);
extern char *Iguana_validcommands[];
extern bits256 GENESIS_PUBKEY,GENESIS_PRIVKEY;

187
crypto777/bitcoind_RPC.c

@ -14,6 +14,7 @@
******************************************************************************/
//#define KEEPALIVE breaks marketmaker api
#ifndef FROM_JS
#include "OS_portable.h"
@ -74,7 +75,7 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
char *retstr = 0;
cJSON *json,*result,*error;
#ifndef FROM_MARKETMAKER
usleep(1000);
//usleep(1000);
#endif
//printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
@ -131,7 +132,7 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
*
************************************************************************/
static int32_t USE_JAY;
//static int32_t USE_JAY;
char *Jay_NXTrequest(char *command,char *params)
{
@ -141,23 +142,28 @@ char *Jay_NXTrequest(char *command,char *params)
return(retstr);
}
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout)
static void bitcoind_init()
{
CURL *curl_handle; static int didinit,count,count2; static double elapsedsum,elapsedsum2; extern int32_t USE_JAY;
struct MemoryStruct chunk;
struct curl_slist *headers = NULL; struct return_string s; CURLcode res;
char *bracket0,*bracket1,*retstr,*databuf = 0; long len; int32_t specialcase,numretries; double starttime;
static int32_t didinit;
if ( didinit == 0 )
{
didinit = 1;
curl_global_init(CURL_GLOBAL_ALL); //init the curl session
//curl_handle = curl_easy_init();
}
if ( (0) && (USE_JAY != 0 && (strncmp(url,"http://127.0.0.1:7876/nxt",strlen("http://127.0.0.1:7876/nxt")) == 0 || strncmp(url,"https://127.0.0.1:7876/nxt",strlen("https://127.0.0.1:7876/nxt")) == 0)) )
{
if ( (databuf= Jay_NXTrequest(command,params)) != 0 )
return(databuf);
}
}
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout)
{
#ifdef KEEPALIVE
static
#endif
CURL *curl_handle = 0;
static int count,count2; static double elapsedsum,elapsedsum2; extern int32_t USE_JAY;
struct MemoryStruct chunk;
struct curl_slist *headers = NULL; struct return_string s; CURLcode res;
char *bracket0,*bracket1,*retstr,*databuf = 0; long len; int32_t specialcase,numretries; double starttime;
bitcoind_init();
numretries = 0;
if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 )
specialcase = 1;
@ -174,7 +180,8 @@ try_again:
if ( retstrp != 0 )
*retstrp = 0;
starttime = OS_milliseconds();
curl_handle = curl_easy_init();
if ( curl_handle == 0 )
curl_handle = curl_easy_init();
headers = curl_slist_append(0,"Expect:");
curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
@ -244,7 +251,10 @@ try_again:
//laststart = milliseconds();
res = curl_easy_perform(curl_handle);
curl_slist_free_all(headers);
#ifndef KEEPALIVE
curl_easy_cleanup(curl_handle);
curl_handle = 0;
#endif
if ( databuf != 0 ) // clean up temporary buffer
{
free(databuf);
@ -279,7 +289,7 @@ try_again:
count++;
elapsedsum += (OS_milliseconds() - starttime);
if ( (count % 100000) == 0)
printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url);
printf("%d: %s ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,debugstr,elapsedsum/count,(OS_milliseconds() - starttime),command,url);
if ( retstrp != 0 )
{
*retstrp = retstr;
@ -301,6 +311,153 @@ try_again:
}
}
char *bitcoind_RPCnew(void *curl_handle,char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params,int32_t timeout)
{
static int count,count2; static double elapsedsum,elapsedsum2; extern int32_t USE_JAY;
struct MemoryStruct chunk;
struct curl_slist *headers = NULL; struct return_string s; CURLcode res;
char *bracket0,*bracket1,*retstr,*databuf = 0; long len; int32_t flag=0,specialcase,numretries; double starttime;
bitcoind_init();
numretries = 0;
if ( url[0] == 0 )
strcpy(url,"http://127.0.0.1:7776");
try_again:
if ( curl_handle == 0 )
{
curl_handle = curl_easy_init();
flag = 1;
}
if ( retstrp != 0 )
*retstrp = 0;
starttime = OS_milliseconds();
headers = curl_slist_append(0,"Expect:");
curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle,CURLOPT_URL, url);
if ( (0) )
{
init_string(&s);
curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulate); // send all data to this function
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
}
else
{
memset(&chunk,0,sizeof(chunk));
curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback);
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA,(void *)&chunk);
}
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
if ( timeout > 0 )
{
if ( bitcoind_RPC_inittime != 0 )
{
#ifndef _WIN32
curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,1);
#else
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, timeout*100);
#endif
} else curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,timeout); // causes problems with iguana timeouts
}
if ( strncmp(url,"https",5) == 0 )
{
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0);
}
if ( userpass != 0 )
curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass);
databuf = 0;
if ( params != 0 )
{
if ( command != 0 )
{
len = strlen(params);
if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) {
bracket0 = bracket1 = (char *)"";
}
else
{
bracket0 = (char *)"[";
bracket1 = (char *)"]";
}
char agentstr[64];
databuf = (char *)malloc(256 + strlen(command) + strlen(params));
if ( debugstr[0] != 0 )
sprintf(agentstr,"\"agent\":\"%s\",",debugstr);
else agentstr[0] = 0;
sprintf(databuf,"{\"id\":\"jl777\",%s\"method\":\"%s\",\"params\":%s%s%s}",agentstr,command,bracket0,params,bracket1);
//printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
//
} //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params);
curl_easy_setopt(curl_handle,CURLOPT_POST,1L);
if ( databuf != 0 )
curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf);
else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params);
}
res = curl_easy_perform(curl_handle);
curl_slist_free_all(headers);
if ( databuf != 0 ) // clean up temporary buffer
{
free(databuf);
databuf = 0;
}
if ( flag != 0 )
{
curl_easy_cleanup(curl_handle);
curl_handle = 0;
}
retstr = chunk.memory; // retstr = s.ptr;
if ( res != CURLE_OK )
{
numretries++;
if ( timeout != 0 )
{
//printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,retstr,res);
free(retstr);
return(0);
}
else if ( numretries >= 4 )
{
printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries);
//printf("Maximum number of retries exceeded!\n");
free(retstr);
return(0);
}
free(retstr);
sleep((1<<numretries));
goto try_again;
}
else
{
if ( command != 0 )
{
count++;
elapsedsum += (OS_milliseconds() - starttime);
if ( (count % 100000) == 0)
printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url);
if ( retstrp != 0 )
{
*retstrp = retstr;
return(retstr);
}
//printf("%s <- %s\n",url,command);
return(post_process_bitcoind_RPC(debugstr,command,retstr,params));
}
else
{
if ( (0) && specialcase != 0 )
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,retstr);
count2++;
elapsedsum2 += (OS_milliseconds() - starttime);
if ( (count2 % 10000) == 0)
printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command);
return(retstr);
}
}
}
/************************************************************************
*
* Initialize the string handler so that it is thread safe

6
crypto777/cJSON.c

@ -902,10 +902,10 @@ char *get_cJSON_fieldname(cJSON *obj)
{
if ( obj != 0 )
{
if ( obj->child != 0 && obj->child->string != 0 )
return(obj->child->string);
else if ( obj->string != 0 )
if ( obj->string != 0 )
return(obj->string);
if ( obj->child != 0 && obj->child->string != 0 )
return(obj->child->string);
}
return((char *)"<no cJSON string field>");
}

41
docker-compose.yml

@ -0,0 +1,41 @@
version: '2'
services:
seednode:
build:
context: ./
dockerfile: Dockerfile.seednode
volumes:
- ~/.zcash-params:/home/jenkins/.zcash-params
- ~/.komodo:/home/jenkins/.komodo
- .:/usr/mm
env_file:
- .env.seed
tty: true
networks:
default:
ipv4_address: 10.100.0.2
clientnode:
build:
context: ./
dockerfile: Dockerfile.clientnode
volumes:
- ~/.zcash-params:/home/jenkins/.zcash-params
- ~/.komodo:/home/jenkins/.komodo
- .:/usr/mm
links:
- seednode
tty: true
env_file:
- .env.client
networks:
default:
ipv4_address: 10.100.0.3
networks:
default:
driver: bridge
ipam:
config:
- subnet: 10.100.0.0/16
gateway: 10.100.0.1

5
etomic_build/client

@ -1,5 +0,0 @@
#!/bin/bash
source passphrase
source coins
./stop
iguana/exchanges/marketmaker "{\"netid\":9999,\"seednode\":\"5.9.253.204\",\"gui\":\"nogui\",\"client\":1, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$passphrase\", \"coins\":$coins}" &

4
etomic_build/client/buy_BEER_OTHER

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"$1\",\"rel\":\"BEER\",\"price\":1}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"buy\",\"base\":\"BEER\",\"rel\":\"$1\",\"relvolume\":0.1,\"price\":1}"

4
etomic_build/client/client

@ -0,0 +1,4 @@
#!/bin/bash
source passphrase
source ../coins
../../build/iguana/exchanges/marketmaker-testnet "{\"netid\":9999,\"seednode\":\"10.100.0.2\",\"gui\":\"nogui\",\"client\":1, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$passphrase\", \"coins\":$coins}"

7
etomic_build/client/enable

@ -0,0 +1,7 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETOMIC\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETH\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"NODEC\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"JST\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BEER\"}"

1
etomic_build/client/myipaddr

@ -0,0 +1 @@
10.100.0.3

1
etomic_build/client/passphrase

@ -0,0 +1 @@
export passphrase="$PASSPHRASE"

4
etomic_build/client/setpassphrase

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
source passphrase
curl --url "http://127.0.0.1:7783" --data "{\"netid\":9999,\"seednode\":\"10.100.0.2\",\"userpass\":\"1d8b27b21efabcd96571cd56f91a40fb9aa4cc623d273c63bf9223dc6f8cd81f\",\"method\":\"passphrase\",\"passphrase\":\"$passphrase\",\"gui\":\"nogui\"}"

2
etomic_build/client/userpass

@ -0,0 +1,2 @@
#export userpass="<put the userpass value from the first API call here>"
export userpass="$USERPASS"

2
etomic_build/coins

File diff suppressed because one or more lines are too long

3
etomic_build/enable

@ -1,5 +1,4 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETH\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETOMIC\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETH\"}"

1
etomic_build/passphrase

@ -1 +0,0 @@
export passphrase="<put a very strong passphrase here>"

5
etomic_build/run

@ -1,5 +0,0 @@
#!/bin/bash
source passphrase
source coins
./stop
$1 iguana/exchanges/marketmaker "{\"netid\":9999,\"gui\":\"nogui\", \"profitmargin\":0.01, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$passphrase\", \"coins\":$coins}" &

7
etomic_build/seed/enable

@ -0,0 +1,7 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETOMIC\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"ETH\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"NODEC\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"JST\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BEER\"}"

1
etomic_build/seed/myipaddr

@ -0,0 +1 @@
10.100.0.2

1
etomic_build/seed/passphrase

@ -0,0 +1 @@
export passphrase="$PASSPHRASE"

4
etomic_build/seed/run

@ -0,0 +1,4 @@
#!/bin/bash
source passphrase
source ../coins
../../build/iguana/exchanges/marketmaker-testnet "{\"netid\":9999,\"gui\":\"nogui\", \"profitmargin\":0.01, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"$passphrase\", \"coins\":$coins}"

4
etomic_build/seed/sell_BEER_OTHER

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"setprice\",\"base\":\"BEER\",\"rel\":\"$1\",\"price\":0.9}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"BEER\",\"rel\":\"$1\",\"basevolume\":0.1,\"price\":0.9}"

4
etomic_build/seed/setpassphrase

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
source passphrase
curl --url "http://127.0.0.1:7783" --data "{\"netid\":9999,\"seednode\":\"5.9.253.204\",\"userpass\":\"1d8b27b21efabcd96571cd56f91a40fb9aa4cc623d273c63bf9223dc6f8cd81f\",\"method\":\"passphrase\",\"passphrase\":\"$passphrase\",\"gui\":\"nogui\"}"

2
etomic_build/seed/userpass

@ -0,0 +1,2 @@
#export userpass="<put the userpass value from the first API call here>"
export userpass="$USERPASS"

2
etomic_build/userpass

@ -1,2 +1,2 @@
#export userpass="<put the userpass value from the first API call here>"
export userpass="c3d8c2a364b7d18c1f9d7321d017b92e9f9c791e4f5c741214fefdea8a071256"
export userpass="$USERPASS"

1
iguana/coins/ccl_7776

@ -0,0 +1 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"CCL.conf\",\"path\":\"${HOME#"/"}/.komodo/CCL\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"CCL\",\"name\":\"CCL\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"5c31ff66\",\"p2p\":20848,\"rpc\":20849,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

2
iguana/coins/rfox_7776

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"RFOX.conf\",\"path\":\"${HOME#"/"}/.komodo/RFOX\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"RFOX\",\"name\":\"RFOX\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"4cad0644\",\"p2p\":32268,\"rpc\":32269,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

2
iguana/coins/sec_7776

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"SEC.conf\",\"path\":\"${HOME#"/"}/.komodo/SEC\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"SEC\",\"name\":\"SEC\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"8f27938c\",\"p2p\":11539,\"rpc\":11540,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"185.148.145.43\"}"

2
iguana/coins/vrsc_7776

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"VRSC.conf\",\"path\":\"${HOME#"/"}/.komodo/VRSC\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"VRSC\",\"name\":\"Verus\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"91db4d20\",\"p2p\":27485,\"rpc\":27486,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"54.39.23.248\"}"

1
iguana/coins/zilla_7776

@ -0,0 +1 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"ZILLA.conf\",\"path\":\"${HOME#"/"}/.komodo/ZILLA\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"ZILLA\",\"name\":\"ZILLA\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"91db4d20\",\"p2p\":10040,\"rpc\":10041,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"54.39.23.248\"}"

6
iguana/dPoW.h

@ -109,7 +109,7 @@ struct dpow_recvdata { uint64_t recvmask,bestmask; int8_t bestk; };
struct dpow_block
{
bits256 hashmsg,desttxid,srctxid,beacon,commit,MoM;
bits256 hashmsg,desttxid,srctxid,beacon,commit,MoM,mysrcutxo,mydestutxo;
struct iguana_info *srccoin,*destcoin; char *opret_symbol;
uint64_t destsigsmasks[DPOW_MAXRELAYS],srcsigsmasks[DPOW_MAXRELAYS];
uint64_t recvmask,bestmask,ratifybestmask,ratifyrecvmask,pendingbestmask,pendingratifybestmask,ratifysigmasks[2];
@ -119,6 +119,7 @@ struct dpow_block
int32_t rawratifiedlens[2],height,numnotaries,numerrors,completed,minsigs,duration,numratified,isratify,require0,scores[DPOW_MAXRELAYS];
int8_t myind,bestk,ratifybestk,pendingbestk,pendingratifybestk,matches,bestmatches;
cJSON *ratified;
uint16_t CCid;
uint8_t ratified_pubkeys[DPOW_MAXRELAYS][33],ratifysigs[2][DPOW_MAXSIGLEN],ratifysiglens[2];
char handles[DPOW_MAXRELAYS][32];
char signedtx[32768]; uint8_t ratifyrawtx[2][32768]; uint32_t pendingcrcs[2];
@ -143,6 +144,7 @@ struct dpow_info
uint32_t SRCREALTIME,lastsrcupdate,destupdated,srcconfirms,numdesttx,numsrctx,lastsplit,cancelratify;
int32_t lastheight,maxblocks,SRCHEIGHT,DESTHEIGHT,prevDESTHEIGHT,SHORTFLAG,ratifying,minsigs,freq;
struct pax_transaction *PAX;
uint32_t fullCCid;
portable_mutex_t paxmutex,dexmutex;
uint32_t ipbits[128],numipbits;
struct dpow_block **blocks,*currentbp;
@ -158,7 +160,7 @@ struct komodo_ccdataMoMoM
};
uint64_t dpow_notarybestk(uint64_t refmask,struct dpow_block *bp,int8_t *lastkp);
int32_t dpow_paxpending(uint8_t *hex,int32_t hexsize,uint32_t *paxwdcrcp,bits256 MoM,uint32_t MoMdepth,int32_t src_or_dest,struct dpow_block *bp);
int32_t dpow_paxpending(struct supernet_info *myinfo,uint8_t *hex,int32_t hexsize,uint32_t *paxwdcrcp,bits256 MoM,uint32_t MoMdepth,uint16_t CCid,int32_t src_or_dest,struct dpow_block *bp);
void dex_updateclient(struct supernet_info *myinfo);
char *dex_reqsend(struct supernet_info *myinfo,char *handler,uint8_t *data,int32_t datalen,int32_t M,char *field);
char *basilisk_respond_addmessage(struct supernet_info *myinfo,uint8_t *key,int32_t keylen,uint8_t *data,int32_t datalen,int32_t sendping,uint32_t duration);

14
iguana/dpow/dpow_fsm.c

@ -235,7 +235,7 @@ bits256 dpow_calcMoM(uint32_t *MoMdepthp,struct supernet_info *myinfo,struct igu
bits256 MoM; cJSON *MoMjson,*infojson; int32_t prevMoMheight;
*MoMdepthp = 0;
memset(MoM.bytes,0,sizeof(MoM));
if ( strcmp(coin->symbol,"GAME") == 0 ) // 80 byte OP_RETURN limit
if ( strcmp(coin->symbol,"GAME") == 0 || strcmp(coin->symbol,"HUSH") == 0 ) // 80 byte OP_RETURN limit
return(MoM);
if ( (infojson= dpow_getinfo(myinfo,coin)) != 0 )
{
@ -302,6 +302,7 @@ void dpow_statemachinestart(void *ptr)
Numallocated++;
bp->MoM = MoM;
bp->MoMdepth = MoMdepth;
bp->CCid = dp->fullCCid & 0xffff;
bp->minsigs = minsigs;
bp->duration = duration;
bp->srccoin = src;
@ -438,7 +439,7 @@ void dpow_statemachinestart(void *ptr)
return;
}
bp->myind = myind;
printf("[%d] notarize %s->%s %s ht.%d minsigs.%d duration.%d start.%u MoM[%d] %s\n",bp->myind,dp->symbol,dp->dest,bits256_str(str,checkpoint.blockhash.hash),checkpoint.blockhash.height,minsigs,duration,checkpoint.timestamp,bp->MoMdepth,bits256_str(str2,bp->MoM));
printf("[%d] notarize %s->%s %s ht.%d minsigs.%d duration.%d start.%u MoM[%d] %s CCid.%u\n",bp->myind,dp->symbol,dp->dest,bits256_str(str,checkpoint.blockhash.hash),checkpoint.blockhash.height,minsigs,duration,checkpoint.timestamp,bp->MoMdepth,bits256_str(str2,bp->MoM),bp->CCid);
if ( bp->isratify != 0 && memcmp(bp->notaries[0].pubkey,bp->ratified_pubkeys[0],33) != 0 )
{
for (i=0; i<33; i++)
@ -487,6 +488,11 @@ void dpow_statemachinestart(void *ptr)
bp->notaries[myind].ratifydestutxo = ep->dest.prev_hash;
bp->notaries[myind].ratifydestvout = ep->dest.prev_vout;
}
else
{
bp->mysrcutxo = ep->src.prev_hash;
bp->mydestutxo = ep->dest.prev_hash;
}
}
/*if ( strcmp(dp->symbol,"CHIPS") == 0 && myind == 0 )
{
@ -520,7 +526,7 @@ void dpow_statemachinestart(void *ptr)
if ( strcmp(bp->destcoin->symbol,"KMD") == 0 )
src_or_dest = 0;
else src_or_dest = 1;
extralen = dpow_paxpending(extras,sizeof(extras),&bp->paxwdcrc,bp->MoM,bp->MoMdepth,src_or_dest,bp);
extralen = dpow_paxpending(myinfo,extras,sizeof(extras),&bp->paxwdcrc,bp->MoM,bp->MoMdepth,bp->CCid,src_or_dest,bp);
bp->notaries[bp->myind].paxwdcrc = bp->paxwdcrc;
}
printf("PAXWDCRC.%x myind.%d isratify.%d DPOW.%s statemachine checkpoint.%d %s start.%u+dur.%d vs %ld MoM[%d] %s\n",bp->paxwdcrc,bp->myind,bp->isratify,src->symbol,checkpoint.blockhash.height,bits256_str(str,checkpoint.blockhash.hash),starttime,bp->duration,time(NULL),bp->MoMdepth,bits256_str(str2,bp->MoM));
@ -541,7 +547,7 @@ void dpow_statemachinestart(void *ptr)
if ( strcmp(bp->destcoin->symbol,"KMD") == 0 )
src_or_dest = 0;
else src_or_dest = 1;
extralen = dpow_paxpending(extras,sizeof(extras),&bp->paxwdcrc,bp->MoM,bp->MoMdepth,src_or_dest,bp);
extralen = dpow_paxpending(myinfo,extras,sizeof(extras),&bp->paxwdcrc,bp->MoM,bp->MoMdepth,bp->CCid,src_or_dest,bp);
bp->notaries[bp->myind].paxwdcrc = bp->paxwdcrc;
}
if ( dp->checkpoint.blockhash.height > checkpoint.blockhash.height ) //(checkpoint.blockhash.height % 100) != 0 &&

28
iguana/dpow/dpow_network.c

@ -1308,8 +1308,8 @@ int32_t dpow_addnotary(struct supernet_info *myinfo,struct dpow_info *dp,char *i
char str[512]; uint32_t ipbits,*ptr; int32_t i,iter,n,retval = -1;
if ( myinfo->IAMNOTARY == 0 )
return(-1);
if ( strcmp(ipaddr,"88.99.251.101") == 0 || strcmp(ipaddr,"82.202.193.100") == 0 )
return(-1);
//if ( strcmp(ipaddr,"88.99.251.101") == 0 || strcmp(ipaddr,"82.202.193.100") == 0 )
// return(-1);
portable_mutex_lock(&myinfo->notarymutex);
if ( myinfo->dpowsock >= 0 )//&& myinfo->dexsock >= 0 )
{
@ -1869,16 +1869,24 @@ void dpow_notarize_update(struct supernet_info *myinfo,struct dpow_info *dp,stru
return;
if ( bp->isratify == 0 && bp->state != 0xffffffff && senderind >= 0 && senderind < bp->numnotaries && bits256_nonz(srcutxo) != 0 && bits256_nonz(destutxo) != 0 )
{
if ( bits256_nonz(srcutxo) != 0 )
if ( bp->myind != senderind )
{
bp->notaries[senderind].src.prev_hash = srcutxo;
bp->notaries[senderind].src.prev_vout = srcvout;
//char str[65]; printf("%s senderind.%d <- %s/v%d\n",dp->symbol,senderind,bits256_str(str,srcutxo),srcvout);
if ( bits256_nonz(srcutxo) != 0 )
{
bp->notaries[senderind].src.prev_hash = srcutxo;
bp->notaries[senderind].src.prev_vout = srcvout;
//char str[65]; printf("%s senderind.%d <- %s/v%d\n",dp->symbol,senderind,bits256_str(str,srcutxo),srcvout);
}
if ( bits256_nonz(destutxo) != 0 )
{
bp->notaries[senderind].dest.prev_hash = destutxo;
bp->notaries[senderind].dest.prev_vout = destvout;
}
}
if ( bits256_nonz(destutxo) != 0 )
else
{
bp->notaries[senderind].dest.prev_hash = destutxo;
bp->notaries[senderind].dest.prev_vout = destvout;
bp->notaries[bp->myind].src.prev_hash = bp->mysrcutxo;
bp->notaries[bp->myind].dest.prev_hash = bp->mydestutxo;
}
if ( bestmask != 0 )
bp->notaries[senderind].bestmask = bestmask;
@ -2070,7 +2078,7 @@ void dpow_send(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_blo
if ( strcmp(bp->destcoin->symbol,"KMD") == 0 )
src_or_dest = 0;
else src_or_dest = 1;
extralen = dpow_paxpending(extras,sizeof(extras),&paxwdcrc,bp->MoM,bp->MoMdepth,src_or_dest,bp);
extralen = dpow_paxpending(myinfo,extras,sizeof(extras),&paxwdcrc,bp->MoM,bp->MoMdepth,bp->CCid,src_or_dest,bp);
bp->paxwdcrc = bp->notaries[bp->myind].paxwdcrc = np->notarize.paxwdcrc = paxwdcrc;
//dpow_bestconsensus(dp,bp);
dpow_nanoutxoset(myinfo,dp,&np->notarize,bp,0);

30
iguana/dpow/dpow_rpc.c

@ -78,6 +78,17 @@ cJSON *dpow_getinfo(struct supernet_info *myinfo,struct iguana_info *coin)
return(json);
}
uint32_t dpow_CCid(struct supernet_info *myinfo,struct iguana_info *coin)
{
uint32_t CCid = 0; cJSON *retjson;
if ( (retjson= dpow_getinfo(myinfo,coin)) != 0 )
{
CCid = juint(retjson,"CCid");
free_json(retjson);
}
return(CCid);
}
char *Notaries_elected[65][2];
//char *seeds[] = { "78.47.196.146", "5.9.102.210", "149.56.29.163", "191.235.80.138", "88.198.65.74", "94.102.63.226", "129.232.225.202", "104.255.64.3", "52.72.135.200", "149.56.28.84", "103.18.58.150", "221.121.144.140", "123.249.79.12", "103.18.58.146", "27.50.93.252", "176.9.0.233", "94.102.63.227", "167.114.227.223", "27.50.68.219", "192.99.233.217", "94.102.63.217", "45.64.168.216" };
int32_t Notaries_numseeds;// = (int32_t)(sizeof(seeds)/sizeof(*seeds))
@ -251,16 +262,16 @@ cJSON *issue_calcMoM(struct iguana_info *coin,int32_t height,int32_t MoMdepth)
return(retjson);
}
cJSON *dpow_MoMoMdata(struct iguana_info *coin,char *symbol,int32_t kmdheight)
cJSON *dpow_MoMoMdata(struct iguana_info *coin,char *symbol,int32_t kmdheight,uint16_t CCid)
{
char buf[128],*retstr=0; cJSON *retjson = 0; struct iguana_info *src;
if ( coin->FULLNODE < 0 && strcmp(coin->symbol,"KMD") == 0 && (src= iguana_coinfind(symbol)) != 0 )
{
sprintf(buf,"[\"%s\", \"%d\", \"%d\"]",symbol,kmdheight,src->MoMoMheight);
sprintf(buf,"[\"%s\", \"%d\", \"%d\"]",symbol,kmdheight,CCid);
if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"MoMoMdata",buf)) != 0 )
{
retjson = cJSON_Parse(retstr);
printf("MoMoM.%s -> %s\n",buf,retstr);
printf("%s kmdheight.%d CCid.%u MoMoM.%s -> %s\n",symbol,kmdheight,CCid,buf,retstr);
free(retstr);
}
usleep(10000);
@ -268,22 +279,29 @@ cJSON *dpow_MoMoMdata(struct iguana_info *coin,char *symbol,int32_t kmdheight)
return(retjson);
}
int32_t dpow_paxpending(uint8_t *hex,int32_t hexsize,uint32_t *paxwdcrcp,bits256 MoM,uint32_t MoMdepth,int32_t src_or_dest,struct dpow_block *bp)
int32_t dpow_paxpending(struct supernet_info *myinfo,uint8_t *hex,int32_t hexsize,uint32_t *paxwdcrcp,bits256 MoM,uint32_t MoMdepth,uint16_t CCid,int32_t src_or_dest,struct dpow_block *bp)
{
struct iguana_info *coin,*kmdcoin=0; char *retstr,*hexstr; cJSON *retjson; int32_t hexlen=0,n=0; uint32_t paxwdcrc;
struct iguana_info *coin,*kmdcoin=0; char *retstr,*hexstr; cJSON *retjson,*infojson; int32_t kmdheight=0,hexlen=0,n=0; uint32_t paxwdcrc;
paxwdcrc = 0;
if ( strcmp(bp->srccoin->symbol,"GAME") != 0 || src_or_dest != 0 )
{
n += iguana_rwbignum(1,&hex[n],sizeof(MoM),MoM.bytes);
MoMdepth = (MoMdepth & 0xffff) | ((uint32_t)CCid<<16);
n += iguana_rwnum(1,&hex[n],sizeof(MoMdepth),(uint32_t *)&MoMdepth);
if ( strncmp(bp->srccoin->symbol,"TXSCL",5) == 0 && src_or_dest == 0 && strcmp(bp->destcoin->symbol,"KMD") == 0 )
{
kmdcoin = bp->destcoin;
if ( (retjson= dpow_MoMoMdata(kmdcoin,bp->srccoin->symbol,(kmdcoin->lastbestheight/10)*10 - 5)) != 0 )
if ( (infojson= dpow_getinfo(myinfo,kmdcoin)) != 0 )
{
kmdheight = jint(infojson,"blocks");
free_json(infojson);
}
if ( (retjson= dpow_MoMoMdata(kmdcoin,bp->srccoin->symbol,kmdheight,bp->CCid)) != 0 )
{
if ( (hexstr= jstr(retjson,"data")) != 0 && (hexlen= (int32_t)strlen(hexstr)) > 0 && n+hexlen/2 <= hexsize )
{
hexlen >>= 1;
printf("add MoMoMdata.(%s)\n",hexstr);
decode_hex(&hex[n],hexlen,hexstr), n += hexlen;
}
free_json(retjson);

16
iguana/dpow/dpow_tx.c

@ -199,7 +199,7 @@ struct dpow_block *dpow_heightfind(struct supernet_info *myinfo,struct dpow_info
return(bp);
}
int32_t dpow_voutstandard(struct dpow_block *bp,uint8_t *serialized,int32_t m,int32_t src_or_dest,uint8_t pubkeys[][33],int32_t numratified)
int32_t dpow_voutstandard(struct supernet_info *myinfo,struct dpow_block *bp,uint8_t *serialized,int32_t m,int32_t src_or_dest,uint8_t pubkeys[][33],int32_t numratified)
{
uint32_t paxwdcrc=0,locktime=0,numvouts; struct iguana_info *coin; uint64_t satoshis,satoshisB; int32_t i,n=0,opretlen,len=0; uint8_t opret[16384],data[16384],extras[16384];
numvouts = 2;
@ -238,7 +238,7 @@ int32_t dpow_voutstandard(struct dpow_block *bp,uint8_t *serialized,int32_t m,in
}
if ( bp->MoMdepth > 0 && strcmp(bp->destcoin->symbol,"KMD") == 0 ) // || strcmp(bp->srccoin->symbol,"KMD") == 0) )
{
n = dpow_paxpending(extras,sizeof(extras),&paxwdcrc,bp->MoM,bp->MoMdepth,src_or_dest,bp);
n = dpow_paxpending(myinfo,extras,sizeof(extras),&paxwdcrc,bp->MoM,bp->MoMdepth,bp->CCid,src_or_dest,bp);
}
satoshis = 0;
len += iguana_rwnum(1,&serialized[len],sizeof(satoshis),&satoshis);
@ -264,7 +264,7 @@ int32_t dpow_voutstandard(struct dpow_block *bp,uint8_t *serialized,int32_t m,in
return(len);
}
bits256 dpow_notarytx(char *signedtx,int32_t *numsigsp,int32_t isPoS,struct dpow_block *bp,int8_t bestk,uint64_t bestmask,int32_t usesigs,int32_t src_or_dest,uint8_t pubkeys[][33],int32_t numratified)
bits256 dpow_notarytx(struct supernet_info *myinfo,char *signedtx,int32_t *numsigsp,int32_t isPoS,struct dpow_block *bp,int8_t bestk,uint64_t bestmask,int32_t usesigs,int32_t src_or_dest,uint8_t pubkeys[][33],int32_t numratified)
{
uint32_t k,m,numsigs,version,vout,crcval,sequenceid = 0xffffffff; bits256 zero; int32_t n,siglen,len; uint8_t serialized[32768],*sig; bits256 txid; struct dpow_entry *ep; struct dpow_coinentry *cp;
signedtx[0] = 0;
@ -329,7 +329,7 @@ bits256 dpow_notarytx(char *signedtx,int32_t *numsigsp,int32_t isPoS,struct dpow
memcpy(&serialized[len],sig,siglen);
len += siglen;
numsigs++;
} else printf("Missing sig from k.%d\n",k);
} //else printf("%s -> %s src_or_dest.%d Missing sig from k.%d\n",bp->srccoin->symbol,bp->destcoin->symbol,src_or_dest,k);
} else serialized[len++] = 0;
len += iguana_rwnum(1,&serialized[len],sizeof(sequenceid),&sequenceid);
//printf("height.%d mod.%d VINI.%d <- i.%d j.%d\n",height,height % numnotaries,m,i,j);
@ -338,7 +338,7 @@ bits256 dpow_notarytx(char *signedtx,int32_t *numsigsp,int32_t isPoS,struct dpow
break;
}
}
if ( (n= dpow_voutstandard(bp,&serialized[len],m,src_or_dest,pubkeys,numratified)) < 0 )
if ( (n= dpow_voutstandard(myinfo,bp,&serialized[len],m,src_or_dest,pubkeys,numratified)) < 0 )
{
printf("error dpow_voutstandard m.%d src_or_dest.%d\n",m,src_or_dest);
return(zero);
@ -516,7 +516,7 @@ int32_t dpow_signedtxgen(struct supernet_info *myinfo,struct dpow_info *dp,struc
srchash.bytes[j] = dp->minerkey33[j+1];
if ( (vins= dpow_vins(coin,bp,bestk,bestmask,1,src_or_dest,useratified)) != 0 )
{
txid = dpow_notarytx(rawtx,&numsigs,coin->chain->isPoS,bp,bestk,bestmask,0,src_or_dest,bp->numratified!=0?bp->ratified_pubkeys:0,useratified*bp->numratified);
txid = dpow_notarytx(myinfo,rawtx,&numsigs,coin->chain->isPoS,bp,bestk,bestmask,0,src_or_dest,bp->numratified!=0?bp->ratified_pubkeys:0,useratified*bp->numratified);
//char str[65]; printf("%s signedtxgen %s src_or_dest.%d (%d %llx) useratified.%d raw.(%s)\n",dp->symbol,bits256_str(str,txid),src_or_dest,bestk,(long long)bestmask,useratified,rawtx);
if ( bits256_nonz(txid) != 0 && rawtx[0] != 0 ) // send tx to share utxo set
{
@ -579,8 +579,8 @@ void dpow_sigscheck(struct supernet_info *myinfo,struct dpow_info *dp,struct dpo
channel = (src_or_dest != 0) ? DPOW_SIGBTCCHANNEL : DPOW_SIGCHANNEL;
if ( bestk >= 0 && bp->state != 0xffffffff && coin != 0 )
{
dpow_notarytx(bp->signedtx,&numsigs,coin->chain->isPoS,bp,bestk,bestmask,0,src_or_dest,pubkeys,numratified); // setcrcval
signedtxid = dpow_notarytx(bp->signedtx,&numsigs,coin->chain->isPoS,bp,bestk,bestmask,1,src_or_dest,pubkeys,numratified);
dpow_notarytx(myinfo,bp->signedtx,&numsigs,coin->chain->isPoS,bp,bestk,bestmask,0,src_or_dest,pubkeys,numratified); // setcrcval
signedtxid = dpow_notarytx(myinfo,bp->signedtx,&numsigs,coin->chain->isPoS,bp,bestk,bestmask,1,src_or_dest,pubkeys,numratified);
if ( strcmp("GAME",coin->symbol) == 0 )
printf("src_or_dest.%d bestk.%d %llx %s numsigs.%d signedtx.(%s)\n",src_or_dest,bestk,(long long)bestmask,bits256_str(str,signedtxid),numsigs,bp->signedtx);
bp->state = 1;

7
iguana/exchanges/CMakeLists.txt

@ -31,4 +31,9 @@ target_link_libraries(marketmaker-mainnet ${MM_LIBS} etomiclib-mainnet)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_link_libraries(marketmaker-mainnet -static-libgcc -static-libstdc++)
target_link_libraries(marketmaker-testnet -static-libgcc -static-libstdc++)
endif()
endif()
if(NOT DEFINED MM_VERSION)
SET(MM_VERSION UNKNOWN)
endif()
target_compile_definitions(marketmaker-mainnet PRIVATE -DMM_VERSION="${MM_VERSION}")
target_compile_definitions(marketmaker-testnet PRIVATE -DMM_VERSION="${MM_VERSION}")

23
iguana/exchanges/LP_bitcoin.c

@ -2011,16 +2011,25 @@ int32_t bitcoin_p2shscript(uint8_t *script,int32_t n,const uint8_t *p2shscript,c
return(n);
}
char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params)
char *bitcoind_passthrut(char *coinstr,char *serverport,char *userpass,char *method,char *params,int32_t timeout)
{
if ( userpass[0] == 0 )
return(clonestr("{\"error\":\"no rpcusername rpcpassword in coin.conf\"}"));
return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,4));
/*struct iguana_info *coin; char *retstr;
if ( (coin= LP_coinfind(coinstr)) != 0 )
{
portable_mutex_lock(&coin->curl_mutex);
retstr = bitcoind_RPCnew(coin->curl_handle,0,coinstr,serverport,userpass,method,params,timeout);
portable_mutex_unlock(&coin->curl_mutex);
return(retstr);
}*/
return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,timeout));
}
char *bitcoind_passthrut(char *coinstr,char *serverport,char *userpass,char *method,char *params,int32_t timeout)
char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params)
{
return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,timeout));
if ( userpass[0] == 0 )
return(clonestr("{\"error\":\"no rpcusername rpcpassword in coin.conf\"}"));
return(bitcoind_passthrut(coinstr,serverport,userpass,method,params,4));
//return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params,4));
}
bits256 bits256_calcaddrhash(char *symbol,uint8_t *serialized,int32_t len)
@ -2093,7 +2102,7 @@ int32_t bitcoin_addr2rmd160(char *symbol,uint8_t taddr,uint8_t *addrtypep,uint8_
}
else if ( (strcmp(symbol,"GRS") == 0 || strcmp(symbol,"SMART") == 0) && (buf[20+offset]&0xff) == hash.bytes[0] && (buf[21+offset]&0xff) == hash.bytes[1] && (buf[22+offset]&0xff) == hash.bytes[2] && (buf[23+offset]&0xff) == hash.bytes[3] )
return(20);
else
else if ( strcmp(symbol,"BTC") != 0 || *addrtypep == 0 || *addrtypep == 5 )
{
int32_t i;
//if ( len > 20 )

22
iguana/exchanges/LP_coins.c

@ -251,10 +251,14 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
}
#ifndef NOTETOMIC
else if (coin->etomic[0] != 0) {
//balance = LP_etomic_get_balance(coin, coin->smartaddr);
int error = 0;
if (coin->inactive == 0) {
balance = LP_etomic_get_balance(coin, coin->smartaddr, &error);
} else {
balance = 0;
}
jaddnum(item,"height",-1);
//jaddnum(item,"balance",dstr(balance));
jaddnum(item,"balance",0);
jaddnum(item,"balance",dstr(balance));
}
#endif
else
@ -373,7 +377,8 @@ struct iguana_info *LP_coinadd(struct iguana_info *cdata)
return(coin);
}
uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t wiftaddr,uint8_t taddr,uint16_t busport,char *confpath)
void *curl_easy_init();
uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *assetname,int32_t isPoS,uint16_t port,uint8_t pubtype,uint8_t p2shtype,uint8_t wiftype,uint64_t txfee,double estimatedrate,int32_t longestchain,uint8_t wiftaddr,uint8_t taddr,uint16_t busport,char *confpath,uint8_t decimals)
{
static void *ctx;
char *name2; uint16_t origport = port;
@ -434,6 +439,9 @@ uint16_t LP_coininit(struct iguana_info *coin,char *symbol,char *name,char *asse
coin->zcash = LP_IS_BITCOINCASH;
//printf("set coin.%s <- LP_IS_BITCOINCASH %d\n",symbol,coin->zcash);
}
coin->curl_handle = curl_easy_init();
portable_mutex_init(&coin->curl_mutex);
coin->decimals = decimals;
return(port);
}
@ -477,7 +485,7 @@ struct iguana_info *LP_coinfind(char *symbol)
else if ( strcmp(symbol,"KMD") == 0 )
name = "komodo";
else return(0);
port = LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0,0,busport,0);
port = LP_coininit(&cdata,symbol,name,assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,0,0,busport,0,0);
if ( port == 0 )
isinactive = 1;
else isinactive = 0;
@ -519,7 +527,9 @@ struct iguana_info *LP_coincreate(cJSON *item)
}
else if ( (name= jstr(item,"name")) == 0 )
name = symbol;
if ( LP_coininit(&cdata,symbol,name,assetname==0?"":assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,juint(item,"wiftaddr"),juint(item,"taddr"),LP_busport(port),jstr(item,"confpath")) < 0 )
uint8_t decimals = juint(item,"decimals");
if ( LP_coininit(&cdata,symbol,name,assetname==0?"":assetname,isPoS,port,pubtype,p2shtype,wiftype,txfee,estimatedrate,longestchain,juint(item,"wiftaddr"),juint(item,"taddr"),LP_busport(port),jstr(item,"confpath"),decimals) < 0 )
{
coin = LP_coinadd(&cdata);
coin->inactive = (uint32_t)time(NULL);

107
iguana/exchanges/LP_commands.c

@ -120,6 +120,7 @@ cancel(uuid)\n\
buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce)\n\
sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce)\n\
withdraw(coin, outputs[], broadcast=0)\n\
eth_withdraw(coin, to, amount, gas, gas_price, broadcast=0)\n\
txblast(coin, utxotxid, utxovout, utxovalue, txfee, passphrase, outputs[], broadcast=0)\n\
sendrawtransaction(coin, signedtx)\n\
swapstatus(pending=0, fast=0)\n\
@ -151,6 +152,7 @@ getprice(base, rel)\n\
//getmessages(firsti=0, num=100)\n\
//deletemessages(firsti=0, num=100)\n\
secretaddresses(prefix='secretaddress', passphrase, num=10, pubtype=60, taddr=0)\n\
gen64addrs(passphrase, taddr=0, pubtype=60)\n\
electrum(coin, ipaddr, port)\n\
snapshot(coin, height)\n\
snapshot_balance(coin, height, addresses[])\n\
@ -173,10 +175,17 @@ unlockedspend(coin, txid)\n\
opreturndecrypt(coin, txid, passphrase)\n\
getendpoint(port=5555)\n\
getfee(coin)\n\
mpnet(onoff)\n\
sleep(seconds=60)\n\
listtransactions(coin, address, count=10, skip=0)\n\
jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
version\n\
\"}"));
if ( strcmp(method,"version") == 0 ) {
retjson = cJSON_CreateObject();
jaddstr(retjson,"result",MM_VERSION);
return(jprint(retjson,1));
}
if ( (base= jstr(argjson,"base")) == 0 )
base = "";
@ -232,12 +241,23 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
{
if ( (ptr= LP_coinsearch("KMD")) != 0 )
{
if ( jint(argjson,"weeks") <= 0 || jdouble(argjson,"amount") < 10. )
return(clonestr("{\"error\":\"instantdex_deposit needs to have weeks and amount\"}"));
else return(LP_instantdex_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jobj(argjson,"broadcast") != 0 ? jint(argjson,"broadcast") : 1));
if ( jint(argjson,"weeks") <= 0 ) {
return(clonestr("{\"error\":\"instantdex_deposit weeks param must be greater than zero\"}"));
}
if ( jdouble(argjson,"amount") < 10. ) {
return(clonestr("{\"error\":\"instantdex_deposit amount param must be equal or greater than 10\"}"));
}
return(LP_instantdex_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jobj(argjson,"broadcast") != 0 ? jint(argjson,"broadcast") : 1));
}
return(clonestr("{\"error\":\"cant find KMD\"}"));
}
else if ( strcmp(method,"mpnet") == 0 )
{
G.mpnet = jint(argjson,"onoff");
printf("MPNET onoff.%d\n",G.mpnet);
return(clonestr("{\"status\":\"success\"}"));
}
else if ( strcmp(method,"getendpoint") == 0 )
{
int32_t err,mode; uint16_t wsport = 5555; char endpoint[64],bindpoint[64];
@ -277,6 +297,10 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
}
return(jprint(retjson,1));
}
else if ( strcmp(method,"verus") == 0 )
{
return(verusblocks());
}
else if ( strcmp(method,"instantdex_claim") == 0 )
{
if ( (ptr= LP_coinsearch("KMD")) != 0 )
@ -392,11 +416,6 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
jaddbits256(retjson,"privkey",privkey);
bitcoin_priv2wif(coin,wiftaddr,wifstr,privkey,wiftype);
jaddstr(retjson,"wif",wifstr);
#ifndef NOTETOMIC
char ethaddr[50];
LP_etomic_pubkeystr_to_addr(pubsecp, ethaddr);
jaddstr(retjson,"ethaddr",ethaddr);
#endif
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"need to have passphrase\"}"));
}
@ -408,6 +427,13 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
{
return(LP_ticker(jstr(argjson,"base"),jstr(argjson,"rel")));
}
else if ( strcmp(method,"gen64addrs") == 0 )
{
uint8_t taddr,pubtype;
pubtype = (jobj(argjson,"pubtype") == 0) ? 60 : juint(argjson,"pubtype");
taddr = (jobj(argjson,"taddr") == 0) ? 0 : juint(argjson,"taddr");
return(LP_gen64addrs(ctx,jstr(argjson,"passphrase"),taddr,pubtype));
}
else if ( strcmp(method,"secretaddresses") == 0 )
{
uint8_t taddr,pubtype;
@ -452,6 +478,12 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
}
else if ( strcmp(method,"inuse") == 0 )
return(jprint(LP_inuse_json(),1));
#ifndef NOTETOMIC
else if ( strcmp(method,"eth_gas_price") == 0 )
{
return LP_eth_gas_price();
}
#endif
else if ( (retstr= LP_istradebots_command(ctx,pubsock,method,argjson)) != 0 )
return(retstr);
if ( base[0] != 0 && rel[0] != 0 )
@ -482,14 +514,14 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
double price,bid,ask;
if ( strcmp(method,"getprice") == 0 )
{
ask = LP_price(base,rel);
if ( (bid= LP_price(rel,base)) > SMALLVAL )
ask = LP_price(1,base,rel);
if ( (bid= LP_price(1,rel,base)) > SMALLVAL )
bid = 1./bid;
}
else
{
ask = LP_getmyprice(base,rel);
if ( (bid= LP_getmyprice(rel,base)) > SMALLVAL )
ask = LP_getmyprice(1,base,rel);
if ( (bid= LP_getmyprice(1,rel,base)) > SMALLVAL )
bid = 1./bid;
}
price = _pairaved(bid,ask);
@ -503,24 +535,24 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
jaddnum(retjson,"price",price);
return(jprint(retjson,1));
}
else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration")));
if ( IAMLP == 0 && LP_isdisabled(base,rel) != 0 )
return(clonestr("{\"error\":\"at least one of coins disabled\"}"));
price = jdouble(argjson,"price");
if ( strcmp(method,"setprice") == 0 )
{
if ( LP_mypriceset(&changed,base,rel,price) < 0 )
if ( LP_mypriceset(1,&changed,base,rel,price) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}"));
//else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 )
//else if ( LP_mypriceset(1,&changed,rel,base,1./price) < 0 )
// return(clonestr("{\"error\":\"couldnt set price\"}"));
else if ( price == 0. || jobj(argjson,"broadcast") == 0 || jint(argjson,"broadcast") != 0 )
return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio));
else return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"orderbook") == 0 )
return(LP_orderbook(base,rel,jint(argjson,"duration")));
else if ( strcmp(method,"myprice") == 0 )
{
if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL )
if ( LP_myprice(1,&bid,&ask,base,rel) > SMALLVAL )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"base",base);
@ -541,7 +573,7 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
} else vol = jdouble(argjson,"relvolume");
if ( price > SMALLVAL )
{
return(LP_autobuy(ctx,fomo,myipaddr,pubsock,base,rel,price,vol,jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"destpubkey"),0,jstr(argjson,"uuid")));
return(LP_autobuy(ctx,fomo,myipaddr,pubsock,base,rel,price,vol,jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"destpubkey"),0,jstr(argjson,"uuid"),jint(argjson,"fill"),jint(argjson,"gtc")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
else if ( strcmp(method,"sell") == 0 )
@ -555,7 +587,7 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
} else vol = jdouble(argjson,"basevolume");
if ( price > SMALLVAL )
{
return(LP_autobuy(ctx,fomo,myipaddr,pubsock,rel,base,1./price,vol,jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"destpubkey"),0,jstr(argjson,"uuid")));
return(LP_autobuy(ctx,fomo,myipaddr,pubsock,rel,base,1./price,vol,jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"destpubkey"),0,jstr(argjson,"uuid"),jint(argjson,"fill"),jint(argjson,"gtc")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
}
@ -580,12 +612,35 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
jaddstr(retjson,"coin",coin);
return(jprint(retjson,1));
}
#ifndef NOTETOMIC
if (strcmp(coin, "ETOMIC") == 0 && LP_RTsmartbalance(ptr) < 20 * SATOSHIDEN) {
if (get_etomic_from_faucet(ptr->smartaddr) != 1) {
return(clonestr("{\"error\":\"Could not get ETOMIC from faucet!\"}"));
}
}
if (ptr->etomic[0] != 0) {
if (isValidAddress(ptr->etomic) == 0) {
return(clonestr("{\"error\":\"'etomic' field is not valid address!\"}"));
}
struct iguana_info *etomic_coin = LP_coinsearch("ETOMIC");
if (etomic_coin->inactive != 0) {
return(clonestr("{\"error\":\"Enable ETOMIC first to use ETH/ERC20!\"}"));
}
if (ptr->decimals == 0 && strcmp(coin, "ETH") != 0) {
ptr->decimals = getErc20DecimalsZeroOnError(ptr->etomic);
if (ptr->decimals == 0) {
return(clonestr("{\"error\":\"Could not get token decimals or token has zero decimals which is not supported!\"}"));
}
}
}
#endif
if ( LP_conflicts_find(ptr) == 0 )
{
cJSON *array;
ptr->inactive = 0;
if ( ptr->smartaddr[0] != 0 )
LP_unspents_load(coin,ptr->smartaddr);
LP_unspents_load(coin,ptr->smartaddr);
if ( strcmp(ptr->symbol,"KMD") == 0 )
LP_importaddress("KMD",BOTS_BONDADDRESS);
@ -797,7 +852,7 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
return(jprint(retjson,1));
}
else if ( strcmp(method,"myprices") == 0 )
return(LP_myprices());
return(LP_myprices(1));
else if ( strcmp(method,"trust") == 0 )
return(LP_pubkey_trustset(jbits256(argjson,"pubkey"),jint(argjson,"trust")));
else if ( strcmp(method,"trusted") == 0 )
@ -858,14 +913,14 @@ jpg(srcfile, destfile, power2=7, password, data="", required, ind=0)\n\
double price,bid,ask;
if ( strcmp(method,"getprice") == 0 )
{
ask = LP_price(base,rel);
if ( (bid= LP_price(rel,base)) > SMALLVAL )
ask = LP_price(1,base,rel);
if ( (bid= LP_price(1,rel,base)) > SMALLVAL )
bid = 1./bid;
}
else
{
ask = LP_getmyprice(base,rel);
if ( (bid= LP_getmyprice(rel,base)) > SMALLVAL )
ask = LP_getmyprice(1,base,rel);
if ( (bid= LP_getmyprice(1,rel,base)) > SMALLVAL )
bid = 1./bid;
}
price = _pairaved(bid,ask);

214
iguana/exchanges/LP_etomic.c

@ -22,6 +22,9 @@
// Created by artem on 24.01.18.
//
#include "LP_etomic.h"
#define ALICE_PAYMENT_SENT 1
#define BOB_DEPOSIT_SENT 1
#define BOB_PAYMENT_SENT 1
int32_t LP_etomic_wait_for_confirmation(char *txId)
{
@ -38,13 +41,16 @@ void LP_etomic_pubkeystr_to_addr(char *pubkey, char *output)
char *LP_etomicalice_send_fee(struct basilisk_swap *swap)
{
char amount[100], secretKey[70], dexaddr[50];
satoshisToWei(amount, swap->myfee.I.amount);
satoshisToWei(amount, LP_DEXFEE(swap->I.alicerealsat));
swap->myfee.I.eth_amount = LP_DEXFEE(swap->I.alicerealsat);
uint8arrayToHex(secretKey, swap->persistent_privkey.bytes, 32);
LP_etomic_pubkeystr_to_addr(INSTANTDEX_PUBKEY, dexaddr);
if (strcmp(swap->I.alicestr,"ETH") == 0 ) {
return(sendEth(dexaddr, amount, secretKey, 1));
return(sendEth(dexaddr, amount, secretKey, 1, 0, 0, 1));
} else {
return(sendErc20(swap->I.alicetomic, dexaddr, amount, secretKey, 1));
struct iguana_info *alicecoin = LP_coinfind(swap->I.alicestr);
return(sendErc20(swap->I.alicetomic, dexaddr, amount, secretKey, 1, 0, 0, 1, alicecoin->decimals));
}
}
@ -55,7 +61,7 @@ uint8_t LP_etomic_verify_alice_fee(struct basilisk_swap *swap)
return(0);
}
EthTxData data = getEthTxData(swap->otherfee.I.ethTxid);
if (strcmp(data.from, swap->I.etomicdest) != 0) {
if (compareAddresses(data.from, swap->I.etomicdest) == 0) {
printf("Alice fee tx %s was sent from wrong address %s\n", swap->otherfee.I.ethTxid, data.from);
return(0);
}
@ -63,31 +69,33 @@ uint8_t LP_etomic_verify_alice_fee(struct basilisk_swap *swap)
char dexaddr[50];
LP_etomic_pubkeystr_to_addr(INSTANTDEX_PUBKEY, dexaddr);
if ( strcmp(swap->I.alicestr,"ETH") == 0 ) {
if (strcmp(data.to, dexaddr) != 0) {
if (compareAddresses(data.to, dexaddr) == 0) {
printf("Alice fee %s was sent to wrong address %s\n", swap->otherfee.I.ethTxid, data.to);
return(0);
}
uint64_t txValue = weiToSatoshi(data.valueHex);
if (txValue != swap->otherfee.I.amount) {
printf("Alice fee %s amount %" PRIu64 " is not equal to expected %" PRIu64 "\n", swap->otherfee.I.ethTxid, txValue, swap->otherfee.I.amount);
if (txValue != LP_DEXFEE(swap->I.alicerealsat)) {
printf("Alice fee %s amount %" PRIu64 " is not equal to expected %" PRId64 "\n", swap->otherfee.I.ethTxid, txValue, LP_DEXFEE(swap->I.alicerealsat));
return(0);
}
return(1);
} else {
if (strcmp(data.to, swap->I.alicetomic) != 0) {
struct iguana_info *alicecoin = LP_coinfind(swap->I.alicestr);
if (compareAddresses(data.to, swap->I.alicetomic) == 0) {
printf("Alice ERC20 fee %s token address %s is not equal to expected %s\n", swap->otherfee.I.ethTxid, data.to, swap->I.alicetomic);
return(0);
}
char weiAmount[70];
satoshisToWei(weiAmount, swap->otherfee.I.amount);
return(verifyAliceErc20FeeData(swap->I.alicetomic, dexaddr, weiAmount, data.input));
satoshisToWei(weiAmount, LP_DEXFEE(swap->I.alicerealsat));
return(verifyAliceErc20FeeData(swap->I.alicetomic, dexaddr, weiAmount, data.input, alicecoin->decimals));
}
}
char *LP_etomicalice_send_payment(struct basilisk_swap *swap)
{
AliceSendsEthPaymentInput input; AliceSendsErc20PaymentInput input20; BasicTxData txData;
swap->alicepayment.I.eth_amount = swap->I.alicerealsat;
// set input and txData fields from the swap data structure
memset(&txData,0,sizeof(txData));
if ( strcmp(swap->I.alicestr,"ETH") == 0 )
@ -100,28 +108,31 @@ char *LP_etomicalice_send_payment(struct basilisk_swap *swap)
strcpy(txData.from, swap->I.etomicdest);
strcpy(txData.to, ETOMIC_ALICECONTRACT);
satoshisToWei(txData.amount, swap->I.alicesatoshis);
satoshisToWei(txData.amount, swap->I.alicerealsat);
uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32);
return(aliceSendsEthPayment(input,txData));
}
else
{
struct iguana_info *alicecoin = LP_coinfind(swap->I.alicestr);
memset(&input20,0,sizeof(input20));
strcpy(input20.bobAddress, swap->I.etomicsrc);
uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20);
uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20);
uint8arrayToHex(input20.dealId, swap->alicepayment.I.actualtxid.bytes, 32);
strcpy(input20.tokenAddress, swap->I.alicetomic);
satoshisToWei(input20.amount, swap->I.alicesatoshis);
satoshisToWei(input20.amount, swap->I.alicerealsat);
input20.decimals = alicecoin->decimals;
strcpy(txData.from, swap->I.etomicdest);
strcpy(txData.to, ETOMIC_ALICECONTRACT);
strcpy(txData.amount, "0");
uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32);
uint64_t allowance = getErc20Allowance(swap->I.etomicdest, ETOMIC_ALICECONTRACT, swap->I.alicetomic);
if (allowance < swap->I.alicesatoshis) {
uint64_t allowance = getErc20Allowance(swap->I.etomicdest, ETOMIC_ALICECONTRACT, swap->I.alicetomic, alicecoin->decimals);
if (allowance < swap->I.alicerealsat) {
printf("Alice token allowance is too low, setting new allowance\n");
ApproveErc20Input approveErc20Input;
strcpy(approveErc20Input.tokenAddress, swap->I.alicetomic);
@ -149,20 +160,19 @@ uint8_t LP_etomic_verify_alice_payment(struct basilisk_swap *swap, char *txId)
return(0);
}
EthTxData data = getEthTxData(txId);
if (strcmp(data.to, ETOMIC_ALICECONTRACT) != 0) {
if (compareAddresses(data.to, ETOMIC_ALICECONTRACT) == 0) {
printf("Alice payment %s was sent to wrong address %s\n", txId, data.to);
return(0);
}
if (strcmp(data.from, swap->I.etomicdest) != 0) {
if (compareAddresses(data.from, swap->I.etomicdest) == 0) {
printf("Alice payment %s was done from wrong address %s\n", txId, data.from);
return(0);
}
AliceSendsEthPaymentInput input; AliceSendsErc20PaymentInput input20;
if ( strcmp(swap->I.alicestr,"ETH") == 0 ) {
uint64_t paymentAmount = weiToSatoshi(data.valueHex);
if (paymentAmount != swap->I.alicesatoshis) {
printf("Alice payment amount %" PRIu64 " does not match expected %" PRIu64 "\n", paymentAmount, swap->I.alicesatoshis);
if (paymentAmount != swap->I.alicerealsat) {
printf("Alice payment amount %" PRIu64 " does not match expected %" PRIu64 "\n", paymentAmount, swap->I.alicerealsat);
return(0);
}
memset(&input,0,sizeof(input));
@ -173,13 +183,16 @@ uint8_t LP_etomic_verify_alice_payment(struct basilisk_swap *swap, char *txId)
return(verifyAliceEthPaymentData(input, data.input));
} else {
struct iguana_info *alicecoin = LP_coinfind(swap->I.alicestr);
memset(&input20,0,sizeof(input20));
strcpy(input20.bobAddress, swap->I.etomicsrc);
uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20);
uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20);
uint8arrayToHex(input20.dealId, swap->alicepayment.I.actualtxid.bytes, 32);
strcpy(input20.tokenAddress, swap->I.alicetomic);
satoshisToWei(input20.amount, swap->I.alicesatoshis);
satoshisToWei(input20.amount, swap->I.alicerealsat);
input20.decimals = alicecoin->decimals;
return(verifyAliceErc20PaymentData(input20, data.input));
}
@ -187,11 +200,11 @@ uint8_t LP_etomic_verify_alice_payment(struct basilisk_swap *swap, char *txId)
char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->alicePaymentEthTx) < 0) {
printf("Alice ETH payment %s is not found, can't reclaim\n", swap->alicePaymentEthTx);
if (waitForConfirmation(swap->eth_tx_ids[BASILISK_ALICEPAYMENT]) < 0) {
printf("Alice ETH payment %s is not found, can't reclaim\n", swap->eth_tx_ids[BASILISK_ALICEPAYMENT]);
return NULL;
}
EthTxReceipt receipt = getEthTxReceipt(swap->alicePaymentEthTx);
EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_ALICEPAYMENT]);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Alice payment receipt status failed, can't reclaim\n");
return NULL;
@ -201,13 +214,18 @@ char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap)
memset(&txData,0,sizeof(txData));
memset(&input,0,sizeof(input));
struct iguana_info *ecoin;
struct iguana_info *ecoin, *alice_coin;
bits256 privkey;
ecoin = LP_coinfind("ETOMIC");
alice_coin = LP_coinfind(swap->dest);
privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr);
uint8arrayToHex(input.dealId, swap->txids[BASILISK_ALICEPAYMENT].bytes, 32);
satoshisToWei(input.amount, swap->destamount);
if (alicePaymentStatus(input.dealId + 2) != ALICE_PAYMENT_SENT) {
printf("Alice payment smart contract status check failed, can't spend\n");
return NULL;
}
satoshisToWei(input.amount, swap->alicerealsat);
if (swap->alicetomic[0] != 0) {
strcpy(input.tokenAddress, swap->alicetomic);
@ -223,6 +241,8 @@ char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap)
}
uint8arrayToHex(input.bobSecret, invertedSecret.bytes, 32);
input.decimals = alice_coin->decimals;
strcpy(txData.from, swap->etomicdest);
strcpy(txData.to, ETOMIC_ALICECONTRACT);
strcpy(txData.amount, "0");
@ -232,11 +252,11 @@ char *LP_etomicalice_reclaims_payment(struct LP_swap_remember *swap)
char *LP_etomicbob_spends_alice_payment(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->alicePaymentEthTx) < 0) {
printf("Alice ETH payment %s is not found, can't spend\n", swap->alicePaymentEthTx);
if (waitForConfirmation(swap->eth_tx_ids[BASILISK_ALICEPAYMENT]) < 0) {
printf("Alice ETH payment %s is not found, can't spend\n", swap->eth_tx_ids[BASILISK_ALICEPAYMENT]);
return NULL;
}
EthTxReceipt receipt = getEthTxReceipt(swap->alicePaymentEthTx);
EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_ALICEPAYMENT]);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Alice payment receipt status failed, can't spend\n");
return NULL;
@ -253,7 +273,12 @@ char *LP_etomicbob_spends_alice_payment(struct LP_swap_remember *swap)
privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr);
uint8arrayToHex(input.dealId, swap->txids[BASILISK_ALICEPAYMENT].bytes, 32);
satoshisToWei(input.amount, swap->destamount);
if (alicePaymentStatus(input.dealId + 2) != ALICE_PAYMENT_SENT) {
printf("Alice payment smart contract status check failed, can't spend\n");
return NULL;
}
satoshisToWei(input.amount, swap->alicerealsat);
if (swap->alicetomic[0] != 0) {
strcpy(input.tokenAddress, swap->alicetomic);
@ -268,6 +293,8 @@ char *LP_etomicbob_spends_alice_payment(struct LP_swap_remember *swap)
}
uint8arrayToHex(input.aliceSecret, invertedSecret.bytes, 32);
uint8arrayToHex(input.bobHash, swap->secretBn, 20);
struct iguana_info *alice_coin = LP_coinfind(swap->dest);
input.decimals = alice_coin->decimals;
strcpy(txData.from, swap->etomicsrc);
strcpy(txData.to, ETOMIC_ALICECONTRACT);
@ -292,24 +319,27 @@ char *LP_etomicbob_sends_deposit(struct basilisk_swap *swap)
strcpy(txData.from, swap->I.etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
satoshisToWei(txData.amount, swap->bobdeposit.I.amount);
satoshisToWei(txData.amount, LP_DEPOSITSATOSHIS(swap->I.bobrealsat));
uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32);
return bobSendsEthDeposit(input, txData);
} else {
struct iguana_info *bobcoin = LP_coinfind(swap->I.bobstr);
uint8arrayToHex(input20.depositId, swap->bobdeposit.I.actualtxid.bytes, 32);
strcpy(input20.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20);
satoshisToWei(input20.amount, swap->bobdeposit.I.amount);
satoshisToWei(input20.amount, LP_DEPOSITSATOSHIS(swap->I.bobrealsat));
strcpy(input20.tokenAddress, swap->I.bobtomic);
input20.lockTime = swap->bobdeposit.I.locktime;
input20.decimals = bobcoin->decimals;
strcpy(txData.from, swap->I.etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
strcpy(txData.amount, "0");
uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32);
uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic);
if (allowance < swap->bobdeposit.I.amount) {
uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic, bobcoin->decimals);
if (allowance < LP_DEPOSITSATOSHIS(swap->I.bobrealsat)) {
printf("Bob token allowance is too low, setting new allowance\n");
ApproveErc20Input approveErc20Input;
strcpy(approveErc20Input.tokenAddress, swap->I.bobtomic);
@ -337,11 +367,11 @@ uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId)
return(0);
}
EthTxData data = getEthTxData(txId);
if (strcmp(data.to, ETOMIC_BOBCONTRACT) != 0) {
if (compareAddresses(data.to, ETOMIC_BOBCONTRACT) == 0) {
printf("Bob deposit txid %s was sent to wrong address %s\n", txId, data.to);
return(0);
}
if (strcmp(data.from, swap->I.etomicsrc) != 0) {
if (compareAddresses(data.from, swap->I.etomicsrc) == 0) {
printf("Bob deposit txid %s was sent from wrong address %s\n", txId, data.from);
return(0);
}
@ -351,8 +381,8 @@ uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId)
memset(&input20,0,sizeof(input20));
if ( strcmp(swap->I.bobstr,"ETH") == 0 ) {
uint64_t depositAmount = weiToSatoshi(data.valueHex);
if (depositAmount != swap->bobdeposit.I.amount) {
printf("Bob deposit %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, depositAmount, swap->bobdeposit.I.amount);
if (depositAmount != LP_DEPOSITSATOSHIS(swap->I.bobrealsat)) {
printf("Bob deposit %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, depositAmount, LP_DEPOSITSATOSHIS(swap->I.bobrealsat));
return(0);
}
uint8arrayToHex(input.depositId, swap->bobdeposit.I.actualtxid.bytes, 32);
@ -362,12 +392,15 @@ uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId)
return verifyBobEthDepositData(input, data.input);
} else {
struct iguana_info *bobcoin = LP_coinfind(swap->I.bobstr);
uint8arrayToHex(input20.depositId, swap->bobdeposit.I.actualtxid.bytes, 32);
strcpy(input20.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input20.bobHash, swap->I.secretBn, 20);
satoshisToWei(input20.amount, swap->bobdeposit.I.amount);
satoshisToWei(input20.amount, LP_DEPOSITSATOSHIS(swap->I.bobrealsat));
strcpy(input20.tokenAddress, swap->I.bobtomic);
input20.lockTime = swap->bobdeposit.I.locktime;
input20.decimals = bobcoin->decimals;
return verifyBobErc20DepositData(input20, data.input);
}
@ -375,8 +408,8 @@ uint8_t LP_etomic_verify_bob_deposit(struct basilisk_swap *swap, char *txId)
char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->bobDepositEthTx) < 0) {
printf("Bob deposit %s is not found, can't refund\n", swap->bobDepositEthTx);
if (waitForConfirmation(swap->eth_tx_ids[BASILISK_BOBDEPOSIT]) < 0) {
printf("Bob deposit %s is not found, can't refund\n", swap->eth_tx_ids[BASILISK_BOBDEPOSIT]);
return NULL;
}
BobRefundsDepositInput input;
@ -384,17 +417,23 @@ char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap)
memset(&txData,0,sizeof(txData));
memset(&input,0,sizeof(input));
struct iguana_info *ecoin;
struct iguana_info *ecoin, *bobcoin;
bits256 privkey;
ecoin = LP_coinfind("ETOMIC");
bobcoin = LP_coinfind(swap->src);
privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr);
EthTxReceipt receipt = getEthTxReceipt(swap->bobDepositEthTx);
EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_BOBDEPOSIT]);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Bob deposit %s receipt status failed, can't refund\n", swap->bobDepositEthTx);
printf("Bob deposit %s receipt status failed, can't refund\n", swap->eth_tx_ids[BASILISK_BOBDEPOSIT]);
return NULL;
}
uint8arrayToHex(input.depositId, swap->txids[BASILISK_BOBDEPOSIT].bytes, 32);
if (bobDepositStatus(input.depositId + 2) != BOB_DEPOSIT_SENT) {
printf("Bob deposit smart contract status check failed, can't claim\n");
return NULL;
}
strcpy(input.aliceAddress, swap->etomicdest);
bits256 invertedSecret;
@ -409,7 +448,8 @@ char *LP_etomicbob_refunds_deposit(struct LP_swap_remember *swap)
} else {
strcpy(input.tokenAddress, "0x0000000000000000000000000000000000000000");
}
satoshisToWei(input.amount, swap->values[BASILISK_BOBDEPOSIT]);
satoshisToWei(input.amount, LP_DEPOSITSATOSHIS(swap->bobrealsat));
input.decimals = bobcoin->decimals;
strcpy(txData.from, swap->etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
@ -435,24 +475,27 @@ char *LP_etomicbob_sends_payment(struct basilisk_swap *swap)
strcpy(txData.from, swap->I.etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
satoshisToWei(txData.amount, swap->bobpayment.I.amount);
satoshisToWei(txData.amount, swap->I.bobrealsat);
uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32);
return bobSendsEthPayment(input, txData);
} else {
struct iguana_info *bobcoin = LP_coinfind(swap->I.bobstr);
uint8arrayToHex(input20.paymentId, swap->bobpayment.I.actualtxid.bytes, 32);
strcpy(input20.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20);
satoshisToWei(input20.amount, swap->bobpayment.I.amount);
satoshisToWei(input20.amount, swap->I.bobrealsat);
strcpy(input20.tokenAddress, swap->I.bobtomic);
input20.lockTime = swap->bobpayment.I.locktime;
input20.decimals = bobcoin->decimals;
strcpy(txData.from, swap->I.etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
strcpy(txData.amount, "0");
uint8arrayToHex(txData.secretKey, swap->persistent_privkey.bytes, 32);
uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic);
if (allowance < swap->bobpayment.I.amount) {
uint64_t allowance = getErc20Allowance(swap->I.etomicsrc, ETOMIC_BOBCONTRACT, swap->I.bobtomic, bobcoin->decimals);
if (allowance < swap->I.bobrealsat) {
printf("Bob token allowance is too low, setting new allowance\n");
ApproveErc20Input approveErc20Input;
strcpy(approveErc20Input.tokenAddress, swap->I.bobtomic);
@ -480,21 +523,20 @@ uint8_t LP_etomic_verify_bob_payment(struct basilisk_swap *swap, char *txId)
return 0;
}
EthTxData data = getEthTxData(txId);
if (strcmp(data.to, ETOMIC_BOBCONTRACT) != 0) {
if (compareAddresses(data.to, ETOMIC_BOBCONTRACT) == 0) {
printf("Bob payment %s was sent to wrong address %s\n", txId, data.to);
}
if (strcmp(data.from, swap->I.etomicsrc) != 0) {
if (compareAddresses(data.from, swap->I.etomicsrc) == 0) {
printf("Bob payment %s was sent from wrong address %s\n", txId, data.from);
}
BobSendsEthPaymentInput input;
BobSendsErc20PaymentInput input20;
memset(&input,0,sizeof(input));
memset(&input20,0,sizeof(input20));
if ( strcmp(swap->I.bobstr,"ETH") == 0 ) {
uint64_t paymentAmount = weiToSatoshi(data.valueHex);
if (paymentAmount != swap->bobpayment.I.amount) {
printf("Bob payment %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, paymentAmount, swap->bobpayment.I.amount);
if (paymentAmount != swap->I.bobrealsat) {
printf("Bob payment %s amount %" PRIu64 " != expected %" PRIu64 "\n", txId, paymentAmount, swap->I.bobrealsat);
return(0);
}
uint8arrayToHex(input.paymentId, swap->bobpayment.I.actualtxid.bytes, 32);
@ -504,12 +546,15 @@ uint8_t LP_etomic_verify_bob_payment(struct basilisk_swap *swap, char *txId)
return verifyBobEthPaymentData(input, data.input);
} else {
struct iguana_info *bobcoin = LP_coinfind(swap->I.bobstr);
uint8arrayToHex(input20.paymentId, swap->bobpayment.I.actualtxid.bytes, 32);
strcpy(input20.aliceAddress, swap->I.etomicdest);
uint8arrayToHex(input20.aliceHash, swap->I.secretAm, 20);
satoshisToWei(input20.amount, swap->bobpayment.I.amount);
satoshisToWei(input20.amount, swap->I.bobrealsat);
strcpy(input20.tokenAddress, swap->I.bobtomic);
input20.lockTime = swap->bobpayment.I.locktime;
input20.decimals = bobcoin->decimals;
return verifyBobErc20PaymentData(input20, data.input);
}
@ -517,8 +562,8 @@ uint8_t LP_etomic_verify_bob_payment(struct basilisk_swap *swap, char *txId)
char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->bobPaymentEthTx) < 0) {
printf("Bob payment %s is not found, can't reclaim\n", swap->bobPaymentEthTx);
if (waitForConfirmation(swap->eth_tx_ids[BASILISK_BOBPAYMENT]) < 0) {
printf("Bob payment %s is not found, can't reclaim\n", swap->eth_tx_ids[BASILISK_BOBPAYMENT]);
return NULL;
}
BobReclaimsBobPaymentInput input;
@ -526,17 +571,22 @@ char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap)
memset(&txData,0,sizeof(txData));
memset(&input,0,sizeof(input));
struct iguana_info *ecoin;
struct iguana_info *ecoin, *bobcoin;
bits256 privkey;
ecoin = LP_coinfind("ETOMIC");
bobcoin = LP_coinfind(swap->src);
privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr);
EthTxReceipt receipt = getEthTxReceipt(swap->bobPaymentEthTx);
EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_BOBPAYMENT]);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Bob payment receipt status failed, can't reclaim\n");
return NULL;
}
uint8arrayToHex(input.paymentId, swap->txids[BASILISK_BOBPAYMENT].bytes, 32);
if (bobPaymentStatus(input.paymentId + 2) != BOB_PAYMENT_SENT) {
printf("Bob payment smart contract status check failed, can't spend\n");
return NULL;
}
strcpy(input.aliceAddress, swap->etomicdest);
uint8arrayToHex(input.aliceHash, swap->secretAm, 20);
@ -545,7 +595,8 @@ char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap)
} else {
strcpy(input.tokenAddress, "0x0000000000000000000000000000000000000000");
}
satoshisToWei(input.amount, swap->values[BASILISK_BOBPAYMENT]);
satoshisToWei(input.amount, swap->bobrealsat);
input.decimals = bobcoin->decimals;
strcpy(txData.from, swap->etomicsrc);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
@ -556,8 +607,8 @@ char *LP_etomicbob_reclaims_payment(struct LP_swap_remember *swap)
char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->bobPaymentEthTx) < 0) {
printf("Bob payment %s is not found, can't spend\n", swap->bobPaymentEthTx);
if (waitForConfirmation(swap->eth_tx_ids[BASILISK_BOBPAYMENT]) < 0) {
printf("Bob payment %s is not found, can't spend\n", swap->eth_tx_ids[BASILISK_BOBPAYMENT]);
return NULL;
}
AliceSpendsBobPaymentInput input;
@ -565,18 +616,23 @@ char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap)
memset(&txData,0,sizeof(txData));
memset(&input,0,sizeof(input));
EthTxReceipt receipt = getEthTxReceipt(swap->bobPaymentEthTx);
EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_BOBPAYMENT]);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Bob payment %s receipt status failed, can't spend\n", swap->bobPaymentEthTx);
printf("Bob payment %s receipt status failed, can't spend\n", swap->eth_tx_ids[BASILISK_BOBPAYMENT]);
return NULL;
}
struct iguana_info *ecoin;
struct iguana_info *ecoin, *bobcoin;
bits256 privkey;
ecoin = LP_coinfind("ETOMIC");
bobcoin = LP_coinfind(swap->src);
privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr);
uint8arrayToHex(input.paymentId, swap->txids[BASILISK_BOBPAYMENT].bytes, 32);
satoshisToWei(input.amount, swap->values[BASILISK_BOBPAYMENT]);
if (bobPaymentStatus(input.paymentId + 2) != BOB_PAYMENT_SENT) {
printf("Bob payment smart contract status check failed, can't spend\n");
return NULL;
}
satoshisToWei(input.amount, swap->bobrealsat);
if (swap->bobtomic[0] != 0) {
strcpy(input.tokenAddress, swap->bobtomic);
@ -591,6 +647,7 @@ char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap)
invertedSecret.bytes[i] = swap->privAm.bytes[31 - i];
}
uint8arrayToHex(input.aliceSecret, invertedSecret.bytes, 32);
input.decimals = bobcoin->decimals;
strcpy(txData.from, swap->etomicdest);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
@ -601,8 +658,8 @@ char *LP_etomicalice_spends_bob_payment(struct LP_swap_remember *swap)
char *LP_etomicalice_claims_bob_deposit(struct LP_swap_remember *swap)
{
if (waitForConfirmation(swap->bobDepositEthTx) < 0) {
printf("Bob deposit %s is not found, can't claim\n", swap->bobDepositEthTx);
if (waitForConfirmation(swap->eth_tx_ids[BASILISK_BOBDEPOSIT]) < 0) {
printf("Bob deposit %s is not found, can't claim\n", swap->eth_tx_ids[BASILISK_BOBDEPOSIT]);
return NULL;
}
AliceClaimsBobDepositInput input;
@ -610,19 +667,25 @@ char *LP_etomicalice_claims_bob_deposit(struct LP_swap_remember *swap)
memset(&txData,0,sizeof(txData));
memset(&input,0,sizeof(input));
EthTxReceipt receipt = getEthTxReceipt(swap->bobDepositEthTx);
EthTxReceipt receipt = getEthTxReceipt(swap->eth_tx_ids[BASILISK_BOBDEPOSIT]);
if (strcmp(receipt.status, "0x1") != 0) {
printf("Bob deposit receipt status failed, can't claim\n");
return NULL;
}
struct iguana_info *ecoin;
struct iguana_info *ecoin, *bobcoin;
bits256 privkey;
ecoin = LP_coinfind("ETOMIC");
bobcoin = LP_coinfind(swap->src);
privkey = LP_privkey(ecoin->symbol, ecoin->smartaddr, ecoin->taddr);
uint8arrayToHex(input.depositId, swap->txids[BASILISK_BOBDEPOSIT].bytes, 32);
satoshisToWei(input.amount, swap->values[BASILISK_BOBDEPOSIT]);
if (bobDepositStatus(input.depositId + 2) != BOB_DEPOSIT_SENT) {
printf("Bob deposit smart contract status check failed, can't claim\n");
return NULL;
}
satoshisToWei(input.amount, LP_DEPOSITSATOSHIS(swap->bobrealsat));
if (swap->bobtomic[0] != 0) {
strcpy(input.tokenAddress, swap->bobtomic);
@ -632,6 +695,7 @@ char *LP_etomicalice_claims_bob_deposit(struct LP_swap_remember *swap)
strcpy(input.bobAddress, swap->etomicsrc);
uint8arrayToHex(input.bobHash, swap->secretBn, 20);
input.decimals = bobcoin->decimals;
strcpy(txData.from, swap->etomicdest);
strcpy(txData.to, ETOMIC_BOBCONTRACT);
@ -702,13 +766,13 @@ int32_t LP_etomic_pub2addr(char *coinaddr,uint8_t pub64[64])
uint8_t LP_etomic_is_empty_tx_id(char *txId)
{
if (strcmp(txId, EMPTY_ETH_TX_ID) == 0) {
if (txId[0] == 0 || strcmp(txId, EMPTY_ETH_TX_ID) == 0) {
return 1;
}
return 0;
}
uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr)
uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr, int *error)
{
if (coin->etomic[0] == 0) {
printf("Trying to get etomic balance for non-etomic coin %s!", coin->symbol);
@ -716,8 +780,8 @@ uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr)
}
if (strcmp(coin->symbol, "ETH") == 0) {
return getEthBalance(coinaddr);
return getEthBalance(coinaddr, error);
} else {
return getErc20BalanceSatoshi(coinaddr, coin->etomic);
return getErc20BalanceSatoshi(coinaddr, coin->etomic, coin->decimals, error);
}
}

2
iguana/exchanges/LP_etomic.h

@ -49,7 +49,7 @@ int32_t LP_etomic_pub2addr(char *coinaddr,uint8_t pub64[64]);
uint8_t LP_etomic_is_empty_tx_id(char *txId);
uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr);
uint64_t LP_etomic_get_balance(struct iguana_info *coin, char *coinaddr, int *error);
void LP_etomic_pubkeystr_to_addr(char *pubkey, char *output);

44
iguana/exchanges/LP_include.h

@ -59,7 +59,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
//#define LP_DISABLE_DISTCOMBINE
#define LP_MAXVINS 64
#define LP_HTTP_TIMEOUT 3 // 1 is too small due to edge cases of time(NULL)
#define LP_HTTP_TIMEOUT 10 // 1 is too small due to edge cases of time(NULL)
#define LP_AUTOTRADE_TIMEOUT 30
#define LP_RESERVETIME (LP_AUTOTRADE_TIMEOUT * 3)
#define ELECTRUM_TIMEOUT 13
@ -206,7 +206,7 @@ struct basilisk_rawtxinfo
{
char destaddr[64],ethTxid[75];
bits256 txid,signedtxid,actualtxid;
int64_t amount,change,inputsum;
int64_t amount,change,inputsum,eth_amount;
int32_t redeemlen,datalen,completed,vintype,vouttype,numconfirms,spendlen,secretstart,suppress_pubkeys;
uint32_t locktime,crcs[2];
uint8_t addrtype,pubkey33[33],rmd160[20];
@ -220,7 +220,7 @@ struct basilisk_request
bits256 desthash;
char src[68],dest[68];
uint64_t destamount;
int32_t optionhours,DEXselector;
uint32_t optionhours,DEXselector;
};
struct basilisk_rawtx
@ -241,7 +241,7 @@ struct basilisk_swapinfo
bits256 myhash,otherhash,orderhash;
uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration;
int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad,aliceistrusted,bobistrusted,otheristrusted,otherstrust,alicemaxconfirms,bobmaxconfirms;
int64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee;
int64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance,Atxfee,Btxfee,alicerealsat,bobrealsat;
bits256 myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn;
uint32_t crcs_mypub[2],crcs_mychoosei[2],crcs_myprivs[2],crcs_mypriv[2];
@ -256,29 +256,31 @@ struct basilisk_swapinfo
uint8_t userdata_bobrefund[256],userdata_bobrefundlen;
};
#define BASILISK_ALICESPEND 0
#define BASILISK_BOBSPEND 1
#define BASILISK_BOBPAYMENT 2
#define BASILISK_MYFEE 0
#define BASILISK_OTHERFEE 1
#define BASILISK_BOBDEPOSIT 2
#define BASILISK_ALICEPAYMENT 3
#define BASILISK_BOBDEPOSIT 4
#define BASILISK_OTHERFEE 5
#define BASILISK_MYFEE 6
#define BASILISK_BOBPAYMENT 4
#define BASILISK_ALICESPEND 5
#define BASILISK_BOBSPEND 6
#define BASILISK_BOBREFUND 7
#define BASILISK_BOBRECLAIM 8
#define BASILISK_ALICERECLAIM 9
#define BASILISK_ALICECLAIM 10
//0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0
static char *txnames[] = { "alicespend", "bobspend", "bobpayment", "alicepayment", "bobdeposit", "otherfee", "myfee", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" };
static char *txnames[] = { "myfee", "otherfee", "bobdeposit", "alicepayment", "bobpayment", "alicespend", "bobspend", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" };
struct LP_swap_remember
{
bits256 pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)];
uint64_t Atxfee,Btxfee,srcamount,destamount,aliceid;
uint64_t Atxfee,Btxfee,srcamount,destamount,aliceid,alicerealsat,bobrealsat;
int64_t values[sizeof(txnames)/sizeof(*txnames)];
uint32_t finishtime,tradeid,requestid,quoteid,plocktime,dlocktime,expiration,state,otherstate;
int32_t iambob,finishedflag,origfinishedflag,Predeemlen,Dredeemlen,sentflags[sizeof(txnames)/sizeof(*txnames)];
uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],Predeemscript[1024],Dredeemscript[1024],pubkey33[33],other33[33];
char uuidstr[65],Agui[65],Bgui[65],gui[65],src[65],dest[65],bobtomic[128],alicetomic[128],etomicsrc[65],etomicdest[65],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[65],bobcoin[65],*txbytes[sizeof(txnames)/sizeof(*txnames)],bobDepositEthTx[75],bobPaymentEthTx[75],alicePaymentEthTx[75];
char uuidstr[65],Agui[65],Bgui[65],gui[65],src[65],dest[65],bobtomic[128],alicetomic[128],etomicsrc[65],etomicdest[65],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[65],bobcoin[65],*txbytes[sizeof(txnames)/sizeof(*txnames)];
char eth_tx_ids[sizeof(txnames)/sizeof(*txnames)][75];
int64_t eth_values[sizeof(txnames)/sizeof(*txnames)];
};
struct LP_outpoint
@ -303,7 +305,7 @@ struct iguana_info
{
UT_hash_handle hh;
portable_mutex_t txmutex,addrmutex,addressutxo_mutex; struct LP_transaction *transactions; struct LP_address *addresses;
uint64_t txfee;
uint64_t txfee,do_autofill_merge;
int32_t numutxos,notarized,longestchain,firstrefht,firstscanht,lastscanht,height; uint16_t busport,did_addrutxo_reset;
uint32_t txversion,dPoWtime,lastautosplit,lastresetutxo,loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms;
@ -311,9 +313,10 @@ struct iguana_info
// portfolio
double price_kmd,force,perc,goal,goalperc,relvolume,rate;
void *electrum; void *ctx;
uint64_t maxamount,kmd_equiv,balanceA,balanceB,valuesumA,valuesumB;
uint8_t pubkey33[33],zcash;
int32_t privkeydepth;
uint64_t maxamount,kmd_equiv,balanceA,balanceB,valuesumA,valuesumB,fillsatoshis;
uint8_t pubkey33[33],zcash,decimals;
int32_t privkeydepth,bobfillheight;
void *curl_handle; portable_mutex_t curl_mutex;
bits256 cachedtxid,notarizationtxid; uint8_t *cachedtxiddata; int32_t cachedtxidlen;
bits256 cachedmerkle,notarizedhash; int32_t cachedmerkleheight;
};
@ -377,9 +380,10 @@ struct LP_quoteinfo
{
struct basilisk_request R;
bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey;
double maxprice;
int64_t othercredits;
uint64_t satoshis,txfee,destsatoshis,desttxfee,aliceid;
uint32_t timestamp,quotetime,tradeid;
uint32_t timestamp,quotetime,tradeid,gtc,fill,mpnet;
int32_t vout,vout2,destvout,feevout,pair;
char srccoin[65],coinaddr[64],destcoin[65],destaddr[64],gui[64],etomicsrc[65],etomicdest[65],uuidstr[65];
};
@ -427,7 +431,7 @@ struct LP_swapstats
struct LP_pubswap { struct LP_pubswap *next,*prev; struct LP_swapstats *swap; };
#define LP_MAXPRICEINFOS 256
#define LP_MAXPRICEINFOS 255
struct LP_pubkey_info
{
UT_hash_handle hh;
@ -531,6 +535,7 @@ void HashKeccak(uint8_t *hash,void *data,size_t len);
void test_validate(struct iguana_info *coin,char *signedtx);
void LP_instantdex_depositadd(char *coinaddr,bits256 txid);
int64_t LP_instantdex_creditcalc(struct iguana_info *coin,int32_t dispflag,bits256 txid,char *refaddr,char *origcoinaddr);
char *LP_autofillbob(struct iguana_info *coin,uint64_t satoshis);
void LP_ports(uint16_t *pullportp,uint16_t *pubportp,uint16_t *busportp,uint16_t netid);
int32_t LP_destaddr(char *destaddr,cJSON *item);
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration);
@ -580,6 +585,7 @@ int32_t LP_trades_canceluuid(char *uuidstr);
int _decreasing_uint64(const void *a,const void *b);
int32_t LP_alice_eligible(uint32_t quotetime);
int32_t LP_is_slowcoin(char *symbol);
void LP_alicequery_clear();
void LP_listunspent_query(char *symbol,char *coinaddr);
int32_t bitcoin_priv2wif(char *symbol,uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8_t addrtype);

6
iguana/exchanges/LP_instantdex.c

@ -639,7 +639,7 @@ int64_t LP_dynamictrust(int64_t credits,bits256 pubkey,int64_t kmdvalue)
printf("unfinished alice %llu r%u-r%u src.%s %.8f dest.%s %.8f -> price %.8f value %.8f\n",(long long)sp->aliceid,sp->Q.R.requestid,sp->Q.R.quoteid,sp->Q.srccoin,dstr(sp->Q.satoshis),sp->Q.destcoin,dstr(sp->Q.destsatoshis),(double)sp->Q.destsatoshis/(sp->Q.satoshis+1),dstr(LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis)));
}
}
//printf("REJECT: %s instantdex_credits %.8f vs (%.8f + current %.8f)\n",coinaddr,dstr(credits),dstr(swaps_kmdvalue),dstr(kmdvalue));
printf("REJECT: %s instantdex_credits %.8f vs (%.8f + current %.8f)\n",coinaddr,dstr(credits),dstr(swaps_kmdvalue),dstr(kmdvalue));
}
if ( 0 && credits != 0 )
printf("%s %s othercredits %.8f debits %.8f + %.8f -> %.8f\n",coin->symbol,coinaddr,dstr(credits),dstr(swaps_kmdvalue),dstr(kmdvalue),dstr(credits - (swaps_kmdvalue+kmdvalue)));
@ -679,9 +679,9 @@ int64_t LP_instantdex_proofcheck(char *symbol,char *coinaddr,cJSON *proof,int32_
credits = ap->instantdex_credits;
ap->didinstantdex = 1;
ap->instantdextime = (uint32_t)time(NULL);
if ( 0 && ap->instantdex_credits > 0 )
if ( 1 && ap->instantdex_credits > 0 )
printf("validated instantdex %s.[%d] proof.(%s) credits %.8f\n",othersmartaddr,num,jprint(proof,0),dstr(ap->instantdex_credits));
} //else printf("cant find ap.%p or already did %d %.8f\n",ap,ap!=0?ap->didinstantdex:-1,ap!=0?dstr(ap->instantdex_credits):-1);
} else printf("cant find ap.%p or already did %d %.8f\n",ap,ap!=0?ap->didinstantdex:-1,ap!=0?dstr(ap->instantdex_credits):-1);
}
return(credits);
}

6
iguana/exchanges/LP_mmjson.c

@ -259,7 +259,11 @@ int32_t MMJSON_decodeitem(cJSON *lineobj,uint8_t *linebuf,int32_t i,int32_t len,
arbstr[j++] = c;
}
arbstr[j] = 0;
jaddstr(lineobj,fieldstr,arbstr);
if (strcmp(fieldstr, "txChain") == 0) {
cJSON_AddItemToObject(lineobj, fieldstr, cJSON_Parse(arbstr));
} else {
jaddstr(lineobj, fieldstr, arbstr);
}
break;
default:
if ( valind < MMJSON_BOUNDARY )

254
iguana/exchanges/LP_mpnet.c

@ -0,0 +1,254 @@
/******************************************************************************
* Copyright © 2014-2018 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
//
// LP_mpnet.c
// marketmaker
//
bits256 MPNET_txids[1024];
int32_t num_MPNET_txids;
int32_t LP_tradecommand(int32_t from_mpnet,void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen);
int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson);
void LP_gtc_addorder(struct LP_quoteinfo *qp);
char *LP_withdraw(struct iguana_info *coin,cJSON *argjson);
int32_t LP_mpnet_find(bits256 txid)
{
int32_t i;
for (i=0; i<num_MPNET_txids; i++)
if ( bits256_cmp(txid,MPNET_txids[i]) == 0 )
return(i);
return(-1);
}
int32_t LP_mpnet_add(bits256 txid)
{
if ( num_MPNET_txids < sizeof(MPNET_txids)/sizeof(*MPNET_txids) )
{
MPNET_txids[num_MPNET_txids++] = txid;
return(num_MPNET_txids);
}
printf("MPNET_txids[] overflow\n");
return(-1);
}
int32_t LP_mpnet_remove(bits256 txid)
{
int32_t i;
if ( (i= LP_mpnet_find(txid)) >= 0 )
{
MPNET_txids[i] = MPNET_txids[--num_MPNET_txids];
return(i);
}
return(-1);
}
int32_t LP_mpnet_addorder(struct LP_quoteinfo *qp)
{
uint64_t destvalue,destvalue2;
if ( LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) > 0 )
{
LP_gtc_addorder(qp);
return(0);
}
return(-1);
}
void LP_mpnet_init() // problem is coins not enabled yet
{
char fname[1024],line[8192]; FILE *fp; struct LP_quoteinfo Q; cJSON *argjson;
sprintf(fname,"%s/GTC/orders",GLOBAL_DBDIR), OS_compatible_path(fname);
if ( (fp= fopen(fname,"rb+")) != 0 )
{
while ( fgets(line,sizeof(line),fp) > 0 )
{
if ( (argjson= cJSON_Parse(line)) != 0 )
{
if ( LP_quoteparse(&Q,argjson) == 0 )
{
if ( LP_mpnet_addorder(&Q) == 0 )
printf("GTC %s",line);
}
free_json(argjson);
}
}
fclose(fp);
}
}
void LP_mpnet_send(int32_t localcopy,char *msg,int32_t sendflag,char *otheraddr)
{
char fname[1024]; int32_t len; FILE *fp; char *hexstr,*retstr; cJSON *argjson,*outputs,*item; struct iguana_info *coin; uint8_t linebuf[8192];
if ( localcopy != 0 )
{
sprintf(fname,"%s/GTC/orders",GLOBAL_DBDIR), OS_compatible_path(fname);
if ( (fp= fopen(fname,"rb+")) == 0 )
fp = fopen(fname,"wb+");
else fseek(fp,0,SEEK_END);
fprintf(fp,"%s\n",msg);
fclose(fp);
}
if ( G.mpnet != 0 && sendflag != 0 && (coin= LP_coinfind("CHIPS")) != 0 && coin->inactive == 0 )
{
len = MMJSON_encode(linebuf,msg);
//curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"withdraw\",\"coin\":\"CHIPS\",\"outputs\":[{\"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj\":0.0001}],\"opreturn\":\"deadbeef\"}"
if ( len > 0 )
{
argjson = cJSON_CreateObject();
outputs = cJSON_CreateArray();
if ( otheraddr != 0 && otheraddr[0] != 0 )
{
item = cJSON_CreateObject();
jaddnum(item,otheraddr,dstr(10000));
jaddi(outputs,item);
}
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,dstr(10000));
jaddi(outputs,item);
jadd(argjson,"outputs",outputs);
jaddnum(argjson,"broadcast",1);
jaddstr(argjson,"coin",coin->symbol);
hexstr = calloc(1,len*2 + 1);
init_hexbytes_noT(hexstr,linebuf,len);
jaddstr(argjson,"opreturn",hexstr);
free(hexstr);
retstr = LP_withdraw(coin,argjson);
free_json(argjson);
if ( retstr != 0 )
{
//printf("mpnet.%s\n",retstr);
free(retstr);
}
}
}
}
cJSON *LP_mpnet_parse(struct iguana_info *coin,bits256 txid)
{
cJSON *txobj,*vouts,*sobj,*argjson = 0; char *decodestr,*hexstr; uint8_t *buf,linebuf[8192]; int32_t len,n,hlen;
if ( (txobj= LP_gettx("mpnet",coin->symbol,txid,0)) != 0 )
{
if ( (vouts= jarray(&n,txobj,"vout")) != 0 )
{
if ( (sobj= jobj(jitem(vouts,n-1),"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && (hlen= strlen(hexstr)) < sizeof(linebuf)*2 )
{
len = (hlen >> 1);
decode_hex(linebuf,len,hexstr);
buf = linebuf;
//printf("hexstr.(%s)\n",hexstr);
if ( *buf == 0x6a )
{
buf++, len--;
if ( *buf == 0x4d )
{
buf++, len--;
n = buf[0] + buf[1]*256;
buf += 2, len -= 2;
if ( n == len )
{
if ( (decodestr= MMJSON_decode(buf,len)) != 0 )
argjson = cJSON_Parse(decodestr);
}
}
}
if ( 0 && argjson == 0 )
printf("unhandled case.(%s)\n",hexstr);
}
}
if ( 0 && argjson == 0 )
printf("unhandled tx.(%s)\n",jprint(txobj,0));
free_json(txobj);
}
return(argjson);
}
// 2151978
// 404bc4ac452db07ed16376b3d7e77dbfc22b4a68f7243797125bd0d3bdddf8d1
// 893b46634456034a6d5d73b67026aa157b5e2addbfc6344dfbea6bae85f7dde0
// 717c7ef9de8504bd331f3ef52ed0a16ea0e070434e12cb4d63f5f081e999c43d dup
void LP_mpnet_process(void *ctx,char *myipaddr,int32_t pubsock,struct iguana_info *coin,bits256 txid)
{
cJSON *argjson; char str[65];
if ( LP_mpnet_find(txid) < 0 )
{
//printf("unique %s\n",bits256_str(str,txid));
if ( (argjson= LP_mpnet_parse(coin,txid)) != 0 )
{
//printf("MPNET.(%s)\n",jprint(argjson,0));
LP_tradecommand(1,ctx,myipaddr,pubsock,argjson,0,0);
free_json(argjson);
}
LP_mpnet_add(txid);
}
}
cJSON *LP_mpnet_get(void *ctx,char *myipaddr,int32_t pubsock,struct iguana_info *coin)
{
static int32_t lastheight; static bits256 lasthash;
int32_t i,n=0,numtx,checkht = 0,height = 0; bits256 latesthash,hash,txid,zero; char hashstr[65],str[65]; cJSON *txs,*blockjson;
memset(zero.bytes,0,sizeof(zero));
latesthash = LP_getbestblockhash(coin);
bits256_str(hashstr,latesthash);
if ( (blockjson= LP_blockjson(&checkht,coin->symbol,hashstr,0)) != 0 )
{
hash = latesthash;
while ( bits256_cmp(lasthash,hash) != 0 && n++ < 3 )
{
if ( (txs= jarray(&numtx,blockjson,"tx")) != 0 )
{
for (i=0; i<numtx; i++)
{
txid = jbits256i(txs,i);
LP_mpnet_process(ctx,myipaddr,pubsock,coin,txid);
LP_mpnet_remove(txid);
//printf("ht.%d n.%d i.%d %s\n",checkht,n,i,bits256_str(str,txid));
}
}
hash = jbits256(blockjson,"previousblockhash");
free_json(blockjson);
bits256_str(hashstr,hash);
if ( (blockjson= LP_blockjson(&checkht,coin->symbol,hashstr,0)) == 0 )
break;
}
lasthash = latesthash;
if ( blockjson != 0 )
free_json(blockjson);
if ( (txs= LP_getmempool(coin->symbol,coin->smartaddr,zero,zero)) != 0 )
{
numtx = cJSON_GetArraySize(txs);
for (i=0; i<numtx; i++)
{
txid = jbits256i(txs,i);
LP_mpnet_process(ctx,myipaddr,pubsock,coin,txid);
//printf("mp i.%d %s\n",i,bits256_str(str,txid));
}
}
}
return(0);
}
void LP_mpnet_check(void *ctx,char *myipaddr,int32_t pubsock)
{
static uint32_t lasttime;
struct iguana_info *coin = LP_coinfind("CHIPS");
if ( coin != 0 && coin->inactive == 0 && time(NULL) > lasttime+5 )
{
LP_mpnet_get(ctx,myipaddr,pubsock,coin);
lasttime = (uint32_t)time(NULL);
}
}

69
iguana/exchanges/LP_nativeDEX.c

@ -30,6 +30,9 @@
// there is an issue about waiting for notarization for a swap that never starts (expiration ok)
#include <stdio.h>
#ifndef MM_VERSION
#define MM_VERSION "UNKNOWN"
#endif
long LP_cjson_allocated,LP_cjson_total,LP_cjson_count;
@ -90,7 +93,7 @@ void LP_millistats_update(struct LP_millistats *mp)
#include "LP_etomic.h"
#endif
portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex,LP_cJSONmutex,LP_logmutex,LP_statslogmutex,LP_tradesmutex,LP_commandQmutex,LP_blockinit_mutex,LP_pendswap_mutex,LP_listmutex;
portable_mutex_t LP_peermutex,LP_UTXOmutex,LP_utxomutex,LP_commandmutex,LP_cachemutex,LP_swaplistmutex,LP_forwardmutex,LP_pubkeymutex,LP_networkmutex,LP_psockmutex,LP_coinmutex,LP_messagemutex,LP_portfoliomutex,LP_electrummutex,LP_butxomutex,LP_reservedmutex,LP_nanorecvsmutex,LP_tradebotsmutex,LP_gcmutex,LP_inusemutex,LP_cJSONmutex,LP_logmutex,LP_statslogmutex,LP_tradesmutex,LP_commandQmutex,LP_blockinit_mutex,LP_pendswap_mutex,LP_listmutex,LP_gtcmutex;
int32_t LP_canbind;
char *Broadcaststr,*Reserved_msgs[2][1000];
int32_t num_Reserved_msgs[2],max_Reserved_msgs[2];
@ -117,10 +120,10 @@ struct LP_globals
{
//struct LP_utxoinfo *LP_utxoinfos[2],*LP_utxoinfos2[2];
bits256 LP_mypub25519,LP_privkey,LP_mypriv25519,LP_passhash;
uint64_t LP_skipstatus[10000];
uint64_t LP_skipstatus[10000], LP_required_etomic_balance;
uint16_t netid;
uint8_t LP_myrmd160[20],LP_pubsecp[33];
uint32_t LP_sessionid,counter;
uint32_t LP_sessionid,counter,mpnet;
int32_t LP_IAMLP,LP_pendingswaps,USERPASS_COUNTER,LP_numprivkeys,initializing,waiting,LP_numskips;
char seednode[64],USERPASS[65],USERPASS_WIFSTR[64],LP_myrmd160str[41],gui[65],LP_NXTaddr[64];
struct LP_privkey LP_privkeys[100];
@ -176,6 +179,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
#include "LP_bitcoin.c"
#include "LP_coins.c"
#include "LP_rpc.c"
#include "LP_mpnet.c"
#include "LP_NXT.c"
#include "LP_cache.c"
#include "LP_RTmetrics.c"
@ -202,7 +206,7 @@ char *LP_command_process(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson
char *retstr=0; cJSON *retjson; bits256 zero;
if ( jobj(argjson,"result") != 0 || jobj(argjson,"error") != 0 )
return(0);
if ( stats_JSONonly != 0 || LP_tradecommand(ctx,myipaddr,pubsock,argjson,data,datalen) <= 0 )
if ( stats_JSONonly != 0 || LP_tradecommand(0,ctx,myipaddr,pubsock,argjson,data,datalen) <= 0 )
{
if ( (retstr= stats_JSON(ctx,0,myipaddr,pubsock,argjson,"127.0.0.1",stats_JSONonly)) != 0 )
{
@ -423,7 +427,7 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
/*if ( (argjson= cJSON_Parse(str)) != 0 )
{
//portable_mutex_lock(&LP_commandmutex);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 )
if ( LP_tradecommand(0,ctx,myipaddr,pubsock,argjson,0,0) <= 0 )
{
if ( (retstr= stats_JSON(ctx,0,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 )
free(retstr);
@ -480,6 +484,8 @@ int32_t LP_nanomsg_recvs(void *ctx)
nonz += LP_sock_check("PULL",ctx,origipaddr,-1,LP_mypullsock,"127.0.0.1",1);
}
portable_mutex_unlock(&LP_nanorecvsmutex);
//if ( G.mpnet != 0 )
LP_mpnet_check(ctx,origipaddr,LP_mypubsock);
return(nonz);
}
@ -513,21 +519,21 @@ void command_rpcloop(void *ctx)
void LP_coinsloop(void *_coins)
{
static int32_t didfilescreate;
struct LP_address *ap=0; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65]; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t notarized,oldht,j,nonz; char *coins = _coins;
struct LP_address *ap=0; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65],*retstr,*hexstr,*txidstr; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t notarized,oldht,j,nonz; char *coins = _coins;
if ( strcmp("BTC",coins) == 0 )
{
strcpy(LP_coinsloopBTC_stats.name,"BTC coin loop");
LP_coinsloopBTC_stats.threshold = 20000.;
LP_coinsloopBTC_stats.threshold = 200000.;
}
else if ( strcmp("KMD",coins) == 0 )
{
strcpy(LP_coinsloopKMD_stats.name,"KMD coin loop");
LP_coinsloopKMD_stats.threshold = 10000.;
LP_coinsloopKMD_stats.threshold = 100000.;
}
else
{
strcpy(LP_coinsloop_stats.name,"other coins loop");
LP_coinsloop_stats.threshold = 5000.;
LP_coinsloop_stats.threshold = 50000.;
}
while ( LP_STOP_RECEIVED == 0 )
{
@ -576,6 +582,29 @@ void LP_coinsloop(void *_coins)
LP_address_utxo_reset(&num,coin);
coin->did_addrutxo_reset = 1;
}
//free_json(LP_address_balance(coin,coin->smartaddr,1)); expensive invoking gettxout
if ( coin->do_autofill_merge != 0 )
{
if ( (retstr= LP_autofillbob(coin,coin->do_autofill_merge*1.02)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (hexstr= jstr(retjson,"hex")) != 0 )
{
if ( (txidstr= LP_sendrawtransaction(coin->symbol,hexstr,0)) != 0 )
{
printf("autofill created %s\n",txidstr);
free(txidstr);
coin->fillsatoshis = coin->do_autofill_merge;
coin->do_autofill_merge = 0;
coin->bobfillheight = LP_getheight(&notarized,coin);
}
}
free_json(retjson);
}
free(retstr);
}
}
if ( coin->longestchain == 1 ) // special init value
coin->longestchain = LP_getheight(&notarized,coin);
if ( (ep= coin->electrum) != 0 )
@ -656,6 +685,7 @@ void LP_coinsloop(void *_coins)
continue;
}
//if ( strcmp(coin->symbol,"BTC") != 0 && strcmp(coin->symbol,"KMD") != 0 ) // SPV as backup
if ( coin->lastscanht < coin->longestchain )
{
nonz++;
if ( strcmp("BTC",coins) == 0 )//&& coin->lastscanht < coin->longestchain-3 )
@ -664,7 +694,7 @@ void LP_coinsloop(void *_coins)
{
if ( LP_blockinit(coin,coin->lastscanht) < 0 )
{
printf("pleae ignore this blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
printf("please ignore this blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
sleep(10);
break;
}
@ -1099,6 +1129,7 @@ void LP_swapsloop(void *ctx)
if ( (sp->finished= LP_swapwait(0,sp->requestid,sp->quoteid,-1,0)) != 0 )
{
}
sleep(3);
}
}
if ( nonz == 0 )
@ -1109,7 +1140,8 @@ void LP_swapsloop(void *ctx)
LP_alice_eligible((uint32_t)time(NULL));
sleep(6);
}
}
} else sleep(10);
LP_gtc_iteration(ctx,LP_myipaddr,LP_mypubsock);
}
}
@ -1194,7 +1226,7 @@ void queue_loop(void *ctx)
}
if ( (json= cJSON_Parse((char *)ptr->msg)) != 0 )
{
if ( 1 && ptr->msglen < sizeof(linebuf) )
if ( ptr->msglen < sizeof(linebuf) )
{
if ( (k= MMJSON_encode(linebuf,(char *)ptr->msg)) > 0 )
{
@ -1393,8 +1425,7 @@ extern int32_t bitcoind_RPC_inittime;
void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybusport,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson)
{
char *myipaddr=0,version[64]; long filesize,n; int32_t valid,timeout; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx();
sprintf(version,"Marketmaker %s.%s %s rsize.%ld",LP_MAJOR_VERSION,LP_MINOR_VERSION,LP_BUILD_NUMBER,sizeof(struct basilisk_request));
char *myipaddr=0; long filesize,n; int32_t valid,timeout; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx();
bitcoind_RPC_inittime = 1;
if ( LP_MAXPRICEINFOS > 256 )
{
@ -1402,7 +1433,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
exit(-1);
}
LP_showwif = juint(argjson,"wif");
printf("showwif.%d %s %u\n",LP_showwif,version,calc_crc32(0,version,(int32_t)strlen(version)));
printf("showwif.%d version: %s %u\n",LP_showwif,MM_VERSION,calc_crc32(0,MM_VERSION,(int32_t)strlen(MM_VERSION)));
if ( passphrase == 0 || passphrase[0] == 0 )
{
printf("jeezy says we cant use the nullstring as passphrase and I agree\n");
@ -1473,13 +1504,14 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
portable_mutex_init(&LP_blockinit_mutex);
portable_mutex_init(&LP_pendswap_mutex);
portable_mutex_init(&LP_listmutex);
portable_mutex_init(&LP_gtcmutex);
myipaddr = clonestr("127.0.0.1");
#ifndef _WIN32
#ifndef FROM_JS
if ( system("curl -s4 checkip.amazonaws.com > myipaddr") == 0 )
char ipfname[64];
strcpy(ipfname,"myipaddr");
if ( access( ipfname, F_OK ) != -1 || system("curl -s4 checkip.amazonaws.com > myipaddr") == 0 )
{
char ipfname[64];
strcpy(ipfname,"myipaddr");
if ( (myipaddr= OS_filestr(&filesize,ipfname)) != 0 && myipaddr[0] != 0 )
{
n = strlen(myipaddr);
@ -1621,6 +1653,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
int32_t nonz,didremote=0;
LP_statslog_parse();
bitcoind_RPC_inittime = 0;
//LP_mpnet_init(); seems better to have the GUI send in persistent orders, exit mm is a cancel all
while ( LP_STOP_RECEIVED == 0 )
{
nonz = 0;

371
iguana/exchanges/LP_ordermatch.c

@ -18,6 +18,14 @@
// LP_ordermatch.c
// marketmaker
//
struct LP_gtcorder
{
struct LP_gtcorder *next,*prev;
struct LP_quoteinfo Q;
uint32_t cancelled,pending;
} *GTCorders;
struct LP_quoteinfo LP_Alicequery,LP_Alicereserved;
double LP_Alicemaxprice;
bits256 LP_Alicedestpubkey,LP_bobs_reserved;
@ -190,12 +198,12 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str
if ( strcmp(autxo->coinaddr,qp->destaddr) != 0 )
return(-10);
}
if ( autxo != 0 && destvalue < qp->desttxfee+qp->destsatoshis )
if ( strcmp(destcoin, "ETOMIC") != 0 && autxo != 0 && destvalue < qp->desttxfee+qp->destsatoshis )
{
printf("destvalue %.8f destsatoshis %.8f is too small txfee %.8f?\n",dstr(destvalue),dstr(qp->destsatoshis),dstr(qp->desttxfee));
return(-11);
}
if ( butxo != 0 && srcvalue < qp->txfee+qp->satoshis )
if ( strcmp(srccoin, "ETOMIC") != 0 && butxo != 0 && srcvalue < qp->txfee+qp->satoshis )
{
printf("srcvalue %.8f [%.8f] satoshis %.8f is too small txfee %.8f?\n",dstr(srcvalue),dstr(srcvalue) - dstr(qp->txfee+qp->satoshis),dstr(qp->satoshis),dstr(qp->txfee));
return(-33);
@ -213,7 +221,7 @@ double LP_quote_validate(struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo,str
printf("error -14: txfee %.8f < %.8f or desttxfee %.8f < %.8f\n",dstr(qp->txfee),dstr(LP_REQUIRED_TXFEE*txfee),dstr(qp->desttxfee),dstr(LP_REQUIRED_TXFEE*desttxfee));
return(-14);
}
if ( butxo != 0 )
if ( butxo != 0 && strcmp(srccoin, "ETOMIC") != 0)
{
if ( qp->satoshis < (srcvalue / LP_MINVOL) || srcvalue < qp->txfee*LP_MINSIZE_TXFEEMULT )
{
@ -413,14 +421,22 @@ struct LP_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,int32_t iamb
memset(butxo,0,sizeof(*butxo));
if ( iambob != 0 )
{
targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee) + 3*txfee;
if (strcmp(coin->symbol, "ETOMIC") == 0) {
targetval = 100000000 + 3*txfee;
} else {
targetval = LP_basesatoshis(relvolume,price,txfee,desttxfee) + 3*txfee;
}
targetval2 = (targetval / 8) * 9 + 3*txfee;
fee = txfee;
ratio = LP_MINVOL;
}
else
{
targetval = relvolume*SATOSHIDEN + 3*desttxfee;
if (strcmp(coin->symbol, "ETOMIC") == 0) {
targetval = 100000000 + 3*desttxfee;
} else {
targetval = relvolume*SATOSHIDEN + 3*desttxfee;
}
targetval2 = (targetval / 777) + 3*desttxfee;
fee = desttxfee;
ratio = LP_MINCLIENTVOL;
@ -429,7 +445,7 @@ struct LP_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,int32_t iamb
{
if ( (m= LP_address_utxo_ptrs(coin,iambob,utxos,max,ap,coinaddr)) > 1 )
{
if ( 0 )
if ( 1 )
{
int32_t i;
for (i=0; i<m; i++)
@ -494,7 +510,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,char *base,char *rel,double
}
if ( bits256_nonz(privkey) != 0 && bits256_cmp(G.LP_mypub25519,qp->srchash) == 0 )
{
LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,base,qp->satoshis-qp->txfee,rel,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector,qp->fill,qp->gtc);
dtrust = LP_dynamictrust(qp->othercredits,qp->desthash,LP_kmdvalue(qp->destcoin,qp->destsatoshis));
if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp,dtrust > 0)) == 0 )
{
@ -517,27 +533,35 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,char *base,char *rel,double
LP_importaddress(qp->destcoin,qp->destaddr);
LP_otheraddress(qp->srccoin,otheraddr,qp->destcoin,qp->destaddr);
LP_importaddress(qp->srccoin,otheraddr);
bits256 zero;
memset(zero.bytes,0,sizeof(zero));
for (i=0; i<1; i++)
{
LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->desthash,jprint(reqjson,0));
break;
sleep(10);
if ( swap->received != 0 )
bits256 zero;
memset(zero.bytes,0,sizeof(zero));
for (i=0; i<1; i++)
{
printf("swap %u-%u has started t%u\n",swap->I.req.requestid,swap->I.req.quoteid,swap->received);
LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->desthash,jprint(reqjson,0));
break;
sleep(10);
if ( swap->received != 0 )
{
printf("swap %u-%u has started t%u\n",swap->I.req.requestid,swap->I.req.quoteid,swap->received);
break;
}
printf("bob tries %u-%u again i.%d\n",swap->I.req.requestid,swap->I.req.quoteid,i);
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,jprint(reqjson,0));
}
printf("bob tries %u-%u again i.%d\n",swap->I.req.requestid,swap->I.req.quoteid,i);
sleep(1);
printf("send CONNECT for %u-%u\n",qp->R.requestid,qp->R.quoteid);
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,jprint(reqjson,0));
if ( IPC_ENDPOINT >= 0 )
LP_queuecommand(0,jprint(reqjson,0),IPC_ENDPOINT,-1,0);
}
sleep(1);
printf("send CONNECT for %u-%u\n",qp->R.requestid,qp->R.quoteid);
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,jprint(reqjson,0));
if ( IPC_ENDPOINT >= 0 )
LP_queuecommand(0,jprint(reqjson,1),IPC_ENDPOINT,-1,0);
else free_json(reqjson);
if ( qp->mpnet != 0 && qp->gtc == 0 )
{
char *msg = jprint(reqjson,0);
LP_mpnet_send(0,msg,1,qp->destaddr);
free(msg);
}
free_json(reqjson);
retval = 0;
}
else
@ -567,10 +591,60 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,char *base,char *rel,double
return(retval);
}
void LP_gtc_iteration(void *ctx,char *myipaddr,int32_t mypubsock)
{
struct LP_gtcorder *gtc,*tmp; struct LP_quoteinfo *qp; uint64_t destvalue,destvalue2; uint32_t oldest = 0;
if ( Alice_expiration != 0 )
return;
DL_FOREACH_SAFE(GTCorders,gtc,tmp)
{
qp = &gtc->Q;
if ( gtc->cancelled == 0 && (oldest == 0 || gtc->pending < oldest) )
oldest = gtc->pending;
}
DL_FOREACH_SAFE(GTCorders,gtc,tmp)
{
qp = &gtc->Q;
if ( gtc->cancelled == 0 && LP_iseligible(&destvalue,&destvalue2,0,qp->destcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 0 )
{
gtc->cancelled = (uint32_t)time(NULL);
LP_failedmsg(qp->R.requestid,qp->R.quoteid,-9997,qp->uuidstr);
}
if ( gtc->cancelled != 0 )
{
portable_mutex_lock(&LP_gtcmutex);
DL_DELETE(GTCorders,gtc);
free(gtc);
portable_mutex_unlock(&LP_gtcmutex);
}
else
{
if ( gtc->pending <= oldest+60 && time(NULL) > gtc->pending+600 )//LP_AUTOTRADE_TIMEOUT*10 )
{
gtc->pending = qp->timestamp = (uint32_t)time(NULL);
LP_query(ctx,myipaddr,mypubsock,"request",qp);
LP_Alicequery = *qp, LP_Alicemaxprice = gtc->Q.maxprice, Alice_expiration = qp->timestamp + 2*LP_AUTOTRADE_TIMEOUT, LP_Alicedestpubkey = qp->srchash;
char str[65]; printf("LP_gtc fill.%d gtc.%d %s/%s %.8f vol %.8f dest.(%s) maxprice %.8f etomicdest.(%s) uuid.%s fill.%d gtc.%d\n",qp->fill,qp->gtc,qp->srccoin,qp->destcoin,dstr(qp->satoshis),dstr(qp->destsatoshis),bits256_str(str,LP_Alicedestpubkey),gtc->Q.maxprice,qp->etomicdest,qp->uuidstr,qp->fill,qp->gtc);
break;
}
}
}
}
void LP_gtc_addorder(struct LP_quoteinfo *qp)
{
struct LP_gtcorder *gtc;
gtc = calloc(1,sizeof(*gtc));
gtc->Q = *qp;
gtc->pending = (uint32_t)time(NULL);
portable_mutex_lock(&LP_gtcmutex);
DL_APPEND(GTCorders,gtc);
portable_mutex_unlock(&LP_gtcmutex);
}
char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration,uint32_t tradeid,bits256 destpubkey,char *uuidstr)
{
double price;
price = 0.;
struct LP_gtcorder *gtc;
memset(qp->txid.bytes,0,sizeof(qp->txid));
qp->txid2 = qp->txid;
qp->aliceid = LP_aliceid_calc(qp->desttxid,qp->destvout,qp->feetxid,qp->feevout);
@ -578,9 +652,25 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q
qp->tradeid = LP_rand();
qp->srchash = destpubkey;
strncpy(qp->uuidstr,uuidstr,sizeof(qp->uuidstr)-1);
LP_query(ctx,myipaddr,mypubsock,"request",qp);
LP_Alicequery = *qp, LP_Alicemaxprice = maxprice, Alice_expiration = qp->timestamp + timeout, LP_Alicedestpubkey = destpubkey;
char str[65]; printf("LP_trade %s/%s %.8f vol %.8f dest.(%s) maxprice %.8f etomicdest.(%s) uuid.%s\n",qp->srccoin,qp->destcoin,dstr(qp->satoshis),dstr(qp->destsatoshis),bits256_str(str,LP_Alicedestpubkey),maxprice,qp->etomicdest,qp->uuidstr);
qp->maxprice = maxprice;
qp->timestamp = (uint32_t)time(NULL);
if ( qp->gtc != 0 )
{
//strcpy(&qp->uuidstr[strlen(qp->uuidstr)-6],"cccccc");
LP_gtc_addorder(qp);
}
{
LP_query(ctx,myipaddr,mypubsock,"request",qp);
LP_Alicequery = *qp, LP_Alicemaxprice = qp->maxprice, Alice_expiration = qp->timestamp + timeout, LP_Alicedestpubkey = qp->srchash;
}
if ( qp->gtc == 0 )
{
cJSON *reqjson = LP_quotejson(qp);
char *msg = jprint(reqjson,1);
LP_mpnet_send(1,msg,1,0);
free(msg);
}
char str[65]; printf("LP_trade mpnet.%d fill.%d gtc.%d %s/%s %.8f vol %.8f dest.(%s) maxprice %.8f etomicdest.(%s) uuid.%s fill.%d gtc.%d\n",qp->mpnet,qp->fill,qp->gtc,qp->srccoin,qp->destcoin,dstr(qp->satoshis),dstr(qp->destsatoshis),bits256_str(str,LP_Alicedestpubkey),qp->maxprice,qp->etomicdest,qp->uuidstr,qp->fill,qp->gtc);
return(LP_recent_swaps(0,uuidstr));
}
@ -615,7 +705,7 @@ int32_t LP_alice_eligible(uint32_t quotetime)
{
if ( Alice_expiration != 0 && quotetime > Alice_expiration )
{
if ( LP_Alicequery.uuidstr[0] != 0 )
if ( LP_Alicequery.uuidstr[0] != 0 && LP_Alicequery.gtc == 0 )
LP_failedmsg(LP_Alicequery.R.requestid,LP_Alicequery.R.quoteid,-9999,LP_Alicequery.uuidstr);
printf("time expired for Alice_request\n");
LP_alicequery_clear();
@ -628,16 +718,45 @@ char *LP_cancel_order(char *uuidstr)
int32_t num = 0; cJSON *retjson;
if ( uuidstr != 0 )
{
num = LP_trades_canceluuid(uuidstr);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddnum(retjson,"numentries",num);
if ( strcmp(LP_Alicequery.uuidstr,uuidstr) == 0 )
if ( uuidstr[0] == 'G' )
{
LP_failedmsg(LP_Alicequery.R.requestid,LP_Alicequery.R.quoteid,-9998,LP_Alicequery.uuidstr);
LP_alicequery_clear();
jaddstr(retjson,"status","uuid canceled");
} else jaddstr(retjson,"status","will stop trade negotiation, but if swap started it wont cancel");
struct LP_gtcorder *gtc,*tmp;
DL_FOREACH_SAFE(GTCorders,gtc,tmp)
{
if ( strcmp(gtc->Q.uuidstr,uuidstr) == 0 )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"cancelled",uuidstr);
jaddnum(retjson,"pending",gtc->pending);
if ( gtc->cancelled == 0 )
{
gtc->cancelled = (uint32_t)time(NULL);
jaddstr(retjson,"status","uuid canceled");
LP_failedmsg(gtc->Q.R.requestid,gtc->Q.R.quoteid,-9997,gtc->Q.uuidstr);
}
else
{
jaddstr(retjson,"status","uuid already canceled");
LP_failedmsg(gtc->Q.R.requestid,gtc->Q.R.quoteid,-9996,gtc->Q.uuidstr);
}
}
}
return(clonestr("{\"error\":\"gtc uuid not found\"}"));
}
else
{
num = LP_trades_canceluuid(uuidstr);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddnum(retjson,"numentries",num);
if ( strcmp(LP_Alicequery.uuidstr,uuidstr) == 0 )
{
LP_failedmsg(LP_Alicequery.R.requestid,LP_Alicequery.R.quoteid,-9998,LP_Alicequery.uuidstr);
LP_alicequery_clear();
jaddstr(retjson,"status","uuid canceled");
} else jaddstr(retjson,"status","will stop trade negotiation, but if swap started it wont cancel");
}
return(jprint(retjson,1));
}
return(clonestr("{\"error\":\"uuid not cancellable\"}"));
@ -645,16 +764,22 @@ char *LP_cancel_order(char *uuidstr)
char *LP_connectedalice(struct LP_quoteinfo *qp,char *pairstr) // alice
{
cJSON *retjson; char otheraddr[64],*msg; double bid,ask,price,qprice; int32_t pairsock = -1; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,A,B,*butxo; struct basilisk_swap *swap; struct iguana_info *coin;
cJSON *retjson; char otheraddr[64],*msg; double bid,ask,price,qprice; int32_t changed,pairsock = -1; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,A,B,*butxo; struct basilisk_swap *swap; struct iguana_info *coin;
if ( bits256_cmp(qp->desthash,G.LP_mypub25519) != 0 )
{
LP_aliceid(qp->tradeid,qp->aliceid,"error1",0,0);
LP_failedmsg(qp->R.requestid,qp->R.quoteid,-4000,qp->uuidstr);
return(clonestr("{\"result\",\"update stats\"}"));
}
printf("CONNECTED numpending.%d tradeid.%u requestid.%u quoteid.%u pairstr.%s\n",G.LP_pendingswaps,qp->tradeid,qp->R.requestid,qp->R.quoteid,pairstr!=0?pairstr:"");
LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
printf("CONNECTED mpnet.%d fill.%d gtc.%d numpending.%d tradeid.%u requestid.%u quoteid.%u pairstr.%s\n",qp->mpnet,qp->fill,qp->gtc,G.LP_pendingswaps,qp->tradeid,qp->R.requestid,qp->R.quoteid,pairstr!=0?pairstr:"");
LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-qp->txfee,qp->destcoin,qp->destsatoshis-qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector,qp->fill,qp->gtc);
//printf("calculated requestid.%u quoteid.%u\n",qp->R.requestid,qp->R.quoteid);
if ( LP_Alicequery.srccoin[0] != 0 && LP_Alicequery.destcoin[0] != 0 )
{
LP_mypriceset(0,&changed,LP_Alicequery.destcoin,LP_Alicequery.srccoin,0.);
LP_mypriceset(0,&changed,LP_Alicequery.srccoin,LP_Alicequery.destcoin,0.);
}
LP_alicequery_clear();
memset(&LP_Alicereserved,0,sizeof(LP_Alicereserved));
LP_aliceid(qp->tradeid,qp->aliceid,"connected",qp->R.requestid,qp->R.quoteid);
autxo = &A;
@ -671,7 +796,7 @@ char *LP_connectedalice(struct LP_quoteinfo *qp,char *pairstr) // alice
printf("quote %s/%s validate error %.0f\n",qp->srccoin,qp->destcoin,qprice);
return(clonestr("{\"error\":\"quote validation error\"}"));
}
if ( LP_myprice(&bid,&ask,qp->srccoin,qp->destcoin) <= SMALLVAL || bid <= SMALLVAL )
if ( LP_myprice(0,&bid,&ask,qp->srccoin,qp->destcoin) <= SMALLVAL || bid <= SMALLVAL )
{
printf("this node has no price for %s/%s (%.8f %.8f)\n",qp->destcoin,qp->srccoin,bid,ask);
LP_availableset(qp->desttxid,qp->vout);
@ -862,7 +987,7 @@ void LP_reserved(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo
double LP_trades_bobprice(double *bidp,double *askp,struct LP_quoteinfo *qp)
{
double price; struct iguana_info *coin; char str[65];
price = LP_myprice(bidp,askp,qp->srccoin,qp->destcoin);
price = LP_myprice(1,bidp,askp,qp->srccoin,qp->destcoin);
if ( (coin= LP_coinfind(qp->srccoin)) == 0 || price <= SMALLVAL || *askp <= SMALLVAL )
{
//printf("this node has no price for %s/%s\n",qp->srccoin,qp->destcoin);
@ -906,7 +1031,7 @@ double LP_trades_pricevalidate(struct LP_quoteinfo *qp,struct iguana_info *coin,
printf("quote %s/%s validate error %.0f\n",qp->srccoin,qp->destcoin,qprice);
return(-3);
}
if ( qprice < (price - 0.00000001) * 0.998 )
if ( qprice < (price - 0.00000001) * 0.998)
{
printf(" quote price %.8f (%llu/%llu %.8f) too low vs %.8f for %s/%s price %.8f %.8f\n",qprice,(long long)qp->destsatoshis,(long long)(qp->satoshis-qp->txfee),(double)qp->destsatoshis/(qp->satoshis-qp->txfee),price,qp->srccoin,qp->destcoin,price,(price - 0.00000001) * 0.998);
return(-77);
@ -916,10 +1041,11 @@ double LP_trades_pricevalidate(struct LP_quoteinfo *qp,struct iguana_info *coin,
struct LP_quoteinfo *LP_trades_gotrequest(void *ctx,struct LP_quoteinfo *qp,struct LP_quoteinfo *newqp,char *pairstr)
{
double price=0.,p=0.,qprice,myprice,bestprice,range,bid,ask; struct iguana_info *coin,*othercoin; struct LP_utxoinfo A,B,*autxo,*butxo; cJSON *reqjson; char str[65]; struct LP_address_utxo *utxos[4096]; int32_t i,r,counter,max = (int32_t)(sizeof(utxos)/sizeof(*utxos));
int32_t voliters=10,priceiters=33;
double price=0.,p=0.,qprice,myprice,bestprice,range,bid,ask; uint64_t satoshis; struct iguana_info *coin,*othercoin; struct LP_utxoinfo A,B,*autxo,*butxo; cJSON *reqjson,*retjson; char str[65],*retstr,*txidstr,*hexstr; struct LP_address_utxo *utxos[4096]; int32_t i,j,notarized,r,num,counter,max = (int32_t)(sizeof(utxos)/sizeof(*utxos));
*newqp = *qp;
qp = newqp;
//printf("bob %s received REQUEST.(%s)\n",bits256_str(str,G.LP_mypub25519),qp->uuidstr+32);
printf("bob %s received REQUEST.(%s) mpnet.%d fill.%d gtc.%d\n",bits256_str(str,G.LP_mypub25519),qp->uuidstr+32,qp->mpnet,qp->fill,qp->gtc);
if ( (coin= LP_coinfind(qp->srccoin)) == 0 || (othercoin= LP_coinfind(qp->destcoin)) == 0 )
return(0);
if ( (myprice= LP_trades_bobprice(&bid,&ask,qp)) == 0. )
@ -970,7 +1096,7 @@ struct LP_quoteinfo *LP_trades_gotrequest(void *ctx,struct LP_quoteinfo *qp,stru
}
else
{
//printf("ignore as qprice %.8f vs myprice %.8f\n",qprice,myprice);
printf("%s/%s ignore as qprice %.8f vs myprice %.8f\n",qp->srccoin,qp->destcoin,qprice,myprice);
return(0);
}
//LP_RTmetrics_update(qp->srccoin,qp->destcoin);
@ -997,46 +1123,85 @@ struct LP_quoteinfo *LP_trades_gotrequest(void *ctx,struct LP_quoteinfo *qp,stru
return(0);
}
}
LP_address_utxo_reset(&num,coin);
i = 0;
while ( i < 33 && price >= myprice )
{
if ( (butxo= LP_address_myutxopair(butxo,1,utxos,max,LP_coinfind(qp->srccoin),qp->coinaddr,qp->txfee,dstr(qp->destsatoshis),price,qp->desttxfee)) != 0 )
{
strcpy(qp->gui,G.gui);
strcpy(qp->coinaddr,coin->smartaddr);
qp->srchash = G.LP_mypub25519;
qp->txid = butxo->payment.txid;
qp->vout = butxo->payment.vout;
qp->txid2 = butxo->deposit.txid;
qp->vout2 = butxo->deposit.vout;
qp->satoshis = butxo->swap_satoshis;// + qp->txfee;
qp->quotetime = (uint32_t)time(NULL);
while ( i < priceiters && price >= myprice )
{
for (j=0; j<voliters; j++)
{
printf("priceiter.%d voliter.%d price %.8f vol %.8f\n",i,j,price,dstr(qp->destsatoshis));
if ( (butxo= LP_address_myutxopair(&B,1,utxos,max,coin,qp->coinaddr,qp->txfee,dstr(qp->destsatoshis),price,qp->desttxfee)) != 0 )
{
strcpy(qp->gui,G.gui);
strcpy(qp->coinaddr,coin->smartaddr);
qp->srchash = G.LP_mypub25519;
qp->txid = butxo->payment.txid;
qp->vout = butxo->payment.vout;
qp->txid2 = butxo->deposit.txid;
qp->vout2 = butxo->deposit.vout;
if (coin->etomic[0] == 0) {
qp->satoshis = butxo->swap_satoshis;// + qp->txfee;
} else {
qp->satoshis = LP_basesatoshis(dstr(qp->destsatoshis), price, qp->txfee, qp->desttxfee);
}
qp->quotetime = (uint32_t)time(NULL);
break;
}
if ( qp->fill != 0 )
break;
qp->destsatoshis = (qp->destsatoshis * 2) / 3;
}
else
if ( butxo != 0 && j < voliters )
{
printf("i.%d cant find utxopair aliceid.%llu %s/%s %.8f -> relvol %.8f\n",i,(long long)qp->aliceid,qp->srccoin,qp->destcoin,dstr(LP_basesatoshis(dstr(qp->destsatoshis),price,qp->txfee,qp->desttxfee)),dstr(qp->destsatoshis));
return(0);
if ( qp->satoshis <= qp->txfee )
return(0);
p = (double)qp->destsatoshis / (qp->satoshis - qp->txfee);
if ( LP_trades_pricevalidate(qp,coin,p) < 0. )
{
if ( qp->fill != 0 )
return(0);
price *= 0.995;
i++;
continue;
}
if ( i == 0 && p < myprice )
{
price = qprice;
printf("reset price <- qprice %.8f\n",qprice);
}
else
{
if ( qprice >= p || qp->fill != 0 )
break;
price *= 0.995;
}
if ( qp->fill != 0 )
break;
i++;
}
if ( qp->satoshis <= qp->txfee )
return(0);
p = (double)qp->destsatoshis / (qp->satoshis - qp->txfee);
if ( LP_trades_pricevalidate(qp,coin,p) < 0. )
return(0);
if ( i == 0 && p < myprice )
else if ( qp->fill != 0 || i == priceiters )
{
price = qprice;
printf("reset price <- qprice %.8f\n",qprice);
printf("i.%d cant find utxopair aliceid.%llu %s/%s %.8f -> relvol %.8f txfee %.8f\n",i,(long long)qp->aliceid,qp->srccoin,qp->destcoin,dstr(LP_basesatoshis(dstr(qp->destsatoshis),price,qp->txfee,qp->desttxfee)),dstr(qp->destsatoshis),dstr(qp->txfee));
if ( qp->gtc != 0 && qp->fill != 0 && coin != 0 && coin->electrum == 0 )
{
LP_address_utxo_reset(&num,coin);
satoshis = LP_basesatoshis(dstr(qp->destsatoshis),price,qp->txfee,qp->desttxfee) + 3*qp->txfee;
if ( LP_getheight(&notarized,coin) > coin->bobfillheight+3 && fabs((double)coin->fillsatoshis - satoshis)/satoshis > 0.1 )
{
printf("queue up do_autofill_merge %.8f\n",dstr(satoshis));
coin->do_autofill_merge = satoshis;
}
}
return(0);
}
else
{
if ( qprice >= p )
break;
price *= 0.995;
i++;
}
i++;
}
printf("%s/%s i.%d qprice %.8f myprice %.8f price %.8f [%.8f]\n",qp->srccoin,qp->destcoin,i,qprice,myprice,price,p);
if ( LP_allocated(qp->txid,qp->vout) == 0 && LP_allocated(qp->txid2,qp->vout2) == 0 )
printf("%s/%s i.%d j.%d qprice %.8f myprice %.8f price %.8f [%.8f]\n",qp->srccoin,qp->destcoin,i,j,qprice,myprice,price,p);
if ( butxo != 0 && bits256_nonz(qp->txid) != 0 && bits256_nonz(qp->txid2) != 0 && LP_allocated(qp->txid,qp->vout) == 0 && LP_allocated(qp->txid2,qp->vout2) == 0 )
{
//printf("found unallocated txids\n");
reqjson = LP_quotejson(qp);
@ -1047,10 +1212,18 @@ struct LP_quoteinfo *LP_trades_gotrequest(void *ctx,struct LP_quoteinfo *qp,stru
jaddnum(reqjson,"quotetime",qp->quotetime);
jaddnum(reqjson,"pending",qp->timestamp + LP_RESERVETIME);
jaddstr(reqjson,"method","reserved");
LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->desthash,jprint(reqjson,0));
bits256 zero;
memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,jprint(reqjson,0));
{
LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->desthash,jprint(reqjson,0));
bits256 zero;
memset(zero.bytes,0,sizeof(zero));
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,jprint(reqjson,0));
}
if ( qp->mpnet != 0 && qp->gtc == 0 )
{
char *msg = jprint(reqjson,0);
LP_mpnet_send(0,msg,1,qp->destaddr);
free(msg);
}
free_json(reqjson);
//printf("Send RESERVED id.%llu\n",(long long)qp->aliceid);
return(qp);
@ -1061,7 +1234,7 @@ struct LP_quoteinfo *LP_trades_gotrequest(void *ctx,struct LP_quoteinfo *qp,stru
struct LP_quoteinfo *LP_trades_gotreserved(void *ctx,struct LP_quoteinfo *qp,struct LP_quoteinfo *newqp)
{
char *retstr; double qprice;
//char str[65]; printf("alice %s received RESERVED.(%s) %.8f\n",bits256_str(str,G.LP_mypub25519),qp->uuidstr+32,(double)qp->destsatoshis/(qp->satoshis+1));
char str[65]; printf("alice %s received RESERVED.(%s) %.8f mpnet.%d fill.%d gtc.%d\n",bits256_str(str,G.LP_mypub25519),qp->uuidstr+32,(double)qp->destsatoshis/(qp->satoshis+1),qp->mpnet,qp->fill,qp->gtc);
*newqp = *qp;
qp = newqp;
if ( (qprice= LP_trades_alicevalidate(ctx,qp)) > 0. )
@ -1103,7 +1276,7 @@ struct LP_quoteinfo *LP_trades_gotconnect(void *ctx,struct LP_quoteinfo *qp,stru
struct LP_quoteinfo *LP_trades_gotconnected(void *ctx,struct LP_quoteinfo *qp,struct LP_quoteinfo *newqp,char *pairstr)
{
char *retstr; int32_t changed; double val;
//char str[65]; printf("alice %s received CONNECTED.(%llu)\n",bits256_str(str,G.LP_mypub25519),(long long)qp->aliceid);
char str[65]; printf("alice %s received CONNECTED.(%llu) mpnet.%d fill.%d gtc.%d\n",bits256_str(str,G.LP_mypub25519),(long long)qp->aliceid,qp->mpnet,qp->fill,qp->gtc);
*newqp = *qp;
qp = newqp;
if ( (val= LP_trades_alicevalidate(ctx,qp)) > 0. )
@ -1112,7 +1285,7 @@ struct LP_quoteinfo *LP_trades_gotconnected(void *ctx,struct LP_quoteinfo *qp,st
LP_aliceid(qp->tradeid,qp->aliceid,"connected",0,0);
if ( (retstr= LP_connectedalice(qp,pairstr)) != 0 )
free(retstr);
LP_mypriceset(&changed,qp->destcoin,qp->srccoin,0.);
LP_mypriceset(0,&changed,qp->destcoin,qp->srccoin,0.);
LP_alicequery_clear();
return(qp);
} else LP_failedmsg(qp->R.requestid,qp->R.quoteid,val,qp->uuidstr);
@ -1367,7 +1540,7 @@ void LP_tradecommandQ(struct LP_quoteinfo *qp,char *pairstr,int32_t funcid)
//printf("queue.%d uuid.(%s)\n",funcid,qtp->Q.uuidstr);
}
int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen)
int32_t LP_tradecommand(int32_t from_mpnet,void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen)
{
int32_t Qtrades = 1;
char *method,str[65]; int32_t i,num,DEXselector = 0; uint64_t aliceid; double qprice,bestprice,price,bid,ask; cJSON *proof; uint64_t rq; struct iguana_info *coin; struct LP_quoteinfo Q,Q2; int32_t counter,retval=-1;
@ -1380,7 +1553,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
}
if ( Q.satoshis < Q.txfee )
return(1);
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector,Q.fill,Q.gtc);
rq = ((uint64_t)Q.R.requestid << 32) | Q.R.quoteid;
if ( Q.uuidstr[0] == 0 || (Q.timestamp > 0 && time(NULL) > Q.timestamp + LP_AUTOTRADE_TIMEOUT*20) ) // eat expired packets, some old timestamps floating about?
{
@ -1390,7 +1563,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
LP_tradecommand_log(argjson);
qprice = (double)Q.destsatoshis / (Q.satoshis - Q.txfee); //jdouble(argjson,"price");
//printf("%s\n",jprint(argjson,0));
printf("%-4d uuid.%32s %12s %5s/%-5s %12.8f -> %12.8f (%11.8f) | RT.%d %d n%d\n",(uint32_t)time(NULL) % 3600,Q.uuidstr+32,method,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),qprice,LP_RTcount,LP_swapscount,G.netid);
printf("%-4d uuid.%32s M.%d g.%d f.%d %12s %5s/%-5s %12.8f -> %12.8f (%11.8f) | RT.%d %d n%d\n",(uint32_t)time(NULL) % 3600,Q.uuidstr+32,from_mpnet,Q.gtc,Q.fill,method,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),qprice,LP_RTcount,LP_swapscount,G.netid);
retval = 1;
aliceid = j64bits(argjson,"aliceid");
if ( strcmp(method,"reserved") == 0 )
@ -1438,7 +1611,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
if ( i == sizeof(rqs)/sizeof(*rqs) )
i = (rand() % (sizeof(rqs)/sizeof(*rqs)));
rqs[i] = rq;
//printf("CONNECTED.(%s)\n",jprint(argjson,0));
printf("CONNECTED.(%s)\n",jprint(argjson,0));
if ( (proof= jarray(&num,argjson,"proof")) != 0 && num > 0 )
Q.othercredits = LP_instantdex_proofcheck(Q.srccoin,Q.coinaddr,proof,num);
if ( Qtrades == 0 )
@ -1446,7 +1619,9 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
else LP_tradecommandQ(&Q,jstr(argjson,"pair"),LP_CONNECTED);
}
}
price = LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin);
if ( strcmp(method,"request") == 0 || strcmp(method,"connect") == 0 ) // bob
price = LP_myprice(1,&bid,&ask,Q.srccoin,Q.destcoin);
else price = LP_myprice(0,&bid,&ask,Q.srccoin,Q.destcoin); // alice
if ( (coin= LP_coinfind(Q.srccoin)) == 0 || coin->inactive != 0 )
{
//printf("%s is not active\n",Q.srccoin);
@ -1459,7 +1634,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
}
if ( LP_aliceonly(Q.srccoin) > 0 )
{
printf("{\"error\":\"GAME can only be alice coin\"}\n");
printf("{\"error\":\"alice only coins can only be alice coin\"}\n");
return(retval);
}
if ( strcmp(method,"request") == 0 ) // bob
@ -1469,6 +1644,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
if ( Q.destvout != Q.feevout || bits256_cmp(Q.desttxid,Q.feetxid) != 0 )
{
bestprice = LP_bob_competition(&counter,aliceid,qprice,-1);
//printf("bestprice %.8f\n",bestprice);
if ( Qtrades == 0 )//|| (bits256_cmp(Q.srchash,G.LP_mypub25519) == 0 && bits256_cmp(G.LP_mypub25519,Q.desthash) != 0) )
LP_trades_gotrequest(ctx,&Q,&Q2,jstr(argjson,"pair"));
else LP_tradecommandQ(&Q,jstr(argjson,"pair"),LP_REQUEST);
@ -1489,7 +1665,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
if ( i == sizeof(rqs)/sizeof(*rqs) )
i = (rand() % (sizeof(rqs)/sizeof(*rqs)));
rqs[i] = rq;
//printf("CONNECT.(%s)\n",jprint(argjson,0));
printf("CONNECT.(%s)\n",jprint(argjson,0));
if ( (proof= jarray(&num,argjson,"proof")) != 0 && num > 0 )
Q.othercredits = LP_instantdex_proofcheck(Q.destcoin,Q.destaddr,proof,num);
if ( Qtrades == 0 )
@ -1502,7 +1678,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
return(retval);
}
char *LP_autobuy(void *ctx,int32_t fomoflag,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui,uint32_t nonce,bits256 destpubkey,uint32_t tradeid,char *uuidstr)
char *LP_autobuy(void *ctx,int32_t fomoflag,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui,uint32_t nonce,bits256 destpubkey,uint32_t tradeid,char *uuidstr,int32_t fillflag,int32_t gtcflag)
{
uint64_t desttxfee,txfee,balance; uint32_t lastnonce; int64_t bestsatoshis=0,destsatoshis; struct iguana_info *basecoin,*relcoin; struct LP_utxoinfo *autxo,B,A; struct LP_quoteinfo Q; bits256 pubkeys[100]; struct LP_address_utxo *utxos[4096]; int32_t num=0,maxiters=100,i,max=(int32_t)(sizeof(utxos)/sizeof(*utxos)); char _uuidstr[65];
basecoin = LP_coinfind(base);
@ -1589,6 +1765,10 @@ char *LP_autobuy(void *ctx,int32_t fomoflag,char *myipaddr,int32_t mypubsock,cha
memset(&A,0,sizeof(A));
if ( (autxo= LP_address_myutxopair(&A,0,utxos,max,relcoin,relcoin->smartaddr,txfee,dstr(destsatoshis),maxprice,desttxfee)) != 0 )
break;
if ( fillflag != 0 )
{
return(clonestr("{\"error\":\"cant find a deposit that is big enough in size. make another deposit that is just a bit larger than what you want to trade\"}"));
}
destsatoshis *= 0.98;
if ( destsatoshis < desttxfee*LP_MINSIZE_TXFEEMULT )
break;
@ -1604,13 +1784,13 @@ char *LP_autobuy(void *ctx,int32_t fomoflag,char *myipaddr,int32_t mypubsock,cha
autxo->swap_satoshis = destsatoshis;
//printf("first path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->swap_satoshis));
}
else if ( autxo->swap_satoshis - desttxfee < destsatoshis )
else if ( autxo->swap_satoshis - desttxfee < destsatoshis && relcoin->etomic[0] == 0)
{
autxo->swap_satoshis -= desttxfee;
destsatoshis = autxo->swap_satoshis;
printf("second path dest %.8f from %.8f\n",dstr(destsatoshis),dstr(autxo->swap_satoshis));
}
if ( destsatoshis < (autxo->payment.value / LP_MINCLIENTVOL) || autxo->payment.value < desttxfee*LP_MINSIZE_TXFEEMULT )
if ( relcoin->etomic[0] == 0 && (destsatoshis < (autxo->payment.value / LP_MINCLIENTVOL) || autxo->payment.value < desttxfee*LP_MINSIZE_TXFEEMULT ))
{
printf("destsatoshis %.8f vs utxo %.8f this would have triggered an quote error -13\n",dstr(destsatoshis),dstr(autxo->payment.value));
return(clonestr("{\"error\":\"cant find a deposit that is close enough in size. make another deposit that is a bit larger than what you want to trade\"}"));
@ -1640,8 +1820,11 @@ char *LP_autobuy(void *ctx,int32_t fomoflag,char *myipaddr,int32_t mypubsock,cha
}
}
int32_t changed;
LP_mypriceset(&changed,rel,base,1. / maxprice);
LP_mypriceset(&changed,base,rel,0.);
Q.mpnet = G.mpnet;
Q.fill = fillflag;
Q.gtc = gtcflag;
LP_mypriceset(0,&changed,rel,base,1. / maxprice);
LP_mypriceset(0,&changed,base,rel,0.);
if ( uuidstr == 0 || uuidstr[0] == 0 )
{
uint8_t uuidhash[256]; bits256 hash; uint64_t millis; int32_t len = 0;

32
iguana/exchanges/LP_portfolio.c

@ -95,14 +95,18 @@ uint64_t LP_balance(uint64_t *valuep,int32_t iambob,char *symbol,char *coinaddr)
cJSON *array,*item; bits256 zero; int32_t i,n; uint64_t valuesum,satoshisum,value;
valuesum = satoshisum = 0;
memset(zero.bytes,0,sizeof(zero));
/*
#ifndef NOTETOMIC
struct iguana_info *coin = LP_coinfind(symbol);
if (coin->etomic[0] != 0) {
valuesum = LP_etomic_get_balance(coin, coinaddr);
if (coin->etomic[0] != 0 && coin->inactive == 0) {
int error = 0;
uint64_t etomic_balance = LP_etomic_get_balance(coin, coinaddr, &error);
if (error == 0) {
valuesum = etomic_balance;
} else {
valuesum = *valuep;
}
} else
#endif
*/
if ( (array= LP_listunspent(symbol,coinaddr,zero,zero)) != 0 )
{
if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
@ -152,7 +156,7 @@ char *LP_portfolio()
coin->balanceA = LP_balance(&coin->valuesumA,0,coin->symbol,coin->smartaddr);
coin->balanceB = LP_balance(&coin->valuesumB,1,coin->symbol,coin->smartaddr);
if ( strcmp(coin->symbol,"KMD") != 0 )
coin->price_kmd = LP_price(coin->symbol,"KMD");
coin->price_kmd = LP_price(1,coin->symbol,"KMD");
else coin->price_kmd = 1.;
coin->maxamount = coin->valuesumA;
if ( coin->valuesumB > coin->maxamount )
@ -274,7 +278,7 @@ void LP_autopriceset(int32_t ind,void *ctx,int32_t dir,struct LP_priceinfo *base
oppomargin = basepp->buymargins[relpp->ind];
if ( (fixedprice= basepp->fixedprices[relpp->ind]) > SMALLVAL )
{
LP_mypriceset(&changed,relpp->symbol,basepp->symbol,fixedprice);
LP_mypriceset(1,&changed,relpp->symbol,basepp->symbol,fixedprice);
//printf("autoprice FIXED %s/%s <- %.8f\n",basepp->symbol,relpp->symbol,fixedprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,fixedprice);
return;
@ -285,7 +289,7 @@ void LP_autopriceset(int32_t ind,void *ctx,int32_t dir,struct LP_priceinfo *base
factor = basepp->factors[relpp->ind];
if ( fabs(price) < SMALLVAL && refbase != 0 && refrel != 0 )
{
price = LP_myprice(&bid,&ask,refbase,refrel);
price = LP_myprice(1,&bid,&ask,refbase,refrel);
//printf("%s/%s USE ref %s/%s %.8f factor %.8f offset %.8f margin %.8f/%.8f\n",basepp->symbol,relpp->symbol,refbase,refrel,price,factor,offset,oppomargin,margin);
}
if ( LP_pricevalid(price) > 0 )
@ -312,7 +316,7 @@ void LP_autopriceset(int32_t ind,void *ctx,int32_t dir,struct LP_priceinfo *base
newprice = LP_autorefs[ind].lastask;
//printf("autopriceset %s/%s <- %.8f %.8f (%.8f %.8f)\n",basepp->symbol,relpp->symbol,price,newprice,LP_autorefs[ind].lastbid,LP_autorefs[ind].lastask);
}
LP_mypriceset(&changed,relpp->symbol,basepp->symbol,newprice);
LP_mypriceset(1,&changed,relpp->symbol,basepp->symbol,newprice);
if ( changed != 0 || time(NULL) > lasttime+LP_ORDERBOOK_DURATION*.777)
{
lasttime = (uint32_t)time(NULL);
@ -582,9 +586,9 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
LP_autorefs[i].lastask = askprice;
else LP_autorefs[i].lastask = (LP_autorefs[i].lastask * 0.9) + (0.1 * askprice);
askprice = LP_autorefs[i].lastask;
LP_mypriceset(&changed,rel,base,bidprice);
LP_mypriceset(1,&changed,rel,base,bidprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,rel,base,bidprice);
LP_mypriceset(&changed,base,rel,askprice);
LP_mypriceset(1,&changed,base,rel,askprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,base,rel,askprice);
//printf("price %.8f -> %.8f %.8f\n",price,bidprice,askprice);
}
@ -626,7 +630,7 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
LP_autorefs[i].lastbid = newprice;
else LP_autorefs[i].lastbid = (LP_autorefs[i].lastbid * 0.99) + (0.01 * newprice);
newprice = LP_autorefs[i].lastbid;
LP_mypriceset(&changed,rel,base,newprice);
LP_mypriceset(1,&changed,rel,base,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,rel,base,newprice);
//printf("%s/%s price %.8f margin %.8f/%.8f newprice %.8f %.8f\n",base,rel,price,buymargin,sellmargin,newprice,(1. / newprice) * (1. + sellmargin));
newprice = (1. / price) * (1. + sellmargin);
@ -634,7 +638,7 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
LP_autorefs[i].lastask = newprice;
else LP_autorefs[i].lastask = (LP_autorefs[i].lastask * 0.99) + (0.01 * newprice);
newprice = LP_autorefs[i].lastask;
LP_mypriceset(&changed,base,rel,newprice);
LP_mypriceset(1,&changed,base,rel,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,base,rel,newprice);
} //else printf("null return from CMC\n");
}
@ -782,7 +786,7 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
char *retstr2; uint64_t txfee,desttxfee; double bid,ask,maxprice; bits256 zero; uint32_t requestid,quoteid,iter,i; cJSON *retjson2; struct LP_utxoinfo A; struct LP_address_utxo *utxos[1000]; int32_t max=(int32_t)(sizeof(utxos)/sizeof(*utxos));
LP_txfees(&txfee,&desttxfee,buy->symbol,sell->symbol);
requestid = quoteid = 0;
LP_myprice(&bid,&ask,buy->symbol,sell->symbol);
LP_myprice(1,&bid,&ask,buy->symbol,sell->symbol);
maxprice = ask;
if ( setbaserel != 0 )
{
@ -802,7 +806,7 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
//if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( (retstr2= LP_autobuy(ctx,0,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui,LP_lastnonce+1,zero,1,0)) != 0 )
if ( (retstr2= LP_autobuy(ctx,0,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui,LP_lastnonce+1,zero,1,0,0,0)) != 0 )
{
if ( (retjson2= cJSON_Parse(retstr2)) != 0 )
{

87
iguana/exchanges/LP_prices.c

@ -35,7 +35,7 @@ struct LP_priceinfo
int32_t ind,pad;
double diagval,high[2],low[2],last[2],bid[2],ask[2];
double relvals[LP_MAXPRICEINFOS];
double myprices[LP_MAXPRICEINFOS];
double myprices[2][LP_MAXPRICEINFOS];
double minprices[LP_MAXPRICEINFOS]; // autoprice
double fixedprices[LP_MAXPRICEINFOS]; // fixedprices
double buymargins[LP_MAXPRICEINFOS];
@ -451,16 +451,16 @@ void LP_priceinfoupdate(char *base,char *rel,double price)
}
}
double LP_myprice(double *bidp,double *askp,char *base,char *rel)
double LP_myprice(int32_t iambob,double *bidp,double *askp,char *base,char *rel)
{
struct LP_priceinfo *basepp,*relpp; double val;
*bidp = *askp = 0.;
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
*askp = basepp->myprices[relpp->ind];
*askp = basepp->myprices[iambob][relpp->ind];
if ( LP_pricevalid(*askp) > 0 )
{
val = relpp->myprices[basepp->ind];
val = relpp->myprices[iambob][basepp->ind];
if ( LP_pricevalid(val) > 0 )
{
*bidp = 1. / val;
@ -474,7 +474,7 @@ double LP_myprice(double *bidp,double *askp,char *base,char *rel)
}
else
{
val = relpp->myprices[basepp->ind];
val = relpp->myprices[iambob][basepp->ind];
if ( LP_pricevalid(val) > 0 )
{
*bidp = 1. / val;
@ -486,7 +486,7 @@ double LP_myprice(double *bidp,double *askp,char *base,char *rel)
return(0.);
}
char *LP_myprices()
char *LP_myprices(int32_t iambob)
{
int32_t baseid,relid; double bid,ask; char *base,*rel; cJSON *item,*array;
array = cJSON_CreateArray();
@ -496,7 +496,7 @@ char *LP_myprices()
for (relid=0; relid<LP_numpriceinfos; relid++)
{
rel = LP_priceinfos[relid].symbol;
if ( LP_myprice(&bid,&ask,base,rel) > SMALLVAL )
if ( LP_myprice(iambob,&bid,&ask,base,rel) > SMALLVAL )
{
item = cJSON_CreateObject();
jaddstr(item,"base",base);
@ -510,7 +510,7 @@ char *LP_myprices()
return(jprint(array,1));
}
int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
int32_t LP_mypriceset(int32_t iambob,int32_t *changedp,char *base,char *rel,double price)
{
struct LP_priceinfo *basepp=0,*relpp=0; struct LP_pubkey_info *pubp; double minprice,maxprice,margin,buymargin,sellmargin;
*changedp = 0;
@ -519,43 +519,46 @@ int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
if ( base != 0 && rel != 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
if ( price == 0. || fabs(basepp->myprices[relpp->ind] - price)/price > 0.001 )
if ( price == 0. || fabs(basepp->myprices[iambob][relpp->ind] - price)/price > 0.001 )
*changedp = 1;
sellmargin = relpp->sellmargins[basepp->ind];
buymargin = relpp->buymargins[basepp->ind];
margin = (sellmargin + buymargin) * 0.5;
if ( price == 0. )
if ( iambob != 0 )
{
relpp->minprices[basepp->ind] = 0.;
relpp->fixedprices[basepp->ind] = 0.;
relpp->buymargins[basepp->ind] = 0.;
relpp->sellmargins[basepp->ind] = 0.;
relpp->offsets[basepp->ind] = 0.;
relpp->factors[basepp->ind] = 0.;
LP_autoref_clear(base,rel);
margin = 0.;
}
else if ( (minprice= basepp->minprices[relpp->ind]) > SMALLVAL && price < minprice )
{
//printf("%s/%s price %.8f less than minprice %.8f\n",base,rel,price,minprice);
price = minprice * (1. - margin);
}
else if ( (maxprice= relpp->minprices[basepp->ind]) > SMALLVAL )
{
if ( price > (1. / maxprice) )
sellmargin = relpp->sellmargins[basepp->ind];
buymargin = relpp->buymargins[basepp->ind];
margin = (sellmargin + buymargin) * 0.5;
if ( price == 0. )
{
relpp->minprices[basepp->ind] = 0.;
relpp->fixedprices[basepp->ind] = 0.;
relpp->buymargins[basepp->ind] = 0.;
relpp->sellmargins[basepp->ind] = 0.;
relpp->offsets[basepp->ind] = 0.;
relpp->factors[basepp->ind] = 0.;
LP_autoref_clear(base,rel);
margin = 0.;
}
else if ( (minprice= basepp->minprices[relpp->ind]) > SMALLVAL && price < minprice )
{
//printf("%s/%s price %.8f less than minprice %.8f\n",base,rel,price,minprice);
price = minprice * (1. - margin);
}
else if ( (maxprice= relpp->minprices[basepp->ind]) > SMALLVAL )
{
//printf("%s/%s price %.8f less than maxprice %.8f, more than %.8f\n",base,rel,price,maxprice,1./maxprice);
price = (1. / maxprice) * (1. + margin);
if ( price > (1. / maxprice) )
{
//printf("%s/%s price %.8f less than maxprice %.8f, more than %.8f\n",base,rel,price,maxprice,1./maxprice);
price = (1. / maxprice) * (1. + margin);
}
}
}
/*else if ( basepp->myprices[relpp->ind] > SMALLVAL )
{
price = (basepp->myprices[relpp->ind] * 0.9) + (0.1 * price);
}*/
basepp->myprices[relpp->ind] = price; // ask
basepp->myprices[iambob][relpp->ind] = price; // ask
//printf("LP_mypriceset base.%s rel.%s <- price %.8f\n",base,rel,price);
//relpp->myprices[basepp->ind] = (1. / price); // bid, but best to do one dir at a time
if ( (pubp= LP_pubkeyadd(G.LP_mypub25519)) != 0 )
if ( iambob != 0 && (pubp= LP_pubkeyadd(G.LP_mypub25519)) != 0 )
{
pubp->timestamp = (uint32_t)time(NULL);
LP_pubkey_update(pubp,basepp->ind,relpp->ind,price,0,0,0,0,0);
@ -569,12 +572,12 @@ int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
return(-1);
}
double LP_price(char *base,char *rel)
double LP_price(int32_t iambob,char *base,char *rel)
{
struct LP_priceinfo *basepp; int32_t relind; double price = 0.;
if ( (basepp= LP_priceinfoptr(&relind,base,rel)) != 0 )
{
if ( (price= basepp->myprices[relind]) == 0. )
if ( (price= basepp->myprices[iambob][relind]) == 0. )
{
price = basepp->relvals[relind];
}
@ -582,19 +585,19 @@ double LP_price(char *base,char *rel)
return(price);
}
double LP_getmyprice(char *base,char *rel)
double LP_getmyprice(int32_t iambob,char *base,char *rel)
{
struct LP_priceinfo *basepp; int32_t relind; double price = 0.;
if ( (basepp= LP_priceinfoptr(&relind,base,rel)) != 0 )
{
if ( (price= basepp->myprices[relind]) == 0. )
if ( (price= basepp->myprices[iambob][relind]) == 0. )
{
}
}
return(price);
}
cJSON *LP_priceinfomatrix(int32_t usemyprices)
cJSON *LP_priceinfomatrix(int32_t iambob,int32_t usemyprices)
{
int32_t i,j,n,m; double total,sum,val; struct LP_priceinfo *pp; uint32_t now; struct LP_cacheinfo *ptr,*tmp; cJSON *vectorjson = cJSON_CreateObject();
now = (uint32_t)time(NULL);
@ -611,7 +614,7 @@ cJSON *LP_priceinfomatrix(int32_t usemyprices)
pp->diagval = sum = n = 0;
for (j=0; j<LP_numpriceinfos; j++)
{
if ( usemyprices == 0 || (val= pp->myprices[j]) == 0. )
if ( usemyprices == 0 || (val= pp->myprices[iambob][j]) == 0. )
val = pp->relvals[j];
if ( val > SMALLVAL )
{
@ -661,7 +664,7 @@ struct LP_priceinfo *LP_priceinfoadd(char *symbol)
pp->coinbits = stringbits(symbol);
pp->ind = LP_numpriceinfos++;
//LP_numpriceinfos++;
if ( (retjson= LP_priceinfomatrix(0)) != 0 )
if ( (retjson= LP_priceinfomatrix(1,0)) != 0 )
free_json(retjson);
return(pp);
}
@ -1016,7 +1019,7 @@ int64_t LP_KMDvalue(struct iguana_info *coin,int64_t balance)
KMDvalue = balance;
else
{
if ( (price= LP_price(coin->symbol,"KMD")) > SMALLVAL )
if ( (price= LP_price(1,coin->symbol,"KMD")) > SMALLVAL )
KMDvalue = price * balance;
}
}

194
iguana/exchanges/LP_privkey.c

@ -202,6 +202,66 @@ char *LP_secretaddresses(void *ctx,char *prefix,char *passphrase,int32_t n,uint8
return(jprint(retjson,1));
}
uint32_t komodo_segid32(char *coinaddr)
{
bits256 addrhash;
vcalc_sha256(0,(uint8_t *)&addrhash,(uint8_t *)coinaddr,(int32_t)strlen(coinaddr));
return(addrhash.uints[0]);
}
char *LP_gen64addrs(void *ctx,char *passphrase,uint8_t taddr,uint8_t pubtype)
{
int32_t i,segid,n=64; uint8_t tmptype,pubkey33[33],rmd160[20]; char str[65],str2[65],buf[8192],wifstr[64],coinaddr[64],coinaddrs[64][64],wifstrs[64][64]; uint64_t mask = 0; bits256 checkprivkey,privkey,pubkey; cJSON *retjson,*addrs,*array;
if ( passphrase == 0 || passphrase[0] == 0 )
passphrase = "password";
memset(coinaddrs,0,sizeof(coinaddrs));
memset(wifstrs,0,sizeof(wifstrs));
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
bitcoin_priv2pub(ctx,"KMD",pubkey33,coinaddr,privkey,taddr,pubtype);
//sprintf(output,"\"addresses\":[");
for (i=0; bitweight(mask)<64; i++)
{
sprintf(buf,"%s %03d",passphrase,i);
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)buf,(int32_t)strlen(buf));
bitcoin_priv2pub(ctx,"KMD",pubkey33,coinaddr,privkey,taddr,pubtype);
bitcoin_priv2wif("KMD",0,wifstr,privkey,188);
bitcoin_wif2priv("KMD",0,&tmptype,&checkprivkey,wifstr);
bitcoin_addr2rmd160("KMD",taddr,&tmptype,rmd160,coinaddr);
if ( bits256_cmp(checkprivkey,privkey) != 0 )
{
printf("WIF.(%s) error -> %s vs %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkprivkey));
free_json(retjson);
return(clonestr("{\"error\":\"couldnt validate wifstr\"}"));
}
else if ( tmptype != pubtype )
{
printf("checktype.%d != pubtype.%d\n",tmptype,pubtype);
free_json(retjson);
return(clonestr("{\"error\":\"couldnt validate pubtype\"}"));
}
segid = komodo_segid32(coinaddr) & 0x3f;
if ( (mask & (1LL << segid)) == 0 )
{
mask |= (1LL << segid);
strcpy(coinaddrs[segid],coinaddr);
strcpy(wifstrs[segid],wifstr);
printf("./komodo-cli -ac_name=POSTEST64 importprivkey %s "" %s\n",wifstr,bitweight(mask)<64?"false":"true");
}
//sprintf(output+strlen(output),"\\\"%s\\\"%c ",coinaddr,i<n-1?',':' ');
}
retjson = cJSON_CreateObject();
addrs = cJSON_CreateObject();
array = cJSON_CreateArray();
for (i=0; i<n; i++)
jaddstr(addrs,coinaddrs[i],wifstrs[i]);
jadd(retjson,"addrpairs",addrs);
for (i=0; i<n; i++)
jaddistr(array,coinaddrs[i]);
jadd(retjson,"addresses",array);
//printf("%s]\n",output);
return(jprint(retjson,1));
}
static const char base58_chars[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
int32_t LP_wifstr_valid(char *symbol,char *wifstr)
@ -227,7 +287,7 @@ int32_t LP_wifstr_valid(char *symbol,char *wifstr)
}
if ( n == 0 || A == 0 || a == 0 )
return(0);
if ( A > 5*a || a > 5*A || a > n*20 || A > n*20 ) // unlikely it is a real wif
if ( A > 5*a || a > 5*A || a > n*26 || A > n*26 ) // unlikely it is a real wif
{
printf("reject wif %s due to n.%d a.%d A.%d (%d %d %d %d)\n",wifstr,n,a,A,A > 5*a,a < 5*A,a > n*20,A > n*20);
return(0);
@ -292,6 +352,7 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
{
//static uint32_t counter;
bits256 privkey,userpub,zero,userpass,checkkey,tmpkey; char str[65],str2[65],tmpstr[128]; cJSON *retjson; uint8_t tmptype,sig[128]; int32_t notarized,siglen; uint64_t nxtaddr;
uint8_t rmd160[20];
if ( (wifstr == 0 || wifstr[0] == 0) && LP_wifstr_valid(coin->symbol,passphrase) > 0 )
{
wifstr = passphrase;
@ -339,7 +400,7 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
#ifndef NOTETOMIC
if ( coin->etomic[0] != 0 )
{
uint8_t check64[64],checktype,checkrmd160[20],rmd160[20]; char checkaddr[64],checkaddr2[64];
uint8_t check64[64],checktype,checkrmd160[20]; char checkaddr[64],checkaddr2[64];
if ( LP_etomic_priv2pub(check64,privkey) == 0 )
{
if ( memcmp(check64,coin->pubkey33+1,32) == 0 )
@ -374,8 +435,8 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
coin->counter++;
memcpy(G.LP_pubsecp,coin->pubkey33,33);
bitcoin_priv2wif(coin->symbol,coin->wiftaddr,tmpstr,privkey,coin->wiftype);
bitcoin_addr2rmd160(coin->symbol,coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr);
LP_privkeyadd(privkey,G.LP_myrmd160);
bitcoin_addr2rmd160(coin->symbol,coin->taddr,&tmptype,rmd160,coin->smartaddr);
LP_privkeyadd(privkey,rmd160);
G.LP_privkey = privkey;
if ( G.counter++ == 0 )
{
@ -415,13 +476,47 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
return(privkey);
}
void verusblocks(struct iguana_info *coin,char *coinaddr)
void verus_utxos(struct iguana_info *coin,char *coinaddr)
{
cJSON *array,*item; char buf[64],str[65]; int32_t i,m,vout,n=0; bits256 txid;
sprintf(buf,"[%d, 99999999, [\"%s\"]]",1,coinaddr);
array = bitcoin_json(coin,"listunspent",buf);
if ( array != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=m=0; i<n; i++)
{
item = jitem(array,i);
if ( fabs(jdouble(item,"amount") - 64.) < 0.00011 )
{
txid = jbits256(item,"txid");
vout = jint(item,"vout");
printf("%d: %s/v%d\n",m,bits256_str(str,txid),vout);
m++;
}
}
}
free_json(array);
}
printf("scanned %d utxos m.%d\n",n,m);
}
char *verusblocks()
{
bits256 hash,txid; uint8_t script[44]; double value,powsum,supply,possum,histo[1280],myhisto[1280]; int32_t numpow,numpos,num,locked,height,i,m,n,z,posflag,npos,npow; char hashstr[64],firstaddr[64],stakingaddr[64],*addr0,*lastaddr,*hexstr; cJSON *blockjson,*txobj,*vouts,*vout,*vout1,*sobj,*addresses,*txs;
bits256 hash,txid; uint8_t script[44]; double value,avestakedsize,stakedval,RTu3sum,powsum,supply,possum,histo[1280],myhisto[1280]; int32_t num10,num17,num20,num16,num23000,numpow,numpos,num,locked,height,i,m,n,z,gotblock,numstaked,posflag,npos,npow; char hashstr[64],firstaddr[64],stakingaddr[64],*addr0,*lastaddr,*hexstr; cJSON *blockjson,*txobj,*vouts,*vout,*vout1,*sobj,*addresses,*txs;
struct iguana_info *coin = LP_coinfind("VRSC");
if ( coin == 0 )
return(clonestr("{\"error\":\"VRSC not active\"}"));
char *coinaddr = "RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj";
if ( strcmp(coinaddr,coin->smartaddr) != 0 )
return(clonestr("{\"error\":\"mismatched smartaddr\"}"));
//verus_utxos(coin,coin->smartaddr);
hash = LP_getbestblockhash(coin);
memset(histo,0,sizeof(histo));
memset(myhisto,0,sizeof(myhisto));
possum = powsum = supply = 0.;
num23000 = num16 = num17 = num10 = num20 = numstaked = 0;
avestakedsize = possum = powsum = supply = RTu3sum = 0.;
numpow = numpos = num = npos = npow = 0;
if ( bits256_nonz(hash) != 0 )
{
@ -430,6 +525,7 @@ void verusblocks(struct iguana_info *coin,char *coinaddr)
while ( (blockjson= LP_blockjson(&height,coin->symbol,hashstr,0)) != 0 )
{
num++;
stakedval = 0.;
height = juint(blockjson,"height");
if ( (txs= jarray(&n,blockjson,"tx")) != 0 )
{
@ -437,6 +533,7 @@ void verusblocks(struct iguana_info *coin,char *coinaddr)
value = 0;
posflag = 0;
locked = 0;
gotblock = 0;
lastaddr = addr0 = "";
memset(script,0,sizeof(script));
memset(firstaddr,0,sizeof(firstaddr));
@ -451,6 +548,13 @@ void verusblocks(struct iguana_info *coin,char *coinaddr)
value = jdouble(vout,"value");
supply += value;
hexstr = 0;
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 )
{
if ( strcmp(hexstr,"2102ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92ac") == 0 || strcmp(hexstr,"2102aef0f54a967031f4c63b36d12741fbb9ca39713baedfff7f8c0d0d8ee14ee0ebac") == 0 || strcmp(hexstr,"76a914cc39e9e699f86b03a5cf1d7f2a0b411cf652641788ac") == 0 || strcmp(hexstr,"76a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac") == 0 )
{
gotblock = 1;
}
}
if ( m == 2 && (vout1= jitem(vouts,1)) != 0 )
{
// 6a2001039bbc0bb17576a9149a3af738444dd86b55c86752247aec2e7deb842688ac
@ -470,7 +574,7 @@ void verusblocks(struct iguana_info *coin,char *coinaddr)
locked = ((int32_t)script[6] << 16) + ((int32_t)script[5] << 8) + script[4];
addr0 = firstaddr;
} else printf("unexpected vout1.(%s) (%s).%d %.8f\n",jprint(vout1,0),hexstr!=0?hexstr:"",(int32_t)strlen(hexstr),jdouble(vout1,"value"));
} else printf("coinbase without opret (%s)\n",jprint(vouts,0));
} //else printf("coinbase without opret (%s)\n",jprint(vouts,0));
}
}
free_json(txobj);
@ -489,8 +593,12 @@ void verusblocks(struct iguana_info *coin,char *coinaddr)
else
{
strcpy(stakingaddr,lastaddr);
stakedval = jdouble(vout,"value");
avestakedsize += stakedval;
numstaked++;
//printf("stakedval %f\n",stakedval);
posflag = 1;
//printf("ht.%d found staking address.(%s)\n",height,stakingaddr);
//printf("ht.%d found staking address.(%s) %.8f (%s)\n",height,stakingaddr,stakedval,jprint(vout,0));
}
} else printf("no addresses[0] in (%s) %s\n",jprint(vout,0),sobj!=0?jprint(sobj,0):"");
} //else printf("n.%d m.%d no first out in lastvout.(%s)\n",n,m,jprint(txobj,0));
@ -500,17 +608,37 @@ void verusblocks(struct iguana_info *coin,char *coinaddr)
if ( posflag != 0 )
{
numpos++;
if ( num < 100 )
printf("ht.%-5d lock.%-7d PoS coinbase.(%s) staked.(%s) %.8f\n",height,locked,addr0,stakingaddr,value);
if ( strcmp(coinaddr,stakingaddr) == 0 || strcmp("RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC",stakingaddr) == 0 )
{
if (strcmp("RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC",stakingaddr) == 0 )
RTu3sum += value;
possum += value, npos++;
if ( num < 1500 )
printf("ht.%-5d lock.%-7d PoS cb.(%s) stake.(%s) %.8f %.8f\n",height,locked,addr0,stakingaddr,value,stakedval);
if ( height > 23000 )
{
char strbuf[64];
sprintf(strbuf,"%.0f",stakedval);
if ( strcmp(strbuf,"20") == 0 )
num20++;
else if ( strcmp(strbuf,"17") == 0 )
num17++;
else if ( strcmp(strbuf,"16") == 0 )
num16++;
else if ( strcmp(strbuf,"10") == 0 )
num10++;
else printf("got strbuf.(%s)\n",strbuf);
}
}
else if ( 0 && num < 100 )
printf("ht.%-5d lock.%-7d PoS cb.(%s) stake.(%s) %.8f %.8f\n",height,locked,addr0,stakingaddr,value,stakedval);
}
else
{
numpow++;
if ( num < 100 )
if ( num < 100 && strcmp(coinaddr,addr0) == 0 )
printf("ht.%-5d lock.%-7d PoW coinbase.(%s) %.8f\n",height,locked,addr0,value);
if ( strcmp(coinaddr,addr0) == 0 || strcmp("RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC",stakingaddr) == 0 )
if ( strcmp(coinaddr,addr0) == 0 || gotblock != 0 )
powsum += value, npow++;
}
histo[locked/1000] += value;
@ -521,24 +649,34 @@ void verusblocks(struct iguana_info *coin,char *coinaddr)
free_json(blockjson);
if ( height == 5040 )
break;
else if ( num == 1000 )
else if ( height == 23000 )
{
printf("num.%d PoW %.2f%% %.8f %d v %d PoS %.2f%% %.8f -> %.8f supply %.8f PoW %.1f%% PoS %.1f%% both %.1f%%\n",num,100.*(double)numpow/num,powsum,npow,npos,100.*(double)numpos/num,possum,powsum+possum,supply,100.*powsum/supply,100.*possum/supply,100.*(powsum+possum)/supply);
num23000 = num;
printf("num10.%d num16.%d num17.%d num20.%d / num23000.%d -> %.2f%% %.2f%% %.2f%% %.2f%% [%.3f %.3f %.3f %.3f] %.3f ave %.8f\n",num10,num16,num17,num20,num23000,100.*(double)num10/num23000,100.*(double)num16/num23000,100.*(double)num17/num23000,100.*(double)num20/num23000,(100.*(double)num10/num23000)/2.87,(100.*(double)num16/num23000)/10.5,(100.*(double)num17/num23000)/4.88,(100.*(double)num20/num23000)/5.74,(100.*(double)(num10+num16+num17+num20)/num23000)/24,avestakedsize/numstaked);
}
else if ( (num % 1000) == 0 || (num < 1000 && (num % 100) == 0) )
{
printf("num.%d PoW %.2f%% %.0f %d v %d PoS %.2f%% %.0f -> %.0f supply %.0f PoW %.1f%% PoS %.1f%% both %.1f%% RTu3 %.8f %.1f%%\n",num,100.*(double)numpow/num,powsum,npow,npos,100.*(double)numpos/num,possum,powsum+possum,supply,100.*powsum/supply,100.*possum/supply,100.*(powsum+possum)/supply,RTu3sum,100.*RTu3sum/supply);
}
}
}
if ( num > 0 )
{
for (i=0; i<sizeof(histo)/sizeof(*histo); i++)
if ( histo[i] != 0 )
printf("%d %.8f, ",i*1000,histo[i]);
printf("timelocked\n");
for (i=0; i<sizeof(myhisto)/sizeof(*myhisto); i++)
if ( myhisto[i] != 0 )
printf("%d %.8f, ",i*1000,myhisto[i]);
printf("mytimelocked\n");
printf("num.%d PoW %.2f%% %.8f %d v %d PoS %.2f%% %.8f -> %.8f supply %.8f PoW %.1f%% PoS %.1f%% both %.1f%%\n",num,100.*(double)numpow/num,powsum,npow,npos,100.*(double)numpos/num,possum,powsum+possum,supply,100.*powsum/supply,100.*possum/supply,100.*(powsum+possum)/supply);
if ( 0 )
{
for (i=0; i<sizeof(histo)/sizeof(*histo); i++)
if ( histo[i] != 0 )
printf("%d %.8f, ",i*1000,histo[i]);
printf("timelocked\n");
for (i=0; i<sizeof(myhisto)/sizeof(*myhisto); i++)
if ( myhisto[i] != 0 )
printf("%d %.8f, ",i*1000,myhisto[i]);
printf("mytimelocked\n");
}
printf("num.%d PoW %.2f%% %.8f %d v %d PoS %.2f%% %.8f -> %.8f supply %.8f PoW %.1f%% PoS %.1f%% both %.1f%% RTu3sum %.8f %.1f%%\n",num,100.*(double)numpow/num,powsum,npow,npos,100.*(double)numpos/num,possum,powsum+possum,supply,100.*powsum/supply,100.*possum/supply,100.*(powsum+possum)/supply,RTu3sum,100.*RTu3sum/supply);
printf("num10.%d num16.%d num17.%d num20.%d / num23000.%d -> %.2f%% %.2f%% %.2f%% %.2f%% [%.3f %.3f %.3f %.3f] %.3f ave %.8f\n",num10,num16,num17,num20,num23000,100.*(double)num10/num23000,100.*(double)num16/num23000,100.*(double)num17/num23000,100.*(double)num20/num23000,(100.*(double)num10/num23000)/2.87,(100.*(double)num16/num23000)/10.5,(100.*(double)num17/num23000)/4.88,(100.*(double)num20/num23000)/5.74,(100.*(double)(num10+num16+num17+num20)/num23000)/24,avestakedsize/numstaked);
}
return(clonestr("{\"result\":\"success\"}"));
}
void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase)
@ -559,10 +697,6 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase)
if ( bits256_nonz(privkey) == 0 || coin->smartaddr[0] == 0 )
{
privkey = LP_privkeycalc(ctx,pubkey33,&pubkey,coin,passphrase,"");
if ( strcmp(coin->symbol,"VRSC") == 0 && strcmp("RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj",coin->smartaddr) == 0 )
{
verusblocks(coin,coin->smartaddr);
}
}
}
//printf("i.%d of %d\n",i,LP_numcoins);
@ -580,6 +714,7 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase)
int32_t LP_passphrase_init(char *passphrase,char *gui,uint16_t netid,char *seednode)
{
static void *ctx; struct iguana_info *coin,*tmp; int32_t counter;
uint8_t pubkey33[100];
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( G.LP_pendingswaps != 0 )
@ -614,8 +749,11 @@ int32_t LP_passphrase_init(char *passphrase,char *gui,uint16_t netid,char *seedn
memset(&G,0,sizeof(G));
G.netid = netid;
safecopy(G.seednode,seednode,sizeof(G.seednode));
vcalc_sha256(0,G.LP_passhash.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
LP_privkey_updates(ctx,LP_mypubsock,passphrase);
bitcoin_pubkey33(ctx, pubkey33, G.LP_privkey);
calc_rmd160_sha256(G.LP_myrmd160, pubkey33, 33);
init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20);
G.LP_sessionid = (uint32_t)time(NULL);
safecopy(G.gui,gui,sizeof(G.gui));

116
iguana/exchanges/LP_remember.c

@ -13,10 +13,33 @@
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include "LP_include.h"
#include "../../includes/cJSON.h"
//
// LP_remember.c
// marketmaker
//
char *coin_name_by_tx_index(struct LP_swap_remember *rswap, int32_t tx_index)
{
switch (tx_index) {
case BASILISK_MYFEE:
case BASILISK_OTHERFEE:
case BASILISK_ALICEPAYMENT:
case BASILISK_ALICERECLAIM:
case BASILISK_BOBSPEND:
return rswap->dest;
case BASILISK_BOBDEPOSIT:
case BASILISK_BOBPAYMENT:
case BASILISK_BOBRECLAIM:
case BASILISK_BOBREFUND:
case BASILISK_ALICESPEND:
case BASILISK_ALICECLAIM:
return rswap->src;
default:
return 0;
}
}
void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,int32_t scriptlen)
{
int32_t i; char scriptstr[513];
@ -70,6 +93,13 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx
fprintf(fp,",\"bobtomic\":\"%s\"",swap->I.bobtomic);
if ( swap->I.etomicsrc[0] != 0 )
fprintf(fp,",\"etomicsrc\":\"%s\"",swap->I.etomicsrc);
#ifndef NOTETOMIC
if (swap->myfee.I.ethTxid[0] != 0) {
fprintf(fp,",\"aliceFeeEthTx\":\"%s\"", swap->myfee.I.ethTxid);
}
if (swap->otherfee.I.ethTxid[0] != 0) {
fprintf(fp,",\"aliceFeeEthTx\":\"%s\"", swap->otherfee.I.ethTxid);
}
if (swap->bobdeposit.I.ethTxid[0] != 0) {
fprintf(fp,",\"bobDepositEthTx\":\"%s\"", swap->bobdeposit.I.ethTxid);
}
@ -80,6 +110,9 @@ void basilisk_dontforget(struct basilisk_swap *swap,struct basilisk_rawtx *rawtx
fprintf(fp,",\"alicePaymentEthTx\":\"%s\"", swap->alicepayment.I.ethTxid);
}
fprintf(fp,",\"aliceRealSat\":\"%" PRId64 "\"", swap->I.alicerealsat);
fprintf(fp,",\"bobRealSat\":\"%" PRId64 "\"", swap->I.bobrealsat);
#endif
fprintf(fp,",\"alicecoin\":\"%s\"",swap->I.alicestr);
if ( swap->I.alicetomic[0] != 0 )
fprintf(fp,",\"alicetomic\":\"%s\"",swap->I.alicetomic);
@ -250,6 +283,22 @@ void basilisk_dontforget_update(struct basilisk_swap *swap,struct basilisk_rawtx
{
if ( (reqjson= cJSON_Parse(fstr)) != 0 )
{
#ifndef NOTETOMIC
if (strcmp(rawtx->symbol,"ETOMIC") == 0) {
jdelete(reqjson,"txid");
jdelete(reqjson,"amount");
jaddstr(reqjson,"txid", rawtx->I.ethTxid);
jaddnum(reqjson,"amount", dstr(rawtx->I.eth_amount));
jdelete(reqjson, "coin");
if (rawtx == &swap->myfee || rawtx == &swap->otherfee || rawtx == &swap->alicepayment || rawtx == &swap->bobspend || rawtx == &swap->alicereclaim) {
jaddstr(reqjson,"coin", swap->I.alicestr);
}
if (rawtx == &swap->bobdeposit || rawtx == &swap->bobrefund || rawtx == &swap->aliceclaim || rawtx == &swap->bobpayment || rawtx == &swap->bobreclaim || rawtx == &swap->alicespend) {
jaddstr(reqjson,"coin", swap->I.bobstr);
}
}
#endif
if ( jobj(reqjson,"method") != 0 )
jdelete(reqjson,"method");
jaddstr(reqjson,"method","update");
@ -429,9 +478,9 @@ int32_t basilisk_isbobcoin(int32_t iambob,int32_t ind)
case BASILISK_OTHERFEE: return(!iambob); break;
case BASILISK_BOBSPEND:
case BASILISK_ALICEPAYMENT:
case BASILISK_ALICERECLAIM:
case BASILISK_ALICECLAIM: return(0);
case BASILISK_ALICERECLAIM: return(0);
break;
case BASILISK_ALICECLAIM:
case BASILISK_BOBDEPOSIT:
case BASILISK_ALICESPEND:
case BASILISK_BOBPAYMENT:
@ -656,13 +705,31 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap)
jaddnum(item,"alicetxfee",dstr(rswap->Atxfee));
jadd64bits(item,"aliceid",rswap->aliceid);
array = cJSON_CreateArray();
cJSON *tx_chain = cJSON_CreateArray();
for (i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
{
if ( rswap->sentflags[i] != 0 )
jaddistr(array,txnames[i]);
if ( rswap->sentflags[i] != 0 ) {
jaddistr(array, txnames[i]);
cJSON *tx = cJSON_CreateObject();
jaddstr(tx, "stage", txnames[i]);
jaddstr(tx, "coin", coin_name_by_tx_index(rswap, i));
#ifndef NOTETOMIC
if (LP_etomic_is_empty_tx_id(rswap->eth_tx_ids[i]) == 0) {
jaddstr(tx, "txid", rswap->eth_tx_ids[i]);
jaddnum(tx, "amount", dstr(rswap->eth_values[i]));
} else {
#endif
jaddbits256(tx, "txid", rswap->txids[i]);
jaddnum(tx, "amount", dstr(rswap->values[i]));
#ifndef NOTETOMIC
}
#endif
jaddi(tx_chain, tx);
}
if ( rswap->txbytes[i] != 0 )
free(rswap->txbytes[i]), rswap->txbytes[i] = 0;
}
jadd(item, "txChain", tx_chain);
jadd(item,"sentflags",array);
array = cJSON_CreateArray();
for (i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
@ -681,6 +748,7 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap)
jaddbits256(item,"paymentspent",rswap->paymentspent);
jaddbits256(item,"Apaymentspent",rswap->Apaymentspent);
jaddbits256(item,"depositspent",rswap->depositspent);
jaddbits256(item,"alicedexfee",rswap->iambob == 0 ? rswap->txids[BASILISK_MYFEE] : rswap->txids[BASILISK_OTHERFEE]);
return(item);
}
@ -901,16 +969,32 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap,int32_t forceflag)
strcpy(rswap->etomicdest,jstr(txobj,"etomicdest"));
}
rswap->bobrealsat = jint(txobj, "bobRealSat");
rswap->alicerealsat = jint(txobj, "aliceRealSat");
if (jstr(txobj,"aliceFeeEthTx") != 0) {
if (rswap->iambob == 0) {
strcpy(rswap->eth_tx_ids[BASILISK_MYFEE], jstr(txobj, "aliceFeeEthTx"));
rswap->eth_values[BASILISK_MYFEE] = LP_DEXFEE(rswap->alicerealsat);
} else {
strcpy(rswap->eth_tx_ids[BASILISK_OTHERFEE], jstr(txobj, "aliceFeeEthTx"));
rswap->eth_values[BASILISK_OTHERFEE] = LP_DEXFEE(rswap->alicerealsat);
}
}
if (jstr(txobj,"bobDepositEthTx") != 0) {
strcpy(rswap->bobDepositEthTx, jstr(txobj,"bobDepositEthTx"));
strcpy(rswap->eth_tx_ids[BASILISK_BOBDEPOSIT], jstr(txobj,"bobDepositEthTx"));
rswap->eth_values[BASILISK_BOBDEPOSIT] = LP_DEPOSITSATOSHIS(rswap->bobrealsat);
}
if (jstr(txobj,"bobPaymentEthTx") != 0) {
strcpy(rswap->bobPaymentEthTx, jstr(txobj,"bobPaymentEthTx"));
strcpy(rswap->eth_tx_ids[BASILISK_BOBPAYMENT], jstr(txobj,"bobPaymentEthTx"));
rswap->eth_values[BASILISK_BOBPAYMENT] = rswap->bobrealsat;
}
if (jstr(txobj,"alicePaymentEthTx") != 0) {
strcpy(rswap->alicePaymentEthTx, jstr(txobj,"alicePaymentEthTx"));
strcpy(rswap->eth_tx_ids[BASILISK_ALICEPAYMENT], jstr(txobj,"alicePaymentEthTx"));
rswap->eth_values[BASILISK_ALICEPAYMENT] = rswap->alicerealsat;
}
if (jstr(txobj,"bobtomic") != 0) {
@ -1275,6 +1359,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
{
char *aliceSpendEthTxId = LP_etomicalice_spends_bob_payment(&rswap);
if (aliceSpendEthTxId != NULL) {
strcpy(rswap.eth_tx_ids[BASILISK_ALICESPEND], aliceSpendEthTxId);
rswap.eth_values[BASILISK_ALICESPEND] = rswap.bobrealsat;
free(aliceSpendEthTxId);
} else {
printf("Alice spend ETH tx send failed!\n");
@ -1324,6 +1410,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
{
char *aliceClaimsEthTxId = LP_etomicalice_claims_bob_deposit(&rswap);
if (aliceClaimsEthTxId != NULL) {
strcpy(rswap.eth_tx_ids[BASILISK_ALICECLAIM], aliceClaimsEthTxId);
rswap.eth_values[BASILISK_ALICECLAIM] = LP_DEPOSITSATOSHIS(rswap.bobrealsat);
free(aliceClaimsEthTxId);
} else {
printf("Alice Bob deposit claim ETH tx failed!\n");
@ -1356,7 +1444,13 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
if ( rswap.alicetomic[0] != 0 )
{
char *aliceReclaimEthTx = LP_etomicalice_reclaims_payment(&rswap);
free(aliceReclaimEthTx);
if (aliceReclaimEthTx != NULL) {
strcpy(rswap.eth_tx_ids[BASILISK_ALICERECLAIM], aliceReclaimEthTx);
rswap.eth_values[BASILISK_ALICERECLAIM] = rswap.alicerealsat;
free(aliceReclaimEthTx);
} else {
printf("Alice could not reclaim ETH/ERC20 payment!\n");
}
}
#endif
}
@ -1400,6 +1494,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
{
char *bobSpendEthTx = LP_etomicbob_spends_alice_payment(&rswap);
if (bobSpendEthTx != NULL) {
strcpy(rswap.eth_tx_ids[BASILISK_BOBSPEND], bobSpendEthTx);
rswap.eth_values[BASILISK_BOBSPEND] = rswap.alicerealsat;
free(bobSpendEthTx);
} else {
printf("Bob spends Alice payment ETH tx send failed!\n");
@ -1437,6 +1533,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
{
char *bobReclaimEthTx = LP_etomicbob_reclaims_payment(&rswap);
if (bobReclaimEthTx != NULL) {
strcpy(rswap.eth_tx_ids[BASILISK_BOBRECLAIM], bobReclaimEthTx);
rswap.eth_values[BASILISK_BOBRECLAIM] = rswap.bobrealsat;
free(bobReclaimEthTx);
} else {
printf("Bob reclaims payment ETH tx send failed!\n");
@ -1490,6 +1588,8 @@ cJSON *basilisk_remember(int32_t fastflag,int64_t *KMDtotals,int64_t *BTCtotals,
{
char *bobRefundsEthTx = LP_etomicbob_refunds_deposit(&rswap);
if (bobRefundsEthTx != NULL) {
strcpy(rswap.eth_tx_ids[BASILISK_BOBREFUND], bobRefundsEthTx);
rswap.eth_values[BASILISK_BOBREFUND] = LP_DEPOSITSATOSHIS(rswap.bobrealsat);
free(bobRefundsEthTx);
} else {
printf("Bob refunds deposit ETH tx send failed!\n");

34
iguana/exchanges/LP_rpc.c

@ -137,6 +137,12 @@ int32_t LP_getheight(int32_t *notarizedp,struct iguana_info *coin)
uint64_t LP_RTsmartbalance(struct iguana_info *coin)
{
#ifndef NOTETOMIC
if (coin->etomic[0] != 0) {
int error = 0;
return LP_etomic_get_balance(coin, coin->smartaddr, &error);
}
#endif
cJSON *array,*item; char buf[512],*retstr; int32_t i,n; uint64_t valuesum,value; bits256 zero;
valuesum = 0;
memset(zero.bytes,0,sizeof(zero));
@ -249,18 +255,21 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
if ( bits256_nonz(txid) == 0 )
return(cJSON_Parse("{\"error\":\"null txid\"}"));
if ( coin->electrum == 0 )
{
sprintf(buf,"[\"%s\", %d, true]",bits256_str(str,txid),vout);
return(bitcoin_json(coin,"gettxout",buf));
}
else
{
if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts )
{
if ( tx->outpoints[vout].spendheight > 0 )
{
//fprintf(stderr,"LP_gettxout (%s) tx->outpoints[vout].spendheight > 0\n",coinaddr);
return(0);
}
//return(LP_gettxout_json(txid,vout,tx->height,tx->outpoints[vout].coinaddr,tx->outpoints[vout].value));
}
sprintf(buf,"[\"%s\", %d, true]",bits256_str(str,txid),vout);
return(bitcoin_json(coin,"gettxout",buf));
}
else
{
if ( coinaddr[0] == 0 )
{
if ( (txobj= electrum_transaction(&height,symbol,coin->electrum,&txobj,txid,0)) != 0 )
@ -275,7 +284,10 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 )
{
if ( up->spendheight > 0 )
{
//fprintf(stderr,"LP_gettxout (%s) up->spendheight > 0\n",coinaddr);
return(0);
}
//return(LP_gettxout_json(txid,vout,up->U.height,coinaddr,up->U.value));
}
memset(zero.bytes,0,sizeof(zero));
@ -401,6 +413,8 @@ int32_t LP_address_isvalid(char *symbol,char *address)
int32_t isvalid = 0; cJSON *retjson;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( strcmp(symbol,"BCH") == 0 && (address[0] == '1' || address[0] == '3') )
return(-1);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( jobj(retjson,"isvalid") != 0 && is_cJSON_True(jobj(retjson,"isvalid")) != 0 )
@ -750,7 +764,9 @@ again:
}
if ( strcmp(coin->estimatefeestr,"estimatesmartfee") == 0 && (rate= jdouble(errjson,"feerate")) != 0 )
{
printf("extracted feerate %.8f from estimatesmartfee\n",rate);
static uint32_t counter;
if ( counter++ < 10 )
printf("extracted feerate %.8f from estimatesmartfee\n",rate);
rate /= 1024.;
}
free_json(errjson);
@ -1036,7 +1052,7 @@ cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t hei
coin = LP_coinfind(symbol);
if ( coin == 0 || coin->electrum != 0 )
{
printf("unexpected electrum path for %s\n",symbol);
//printf("unexpected electrum path for %s\n",symbol);
return(0);
}
if ( blockhashstr == 0 )
@ -1135,7 +1151,7 @@ int32_t LP_txhasnotarization(bits256 *notarizedhashp,struct iguana_info *coin,bi
{
cJSON *txobj,*vins,*vin,*vouts,*vout,*spentobj,*sobj; char *hexstr; uint8_t script[1024]; bits256 spenttxid; uint64_t notarymask; int32_t i,j,numnotaries,len,spentvout,numvins,numvouts,hasnotarization = 0;
memset(notarizedhashp,0,sizeof(*notarizedhashp));
if ( (txobj= LP_gettx("LP_txhasnotarization",coin->symbol,txid,0)) != 0 )
if ( (txobj= LP_gettx("LP_txhasnotarization",coin->symbol,txid,1)) != 0 )
{
if ( (vins= jarray(&numvins,txobj,"vin")) != 0 )
{
@ -1147,7 +1163,7 @@ int32_t LP_txhasnotarization(bits256 *notarizedhashp,struct iguana_info *coin,bi
vin = jitem(vins,i);
spenttxid = jbits256(vin,"txid");
spentvout = jint(vin,"vout");
if ( (spentobj= LP_gettx("LP_txhasnotarization",coin->symbol,spenttxid,0)) != 0 )
if ( (spentobj= LP_gettx("LP_txhasnotarization",coin->symbol,spenttxid,1)) != 0 )
{
if ( (vouts= jarray(&numvouts,spentobj,"vout")) != 0 )
{

7
iguana/exchanges/LP_scan.c

@ -23,7 +23,7 @@ int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
{
int32_t i,iter,numtx,checkht=-1; cJSON *blockobj,*txs,*txobj; bits256 txid; struct LP_transaction *tx;
portable_mutex_lock(&LP_blockinit_mutex);
if ( (blockobj= LP_blockjson(&checkht,coin->symbol,0,height)) != 0 && checkht == height )
if ( (blockobj= LP_blockjson(&checkht,coin->symbol,0,height)) != 0 && (checkht == 0 || checkht == height) )
{
if ( (txs= jarray(&numtx,blockobj,"tx")) != 0 )
{
@ -54,9 +54,10 @@ int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
free_json(blockobj);
}
portable_mutex_unlock(&LP_blockinit_mutex);
if ( checkht == height )
if ( checkht == 0 || checkht == height )
return(0);
else return(-1);
printf("%s blockinit error checkht.%d vs height.%d\n",ASSETCHAINS_SYMBOL,checkht,height);
return(-1);
}
int32_t LP_scanblockchain(struct iguana_info *coin,int32_t startheight,int32_t endheight)

58
iguana/exchanges/LP_signatures.c

@ -19,7 +19,7 @@
// marketmaker
//
struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector)
struct basilisk_request *LP_requestinit(struct basilisk_request *rp,bits256 srchash,bits256 desthash,char *src,uint64_t srcsatoshis,char *dest,uint64_t destsatoshis,uint32_t timestamp,uint32_t quotetime,int32_t DEXselector,int32_t fillflag,int32_t gtcflag)
{
struct basilisk_request R;
memset(rp,0,sizeof(*rp));
@ -45,6 +45,14 @@ cJSON *LP_quotejson(struct LP_quoteinfo *qp)
if ( jobj(retjson,"gui") == 0 )
jaddstr(retjson,"gui",qp->gui[0] != 0 ? qp->gui : LP_gui);
jaddstr(retjson,"uuid",qp->uuidstr);
if ( qp->maxprice != 0 )
jaddnum(retjson,"maxprice",qp->maxprice);
if ( qp->mpnet != 0 )
jaddnum(retjson,"mpnet",qp->mpnet);
if ( qp->gtc != 0 )
jaddnum(retjson,"gtc",qp->gtc);
if ( qp->fill != 0 )
jaddnum(retjson,"fill",qp->fill);
jadd64bits(retjson,"aliceid",qp->aliceid);
jaddnum(retjson,"tradeid",qp->tradeid);
jaddstr(retjson,"base",qp->srccoin);
@ -113,28 +121,36 @@ int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson)
{
uint32_t rid,qid; char etomic[64],activesymbol[65],*etomicstr;
memset(qp,0,sizeof(*qp));
qp->maxprice = jdouble(argjson,"maxprice");
qp->mpnet = juint(argjson,"mpnet");
qp->gtc = juint(argjson,"gtc");
qp->fill = juint(argjson,"fill");
safecopy(qp->gui,LP_gui,sizeof(qp->gui));
safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin));
safecopy(qp->uuidstr,jstr(argjson,"uuid"),sizeof(qp->uuidstr));
#ifndef NOTETOMIC
if ( LP_etomicsymbol(activesymbol,etomic,qp->srccoin) != 0 )
{
if ( (etomicstr= jstr(argjson,"bobtomic")) == 0 || strcmp(etomicstr,etomic) != 0 )
if ( (etomicstr= jstr(argjson,"bobtomic")) == 0 || compareAddresses(etomicstr,etomic) == 0 )
{
printf("etomic src mismatch (%s) vs (%s)\n",etomicstr!=0?etomicstr:"",etomic);
return(-1);
}
}
#endif
safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr));
safecopy(qp->etomicsrc,jstr(argjson,"etomicsrc"),sizeof(qp->etomicsrc));
safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin));
#ifndef NOTETOMIC
if ( LP_etomicsymbol(activesymbol,etomic,qp->destcoin) != 0 )
{
if ( (etomicstr= jstr(argjson,"alicetomic")) == 0 || strcmp(etomicstr,etomic) != 0 )
if ( (etomicstr= jstr(argjson,"alicetomic")) == 0 || compareAddresses(etomicstr,etomic) == 0 )
{
printf("etomic dest mismatch (%s) vs (%s)\n",etomicstr!=0?etomicstr:"",etomic);
return(-1);
}
}
#endif
safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr));
safecopy(qp->etomicdest,jstr(argjson,"etomicdest"),sizeof(qp->etomicdest));
qp->aliceid = j64bits(argjson,"aliceid");
@ -152,9 +168,9 @@ int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson)
qp->destvout = jint(argjson,"destvout");
qp->desthash = jbits256(argjson,"desthash");
qp->txfee = j64bits(argjson,"txfee");
if ( (qp->satoshis= j64bits(argjson,"satoshis")) > qp->txfee )
if ( (qp->satoshis= j64bits(argjson,"satoshis")) > qp->txfee && fabs(qp->maxprice) < SMALLVAL )
{
//qp->price = (double)qp->destsatoshis / (qp->satoshis = qp->txfee);
qp->maxprice = (double)qp->destsatoshis / (qp->satoshis - qp->txfee);
}
qp->destsatoshis = j64bits(argjson,"destsatoshis");
qp->desttxfee = j64bits(argjson,"desttxfee");
@ -442,6 +458,17 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re
jaddstr(reqjson,"pubsecp",pubsecpstr);
if ( (kmd= LP_coinfind("KMD")) != 0 && (ap= LP_address(kmd,kmd->smartaddr)) != 0 && ap->instantdex_credits != 0 )
jaddnum(reqjson,"credits",dstr(ap->instantdex_credits));
#ifndef NOTETOMIC
if (basecoin->etomic[0] != 0) {
int error = 0;
uint64_t etomic_coin_balance = LP_etomic_get_balance(basecoin, basecoin->smartaddr, &error);
jaddstr(reqjson,"utxocoin","ETH_OR_ERC20");
jaddnum(reqjson,"bal",dstr(etomic_coin_balance));
jaddnum(reqjson,"min",dstr(etomic_coin_balance));
jaddnum(reqjson,"max",dstr(etomic_coin_balance));
jaddnum(reqjson,"n",1);
} else
#endif
if ( (numutxos= LP_address_minmax(1,&median,&minsize,&maxsize,basecoin,basecoin->smartaddr)) != 0 )
{
//printf("send %s numutxos.%d median %.8f min %.8f max %.8f\n",base,numutxos,dstr(median),dstr(minsize),dstr(maxsize));
@ -717,13 +744,20 @@ void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_
jadd(reqjson,"proof",LP_instantdex_txids(0,coin->smartaddr));
}
msg = jprint(reqjson,1);
//printf("QUERY.(%s)\n",msg);
if ( IPC_ENDPOINT >= 0 )
LP_queuecommand(0,msg,IPC_ENDPOINT,-1,0);
memset(&zero,0,sizeof(zero));
if ( bits256_nonz(qp->srchash) != 0 )
LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->srchash,clonestr(msg));
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,clonestr(msg));
{
//printf("QUERY.(%s)\n",msg);
if ( IPC_ENDPOINT >= 0 )
LP_queuecommand(0,msg,IPC_ENDPOINT,-1,0);
memset(&zero,0,sizeof(zero));
LP_reserved_msg(1,qp->srccoin,qp->destcoin,zero,clonestr(msg));
//if ( bits256_nonz(qp->srchash) != 0 )
{
sleep(1);
LP_reserved_msg(1,qp->srccoin,qp->destcoin,qp->srchash,clonestr(msg));
}
}
if ( strcmp(method,"connect") == 0 && qp->mpnet != 0 && qp->gtc == 0 )
LP_mpnet_send(0,msg,1,qp->coinaddr);
free(msg);
}

135
iguana/exchanges/LP_socket.c

@ -25,6 +25,83 @@
#define WIN32_LEAN_AND_MEAN
#include <WinSock2.h>
#endif
#ifdef _WIN32
#include <WinSock2.h>
#endif
int32_t set_blocking_mode(int32_t sock,int32_t is_blocking) // from https://stackoverflow.com/questions/2149798/how-to-reset-a-socket-back-to-blocking-mode-after-i-set-it-to-nonblocking-mode?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
{
int32_t ret;
#ifdef _WIN32
/// @note windows sockets are created in blocking mode by default
// currently on windows, there is no easy way to obtain the socket's current blocking mode since WSAIsBlocking was deprecated
u_long non_blocking = is_blocking ? 0 : 1;
ret = (NO_ERROR == ioctlsocket(sock,FIONBIO,&non_blocking));
#else
const int flags = fcntl(sock, F_GETFL, 0);
if ((flags & O_NONBLOCK) && !is_blocking) { fprintf(stderr,"set_blocking_mode(): socket was already in non-blocking mode\n"); return ret; }
if (!(flags & O_NONBLOCK) && is_blocking) { fprintf(stderr,"set_blocking_mode(): socket was already in blocking mode\n"); return ret; }
ret = (0 == fcntl(sock, F_SETFL, is_blocking ? (flags ^ O_NONBLOCK) : (flags | O_NONBLOCK)));
#endif
if ( ret == 0 )
return(-1);
else return(0);
}
int32_t komodo_connect(int32_t sock,struct sockaddr *saddr,socklen_t addrlen)
{
struct timeval tv; fd_set wfd,efd; int32_t res,so_error; socklen_t len;
#ifdef _WIN32
set_blocking_mode(sock, 0);
#else
fcntl(sock, F_SETFL, O_NONBLOCK);
#endif // _WIN32
res = connect(sock,saddr,addrlen);
if ( res == -1 )
{
#ifdef _WIN32
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms737625%28v=vs.85%29.aspx - read about WSAEWOULDBLOCK return
errno = WSAGetLastError();
printf("[Decker] errno.%d --> ", errno);
if ( errno != EINPROGRESS && errno != WSAEWOULDBLOCK ) // connect failed, do something...
#else
if ( errno != EINPROGRESS ) // connect failed, do something...
#endif
{
printf("close socket ...\n");
closesocket(sock);
return(-1);
}
//printf("continue with select ...\n");
FD_ZERO(&wfd);
FD_SET(sock,&wfd);
FD_ZERO(&efd);
FD_SET(sock,&efd);
tv.tv_sec = 10;
tv.tv_usec = 0;
res = select(sock+1,NULL,&wfd,&efd,&tv);
if ( res == -1 ) // select failed, do something...
{
closesocket(sock);
return(-1);
}
if ( res == 0 ) // connect timed out...
{
closesocket(sock);
return(-1);
}
if ( FD_ISSET(sock,&efd) )
{
// connect failed, do something...
getsockopt(sock,SOL_SOCKET,SO_ERROR,&so_error,&len);
closesocket(sock);
return(-1);
}
}
set_blocking_mode(sock,1);
return(0);
}
int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port)
{
@ -124,25 +201,35 @@ int32_t LP_socket(int32_t bindflag,char *hostname,uint16_t port)
#endif
if ( bindflag == 0 )
{
//printf("call connect sock.%d\n",sock);
result = connect(sock,(struct sockaddr *)&saddr,addrlen);
//printf("called connect result.%d\n",result);
timeout.tv_sec = 2;
timeout.tv_usec = 0;
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout));
if ( result != 0 )
//#ifdef _WIN32
if ( 1 ) // connect using async to allow timeout, then switch to sync
{
if ( errno != ECONNRESET && errno != ENOTCONN && errno != ECONNREFUSED && errno != ETIMEDOUT && errno != EHOSTUNREACH )
uint32_t starttime = (uint32_t)time(NULL);
//printf("call connect sock.%d\n",sock);
result = komodo_connect(sock,(struct sockaddr *)&saddr,addrlen);
//printf("called connect result.%d lag.%d\n",result,(int32_t)(time(NULL) - starttime));
if ( result < 0 )
return(-1);
timeout.tv_sec = 10;
timeout.tv_usec = 0;
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout));
}
//#else
else
{
result = connect(sock,(struct sockaddr *)&saddr,addrlen);
if ( result != 0 )
{
//printf("%s(%s) port.%d failed: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno);
if ( errno != ECONNRESET && errno != ENOTCONN && errno != ECONNREFUSED && errno != ETIMEDOUT && errno != EHOSTUNREACH )
{
//printf("%s(%s) port.%d failed: %s sock.%d. errno.%d\n",bindflag!=0?"bind":"connect",hostname,port,strerror(errno),sock,errno);
}
if ( sock >= 0 )
closesocket(sock);
return(-1);
}
if ( sock >= 0 )
closesocket(sock);
return(-1);
}
timeout.tv_sec = 10;
timeout.tv_usec = 0;
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(void *)&timeout,sizeof(timeout));
//#endif
}
else
{
@ -422,7 +509,7 @@ cJSON *electrum_submit(char *symbol,struct electrum_info *ep,cJSON **retjsonp,ch
{
*retjsonp = 0;
sprintf(stratumreq,"{ \"jsonrpc\":\"2.0\", \"id\": %u, \"method\":\"%s\", \"params\": %s }\n",ep->stratumid,method,params);
//printf("%s %s",symbol,stratumreq);
//printf("timeout.%d exp.%d %s %s",timeout,(int32_t)(expiration-time(NULL)),symbol,stratumreq);
memset(ep->buf,0,ep->bufsize);
sitem = electrum_sitem(ep,stratumreq,timeout,retjsonp);
portable_mutex_lock(&ep->mutex); // this helps performance!
@ -1190,7 +1277,21 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
jaddnum(retjson,"restart",kickval);
}
}
#ifndef NOTETOMIC
if (strcmp(coin->symbol, "ETOMIC") == 0) {
cJSON *balance = cJSON_CreateObject();
electrum_address_getbalance(coin->symbol, ep, &balance, coin->smartaddr);
int64_t confirmed = get_cJSON_int(balance, "confirmed");
int64_t unconfirmed = get_cJSON_int(balance, "unconfirmed");
if ((confirmed + unconfirmed) < 20 * SATOSHIDEN && get_etomic_from_faucet(coin->smartaddr) != 1) {
coin->inactive = (uint32_t)time(NULL);
coin->electrum = ep->prev;
cJSON_Delete(balance);
return(cJSON_Parse("{\"error\":\"Could not get ETOMIC from faucet!\"}"));
}
cJSON_Delete(balance);
}
#endif
//printf("(%s)\n",jprint(retjson,0));
return(retjson);
}

2
iguana/exchanges/LP_statemachine.c

@ -3645,7 +3645,7 @@ if ( LP_pricevalid(price) > 0 )
{
LP_query(ctx,myipaddr,mypubsock,"connect",qp);
//price = LP_pricecache(qp,qp->srccoin,qp->destcoin,qp->txid,qp->vout);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-2*qp->txfee,qp->destcoin,qp->destsatoshis-2*qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector);
LP_requestinit(&qp->R,qp->srchash,qp->desthash,qp->srccoin,qp->satoshis-2*qp->txfee,qp->destcoin,qp->destsatoshis-2*qp->desttxfee,qp->timestamp,qp->quotetime,DEXselector,qp->fill,qp->gtc);
while ( time(NULL) < expiration )
{
if ( aliceutxo->S.swap != 0 )

86
iguana/exchanges/LP_swap.c

@ -854,7 +854,17 @@ void LP_bobloop(void *_swap)
expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
bobwaittimeout = LP_calc_waittimeout(bobstr);
alicewaittimeout = LP_calc_waittimeout(alicestr);
if ( swap != 0 )
#ifndef NOTETOMIC
if (swap->I.bobtomic[0] != 0 || swap->I.alicetomic[0] != 0) {
int error = 0;
uint64_t eth_balance = getEthBalance(swap->I.etomicsrc, &error);
if (eth_balance < 500000) {
err = -5000, printf("Bob ETH balance too low, aborting swap!\n");
}
}
#endif
if ( swap != 0 && err == 0)
{
if ( LP_waitsend("pubkeys",120,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
err = -2000, printf("error waitsend pubkeys\n");
@ -866,7 +876,6 @@ void LP_bobloop(void *_swap)
err = -2003, printf("error bobscripts deposit\n");
else
{
uint8_t error = 0;
swap->bobrefund.utxovout = 0;
swap->bobrefund.utxotxid = swap->bobdeposit.I.signedtxid;
basilisk_bobdeposit_refund(swap,swap->I.putduration);
@ -876,24 +885,32 @@ void LP_bobloop(void *_swap)
LP_unavailableset(swap->bobdeposit.utxotxid,swap->bobdeposit.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash);
if ( LP_waitfor(swap->N.pair,swap,bobwaittimeout,LP_verify_otherfee) < 0 )
{
error = 1;
err = -2004, printf("error waiting for alicefee\n");
}
if ( error == 0 )
if ( err == 0 )
{
if ( LP_swapdata_rawtxsend(swap->N.pair,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0) == 0 )
{
error = 1;
err = -2005, printf("error sending bobdeposit\n");
}
}
LP_unavailableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash);
if ( error == 0 && LP_waitfor(swap->N.pair,swap,alicewaittimeout,LP_verify_alicepayment) < 0 )
{
error = 1;
err = -2006, printf("error waiting for alicepayment\n");
if (err == 0) {
LP_unavailableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash);
m = swap->I.bobconfirms;
while ((n = LP_numconfirms(bobstr, swap->bobdeposit.I.destaddr, swap->bobdeposit.I.signedtxid, 0, 1)) < m) {
LP_swap_critical = (uint32_t) time(NULL);
LP_unavailableset(swap->bobpayment.utxotxid, swap->bobpayment.utxovout, (uint32_t) time(NULL) + 60, swap->I.otherhash);
char str[65];
printf("%d wait for bobdeposit %s numconfs.%d %s %s\n", n, swap->bobdeposit.I.destaddr, m, bobstr, bits256_str(str, swap->bobdeposit.I.signedtxid));
sleep(10);
}
printf("wait for alicepayment\n");
if (LP_waitfor(swap->N.pair, swap, bobwaittimeout + alicewaittimeout, LP_verify_alicepayment) < 0) {
err = -2006, printf("error waiting for alicepayment\n");
}
}
if (error == 0)
if (err == 0)
{
LP_swap_critical = (uint32_t)time(NULL);
if ( basilisk_bobscripts_set(swap,0,1) < 0 )
@ -901,6 +918,7 @@ void LP_bobloop(void *_swap)
else
{
m = swap->I.aliceconfirms;
LP_unavailableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash);
while ( (n= LP_numconfirms(alicestr,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) // sync with alice
{
LP_unavailableset(swap->bobpayment.utxotxid,swap->bobpayment.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash);
@ -927,7 +945,8 @@ void LP_bobloop(void *_swap)
LP_swap_endcritical = (uint32_t)time(NULL);
if ( err < 0 )
LP_failedmsg(swap->I.req.requestid,swap->I.req.quoteid,err,swap->uuidstr);
sleep(13);
if ( swap->I.aliceconfirms > 0 )
sleep(13);
LP_pendswap_add(swap->I.expiration,swap->I.req.requestid,swap->I.req.quoteid);
//swap->I.finished = LP_swapwait(swap->I.expiration,swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*3,swap->I.aliceconfirms == 0 ? 3 : 30);
basilisk_swap_finished(swap);
@ -939,6 +958,7 @@ void LP_bobloop(void *_swap)
void LP_aliceloop(void *_swap)
{
uint8_t *data; char bobstr[65],alicestr[65]; int32_t bobwaittimeout,alicewaittimeout,maxlen,n,m,err=0; uint32_t expiration; struct basilisk_swap *swap = _swap;
LP_alicequery_clear();
G.LP_pendingswaps++;
LP_etomicsymbol(bobstr,swap->I.bobtomic,swap->I.bobstr);
LP_etomicsymbol(alicestr,swap->I.alicetomic,swap->I.alicestr);
@ -947,7 +967,18 @@ void LP_aliceloop(void *_swap)
expiration = (uint32_t)time(NULL) + LP_SWAPSTEP_TIMEOUT;
bobwaittimeout = LP_calc_waittimeout(bobstr);
alicewaittimeout = LP_calc_waittimeout(alicestr);
if ( swap != 0 )
#ifndef NOTETOMIC
if (swap->I.bobtomic[0] != 0 || swap->I.alicetomic[0] != 0) {
int error = 0;
uint64_t eth_balance = getEthBalance(swap->I.etomicdest, &error);
if (eth_balance < 500000) {
err = -5001, printf("Alice ETH balance too low, aborting swap!\n");
}
}
#endif
if ( swap != 0 && err == 0)
{
printf("start swap iamalice pair.%d\n",swap->N.pair);
if ( LP_sendwait("pubkeys",120,swap->N.pair,swap,data,maxlen,LP_pubkeys_verify,LP_pubkeys_data) < 0 )
@ -973,6 +1004,7 @@ void LP_aliceloop(void *_swap)
while ( (n= LP_numconfirms(bobstr,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,0,1)) < m )
{
LP_swap_critical = (uint32_t)time(NULL);
LP_unavailableset(swap->alicepayment.utxotxid,swap->alicepayment.utxovout,(uint32_t)time(NULL)+60,swap->I.otherhash);
char str[65];printf("%d wait for bobdeposit %s numconfs.%d %s %s\n",n,swap->bobdeposit.I.destaddr,m,bobstr,bits256_str(str,swap->bobdeposit.I.signedtxid));
sleep(10);
}
@ -999,6 +1031,7 @@ void LP_aliceloop(void *_swap)
char str[65];printf("%d wait for bobpayment %s numconfs.%d %s %s\n",n,swap->bobpayment.I.destaddr,swap->I.bobconfirms,bobstr,bits256_str(str,swap->bobpayment.I.signedtxid));
sleep(10);
}
char str[65];printf("%d waited for bobpayment %s numconfs.%d %s %s\n",n,swap->bobpayment.I.destaddr,swap->I.bobconfirms,bobstr,bits256_str(str,swap->bobpayment.I.signedtxid));
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
}
@ -1009,7 +1042,8 @@ void LP_aliceloop(void *_swap)
LP_swap_endcritical = (uint32_t)time(NULL);
if ( err < 0 )
LP_failedmsg(swap->I.req.requestid,swap->I.req.quoteid,err,swap->uuidstr);
sleep(13);
if ( swap->I.bobconfirms > 0 )
sleep(13);
LP_pendswap_add(swap->I.expiration,swap->I.req.requestid,swap->I.req.quoteid);
//swap->I.finished = LP_swapwait(swap->I.expiration,swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*3,swap->I.aliceconfirms == 0 ? 3 : 30);
basilisk_swap_finished(swap);
@ -1178,6 +1212,16 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
free(swap);
return(0);
}
#ifndef NOTETOMIC
if (strcmp(alicestr, "ETOMIC") == 0) {
swap->I.alicerealsat = swap->I.alicesatoshis;
swap->I.alicesatoshis = 100000000;
}
if (strcmp(bobstr, "ETOMIC") == 0) {
swap->I.bobrealsat = swap->I.bobsatoshis;
swap->I.bobsatoshis = 100000000;
}
#endif
if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE )
swap->I.bobinsurance = LP_MIN_TXFEE;
if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < LP_MIN_TXFEE )
@ -1298,6 +1342,20 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
swap->bobpayment.utxotxid = qp->txid, swap->bobpayment.utxovout = qp->vout;
swap->bobdeposit.utxotxid = qp->txid2, swap->bobdeposit.utxovout = qp->vout2;
swap->alicepayment.utxotxid = qp->desttxid, swap->alicepayment.utxovout = qp->destvout;
#ifndef NOTETOMIC
if (strcmp(alicestr, "ETOMIC") == 0) {
swap->alicepayment.I.eth_amount = swap->I.alicerealsat;
if (swap->I.iambob == 1) {
swap->otherfee.I.eth_amount = LP_DEXFEE(swap->I.alicerealsat);
} else {
swap->myfee.I.eth_amount = LP_DEXFEE(swap->I.alicerealsat);
}
}
if (strcmp(bobstr, "ETOMIC") == 0) {
swap->bobpayment.I.eth_amount = swap->I.bobrealsat;
swap->bobdeposit.I.eth_amount = LP_DEPOSITSATOSHIS(swap->I.bobrealsat);
}
#endif
LP_mark_spent(bobstr,qp->txid,qp->vout);
LP_mark_spent(bobstr,qp->txid2,qp->vout2);
LP_mark_spent(alicestr,qp->desttxid,qp->destvout);

2
iguana/exchanges/LP_tradebots.c

@ -338,7 +338,7 @@ void LP_tradebot_timeslice(void *ctx,struct LP_tradebot *bot)
{
if ( remaining < 0.001 )
break;
if ( (retstr= LP_autobuy(ctx,0,LP_myipaddr,LP_mypubsock,bot->base,bot->rel,bot->maxprice,remaining/i,0,0,G.gui,0,destpubkey,tradeid,0)) != 0 )
if ( (retstr= LP_autobuy(ctx,0,LP_myipaddr,LP_mypubsock,bot->base,bot->rel,bot->maxprice,remaining/i,0,0,G.gui,0,destpubkey,tradeid,0,0,0)) != 0 )
{
if ( (retjson2= cJSON_Parse(retstr)) != 0 )
{

161
iguana/exchanges/LP_transaction.c

@ -1117,13 +1117,13 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_
preselected[numpre++] = up;
else
{
printf("couldnt add address_utxo %s/v%d after not finding\n",bits256_str(str,utxotxid),utxovout);
//printf("couldnt add address_utxo %s/v%d after not finding\n",bits256_str(str,utxotxid),utxovout);
sleep(1);
value = LP_txvalue(0,coin->symbol,utxotxid,utxovout);
LP_address_utxoadd(0,(uint32_t)time(NULL),"withdraw",coin,coin->smartaddr,utxotxid,utxovout,value,1,-1);
if ( (up= LP_address_utxofind(coin,coin->smartaddr,utxotxid,utxovout)) != 0 )
preselected[numpre++] = up;
else printf("second couldnt add address_utxo after not finding\n");
else printf("second couldnt add address_utxo %s/v%d after not finding\n",bits256_str(str,utxotxid),utxovout);
//return(0);
}
}
@ -1831,6 +1831,7 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
locktime = juint(argjson,"locktime");
txfee = juint(argjson,"txfee");
autofee = (strcmp(coin->symbol,"BTC") == 0);
//printf("LP_withdraw: %s/v%d %s\n",bits256_str(str,utxotxid),utxovout,jprint(outputs,0));
if ( txfee == 0 )
{
autofee = 1;
@ -1886,7 +1887,7 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
if ( autofee != 0 && iter == 0 && strcmp(coin->symbol,"BTC") == 0 )
{
txfee = newtxfee = LP_txfeecalc(coin,0,datalen);
printf("txfee %.8f -> newtxfee %.8f, numvins.%d\n",dstr(txfee),dstr(newtxfee),numvins);
printf("txfee %.8f -> newtxfee %.8f, numvins.%d datalen.%d\n",dstr(txfee),dstr(newtxfee),numvins,datalen);
for (i=0; i<numvins; i++)
{
item = jitem(vins,i);
@ -1949,7 +1950,7 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
char *LP_autosplit(struct iguana_info *coin)
{
char *retstr; cJSON *argjson,*withdrawjson,*outputs,*item; int64_t total,balance,halfval,txfee;
char *retstr; cJSON *argjson,*withdrawjson,*outputs,*item; int64_t total,balance,txfee;
if ( coin->etomic[0] == 0 )
{
if ( coin->electrum != 0 )
@ -1961,17 +1962,21 @@ char *LP_autosplit(struct iguana_info *coin)
//printf("balance %.8f, txfee %.8f, threshold %.8f\n",dstr(balance),dstr(txfee),dstr((1000000 - (txfee + 100000))));
if ( balance > txfee && balance >= (1000000 - (txfee + 100000)) )
{
halfval = (balance / 100) * 45;
// .95 / .02 / .02 / 0.005
//halfval = (balance / 100) * 45;
argjson = cJSON_CreateObject();
outputs = cJSON_CreateArray();
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,dstr(halfval));
jaddnum(item,coin->smartaddr,dstr(balance/100) * 95);
jaddi(outputs,item);
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,dstr(halfval));
jaddnum(item,coin->smartaddr,dstr(balance/50));
jaddi(outputs,item);
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,dstr(balance - 2*halfval));
jaddnum(item,coin->smartaddr,dstr(balance/50));
jaddi(outputs,item);
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,0.0001);
jaddi(outputs,item);
jadd(argjson,"outputs",outputs);
jaddnum(argjson,"broadcast",1);
@ -1985,6 +1990,43 @@ char *LP_autosplit(struct iguana_info *coin)
return(clonestr("{\"error\":\"couldnt autosplit\"}"));
}
char *LP_autofillbob(struct iguana_info *coin,uint64_t satoshis)
{
char *retstr; cJSON *argjson,*withdrawjson,*outputs,*item; int64_t total,balance,txfee;
if ( coin->etomic[0] == 0 )
{
if ( coin->electrum != 0 )
balance = LP_unspents_load(coin->symbol,coin->smartaddr);
else balance = LP_RTsmartbalance(coin);
if ( strcmp("BTC",coin->symbol) == 0 )
txfee = LP_txfeecalc(coin,0,1000);
balance -= (txfee + 1000000);
if ( balance < (satoshis<<2) )
return(clonestr("{\"error\":\"couldnt autofill balance too small\"}"));
if ( balance > satoshis+3*txfee && balance >= (txfee + 1000000) )
{
argjson = cJSON_CreateObject();
outputs = cJSON_CreateArray();
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,dstr(satoshis + 3000000));
jaddi(outputs,item);
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,dstr(LP_DEPOSITSATOSHIS(satoshis) + 3000000));
jaddi(outputs,item);
item = cJSON_CreateObject();
jaddnum(item,coin->smartaddr,0.0001);
jaddi(outputs,item);
jadd(argjson,"outputs",outputs);
jaddnum(argjson,"broadcast",0);
jaddstr(argjson,"coin",coin->symbol);
retstr = LP_withdraw(coin,argjson);
free_json(argjson);
return(retstr);
} else return(clonestr("{\"error\":\"balance too small to autosplit, please make more deposits\"}"));
}
return(clonestr("{\"error\":\"couldnt autofill etomic needs separate support\"}"));
}
char *LP_movecoinbases(char *symbol)
{
static bits256 zero; bits256 utxotxid,txid; struct iguana_info *coin; cJSON *retjson,*outputs,*argjson,*txids,*unspents,*item,*gen,*output; int32_t i,n,utxovout; char *retstr,*hexstr;
@ -2045,31 +2087,112 @@ char *LP_movecoinbases(char *symbol)
#ifndef NOTETOMIC
char *LP_eth_tx_fee(struct iguana_info *coin, char *dest_addr, char *amount, int64_t gas, int64_t gas_price)
{
bits256 privkey;
cJSON *retjson = cJSON_CreateObject();
int64_t actual_gas_price = 0, actual_gas = 0;
char privkey_str[70];
if (gas_price > 0) {
actual_gas_price = gas_price;
} else {
actual_gas_price = getGasPriceFromStation(0);
if (actual_gas_price == 0) {
return (clonestr("{\"error\":\"Couldn't get gas price from station!\"}"));
}
}
cJSON_AddNumberToObject(retjson, "gas_price", actual_gas_price);
if (gas > 0) {
actual_gas = gas;
} else if (strcmp(coin->symbol, "ETH") == 0) {
actual_gas = 21000;
} else {
privkey = LP_privkey(coin->symbol, coin->smartaddr, coin->taddr);
uint8arrayToHex(privkey_str, privkey.bytes, 32);
actual_gas = estimate_erc20_gas(coin->etomic, dest_addr, amount, privkey_str, coin->decimals);
if (actual_gas == 0) {
return (clonestr("{\"error\":\"Couldn't estimate erc20 transfer gas usage!\"}"));
}
}
cJSON_AddNumberToObject(retjson, "gas", actual_gas);
double_t eth_fee = (actual_gas_price * actual_gas) / 1000000000.0;
cJSON_AddNumberToObject(retjson, "eth_fee", eth_fee);
return(jprint(retjson,1));
}
char *LP_eth_withdraw(struct iguana_info *coin,cJSON *argjson)
{
cJSON *retjson = cJSON_CreateObject();
cJSON *gas_json = cJSON_GetObjectItem(argjson, "gas");
cJSON *gas_price_json = cJSON_GetObjectItem(argjson, "gas_price");
char *dest_addr, *tx_id, privkey_str[70], amount_str[100];
int64_t amount;
int64_t amount = 0, gas = 0, gas_price = 0, broadcast = 0;
bits256 privkey;
dest_addr = jstr(argjson, "to");
if (dest_addr == NULL) {
return(clonestr("{\"error\":\"param 'to' is required!\"}"));
}
if (isValidAddress(dest_addr) == 0) {
return(clonestr("{\"error\":\"'to' address is not valid!\"}"));
}
amount = jdouble(argjson, "amount") * 100000000;
privkey = LP_privkey(coin->symbol, coin->smartaddr, coin->taddr);
uint8arrayToHex(privkey_str, privkey.bytes, 32);
if (amount == 0) {
return(clonestr("{\"error\":\"'amount' is not set or equal to zero!\"}"));
}
if (gas_json != NULL && is_cJSON_Number(gas_json)) {
gas = gas_json->valueint;
if (gas < 21000) {
return (clonestr("{\"error\":\"'gas' can't be lower than 21000!\"}"));
}
}
if (gas_price_json != NULL && is_cJSON_Number(gas_price_json)) {
gas_price = gas_price_json->valueint;
if (gas_price < 1) {
return (clonestr("{\"error\":\"'gas_price' can't be lower than 1!\"}"));
}
}
broadcast = jint(argjson, "broadcast");
satoshisToWei(amount_str, amount);
if (strcmp(coin->symbol, "ETH") == 0) {
tx_id = sendEth(dest_addr, amount_str, privkey_str, 0);
if (broadcast == 1) {
privkey = LP_privkey(coin->symbol, coin->smartaddr, coin->taddr);
uint8arrayToHex(privkey_str, privkey.bytes, 32);
if (strcmp(coin->symbol, "ETH") == 0) {
tx_id = sendEth(dest_addr, amount_str, privkey_str, 0, gas, gas_price, 0);
} else {
tx_id = sendErc20(coin->etomic, dest_addr, amount_str, privkey_str, 0, gas, gas_price, 0, coin->decimals);
}
if (tx_id != NULL) {
jaddstr(retjson, "tx_id", tx_id);
free(tx_id);
} else {
jaddstr(retjson, "error", "Error sending transaction");
}
return (jprint(retjson, 1));
} else {
tx_id = sendErc20(coin->etomic, dest_addr, amount_str, privkey_str, 0);
return LP_eth_tx_fee(coin, dest_addr, amount_str, gas, gas_price);
}
jaddstr(retjson, "tx_id", tx_id);
return(jprint(retjson,1));
}
char *LP_eth_gas_price()
{
cJSON *retjson = cJSON_CreateObject();
uint64_t gas_price = getGasPriceFromStation(0);
if (gas_price > 0) {
cJSON_AddNumberToObject(retjson, "gas_price", gas_price);
} else {
cJSON_AddStringToObject(retjson, "error", "Could not get gas price from station!");
}
return(jprint(retjson,1));
}
#endif
int32_t basilisk_rawtx_gen(void *ctx,char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey,uint8_t *changermd160,char *vinaddr)
{
struct iguana_info *coin; int32_t len,retval=-1; char *retstr,*hexstr; cJSON *argjson,*outputs,*item,*retjson,*obj;
@ -2196,7 +2319,7 @@ int32_t LP_swap_getcoinaddr(char *symbol,char *coinaddr,bits256 txid,int32_t vou
{
cJSON *retjson;
coinaddr[0] = 0;
if ( (retjson= LP_gettx("LP_swap_getcoinaddr",symbol,txid,0)) != 0 )
if ( (retjson= LP_gettx("LP_swap_getcoinaddr",symbol,txid,1)) != 0 )
{
LP_txdestaddr(coinaddr,txid,vout,retjson);
free_json(retjson);

49
iguana/exchanges/LP_utxo.c

@ -699,7 +699,8 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr
//printf("address balance call LP_listunspent %s electrum.%p etomic.%d\n",coin->symbol,coin->electrum,coin->etomic[0]);
#ifndef NOTETOMIC
if (coin->etomic[0] != 0) {
balance = LP_etomic_get_balance(coin, coinaddr);
int error = 0;
balance = LP_etomic_get_balance(coin, coinaddr, &error);
} else
#endif
if ( coin->electrum == 0 )
@ -724,7 +725,7 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr
}
else
{
if ( strcmp(coin->smartaddr,coinaddr) != 0 )
//if ( strcmp(coin->smartaddr,coinaddr) != 0 )
{
if ( (retjson= electrum_address_listunspent(coin->symbol,coin->electrum,&retjson,coinaddr,2,zero,zero)) != 0 )
free_json(retjson);
@ -787,7 +788,14 @@ cJSON *LP_balances(char *coinaddr)
}
else
{
if ( (balance= LP_RTsmartbalance(coin)) != 0 )
#ifndef NOTETOMIC
if (coin->etomic[0] == 0 || coin->inactive == 0) {
#endif
balance = LP_RTsmartbalance(coin);
#ifndef NOTETOMIC
}
#endif
if ( balance != 0 )
{
item = cJSON_CreateObject();
jaddstr(item,"coin",coin->symbol);
@ -898,7 +906,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS
struct LP_transaction *tx; int32_t i,height,numvouts,numvins,spentvout; cJSON *vins,*vouts,*vout,*vin; bits256 spenttxid; char str[65];
if ( coin->inactive != 0 )
return(0);
if ( txobj != 0 || (txobj= LP_gettx("LP_transactioninit",coin->symbol,txid,0)) != 0 )
if ( txobj != 0 || (txobj= LP_gettx("LP_transactioninit",coin->symbol,txid,1)) != 0 )
{
if ( coin->electrum == 0 )
height = LP_txheight(coin,txid);
@ -964,7 +972,7 @@ int32_t LP_txheight(struct iguana_info *coin,bits256 txid)
return(height);
if ( coin->electrum == 0 )
{
if ( (txobj= LP_gettx("LP_txheight",coin->symbol,txid,0)) != 0 )
if ( (txobj= LP_gettx("LP_txheight",coin->symbol,txid,1)) != 0 )
{
//*timestampp = juint(txobj,"locktime");
//*blocktimep = juint(txobj,"blocktime");
@ -1067,7 +1075,7 @@ uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_inf
{
if ( (value= LP_value_extract(txobj,0,txid)) == 0 )
{
char str[65]; printf("%s LP_txvalue.%s strange utxo.(%s) vout.%d\n",coin->symbol,bits256_str(str,txid),jprint(txobj,0),vout);
// char str[65]; printf("%s LP_txvalue.%s strange utxo.(%s) vout.%d\n",coin->symbol,bits256_str(str,txid),jprint(txobj,0),vout);
}
else if ( strcmp(coin->symbol,"KMD") == 0 )
{
@ -1185,7 +1193,7 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
return(-1);
}
destaddr[0] = destaddr2[0] = 0;
if ( coin != 0 && IAMLP != 0 && coin->inactive != 0 )
if ( coin != 0 && (strcmp(coin->symbol, "ETOMIC") == 0 || (coin->inactive != 0 && IAMLP != 0)))
bypass = 1;
if ( bypass != 0 )
val = satoshis;
@ -1209,16 +1217,27 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol
strcpy(destaddr,destaddr2);
if ( coin != 0 )
{
if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 )
return(0);
char txid_str[100], txid2_str[100];
bits256_str(txid_str, txid);
bits256_str(txid2_str, txid2);
if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) == 0 ) {
printf("Could not find tx out: %s %d\n", txid_str, vout);
return (0);
}
else free_json(txobj);
if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 )
return(0);
if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid2,vout2)) == 0 ) {
printf("Could not find tx out2: %s %d\n", txid_str, vout2);
return (0);
}
else free_json(txobj);
if ( LP_numconfirms(coin->symbol,destaddr,txid,vout,0) <= 0 )
return(0);
if ( LP_numconfirms(coin->symbol,destaddr,txid2,vout2,0) <= 0 )
return(0);
if ( LP_numconfirms(coin->symbol,destaddr,txid,vout,0) <= 0 ) {
printf("Txid numconfirms is less or equal to zero: %s %d\n", txid_str, vout);
return (0);
}
if ( LP_numconfirms(coin->symbol,destaddr,txid2,vout2,0) <= 0 ) {
printf("Txid numconfirms is less or equal to zero: %s %d\n", txid2_str, vout2);
return (0);
}
}
return(1);
}

2
iguana/exchanges/auto_chipsbtc

@ -1,2 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"minprice\":0.00006,\"maxprice\":0.0002,\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"BTC\",\"margin\":0.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}"
curl --url "http://127.0.0.1:7783" --data "{\"minprice\":0.00002,\"maxprice\":0.0002,\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"BTC\",\"margin\":0.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}"

2
iguana/exchanges/auto_chipskmd

@ -1,2 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"minprice\":0.15,\"maxprice\":0.4,\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"KMD\",\"margin\":0.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}"
curl --url "http://127.0.0.1:7783" --data "{\"minprice\":0.05,\"maxprice\":0.4,\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"KMD\",\"margin\":0.05,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}"

4
iguana/exchanges/coins

File diff suppressed because one or more lines are too long

89
iguana/exchanges/etomicswap/etomiccurl.c

@ -1,7 +1,6 @@
#include "etomiccurl.h"
#include <curl/curl.h>
static char *ethRpcUrl = ETOMIC_URL;
pthread_mutex_t sendTxMutex = PTHREAD_MUTEX_INITIALIZER;
struct string {
@ -36,16 +35,15 @@ size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
cJSON *parseEthRpcResponse(char *requestResult)
{
printf("Trying to parse ETH RPC response: %s\n", requestResult);
cJSON *json = cJSON_Parse(requestResult);
if (json == NULL) {
printf("ETH RPC response parse failed!\n");
printf("ETH RPC response parse failed: %s!\n", requestResult);
return NULL;
}
cJSON *tmp = cJSON_GetObjectItem(json, "result");
cJSON *error = cJSON_GetObjectItem(json, "error");
cJSON *result = NULL;
if (!is_cJSON_Null(tmp)) {
if (tmp != NULL && !is_cJSON_Null(tmp)) {
result = cJSON_Duplicate(tmp, 1);
} else if (error != NULL && !is_cJSON_Null(error)) {
char *errorString = cJSON_PrintUnformatted(error);
@ -56,7 +54,7 @@ cJSON *parseEthRpcResponse(char *requestResult)
return result;
}
char* sendRequest(char* request)
char* sendRequest(char *request, char *url)
{
CURL *curl;
CURLcode res;
@ -72,13 +70,15 @@ char* sendRequest(char* request)
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
curl_easy_setopt(curl, CURLOPT_URL, ethRpcUrl);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
return NULL;
}
/* always cleanup */
@ -98,7 +98,7 @@ cJSON *sendRpcRequest(char *method, cJSON *params)
cJSON_AddItemToObject(request, "params", cJSON_Duplicate(params, 1));
cJSON_AddNumberToObject(request, "id", 1);
string = cJSON_PrintUnformatted(request);
char* requestResult = sendRequest(string);
char* requestResult = sendRequest(string, ETOMIC_URL);
free(string);
cJSON_Delete(request);
cJSON *result = parseEthRpcResponse(requestResult);
@ -151,8 +151,8 @@ char* sendRawTx(char* rawTx)
int64_t getNonce(char* address)
{
// we should lock this mutex and unlock it only when transaction was already sent.
// make sure that sendRawTx is called after getting a nonce!
// we should lock this mutex and unlock it only when transaction was already sent or failed.
// make sure that sendRawTx or unlock_send_tx_mutex is called after getting a nonce!
if (pthread_mutex_lock(&sendTxMutex) != 0) {
printf("Nonce mutex lock failed\n");
};
@ -186,7 +186,7 @@ char* getEthBalanceRequest(char* address)
return balance;
}
char* ethCall(char* to, const char* data)
char *ethCall(char *to, const char *data)
{
cJSON *params = cJSON_CreateArray();
cJSON *txObject = cJSON_CreateObject();
@ -196,7 +196,7 @@ char* ethCall(char* to, const char* data)
cJSON_AddItemToArray(params, cJSON_CreateString("latest"));
cJSON *resultJson = sendRpcRequest("eth_call", params);
cJSON_Delete(params);
char* result = NULL;
char *result = NULL;
if (resultJson != NULL && is_cJSON_String(resultJson) && resultJson->valuestring != NULL) {
result = (char *) malloc(strlen(resultJson->valuestring) + 1);
strcpy(result, resultJson->valuestring);
@ -205,6 +205,26 @@ char* ethCall(char* to, const char* data)
return result;
}
uint64_t estimateGas(char *from, char *to, const char *data)
{
cJSON *params = cJSON_CreateArray();
cJSON *txObject = cJSON_CreateObject();
cJSON_AddStringToObject(txObject, "from", from);
cJSON_AddStringToObject(txObject, "to", to);
cJSON_AddStringToObject(txObject, "data", data);
cJSON_AddItemToArray(params, txObject);
cJSON_AddItemToArray(params, cJSON_CreateString("latest"));
cJSON *resultJson = sendRpcRequest("eth_estimateGas", params);
cJSON_Delete(params);
uint64_t result = 0;
if (resultJson != NULL && is_cJSON_String(resultJson) && resultJson->valuestring != NULL) {
result = (uint64_t)strtoul(resultJson->valuestring, NULL, 0);
result = (result / 100) * 120; // add 20% because real gas usage might differ from estimate
}
cJSON_Delete(resultJson);
return result;
}
EthTxReceipt getEthTxReceipt(char *txId)
{
EthTxReceipt result;
@ -265,7 +285,7 @@ EthTxData getEthTxData(char *txId)
return result;
}
uint64_t getGasPriceFromStation()
uint64_t getGasPriceFromStation(uint8_t defaultOnErr)
{
CURL *curl;
CURLcode res;
@ -283,6 +303,12 @@ uint64_t getGasPriceFromStation()
curl_easy_setopt(curl, CURLOPT_URL, "https://ethgasstation.info/json/ethgasAPI.json");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
uint64_t result;
if (defaultOnErr == 1) {
result = DEFAULT_GAS_PRICE;
} else {
result = 0;
}
/* Check for errors */
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
@ -292,9 +318,9 @@ uint64_t getGasPriceFromStation()
/* always cleanup */
curl_easy_cleanup(curl);
cJSON *resultJson = cJSON_Parse(s.ptr);
uint64_t result = DEFAULT_GAS_PRICE;
free(s.ptr);
if (resultJson == NULL) {
printf("Could not parse gas station response!\n");
return result;
}
@ -342,3 +368,40 @@ int32_t waitForConfirmation(char *txId)
return((int32_t)receipt.confirmations);
}
void unlock_send_tx_mutex()
{
pthread_mutex_unlock(&sendTxMutex);
}
uint8_t get_etomic_from_faucet(char *etomic_addr)
{
char* string;
cJSON *request = cJSON_CreateObject();
cJSON_AddStringToObject(request, "etomicAddress", etomic_addr);
string = cJSON_PrintUnformatted(request);
char* requestResult = sendRequest(string, FAUCET_URL);
free(string);
cJSON_Delete(request);
if (requestResult == NULL) {
return 0;
}
cJSON *json = cJSON_Parse(requestResult);
if (json == NULL) {
printf("ETOMIC faucet response parse failed!\n");
return 0;
}
cJSON *error = cJSON_GetObjectItem(json, "error");
uint8_t result = 0;
if (error != NULL && !is_cJSON_Null(error)) {
char *errorString = cJSON_PrintUnformatted(error);
printf("Got ETOMIC faucet error: %s\n", errorString);
free(errorString);
} else {
result = 1;
}
cJSON_Delete(json);
return result;
}

9
iguana/exchanges/etomicswap/etomiccurl.h

@ -16,9 +16,11 @@ extern "C"{
#define DEFAULT_GAS_PRICE 100
#else
#define ETOMIC_URL "http://195.201.0.6:8555"
#define DEFAULT_GAS_PRICE 4
#define DEFAULT_GAS_PRICE 10
#endif
#define FAUCET_URL "http://195.201.116.176:8000/getEtomic"
typedef struct
{
uint64_t blockNumber;
@ -39,13 +41,16 @@ typedef struct
char* sendRawTx(char* rawTx);
char* sendRawTxWaitConfirm(char* rawTx);
char* ethCall(char* to, const char* data);
uint64_t estimateGas(char *from, char *to, const char *data);
int64_t getNonce(char* address);
char* getEthBalanceRequest(char* address);
EthTxReceipt getEthTxReceipt(char *txId);
EthTxData getEthTxData(char *txId);
uint64_t getEthBlockNumber();
uint64_t getGasPriceFromStation();
uint64_t getGasPriceFromStation(uint8_t defaultOnErr);
int32_t waitForConfirmation(char *txId);
void unlock_send_tx_mutex();
uint8_t get_etomic_from_faucet(char *etomic_addr);
#ifdef __cplusplus
}

302
iguana/exchanges/etomicswap/etomiclib.cpp

@ -4,6 +4,7 @@
#include "etomiclib.h"
#include "etomiccurl.h"
#include <iostream>
#include <regex>
#include <cpp-ethereum/libethcore/Common.h>
#include <cpp-ethereum/libethcore/CommonJS.h>
#include <cpp-ethereum/libethcore/TransactionBase.h>
@ -27,18 +28,18 @@ TransactionSkeleton txDataToSkeleton(BasicTxData txData)
tx.to = jsToAddress(txData.to);
tx.value = jsToU256(txData.amount);
tx.gas = 200000;
tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9);
tx.gasPrice = getGasPriceFromStation(1) * boost::multiprecision::pow(u256(10), 9);
tx.nonce = getNonce(txData.from);
return tx;
}
char *signTx(TransactionSkeleton& tx, char* secret)
{
Secret& secretKey = *(new Secret(secret));
auto baseTx = new TransactionBase(tx, secretKey);
RLPStream& rlpStream = *(new RLPStream());
baseTx->streamRLP(rlpStream);
std::stringstream& ss = *(new std::stringstream);
Secret secretKey(secret);
TransactionBase baseTx(tx, secretKey);
RLPStream rlpStream;
baseTx.streamRLP(rlpStream);
std::stringstream ss;
ss << rlpStream.out();
return stringStreamToChar(ss);
}
@ -50,7 +51,7 @@ char *approveErc20(ApproveErc20Input input)
tx.to = jsToAddress(input.tokenAddress);
tx.value = 0;
tx.gas = 300000;
tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9);
tx.gasPrice = getGasPriceFromStation(1) * boost::multiprecision::pow(u256(10), 9);
tx.nonce = getNonce(input.owner);
std::stringstream ss;
ss << "0x095ea7b3"
@ -101,7 +102,12 @@ uint8_t verifyAliceEthPaymentData(AliceSendsEthPaymentInput input, char *data)
std::stringstream aliceSendsErc20PaymentData(AliceSendsErc20PaymentInput input)
{
uint8_t decimals = getErc20Decimals(input.tokenAddress);
uint8_t decimals;
if (input.decimals > 0) {
decimals = input.decimals;
} else {
decimals = getErc20Decimals(input.tokenAddress);
}
u256 amount = jsToU256(input.amount);
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
@ -148,12 +154,20 @@ char* aliceReclaimsAlicePayment(AliceReclaimsAlicePaymentInput input, BasicTxDat
std::stringstream ss;
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
uint8_t decimals;
if (input.decimals > 0) {
decimals = input.decimals;
} else {
decimals = getErc20Decimals(input.tokenAddress);
}
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
}
ss << "0x8b9a167a"
<< toHex(jsToBytes(input.dealId))
<< toHex(toBigEndian(amount))
@ -179,12 +193,20 @@ char* bobSpendsAlicePayment(BobSpendsAlicePaymentInput input, BasicTxData txData
std::stringstream ss;
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
uint8_t decimals;
if (input.decimals > 0) {
decimals = input.decimals;
} else {
decimals = getErc20Decimals(input.tokenAddress);
}
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
}
ss << "0x392ec66b"
<< toHex(jsToBytes(input.dealId))
<< toHex(toBigEndian(amount))
@ -241,7 +263,13 @@ uint8_t verifyBobEthDepositData(BobSendsEthDepositInput input, char *data)
std::stringstream bobSendsErc20DepositData(BobSendsErc20DepositInput input)
{
uint8_t decimals = getErc20Decimals(input.tokenAddress);
uint8_t decimals;
if (input.decimals > 0) {
decimals = input.decimals;
} else {
decimals = getErc20Decimals(input.tokenAddress);
}
u256 amount = jsToU256(input.amount);
u256 lockTime = input.lockTime;
if (decimals < 18) {
@ -289,7 +317,13 @@ char* bobRefundsDeposit(BobRefundsDepositInput input, BasicTxData txData)
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
uint8_t decimals;
if (input.decimals > 0) {
decimals = input.decimals;
} else {
decimals = getErc20Decimals(input.tokenAddress);
}
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
@ -316,7 +350,13 @@ char* aliceClaimsBobDeposit(AliceClaimsBobDepositInput input, BasicTxData txData
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
uint8_t decimals;
if (input.decimals > 0) {
decimals = input.decimals;
} else {
decimals = getErc20Decimals(input.tokenAddress);
}
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
@ -374,9 +414,15 @@ uint8_t verifyBobEthPaymentData(BobSendsEthPaymentInput input, char *data)
std::stringstream bobSendsErc20PaymentData(BobSendsErc20PaymentInput input)
{
uint8_t decimals = getErc20Decimals(input.tokenAddress);
u256 amount = jsToU256(input.amount);
u256 lockTime = input.lockTime;
uint8_t decimals;
if (input.decimals > 0) {
decimals = input.decimals;
} else {
decimals = getErc20Decimals(input.tokenAddress);
}
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
@ -422,7 +468,13 @@ char* bobReclaimsBobPayment(BobReclaimsBobPaymentInput input, BasicTxData txData
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
uint8_t decimals;
if (input.decimals > 0) {
decimals = input.decimals;
} else {
decimals = getErc20Decimals(input.tokenAddress);
}
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
@ -450,7 +502,13 @@ char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData
u256 amount = jsToU256(input.amount);
dev::Address tokenAddress = jsToAddress(input.tokenAddress);
if (tokenAddress != ZeroAddress) {
uint8_t decimals = getErc20Decimals(input.tokenAddress);
uint8_t decimals;
if (input.decimals > 0) {
decimals = input.decimals;
} else {
decimals = getErc20Decimals(input.tokenAddress);
}
if (decimals < 18) {
amount /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
@ -472,54 +530,69 @@ char* aliceSpendsBobPayment(AliceSpendsBobPaymentInput input, BasicTxData txData
char* privKey2Addr(char* privKey)
{
Secret& secretKey = *(new Secret(privKey));
std::stringstream& ss = *(new std::stringstream);
Secret secretKey(privKey);
std::stringstream ss;
ss << "0x" << toAddress(secretKey);
return stringStreamToChar(ss);
};
char* pubKey2Addr(char* pubKey)
{
Public& publicKey = *(new Public(pubKey));
std::stringstream& ss = *(new std::stringstream);
Public publicKey(pubKey);
std::stringstream ss;
ss << "0x" << toAddress(publicKey);
return stringStreamToChar(ss);
};
char* getPubKeyFromPriv(char* privKey)
char* getPubKeyFromPriv(char *privKey)
{
Public publicKey = toPublic(*(new Secret(privKey)));
std::stringstream& ss = *(new std::stringstream);
Public publicKey = toPublic(Secret(privKey));
std::stringstream ss;
ss << "0x" << publicKey;
return stringStreamToChar(ss);
}
uint64_t getEthBalance(char* address)
uint64_t getEthBalance(char *address, int *error)
{
char* hexBalance = getEthBalanceRequest(address);
// convert wei to satoshi
u256 balance = jsToU256(hexBalance) / boost::multiprecision::pow(u256(10), 10);
free(hexBalance);
return static_cast<uint64_t>(balance);
if (hexBalance != NULL) {
// convert wei to satoshi
u256 balance = jsToU256(hexBalance) / boost::multiprecision::pow(u256(10), 10);
free(hexBalance);
return static_cast<uint64_t>(balance);
} else {
*error = 1;
return 0;
}
}
uint64_t getErc20BalanceSatoshi(char *address, char *tokenAddress)
uint64_t getErc20BalanceSatoshi(char *address, char *tokenAddress, uint8_t setDecimals, int *error)
{
std::stringstream ss;
ss << "0x70a08231"
<< "000000000000000000000000"
<< toHex(jsToAddress(address));
std::stringstream& resultStream = *(new std::stringstream);
char* hexBalance = ethCall(tokenAddress, ss.str().c_str());
// convert wei to satoshi
uint8_t decimals = getErc20Decimals(tokenAddress);
u256 balance = jsToU256(hexBalance);
if (decimals < 18) {
balance *= boost::multiprecision::pow(u256(10), 18 - decimals);
uint8_t decimals;
if (hexBalance != NULL) {
if (setDecimals > 0) {
decimals = setDecimals;
} else {
decimals = getErc20Decimals(tokenAddress);
}
u256 balance = jsToU256(hexBalance);
if (decimals < 18) {
balance *= boost::multiprecision::pow(u256(10), 18 - decimals);
}
balance /= boost::multiprecision::pow(u256(10), 10);
free(hexBalance);
return static_cast<uint64_t>(balance);
} else {
*error = 1;
return 0;
}
balance /= boost::multiprecision::pow(u256(10), 10);
free(hexBalance);
return static_cast<uint64_t>(balance);
}
char *getErc20BalanceHexWei(char *address, char *tokenAddress)
@ -532,7 +605,7 @@ char *getErc20BalanceHexWei(char *address, char *tokenAddress)
return hexBalance;
}
uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress)
uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress, uint8_t set_decimals)
{
std::stringstream ss;
ss << "0xdd62ed3e"
@ -541,7 +614,12 @@ uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress)
<< "000000000000000000000000"
<< toHex(jsToAddress(spender));
char* hexAllowance = ethCall(tokenAddress, ss.str().c_str());
uint8_t decimals = getErc20Decimals(tokenAddress);
uint8_t decimals;
if (set_decimals > 0) {
decimals = set_decimals;
} else {
decimals = getErc20Decimals(tokenAddress);
}
u256 allowance = jsToU256(hexAllowance);
if (decimals < 18) {
allowance *= boost::multiprecision::pow(u256(10), 18 - decimals);
@ -560,6 +638,18 @@ uint8_t getErc20Decimals(char *tokenAddress)
return decimals;
}
uint8_t getErc20DecimalsZeroOnError(char *tokenAddress)
{
char* hexDecimals = ethCall(tokenAddress, "0x313ce567");
if (hexDecimals != NULL) {
auto decimals = (uint8_t) strtol(hexDecimals, NULL, 0);
free(hexDecimals);
return decimals;
} else {
return 0;
}
}
void uint8arrayToHex(char *dest, uint8_t *input, int len)
{
strcpy(dest, "0x");
@ -582,17 +672,30 @@ uint64_t weiToSatoshi(char *wei)
return static_cast<uint64_t>(satoshi);
}
char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm)
char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm, int64_t gas, int64_t gasPrice, uint8_t defaultGasOnErr)
{
TransactionSkeleton tx;
char *from = privKey2Addr(privKey), *result;
tx.from = jsToAddress(from);
tx.to = jsToAddress(to);
tx.value = jsToU256(amount);
tx.gas = 21000;
tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9);
tx.nonce = getNonce(from);
free(from);
if (gas > 0) {
tx.gas = gas;
} else {
tx.gas = 21000;
}
if (gasPrice > 0) {
tx.gasPrice = gasPrice * boost::multiprecision::pow(u256(10), 9);
} else {
tx.gasPrice = getGasPriceFromStation(defaultGasOnErr) * boost::multiprecision::pow(u256(10), 9);
if (tx.gasPrice == 0 && !defaultGasOnErr) {
printf("Could not get gas price from station!\n");
unlock_send_tx_mutex();
return NULL;
}
}
char *rawTx = signTx(tx, privKey);
if (waitConfirm == 0) {
@ -604,10 +707,15 @@ char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm)
return result;
}
std::stringstream getErc20TransferData(char *tokenAddress, char *to, char *amount)
std::stringstream getErc20TransferData(char *tokenAddress, char *to, char *amount, uint8_t setDecimals)
{
u256 amountWei = jsToU256(amount);
uint8_t decimals = getErc20Decimals(tokenAddress);
uint8_t decimals;
if (setDecimals > 0) {
decimals = setDecimals;
} else {
decimals = getErc20Decimals(tokenAddress);
}
if (decimals < 18) {
amountWei /= boost::multiprecision::pow(u256(10), 18 - decimals);
}
@ -620,19 +728,64 @@ std::stringstream getErc20TransferData(char *tokenAddress, char *to, char *amoun
return ss;
}
char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm)
uint64_t estimate_erc20_gas(
char *tokenAddress,
char *to,
char *amount,
char *privKey,
uint8_t decimals
)
{
std::stringstream ss = getErc20TransferData(tokenAddress, to, amount, decimals);
char *from = privKey2Addr(privKey);
uint64_t result = estimateGas(from, tokenAddress, ss.str().c_str());
free(from);
return result;
}
char *sendErc20(
char *tokenAddress,
char *to,
char *amount,
char *privKey,
uint8_t waitConfirm,
int64_t gas,
int64_t gasPrice,
uint8_t defaultGasOnErr,
uint8_t decimals
)
{
TransactionSkeleton tx;
char *from = privKey2Addr(privKey), *result;
std::stringstream ss = getErc20TransferData(tokenAddress, to, amount, decimals);
tx.from = jsToAddress(from);
tx.to = jsToAddress(tokenAddress);
tx.value = 0;
tx.gas = 60000;
tx.gasPrice = getGasPriceFromStation() * boost::multiprecision::pow(u256(10), 9);
tx.nonce = getNonce(from);
if (gas > 0) {
tx.gas = gas;
} else {
uint64_t gasEstimation = estimateGas(from, tokenAddress, ss.str().c_str());
if (gasEstimation > 0) {
tx.gas = gasEstimation;
} else {
tx.gas = 150000;
}
}
free(from);
if (gasPrice > 0) {
tx.gasPrice = gasPrice * boost::multiprecision::pow(u256(10), 9);
} else {
tx.gasPrice = getGasPriceFromStation(defaultGasOnErr) * boost::multiprecision::pow(u256(10), 9);
if (tx.gasPrice == 0 && !defaultGasOnErr) {
printf("Could not get gas price from station!\n");
unlock_send_tx_mutex();
return NULL;
}
}
std::stringstream ss = getErc20TransferData(tokenAddress, to, amount);
tx.data = jsToBytes(ss.str());
char *rawTx = signTx(tx, privKey);
@ -645,12 +798,61 @@ char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8
return result;
}
uint8_t verifyAliceErc20FeeData(char* tokenAddress, char *to, char *amount, char *data)
uint8_t verifyAliceErc20FeeData(char *tokenAddress, char *to, char *amount, char *data, uint8_t decimals)
{
std::stringstream ss = getErc20TransferData(tokenAddress, to, amount);
std::stringstream ss = getErc20TransferData(tokenAddress, to, amount, decimals);
if (strcmp(ss.str().c_str(), data) != 0) {
printf("Alice ERC20 fee data %s is not equal to expected %s\n", data, ss.str().c_str());
return 0;
}
return 1;
}
uint8_t alicePaymentStatus(char *paymentId)
{
char buffer[100];
memset(buffer, 0, sizeof(buffer));
strcpy(buffer, "0x81cd872a");
strcat(buffer, paymentId);
char *hexStatus = ethCall(ETOMIC_ALICECONTRACT, buffer);
auto status = (uint8_t) strtol(hexStatus + 66, NULL, 0);
free(hexStatus);
return status;
}
uint8_t bobDepositStatus(char *depositId)
{
char buffer[100];
memset(buffer, 0, sizeof(buffer));
strcpy(buffer, "0x3d4dff7b");
strcat(buffer, depositId);
char *hexStatus = ethCall(ETOMIC_BOBCONTRACT, buffer);
auto status = (uint8_t) strtol(hexStatus + 130, NULL, 0);
free(hexStatus);
return status;
}
uint8_t bobPaymentStatus(char *paymentId)
{
char buffer[100];
memset(buffer, 0, sizeof(buffer));
strcpy(buffer, "0x0716326d");
strcat(buffer, paymentId);
char *hexStatus = ethCall(ETOMIC_BOBCONTRACT, buffer);
auto status = (uint8_t) strtol(hexStatus + 130, NULL, 0);
free(hexStatus);
return status;
}
uint8_t compareAddresses(char *address1, char *address2)
{
auto addr_bytes_1 = jsToAddress(address1);
auto addr_bytes_2 = jsToAddress(address2);
return static_cast<uint8_t>(addr_bytes_1 == addr_bytes_2);
}
uint8_t isValidAddress(char *address)
{
std::regex r("^(0x|0X)?[a-fA-F0-9]{40}$");
return static_cast<uint8_t>(std::regex_match(address, r));
}

49
iguana/exchanges/etomicswap/etomiclib.h

@ -38,6 +38,7 @@ typedef struct {
char bobAddress[65];
char aliceHash[65];
char bobHash[65];
uint8_t decimals;
} AliceSendsErc20PaymentInput;
typedef struct {
@ -47,6 +48,7 @@ typedef struct {
char bobAddress[65];
char aliceHash[65];
char bobSecret[70];
uint8_t decimals;
} AliceReclaimsAlicePaymentInput;
typedef struct {
@ -56,6 +58,7 @@ typedef struct {
char aliceAddress[65];
char aliceSecret[70];
char bobHash[65];
uint8_t decimals;
} BobSpendsAlicePaymentInput;
typedef struct {
@ -72,6 +75,7 @@ typedef struct {
char aliceAddress[65];
char bobHash[65];
uint64_t lockTime;
uint8_t decimals;
} BobSendsErc20DepositInput;
typedef struct {
@ -80,6 +84,7 @@ typedef struct {
char tokenAddress[65];
char aliceAddress[65];
char bobSecret[70];
uint8_t decimals;
} BobRefundsDepositInput;
typedef struct {
@ -88,6 +93,7 @@ typedef struct {
char tokenAddress[65];
char bobAddress[65];
char bobHash[65];
uint8_t decimals;
} AliceClaimsBobDepositInput;
typedef struct {
@ -104,6 +110,7 @@ typedef struct {
char aliceAddress[65];
char aliceHash[65];
uint64_t lockTime;
uint8_t decimals;
} BobSendsErc20PaymentInput;
typedef struct {
@ -112,6 +119,7 @@ typedef struct {
char tokenAddress[65];
char aliceAddress[65];
char aliceHash[65];
uint8_t decimals;
} BobReclaimsBobPaymentInput;
typedef struct {
@ -120,6 +128,7 @@ typedef struct {
char tokenAddress[65];
char aliceSecret[70];
char bobAddress[65];
uint8_t decimals;
} AliceSpendsBobPaymentInput;
typedef struct {
@ -164,24 +173,50 @@ char* pubKey2Addr(char* pubKey);
char* getPubKeyFromPriv(char* privKey);
// returns satoshis, not wei!
uint64_t getEthBalance(char* address);
uint64_t getErc20BalanceSatoshi(char* address, char tokenAddress[65]);
uint64_t getEthBalance(char* address, int *error);
uint64_t getErc20BalanceSatoshi(char *address, char *tokenAddress, uint8_t setDecimals, int *error);
char *getErc20BalanceHexWei(char* address, char tokenAddress[65]);
uint8_t getErc20Decimals(char *tokenAddress);
// returns satoshis, not wei!
uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress);
uint64_t getErc20Allowance(char *owner, char *spender, char *tokenAddress, uint8_t set_decimals);
void uint8arrayToHex(char *dest, uint8_t *input, int len);
void satoshisToWei(char *dest, uint64_t input);
uint64_t weiToSatoshi(char *wei);
char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm);
char *sendErc20(char *tokenAddress, char *to, char *amount, char *privKey, uint8_t waitConfirm);
char *sendEth(char *to, char *amount, char *privKey, uint8_t waitConfirm, int64_t gas, int64_t gasPrice, uint8_t defaultGasOnErr);
char *sendErc20(
char *tokenAddress,
char *to,
char *amount,
char *privKey,
uint8_t waitConfirm,
int64_t gas,
int64_t gasPrice,
uint8_t defaultGasOnErr,
uint8_t decimals
);
uint8_t verifyAliceErc20FeeData(char* tokenAddress, char *to, char *amount, char *data, uint8_t decimals);
uint8_t alicePaymentStatus(char *paymentId);
uint8_t bobDepositStatus(char *depositId);
uint8_t bobPaymentStatus(char *paymentId);
uint64_t estimate_erc20_gas(
char *tokenAddress,
char *to,
char *amount,
char *privKey,
uint8_t decimals
);
uint8_t compareAddresses(char *address1, char *address2);
uint8_t isValidAddress(char *address);
uint8_t getErc20DecimalsZeroOnError(char *tokenAddress);
uint8_t verifyAliceErc20FeeData(char* tokenAddress, char *to, char *amount, char *data);
// Your prototype or Definition
#ifdef __cplusplus
}
#endif

3
iguana/exchanges/gen64addrs

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"gen64addrs\",\"passphrase\":\"default\"}"

7
iguana/exchanges/mm.c

@ -164,6 +164,7 @@ int main(int argc, const char * argv[])
{
char dirname[512]; double incr; cJSON *retjson;
OS_init();
printf("BarterDEX Marketmaker %s \n",MM_VERSION);
if ( strstr(argv[0],"btc2kmd") != 0 && argv[1] != 0 )
{
bits256 privkey,checkkey; uint8_t tmptype; char kmdwif[64],str[65],str2[65],*retstr;
@ -346,6 +347,12 @@ int main(int argc, const char * argv[])
printf("couldnt write to (%s)\n",dirname);
exit(0);
}
sprintf(dirname,"%s/GTC",GLOBAL_DBDIR), OS_ensure_directory(dirname);
if ( ensure_writable(dirname) < 0 )
{
printf("couldnt write to (%s)\n",dirname);
exit(0);
}
sprintf(dirname,"%s/PRICES",GLOBAL_DBDIR), OS_ensure_directory(dirname);
if ( ensure_writable(dirname) < 0 )
{

102
iguana/exchanges/mm2.md

@ -0,0 +1,102 @@
# Market Maker 2
This document will help us track the information related to the MarketMaker Rust rewrite.
## Rewrite goals
Rewrites and ports
[are costly](http://nibblestew.blogspot.com/2017/04/why-dont-you-just-rewrite-it-in-x.html).
We tend to think that porting is simple, and on some level this intuition is true
because we can skip some high-level design decisions and focus on translating the existing logic,
but it still takes a lot of time
and though we don't need to make some of the new design decisions,
we might spend no less effort to reverse-engineer and understand the old ones.
So why the rewrite then?
Carol, in her talk about rewrites, offers some possible reasons:
"*If* you have some code in C or another language, and need to change it, or it’s slow, or it crashes a
lot, or no one understands it anymore, THEN maybe a rewrite in Rust would be a good fit.
I would also posit that more people are *able* to write production Rust than production C, so if your
team *is* willing to learn Rust, it might actually expand the number of
maintainers." - https://github.com/carols10cents/rust-out-your-c-talk, https://www.youtube.com/watch?v=SKGVItFlK3w.
And we have some of these:
* We *need to change* the MarketMaker:
A more approachable and reliable API.
Ability to embed the MarketMaker in the GUI applications.
Ways to more easily deploy it at home by running it from small computers like on a spare mobile phone or on a Raspberry Pi 3.
Ability to process multiple API calls in parallel.
A faster version of the `swapstatus` API call.
* The MarketMaker *crashes a lot*,
to quote hyperDEX: "The biggest issue with the MM right now, is bobs crash or does not have the orders in users orderbook, or when users try to do a order it doesnt work or goes unmatched or other random stuff"
and lukechilds: "We've frequently experienced crashes while querying all swaps with swapstatus".
We want it to be stable and reliable instead.
## Purely functional core
One of our goals is to make the MarketMaker 2 more
[stable and reliable](https://softwareengineering.stackexchange.com/questions/158054/stability-vs-reliability).
We want it to crash less often.
If there was a failure, we want to simplify and preferably automate recovery.
And we want to reduce the time between a failure and a fix.
We'll make a big step towards these goals if the core of the MarketMaker is purely functional.
That is, if we can untangle the *state* of the MarketMaker from the code operating on that state.
The benefits we want to reap from this are:
* Transparency. Some bugs are hard to fix because we don't have enough information about them. We might be lucky to have been running the program in a debugger or finding the necessary bits it verbose logs, but more often than not this is not the case: we know that a failure has happened, but have no idea where and on what input. Separating the state from the code allows the state to be easily shared with a developer, which means much faster roundtrips between discovering a failure and fixing it.
* Replayability. Having a separate state allows us to easily replay any operation. If a failure occured in the middle of a transaction, it should be possible to try a new version of the code without manually repeating all the steps that were necessary to initiate the transaction. And the updated code will run exactly on the failing transaction, not on some other transaction initiated at a later time, which means that users will benefit from less friction and developers will have a better chance to fix the hard-to-reproduce bugs.
* Testability. Stateless code is much easier to test and according to Kent Beck is often a natural result of a Test-Driven development process.
* Portability. Separating the state from the code allows us to more easily use the stateless parts from the sandboxed environments, such as when running under the Web Assembly (WASM). We only need to port the state-managing layer, fully reusing the stateless code.
* Hot reloading. When the code is separated from state, it's trivial to reload it, both with the shared libraries in CPU-native environments (dlopen) and with WASM in GUI environments. This might positively affect the development cycle, reducing the round-trip time from a failure to a fix.
* Concurrency. MarketMaker can currently only perform a single API operation at the time. The more stateless code we have the easier it should be to introduce the parallel execution of API requests in the future.
Implementation might consist of two layers.
A layer that is ported to the host environment (native, JS, Java, Objective-C, cross-compiled Raspberry Pi 3, etc) and implements the TCP/IP communication, state management, hot reloading, all things that won't fit into the WASM sandbox.
And a layer that implements the core logic in a stateless manner and which is compiled into a native shared library or, in the future, to WASM.
Parts of the state might be marked as sensitive.
This will give the users an option to share only the information that can be freely shared,
without a risk of loosing money that is.
Even without the sensitive information a state snapshot might provide the developer with enough data to quickly triage and/or fix the failure, therefore improving the roundtrip time before a failure and a fix.
Plus users will more easily share their problems when it's quick, automatic and doesn't pose a monetary risk.
The feasibility of this approach is yet to be evaluated, but we can move gradually towards it
by separating the code into the stateful and stateless layers while working on the basic Rust port.
During the initial Rust port we're going to
a) Mark the ported functions as purely functional or stateful, allowing us to more easily focus on the state management code in the future.
b) Where possible, take a low-hanging fruit and try to refactor the functions towards being stateless.
c) Probably mark as stateful the `sleep`ing functions, because `sleep` can be seen as changing the global state (moving the time forwards) and might negatively affect Transparency (we have no idea what's going on while a function is sleeping), Testability (sleeping tests might kill the TDD development cycle), Portability (sleeps are not compatible with WASM), Hot reloading and Concurrency (let's say we want to load new version of the code, but the old version is still sleeping somewhere).
## Gradual rewrite
Above in the [Rewrite goals](#rewrite-goals) section we have identified some of the goals that we pursue with this rewrite.
These goals constitute the Value (in the Lean Production terms) that we are going to create.
For a project to suceed it is usually important to make shorter the path the Value takes to the users.
(Inventory is waste. If we have created the Value but the users can't get their hands on it, we're wasting that Value).
Hence we're going to start with a gradual rewrite. Keeping the version under rewrite immediately avaliable to the users willing to experiment with it.
Let's list the good things that should come out of the gradual rewrite:
* Transparency. With the second version of the MarketMaker being immediately available we can always check the Value we're getting. Is it more stable? Does it have new functions? Or did we hit the wall? What's going on with the code and how can we help? Gradual rewrite is critical for transparency because the change is available in small increments. We can more easily see what function has changed or what new functionality was added when we aren't being uprooted from the familiar context.
* Risk reduction. It comes with transparency, as we can now more easily measure the progress, identify the roadblocks as they occur, see certain problems when they occur and not months after. Plus a gradual rewrite will by default follow the outline of the original project. We have a working system and we're improving it piece by piece, having the original design to fall back to. This makes it less likely for the rewrite to suffer from far-reaching redesign flaws (cf. [Second-system effect](https://en.wikipedia.org/wiki/Second-system_effect)) and creative blocks (cf. [Pantsing](https://www.wikiwrimo.org/wiki/Pantsing)).
* Feedback. Incorporating user feedback is critical for most projects out there, allowing us to iteratively improve the functionality in the right direction (cf. [Fail faster](https://www.youtube.com/watch?v=rDjrOaoHz9s), [PDIA](https://www.youtube.com/watch?v=ZKdjBbiGjao)). The more early we get the feedback, the more time we have to react, and at a lesser cost.
* Motivation. Feedback is not only important to guide us, but also to show us that our work is meaningful and changes lives to the better. It is the cornerstone of Agile (["Build projects around motivated individuals"](https://www.agilealliance.org/agile101/12-principles-behind-the-agile-manifesto/)) and affects our performance on all levels, down to the physical health.
The plan so far is to by default use the C functions as the atomic units of rewrite.
Rust FFI allows us to swap any C function with a similar Rust function.
Porting on this level we
* reuse the function-level modularity of the C language;
* preserve the code meta-data (Git history will show a nice diff between the C and Rust functions, we'll be able to easily investigate the evolution of the code back to its roots);
* avoid the complexity and slow-downs associated with adding RPC/networking layers or drawing new lines of abstraction;
* have a good indicator of the porting progress (how many functions were ported, how many remains).
Focusing on the function call chains that are a common part of a failure/crash or touch on the new functionality
will allow us to leverage the [Pareto principle](https://en.wikipedia.org/wiki/Pareto_principle),
advancing on 80% of desired Value (stability, functionality) with 20% of initial effort.

2
iguana/exchanges/mshark

@ -1,4 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":100}, {\"coin\":\"komodo\",\"balance\":100000}, {\"coin\":\"chips\",\"balance\":100000}],\"divisor\":1400000}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":25}],\"divisor\":1400000}"

6
iguana/exchanges/prices/autoprice

@ -35,15 +35,15 @@ source trackbtc
#source revs
#source trackbtc
sharkholdings="{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"komodo\",\"balance\":120000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":100}"
sharkholdings="{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":25}"
curl --url "http://127.0.0.1:7783" --data "{\"base\":\"MSHARK\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"margin\":$margin,\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[$sharkholdings],\"divisor\":1400000}"
curl --url "http://127.0.0.1:7783" --data "{\"margin\":$margin,\"base\":\"SUPERNET\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"NAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":570}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2100000}],\"divisor\":612529}"
curl --url "http://127.0.0.1:7783" --data "{\"margin\":$margin,\"base\":\"SUPERNET\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"NAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":0.20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":540}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2100000}, {\"coin\":\"verus\",\"balance\":65000}],\"divisor\":777777}"
curl --url "http://127.0.0.1:7783" --data "{\"margin\":$margin,\"base\":\"HODL\",\"rel\":\"KMD\",\"fundvalue_bid\":\"assetNAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RNcUaMUEFLxVwtTo7rgruhwYanGk1jTkeU\",\"holdings\":[{\"coin\":\"siacoin\",\"balance\":185000000,\"comment\":\"using siafunds equal to million siacoin\"}],\"divisor\":10000000}"
dexholdings="{\"coin\":\"blocknet\",\"balance\":2500000}"
dexholdings="{\"coin\":\"blocknet\",\"balance\":2000000}"
curl --url "http://127.0.0.1:7783" --data "{\"base\":\"DEX\",\"rel\":\"KMD\",\"margin\":$margin,\"fundvalue_bid\":\"assetNAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf\",\"holdings\":[$dexholdings],\"divisor\":1000000}"
curl --url "http://127.0.0.1:7783" --data "{\"base\":\"BOTS\",\"rel\":\"KMD\",\"margin\":$margin,\"fundvalue_bid\":\"assetNAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P\",\"holdings\":[$dexholdings],\"divisor\":3333333}"

2
iguana/exchanges/supernet

@ -15,5 +15,5 @@ echo supernet
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balances\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\"}"
echo supernet
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":570}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2100000}],\"divisor\":612529}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":0.10000}, {\"coin\":\"syscoin\",\"balance\":0.20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":540}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":0.20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":0.150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":0.375000}, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }, {\"coin\":\"utrum\",\"balance\":2350000}, {\"coin\":\"verus\",\"balance\":65000}],\"divisor\":777777}"

2
iguana/iguana777.c

@ -1131,7 +1131,7 @@ struct iguana_info *iguana_setcoin(char *symbol,void *launched,int32_t maxpeers,
if ( coin->MAXMEM == 0 )
coin->MAXMEM = IGUANA_DEFAULTRAM;
coin->MAXMEM *= (1024L * 1024 * 1024);
coin->enableCACHE = 0;//(strcmp("BTCD",coin->symbol) == 0);
coin->enableCACHE = 1;//0;//(strcmp("BTCD",coin->symbol) == 0);
if ( jobj(json,"cache") != 0 )
coin->enableCACHE = juint(json,"cache");
if ( (coin->polltimeout= juint(json,"poll")) <= 0 )

20
iguana/iguana_notary.c

@ -430,13 +430,11 @@ THREE_STRINGS_AND_DOUBLE(iguana,dpow,symbol,dest,pubkey,freq)
portable_mutex_init(&dp->paxmutex);
portable_mutex_init(&dp->dexmutex);
PAX_init();
//printf(">>>>>>>>>>>>>>> call paxpending\n");
//uint8_t buf[32768];
//dpow_paxpending(buf);
dp->fullCCid = dpow_CCid(myinfo,src);
myinfo->numdpows++;
for (i=0; i<33; i++)
printf("%02x",dp->minerkey33[i]);
printf(" DPOW with pubkey.(%s) %s.valid%d %s -> %s %s.valid%d, num.%d freq.%d minsigs.%d\n",tmp,srcaddr,srcvalid,dp->symbol,dp->dest,destaddr,destvalid,myinfo->numdpows,dp->freq,dp->minsigs);
printf(" DPOW with pubkey.(%s) %s.valid%d %s -> %s %s.valid%d, num.%d freq.%d minsigs.%d CCid.%u\n",tmp,srcaddr,srcvalid,dp->symbol,dp->dest,destaddr,destvalid,myinfo->numdpows,dp->freq,dp->minsigs,dp->fullCCid);
return(clonestr("{\"result\":\"success\"}"));
}
@ -537,7 +535,7 @@ STRING_ARG(iguana,addnotary,ipaddr)
}
char NOTARY_CURRENCIES[][65] = {
"REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "VOTE2018", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL"
"REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH", "VOTE2018", "NINJA", "OOT", "CHAIN", "BNTN", "PRLPAY", "DSEC", "GLXT", "EQL", "ZILLA", "RFOX", "SEC", "CCL"
};
// "LTC", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK",
@ -958,6 +956,18 @@ ZERO_ARGS(dpow,cancelratify)
return(clonestr("{\"result\":\"queued dpow cancel ratify\"}"));
}
ZERO_ARGS(dpow,ipaddrs)
{
char ipaddr[64]; cJSON *array; int32_t i;
array = cJSON_CreateArray();
for (i=0; i<myinfo->numdpowipbits; i++)
{
expand_ipbits(ipaddr,myinfo->dpowipbits[i]);
jaddistr(array,ipaddr);
}
return(jprint(array,1));
}
TWOINTS_AND_ARRAY(dpow,ratify,minsigs,timestamp,ratified)
{
void **ptrs; bits256 zero; int32_t i; char *source; struct dpow_checkpoint checkpoint;

2
iguana/iguana_ramchain.c

@ -1015,7 +1015,7 @@ int32_t iguana_ramchain_alloc(char *fname,struct iguana_info *coin,struct iguana
char str[65],str2[65]; fprintf(stderr,"ht.%d wait for allocated %s < MAXMEM %s | elapsed %.2f minutes hashsize.%ld allocsize.%ld\n",height,mbstr(str,myallocated(0,-1)+hashsize+allocsize),mbstr(str2,coin->MAXMEM),(double)(time(NULL)-coin->startutc)/60.,(long)hashsize,(long)allocsize);
sleep(13);
}
iguana_meminit(hashmem,"ramhashmem",0,2*hashsize + 65536,0);
iguana_meminit(hashmem,"ramhashmem",0,3*hashsize + 65536,0);
iguana_meminit(mem,"ramchain",0,allocsize + 65536,0);
mem->alignflag = sizeof(uint32_t);
hashmem->alignflag = sizeof(uint32_t);

9
iguana/iguana_wallet.c

@ -1402,7 +1402,7 @@ TWOSTRINGS_AND_INT(bitcoinrpc,walletpassphrase,password,permanentfile,timeout)
THREE_STRINGS(bitcoinrpc,encryptwallet,passphrase,password,permanentfile)
{
char *retstr,buf[128],wifstr[128]; cJSON *retjson; int32_t need_KMD = 0,need_BTC = 0,need_GAME = 0;
char *retstr,buf[128],wifstr[128]; cJSON *retjson; int32_t need_HUSH = 0,need_KMD = 0,need_BTC = 0,need_GAME = 0;
if ( remoteaddr != 0 || coin == 0 )
return(clonestr("{\"error\":\"no remote encrypt or no coin\"}"));
iguana_walletlock(myinfo,coin);
@ -1441,11 +1441,18 @@ THREE_STRINGS(bitcoinrpc,encryptwallet,passphrase,password,permanentfile)
need_BTC = 1;
if ( strcmp(coin->symbol,"GAME") != 0 )
need_GAME = 1;
if ( strcmp(coin->symbol,"HUSH") != 0 )
need_HUSH = 1;
if ( need_KMD != 0 && (coin= iguana_coinfind("KMD")) != 0 )
{
bitcoin_priv2wif(wifstr,waddr.privkey,coin->chain->wiftype);
jaddstr(retjson,"KMDwif",wifstr);
}
if ( need_HUSH != 0 && (coin= iguana_coinfind("HUSH")) != 0 )
{
bitcoin_priv2wif(wifstr,waddr.privkey,coin->chain->wiftype);
jaddstr(retjson,"HUSHwif",wifstr);
}
if ( (coin= iguana_coinfind("LTC")) != 0 )
{
bitcoin_priv2wif(wifstr,waddr.privkey,coin->chain->wiftype);

2
iguana/m_notary

@ -2,4 +2,4 @@
pkill -15 iguana
rm -f ../agents/iguana *.o
git pull
./m_notary_run $1
./m_notary_run "$1" "$2"

25
iguana/m_notary_run

@ -8,7 +8,8 @@ clang -g -Wno-deprecated -c -O2 -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 *.c ../b
clang -g -Wno-deprecated -c -DISNOTARYNODE=1 -DLIQUIDITY_PROVIDER=1 main.c iguana777.c iguana_bundles.c ../basilisk/basilisk.c
clang -g -o ../agents/iguana *.o ../agents/libcrypto777.a -lnanomsg -lcurl -lssl -lcrypto -lpthread -lz -lm
stdbuf -oL $1 ../agents/iguana notary & #> iguana.log 2> error.log &
iguana_arg=${2:-notary}
stdbuf -oL $1 ../agents/iguana $iguana_arg & #> iguana.log 2> error.log &
myip=`curl -s4 checkip.amazonaws.com`
source pubkey.txt
@ -16,14 +17,31 @@ source pubkey.txt
sleep 4
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"SuperNET\",\"method\":\"myipaddr\",\"ipaddr\":\"$myip\"}"
sleep 3
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"167.99.67.33\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"78.47.196.146\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"95.213.238.98\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"82.202.193.98\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"82.202.193.100\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"54.95.68.31\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"142.54.164.114\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"103.6.12.111\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"155.254.17.21\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"138.121.203.210\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"139.99.149.41\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"209.58.169.65\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"5.189.232.34\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"46.4.33.66\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"66.70.180.46\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"88.99.251.101\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"139.99.121.200\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"52.65.58.103\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"159.65.134.48\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"178.128.25.203\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"217.182.203.106\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"149.56.19.212\"}"
curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"95.213.205.222\"}"
#tests/addnotarys_7776
coins/btc_7776
@ -62,6 +80,11 @@ coins/prlpay_7776
coins/dsec_7776
coins/glxt_7776
coins/eql_7776
coins/zilla_7776
coins/vrsc_7776
coins/rfox_7776
coins/sec_7776
coins/ccl_7776
#curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"passthru\",\"method\":\"paxfiats\",\"timeout\":900000}"

4
iguana/m_splitfund

@ -35,3 +35,7 @@ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CHAIN\",\"agent\":\"iguan
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"DSEC\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"GLXT\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"EQL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ZILLA\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RFOX\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SEC\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CCL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"10000\",\"sendflag\":1,\"duplicates\":50}"

2
iguana/mini-gmp.c

@ -4403,7 +4403,7 @@ int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr)
if ( *p != '\0' )
{
int32_t zeroval();
printf("bitcoin_base58decode error: p %02x != 0x00\n",*p);
//printf("bitcoin_base58decode error: p %02x != 0x00\n",*p);
mpz_clear(bn), mpz_clear(bn58);
return(-1);
}

1
includes/iguana_apideclares.h

@ -27,6 +27,7 @@ TWOINTS_AND_ARRAY(dpow,ratify,minsigs,timestamp,ratified);
ZERO_ARGS(dpow,cancelratify);
STRING_ARG(dpow,bindaddr,ipaddr);
STRING_AND_INT(dpow,fundnotaries,symbol,numblocks);
ZERO_ARGS(dpow,ipaddrs);
ZERO_ARGS(pax,start);
INT_ARG(passthru,paxfiats,mask);

60
marketmaker_build_depends.cmd

@ -36,54 +36,66 @@ exit
rem MSBuild /help
echo.
echo Decker will automatically download and build all needed *.dll and *.lib for you ;)
timeout /t 5 /nobreak
mkdir marketmaker_depends
mkdir x64\Release
rem --- pthreads ---
:compile_pthreads
if not exist marketmaker_depends\pthread-win32\bin\x64_MSVC2015.Release\pthread_lib.lib (
cd marketmaker_depends
git clone https://github.com/DeckerSU/pthread-win32
cd pthread-win32
MSBuild pthread.2015.sln /t:Rebuild /p:Configuration=Release /p:Platform=Win32
MSBuild pthread.2015.sln /t:Rebuild /p:Configuration=Release /p:Platform=x64
cd ../..
)
copy marketmaker_depends\pthread-win32\bin\x64_MSVC2015.Release\pthread_lib.lib OSlibs\win\x64\pthread_lib.lib
rem --- nanomsg ---
:compile_nanomsg
cd marketmaker_depends
git clone https://github.com/nanomsg/nanomsg
cd nanomsg
mkdir build_msvc_2015_win32
mkdir build_msvc_2015_win64
cd build_msvc_2015_win64
cmake -G "Visual Studio 14 2015 Win64" ..
cmake --build . --config Release --target nanomsg
cd ../../..
if not exist marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.lib (
if not exist marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.exp (
if not exist marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.dll (
cd marketmaker_depends
git clone https://github.com/nanomsg/nanomsg
cd nanomsg
mkdir build_msvc_2015_win32
mkdir build_msvc_2015_win64
cd build_msvc_2015_win64
cmake -G "Visual Studio 14 2015 Win64" ..
cmake --build . --config Release --target nanomsg
cd ../../..
)
)
)
copy marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.lib OSlibs\win\x64\release\nanomsg.lib
copy marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.exp OSlibs\win\x64\release\nanomsg.exp
copy marketmaker_depends\nanomsg\build_msvc_2015_win64\Release\nanomsg.dll x64\Release\nanomsg.dll
rem --- curl ---
:compile_curl
cd marketmaker_depends
git clone https://github.com/curl/curl
cd curl
mkdir build_msvc_2015_win32
mkdir build_msvc_2015_win64
cd build_msvc_2015_win64
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_USE_WINSSL:BOOL=ON ..
cmake --build . --config Release --target libcurl
if not exist marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.lib (
if not exist marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.exp (
if not exist marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl.dll (
cd marketmaker_depends
git clone https://github.com/curl/curl
cd curl
mkdir build_msvc_2015_win32
mkdir build_msvc_2015_win64
cd build_msvc_2015_win64
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_USE_WINSSL:BOOL=ON ..
cmake --build . --config Release --target libcurl
rem cmake .. -G"Visual Studio 14 2015 Win64" -DCURL_STATICLIB=ON -DCURL_DISABLE_LDAP=ON -DCURL_STATIC_CRT=ON
rem cmake .. -G"Visual Studio 14 2015 Win64" -DCURL_STATICLIB:BOOL=ON -DCURL_STATIC_CRT:BOOL=ON -DHTTP_ONLY:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=RELEASE ..
rem cmake --build . --config Release
rem cmake --build . --config Release --target libcurl
rem cmake .. -G"Visual Studio 14 2015 Win64" -DCURL_STATICLIB=ON -DCURL_DISABLE_LDAP=ON -DCURL_STATIC_CRT=ON
rem cmake .. -G"Visual Studio 14 2015 Win64" -DCURL_STATICLIB:BOOL=ON -DCURL_STATIC_CRT:BOOL=ON -DHTTP_ONLY:BOOL=ON -DCMAKE_BUILD_TYPE:STRING=RELEASE ..
rem cmake --build . --config Release
rem cmake --build . --config Release --target libcurl
cd ../../..
cd ../../..
)
)
)
copy marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.lib OSlibs\win\x64\release\libcurl.lib
copy marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.exp OSlibs\win\x64\release\libcurl.exp
copy marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl.dll x64\Release\libcurl.dll

7
marketmaker_build_etomic.cmd

@ -7,16 +7,13 @@ copy marketmaker_depends\curl\build_msvc_2015_win64\lib\Release\libcurl_imp.lib
copy marketmaker_depends\pthread-win32\bin\x64_MSVC2015.Release\pthread_lib.lib marketmaker_depends\pthread-win32\bin\x64_MSVC2015.Release\pthread.lib
echo [#2] Prepare build etomic needed things ...
git submodule init
git submodule update --init --recursive
cd cpp-ethereum
rem git submodule init
rem git submodule update --init
call scripts\install_deps.bat
call scripts\install_deps.bat
cd ..
mkdir build_win64_release
cd build_win64_release
cmake .. -G "Visual Studio 14 2015 Win64"
cmake .. -G "Visual Studio 14 2015 Win64" -DMM_VERSION="%APPVEYOR_BUILD_VERSION%"
rem Steps before build:
rem

8
start_BEER_OTHER_trade.sh

@ -0,0 +1,8 @@
#!/bin/bash
docker-compose exec -T clientnode ./enable
sleep 3
docker-compose exec -T seednode ./enable
sleep 3
docker-compose exec -T seednode ./sell_BEER_OTHER $1
sleep 3
docker-compose exec -T clientnode ./buy_BEER_OTHER $1

8
start_BEER_OTHER_trade_inverted.sh

@ -0,0 +1,8 @@
#!/bin/bash
docker-compose exec -T clientnode ./enable
sleep 3
docker-compose exec -T seednode ./enable
sleep 3
docker-compose exec -T clientnode ./buy_BEER_OTHER $1
sleep 3
docker-compose exec -T seednode ./sell_BEER_OTHER $1

5
travis_cmake_linux.sh

@ -0,0 +1,5 @@
#!/bin/bash
sudo rm -rf /usr/local/cmake-3.9.2 && sudo rm -rf /usr/local/cmake
wget https://cmake.org/files/v3.12/cmake-3.12.0-rc2-Linux-x86_64.sh
chmod +x cmake-3.12.0-rc2-Linux-x86_64.sh
sudo ./cmake-3.12.0-rc2-Linux-x86_64.sh --skip-license --exclude-subdir --prefix=/usr/local

6
travis_cmake_mac.sh

@ -0,0 +1,6 @@
#!/bin/bash
brew uninstall cmake --force
wget https://cmake.org/files/v3.12/cmake-3.12.0-rc2-Darwin-x86_64.tar.gz
tar -xzf cmake-3.12.0-rc2-Darwin-x86_64.tar.gz
cp -r cmake-3.12.0-rc2-Darwin-x86_64/CMake.app/Contents/bin/* /usr/local/bin/
cp -r cmake-3.12.0-rc2-Darwin-x86_64/CMake.app/Contents/share/* /usr/local/share/
Loading…
Cancel
Save