diff --git a/.gitignore b/.gitignore
index 558848c08..37c54960f 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,7 @@
-
+x64
*.o
-
-
-
-
-
agents/iguana.exe
+Debug/*
iguana/pnacl/Release/iguana_unstripped.pexe
@@ -37,3 +33,220 @@ agents/*
iguana/confs/BTC_hdrs.txt
+
+deprecated/.DS_Store
+
+.DS_Store
+
+
+iguana/help/.tmpmarker
+
+iguana/genesis/.tmpmarker
+
+iguana/help.json
+
+iguana/autoAPI.md
+
+iguana/basilisk.o-2ad8cb38
+=======
+*.pbxproj
+
+iguana/tmp/.tmpmarker
+
+iguana/SVM/rawfeatures/.tmpmarker
+
+iguana/DB/.tmpmarker
+
+iguana/DB/TRANSACTIONS/.tmpmarker
+
+iguana/DB/purgeable/.tmpmarker
+
+iguana/DB/purgeable/BTCD/.tmpmarker
+
+iguana/DB/purgeable/BTC/.tmpmarker
+
+iguana/DB/ECB/.tmpmarker
+
+iguana/genesis/.tmpmarker
+
+iguana/help/.tmpmarker
+
+iguana/SVM/.tmpmarker
+
+iguana/SVM/models/.tmpmarker
+
+SuperNET.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/xcschememanagement.plist
+
+SuperNET.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/SuperNET.xcscheme
+
+iguana/DB/BTC/.tmpmarker
+
+*.vouts
+
+iguana/DB/BTC/vouts/.tmpmarker
+
+iguana/DB/BTC/accounts/.tmpmarker
+
+iguana/DB/BTC/spends/.tmpmarker
+
+iguana/DB/BTC/validated/.tmpmarker
+
+iguana/DB/KMD/.tmpmarker
+
+iguana/DB/KMD/accounts/.tmpmarker
+
+iguana/DB/KMD/spends/.tmpmarker
+
+iguana/DB/KMD/validated/.tmpmarker
+
+iguana/DB/KMD/vouts/.tmpmarker
+
+iguana/DB/purgeable/KMD/.tmpmarker
+
+iguana/DB/ro/.tmpmarker
+
+iguana/DB/ro/BTC/.tmpmarker
+
+iguana/DB/ro/KMD/.tmpmarker
+
+iguana/confs/682c279f7b01b96aee50f11b327bf6c0a3d3481a23a9a265f0796e9bb3765b24
+
+iguana/confs/682c279f7b01b96aee50f11b327bf6c0a3d3481a23a9a265f0796e9bb3765b24.old
+
+iguana/confs/83cb074c13289a91a0cd50a8e6932b2237d1533ec1cbff56ab3d9b1d37f8df35
+
+iguana/confs/83cb074c13289a91a0cd50a8e6932b2237d1533ec1cbff56ab3d9b1d37f8df35.old
+
+iguana/tmp/BTC/.tmpmarker
+
+iguana/tmp/BTC/0/.tmpmarker
+
+iguana/tmp/BTC/0/0/.tmpmarker
+
+iguana/tmp/BTC/peers.txt
+
+iguana/tmp/BTC/RT/.tmpmarker
+
+iguana/tmp/KMD/.tmpmarker
+
+iguana/tmp/KMD/0/.tmpmarker
+
+iguana/tmp/KMD/0/0/.tmpmarker
+
+iguana/tmp/KMD/peers.txt
+
+iguana/tmp/KMD/RT/.tmpmarker
+
+*.xcworkspacedata
+
+*.xcuserstate
+
+includes/iguana_apideclares copy.h
+
+iguana/iguana_tx.o-4b5de8fe
+
+iguana/confs/c6faccf6b625bbb826f47b77c3274e985db7b0a47d435f32bea2f7f3724cdd17
+
+iguana/confs/c6faccf6b625bbb826f47b77c3274e985db7b0a47d435f32bea2f7f3724cdd17.old
+
+iguana/marketmaker
+
+iguana/secp256k1.o-501dfbfe
+
+iguana/confs/cc577d22ca76351d495f147b470103392b5f2ab0948e45608623a7d9728e2c6f
+
+iguana/confs/cc577d22ca76351d495f147b470103392b5f2ab0948e45608623a7d9728e2c6f.old
+
+iguana/DB/DEX.log
+
+iguana/iguana_notary.o-54f98cc3
+
+iguana/basilisk.o-2ad8cb38
+iguana/pangea_hand.o-02d25ec3
+
+iguana/confs/4dfa301d0adf61f0ec08e4d4cb4444f4fc377f45f5d6b1da0814033920d72353
+
+iguana/help.json
+
+iguana/index7778.html
+
+
+iguana/DB/KMD/utxo.dat
+
+iguana/unparsed.txt
+
+iguana/unparsed.txt
+
+iguana/unparsed.txt
+
+iguana/DB/SWAPS/.tmpmarker
+
+iguana/DB/SWAPS/list
+
+iguana/DB/SWAPS/15974209-4014252807
+
+iguana/iguana777.o-0cc60f50
+
+iguana/DB/SWAPS/667293271-3414303895
+
+iguana/DB/SWAPS/667293271-3414303895.swap
+
+iguana/DB/SWAPS/548227681-1452262678.swap
+
+iguana/DB/SWAPS/548227681-1452262678
+
+*.bobdeposit
+
+*.bobpayment
+
+*.bobreclaim
+
+*.bobrefund
+
+*.swap
+
+iguana/DB/SWAPS/1268007736-526212866
+
+iguana/DB/SWAPS/3111936786-3185288772
+
+iguana/DB/SWAPS/3368214189-2405641584
+
+iguana/DB/SWAPS/1133671270-1840176506
+
+iguana/DB/SWAPS/467927158-3437055573
+
+iguana/DB/SWAPS/270159951-1269722638
+
+iguana/DB/SWAPS/244991424-1008712592
+
+iguana/confs/1cc0270abba7f4463a3dcb9908b9d875691a6773fe3cc1b4302233ed76665300
+
+iguana/autoAPI.md
+
+iguana/confs/5228bcea7ae2515a29c3844673de6ee2acba53bf45724744a00ff4306f192912
+
+iguana/confs/630929d976025fafde221c7358eb5805f4359bad3c6b8bd50ad3f6e0a9b5ce78
+
+iguana/confs/5f3283a017c31e52443d61cb43944e2157f7c03eb12d701ebf4a35a695688e1f
+
+iguana/marketmaker.dSYM/Contents/Resources/DWARF/marketmaker
+
+iguana/marketmaker.dSYM/Contents/Info.plist
+
+iguana/confs/97f18454bb61e9eb7a827cfbefe42fbf7ae2832dc74c4812bdaef8bcf5c10474
+
+iguana/DB/PRICES/.tmpmarker
+
+iguana/DB/KMD/0/.tmpmarker
+
+*.swp
+
+iguana/myipaddr
+
+iguana/DB/UNSPENTS/.tmpmarker
+
+*.RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg
+
+iguana/DB/instantdex_RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg_append.json
+
+iguana/DB/instantdex_RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg.json
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 000000000..20c9e805a
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,22 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "C++ Launch (Windows)",
+ "type": "cppvsdbg",
+ "request": "launch",
+ "program": "enter program name, for example ${workspaceRoot}/a.exe",
+ "args": [],
+ "stopAtEntry": false,
+ "cwd": "${workspaceRoot}",
+ "environment": [],
+ "externalConsole": false
+ },
+ {
+ "name": "C++ Attach (Windows)",
+ "type": "cppvsdbg",
+ "request": "attach",
+ "processId": "${command:pickProcess}"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/MyTemplate.vstemplate b/MyTemplate.vstemplate
new file mode 100644
index 000000000..7dd0fb0dc
--- /dev/null
+++ b/MyTemplate.vstemplate
@@ -0,0 +1,22 @@
+
+
+ iguana_template
+ <No description available>
+ VC
+
+
+ 1000
+ true
+ iguana_template
+ true
+ Enabled
+ true
+ __TemplateIcon.ico
+
+
+
+ ConsoleApplication3.vcxproj.filters
+ ReadMe.txt
+
+
+
\ No newline at end of file
diff --git a/OSlibs/android/lib/libcrypto.so b/OSlibs/android/lib/libcrypto.so
deleted file mode 100755
index 8fa44cee8..000000000
Binary files a/OSlibs/android/lib/libcrypto.so and /dev/null differ
diff --git a/OSlibs/android/lib/libcurl.a b/OSlibs/android/lib/libcurl.a
deleted file mode 100755
index bbc4fa4f0..000000000
Binary files a/OSlibs/android/lib/libcurl.a and /dev/null differ
diff --git a/OSlibs/android/lib/libssl.so b/OSlibs/android/lib/libssl.so
deleted file mode 100755
index 8c270c350..000000000
Binary files a/OSlibs/android/lib/libssl.so and /dev/null differ
diff --git a/OSlibs/ios/lib/libcrypto.a b/OSlibs/ios/lib/libcrypto.a
deleted file mode 100644
index 3e9849e14..000000000
Binary files a/OSlibs/ios/lib/libcrypto.a and /dev/null differ
diff --git a/OSlibs/ios/lib/libcurl.a b/OSlibs/ios/lib/libcurl.a
deleted file mode 100644
index 07109972f..000000000
Binary files a/OSlibs/ios/lib/libcurl.a and /dev/null differ
diff --git a/OSlibs/ios/lib/libssl.a b/OSlibs/ios/lib/libssl.a
deleted file mode 100644
index 646b0ad20..000000000
Binary files a/OSlibs/ios/lib/libssl.a and /dev/null differ
diff --git a/OSlibs/osx/libcrypto.a b/OSlibs/osx/libcrypto.a
deleted file mode 100644
index 4d3f97915..000000000
Binary files a/OSlibs/osx/libcrypto.a and /dev/null differ
diff --git a/OSlibs/osx/libcurl.a b/OSlibs/osx/libcurl.a
deleted file mode 100644
index 41192abb7..000000000
Binary files a/OSlibs/osx/libcurl.a and /dev/null differ
diff --git a/OSlibs/osx/libgmp.a b/OSlibs/osx/libgmp.a
deleted file mode 100644
index 3ed321825..000000000
Binary files a/OSlibs/osx/libgmp.a and /dev/null differ
diff --git a/OSlibs/osx/libsecp256k1.a b/OSlibs/osx/libsecp256k1.a
deleted file mode 100644
index 5b2034911..000000000
Binary files a/OSlibs/osx/libsecp256k1.a and /dev/null differ
diff --git a/OSlibs/osx/libssl.a b/OSlibs/osx/libssl.a
deleted file mode 100644
index badeb5f21..000000000
Binary files a/OSlibs/osx/libssl.a and /dev/null differ
diff --git a/OSlibs/win/libcrypto.a b/OSlibs/win/libcrypto.a
deleted file mode 100755
index 62f2adfc8..000000000
Binary files a/OSlibs/win/libcrypto.a and /dev/null differ
diff --git a/OSlibs/win/libcurl.a b/OSlibs/win/libcurl.a
deleted file mode 100755
index 768133dde..000000000
Binary files a/OSlibs/win/libcurl.a and /dev/null differ
diff --git a/OSlibs/win/libcurl.exp b/OSlibs/win/libcurl.exp
new file mode 100644
index 000000000..a2b9da989
Binary files /dev/null and b/OSlibs/win/libcurl.exp differ
diff --git a/OSlibs/win/libcurl.lib b/OSlibs/win/libcurl.lib
new file mode 100644
index 000000000..c2b00f3c8
Binary files /dev/null and b/OSlibs/win/libcurl.lib differ
diff --git a/OSlibs/win/libcurldll.a b/OSlibs/win/libcurldll.a
deleted file mode 100755
index 15cf86362..000000000
Binary files a/OSlibs/win/libcurldll.a and /dev/null differ
diff --git a/OSlibs/win/libpthreadGC2.a b/OSlibs/win/libpthreadGC2.a
deleted file mode 100755
index ff267089b..000000000
Binary files a/OSlibs/win/libpthreadGC2.a and /dev/null differ
diff --git a/OSlibs/win/libpthreadGC2_64.a b/OSlibs/win/libpthreadGC2_64.a
deleted file mode 100755
index 430162364..000000000
Binary files a/OSlibs/win/libpthreadGC2_64.a and /dev/null differ
diff --git a/OSlibs/win/libsecp256k1.a b/OSlibs/win/libsecp256k1.a
deleted file mode 100644
index 778d5d980..000000000
Binary files a/OSlibs/win/libsecp256k1.a and /dev/null differ
diff --git a/OSlibs/win/libssl.a b/OSlibs/win/libssl.a
deleted file mode 100755
index ac3e692a7..000000000
Binary files a/OSlibs/win/libssl.a and /dev/null differ
diff --git a/OSlibs/win/mingw.h b/OSlibs/win/mingw.h
index 1a80c56dc..2c35aa78c 100755
--- a/OSlibs/win/mingw.h
+++ b/OSlibs/win/mingw.h
@@ -1,12 +1,17 @@
#ifndef MINGW_H
#define MINGW_H
+#define ssize_t __int32
#include
#define _USE_W32_SOCKETS 1
+#define WIN32_LEAN_AND_MEAN
+#include
#include
+#define PTW32_STATIC_LIB
#include "pthread.h"
+#ifndef NATIVE_WINDOWS
#define ENOTCONN WSAENOTCONN
#define EWOULDBLOCK WSAEWOULDBLOCK
#define ENOBUFS WSAENOBUFS
@@ -18,25 +23,67 @@
#define EISCONN WSAEISCONN
#define ECONNREFUSED WSAECONNREFUSED
#define EHOSTUNREACH WSAEHOSTUNREACH
-
+#endif
/* winsock doesn't feature poll(), so there is a version implemented
* in terms of select() in mingw.c. The following definitions
* are copied from linux man pages. A poll() macro is defined to
* call the version in mingw.c.
*/
-#define POLLIN 0x0001 /* There is data to read */
+
#define POLLPRI 0x0002 /* There is urgent data to read */
+#if defined(_M_X64)
+ /*
+ * when we are using WSAPoll() with window's struct pollfd struct
+ * we need to update the value for POLLIN and POLLOUT according to window's
+ * WSAPoll() return values
+ * @author - fadedreamz@gmail.com
+ */
+//TODO: need to update other values to match with WSAPoll() function
+#define POLLRDNORM 0x0100
+#define POLLRDBAND 0x0200
+#define POLLWRNORM 0x0010
+#define POLLIN POLLRDNORM | POLLRDBAND /* There is data to read */
+#define POLLOUT POLLWRNORM /* Writing now will not block */
+#else
+#define POLLIN 0x0001 /* There is data to read */
#define POLLOUT 0x0004 /* Writing now will not block */
+#endif
#define POLLERR 0x0008 /* Error condition */
#define POLLHUP 0x0010 /* Hung up */
#define POLLNVAL 0x0020 /* Invalid request: fd not open */
-struct pollfd {
- SOCKET fd; /* file descriptor */
- short events; /* requested events */
- short revents; /* returned events */
-};
+
+ /**
+ * we want to use mingw provided pollfd if and only if we are compiling this
+ * in windows 32bit but exclude it when we are compiling it in win 64
+ *
+ * @author - fadedreamz@gmail.com
+ * @remarks - #if (defined(_M_X64) || defined(__amd64__)) && defined(WIN32)
+ * is equivalent to #if defined(_M_X64) as _M_X64 is defined for MSVC only
+ */
+
+
+// [Decker] pollfs is already defined in winsock2.h
+
+//#if !defined(_M_X64)
+//struct pollfd {
+ //SOCKET fd; /* file descriptor */
+ //short events; /* requested events */
+ //short revents; /* returned events */
+//};
+//#endif
+
+
+#if defined(_M_X64)
+/*
+* we want to use the window's poll function if poll() is invoked in win64
+* as we are using window's pollfd struct when we are using x64
+* @author - fadedreamz@gmail.com
+*/
+#define poll(x, y, z) WSAPoll(x, y, z)
+#else
#define poll(x, y, z) win32_poll(x, y, z)
+#endif
/* These wrappers do nothing special except set the global errno variable if
* an error occurs (winsock doesn't do this by default). They set errno
diff --git a/OSlibs/win/nanomsg.lib b/OSlibs/win/nanomsg.lib
new file mode 100644
index 000000000..f0fdac6fb
Binary files /dev/null and b/OSlibs/win/nanomsg.lib differ
diff --git a/OSlibs/win/pthreadGC2.dll b/OSlibs/win/pthreadGC2.dll
deleted file mode 100755
index 67b9289df..000000000
Binary files a/OSlibs/win/pthreadGC2.dll and /dev/null differ
diff --git a/OSlibs/win/pthreadGC2_64.dll b/OSlibs/win/pthreadGC2_64.dll
deleted file mode 100755
index 841d4a216..000000000
Binary files a/OSlibs/win/pthreadGC2_64.dll and /dev/null differ
diff --git a/OSlibs/win/release/nanomsg.lib b/OSlibs/win/release/nanomsg.lib
new file mode 100644
index 000000000..082e2cf03
Binary files /dev/null and b/OSlibs/win/release/nanomsg.lib differ
diff --git a/OSlibs/win/release/pthreadVC2.lib b/OSlibs/win/release/pthreadVC2.lib
new file mode 100644
index 000000000..d793e7144
Binary files /dev/null and b/OSlibs/win/release/pthreadVC2.lib differ
diff --git a/OSlibs/win/x64/libcurl.lib b/OSlibs/win/x64/libcurl.lib
new file mode 100644
index 000000000..92f23798c
Binary files /dev/null and b/OSlibs/win/x64/libcurl.lib differ
diff --git a/OSlibs/win/x64/libpthreadGC2.a b/OSlibs/win/x64/libpthreadGC2.a
deleted file mode 100644
index 96f31306b..000000000
Binary files a/OSlibs/win/x64/libpthreadGC2.a and /dev/null differ
diff --git a/OSlibs/win/x64/nanomsg.lib b/OSlibs/win/x64/nanomsg.lib
new file mode 100644
index 000000000..9e15cde27
Binary files /dev/null and b/OSlibs/win/x64/nanomsg.lib differ
diff --git a/OSlibs/win/x64/release/libcurl.exp b/OSlibs/win/x64/release/libcurl.exp
new file mode 100644
index 000000000..fc2bcb28c
Binary files /dev/null and b/OSlibs/win/x64/release/libcurl.exp differ
diff --git a/OSlibs/win/x64/release/libcurl.lib b/OSlibs/win/x64/release/libcurl.lib
new file mode 100644
index 000000000..92f23798c
Binary files /dev/null and b/OSlibs/win/x64/release/libcurl.lib differ
diff --git a/OSlibs/win/x64/release/nanomsg.lib b/OSlibs/win/x64/release/nanomsg.lib
new file mode 100644
index 000000000..0a9a4a694
Binary files /dev/null and b/OSlibs/win/x64/release/nanomsg.lib differ
diff --git a/README.md b/README.md
index 98dda7232..57e2376e8 100755
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
-#SuperNET Client "iguana"
+# SuperNET Client "iguana"
OS | Build Status
-------------|------
-Unix (Ubuntu 14.04) | [![Build Status](https://jenkinsmaster.sprnt.pw/buildStatus/icon?job=Unix-jl777)](https://jenkinsmaster.sprnt.pw/job/Unix-jl777)
-Chrome | [![Build Status](https://jenkinsmaster.sprnt.pw/buildStatus/icon?job=PNaCl-jl777)](https://jenkinsmaster.sprnt.pw/job/PNaCl-jl777/)
-Android | [![Build Status](https://jenkinsmaster.sprnt.pw/buildStatus/icon?job=Android)](https://jenkinsmaster.sprnt.pw/job/Android/)
-iOS | [![Build Status](https://jenkinsmaster.sprnt.pw/buildStatus/icon?job=iOS)](https://jenkinsmaster.sprnt.pw/job/iOS/)
-Windows 32 Bit | [![Build Status](https://jenkinsmaster.sprnt.pw/job/Win32/badge/icon)](https://jenkinsmaster.sprnt.pw/job/Win32/)
-Windows 64 Bit | [![Build Status](https://jenkinsmaster.sprnt.pw/job/Win64-jl777/badge/icon)](https://jenkinsmaster.sprnt.pw/job/Win64-jl777/)
+Unix (Ubuntu 14.04) | [![Build Status](https://jenkinsmaster.sprnt.pw/buildStatus/icon?job=iguana-unix-jl777-release-v0.1)](https://jenkinsmaster.sprnt.pw/job/iguana-unix-jl777-release-v0.1)
+Chrome | [![Build Status](https://jenkinsmaster.sprnt.pw/buildStatus/icon?job=iguana-pnacl-jl777-release-v0.1)](https://jenkinsmaster.sprnt.pw/job/iguana-pnacl-jl777-release-v0.1/)
+Android | [![Build Status](https://jenkinsmaster.sprnt.pw/buildStatus/icon?job=iguana-android-jl777-release-v0.1)](https://jenkinsmaster.sprnt.pw/job/iguana-android-jl777-release-v0.1/)
+iOS | [![Build Status](https://jenkinsmaster.sprnt.pw/buildStatus/icon?job=iguana-ios-jl777-release-v0.1)](https://jenkinsmaster.sprnt.pw/job/iguana-ios-jl777-release-v0.1/)
+Windows 32 Bit | [![Build Status](https://jenkinsmaster.sprnt.pw/job/iguana-win32-jl777-release-v0.1/badge/icon)](https://jenkinsmaster.sprnt.pw/job/iguana-win32-jl777-release-v0.1/)
+Windows 64 Bit | [![Build Status](https://jenkinsmaster.sprnt.pw/job/iguana-win64-jl777-release-v0.1/badge/icon)](https://jenkinsmaster.sprnt.pw/job/iguana-win64-jl777-release-v0.1/)
docs.supernet.org | [![Build Status](https://jenkinsmaster.sprnt.pw/buildStatus/icon?job=docs.supernet.org-updating)](https://jenkinsmaster.sprnt.pw/job/docs.supernet.org-updating/)
---
@@ -22,12 +22,12 @@ iguana: most efficient bitcoin core implementation that can simultaneously be fu
komodo: this is the top secret project I cant talk about publicly yet
-> #TL;DR#
->
-> ```sudo apt-get update; sudo apt-get install git build-essential; git clone https://github.com/jl777/SuperNET; cd SuperNET; ./m_onetime m_unix;```
->
-> The above one line gets SuperNET installed, built and launched for unix.
->
+> # TL;DR
+>
+> ```sudo apt-get update; sudo apt-get install git libcurl4-openssl-dev build-essential libnanomsg-dev; git clone https://github.com/jl777/SuperNET; cd SuperNET; ./m_onetime m_unix;```
+>
+> The above one line gets SuperNET installed, built and launched for unix.
+>
> After that ```./m_unix``` updates to latest.
> *Continue below at "Running".*
@@ -40,12 +40,14 @@ TOOL_DIR := /usr/local/gcc-4.8.0-qt-4.8.4-for-mingw32/win32-gcc/bin
MINGW := i586-mingw32
The above two definitions need to be changed to match the mingw install on your system. m_win32 and m_win64 just invokes the makefile in mingw32 and mingw64
-##For chrome app##
+## For chrome app
You need to make sure the nacl sdk is properly installed and you are able to build the examples.
Now you will need to get the external libs, which can be built from scratch using naclports or there use the reference builds of libcurl.a and libz.a in the SuperNET/crypto777/pnacl_libs. You can just copy those over into $(NACL_SDK_ROOT)//lib/pnacl.
+## For android
+You have to build a native libnanomsg for android. This section is work in progress. Contact ca333@protonmail.ch for assistance on building latest iguana for android.
-#ONETIME#
+# ONETIME
Now you are ready to build.
I try to make the build process as simple as possible, so there are no `autoconf`, `autoreconf`, `configure`, `cmake`, `make`, to get properly installed and running and run, etc. You do need a C compiler, like gcc.
@@ -80,12 +82,12 @@ To build just iguana, you can ```cd``` into SuperNET/iguana and do ```./m_unix``
```./m_clean``` will remove the files created from the building
-#RUNNING#
+# RUNNING
The native versions are command line applications: agents/iguana {JSON}
The chrome app pexe requires that the chrome is launched with a command line parameter (tools/chrome.localhost) and then browse to *http://127.0.0.1:7777* to see the pexe
-#SUPERUGLYGUI#
+# SUPERUGLYGUI
Once iguana is running, you can see the superuglyGUI at *http://127.0.0.1:7778/?method*
by submitting API calls using the forms, you will see it go to some specific URL. You can also do a programmatic GET request to ```http://127.0.0.1:7778/api/```
@@ -103,14 +105,14 @@ Internally, all paths convert the request into a standard SuperNET JSON request.
Another approach is to use the bitcoin RPC syntax via:
curl --url "http://127.0.0.1:7778" --data "{\"coin\":\"BTCD\",\"method\":\"getinfo\",\"params\":[]}"
the params:[] array is where the standard bitcoin parameters go, the only change that is needed is to specify the coin
-alternatively {"agent":"SuperNET","method":"bitcoinrpc","coin":"BTCD"} will set the coin
+alternatively {"agent":"SuperNET","method":"bitcoinrpc","coin":"BTCD"} will set the coin
to use for bitcoin RPC calls. this will suffice in single coin environments
curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"iguana",\"method\":\"test\"}"
curl --url "http://127.0.0.1:7778/iguana/test" -> html page with results
curl --url "http://127.0.0.1:7778/api/iguana/test" -> just json text
http://127.0.0.1:7778 -> superugly GUI
-http://127.0.0.1:7778/iguana/test
+http://127.0.0.1:7778/iguana/test
http://127.0.0.1:7778/api/iguana/test
postCall('{"agent":"iguana","method":"test"}'}
iguana_JSON("{\"agent\":\"iguana",\"method\":\"test\"}"); -> direct C function call
@@ -124,7 +126,7 @@ iguana can be invoked with a command line argument. if it is a name of a file, i
"exchanges" -> { "name":"", ... }
"apikey", "apisecret", "userid", "tradepassword" these are as expected
"pollgap" -> gap between each access to exchange for getting prices
-
+
on OSX mksquashfs is not native, you will need to install fuse: https://osxfuse.github.io/ and a squashfs for mac: https://github.com/vasi/squashfuse
**********
@@ -132,9 +134,9 @@ on OSX mksquashfs is not native, you will need to install fuse: https://osxfuse.
A Note on Installation from pebwindkraft at bitco.in
=======================
Though I had xcode installed, aclocal didn’t work. I installed homebrew, and then:
-# brew install autoconf
-# brew install automake
-# brew install gmp
+`brew install autoconf`
+`brew install automake`
+`brew install gmp`
2.) libsecp256
it complained, that libsecp256 was not there in includes, so I linked it.
@@ -156,3 +158,100 @@ once jsoncmp is built, then ./test shows how to use it
the idea is to issue a curl command into a /tmp/file and then use jsoncmp to verify the exact value of one or more fields. it will print to stdout JSON with "error" or "result" and to stderr if there is an error
+##### ../agents/iguana notary
+0.Have iguana installed at http://wiki.supernet.org/wiki/How_To_Install_Iguana_on_Linux
+also install nanomsg: sudo apt-get install libnanomsg-dev
+ports 7775 will be used
+
+cd Supernet/iguana -->
+
+../agents/iguana
+
+#In another SSH window:
+
+cd Supernet/iguana/coins -->
+
+./basilisk
+
+1. Create an iguana wallet with encryptwallet and importprivkey into both komodod and bitcoind using the KMDwif and BTCwif in the encryptwallet result
+
+curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"bitcoinrpc\",\"method\":\"encryptwallet\",\"passphrase\":\"insert very secure password here\"}"
+
+2. Go to SuperNET/iguana/
+
+pico wp
+
+curl --url "http://127.0.0.1:7778" --data "{\"method\":\"walletpassphrase\",\"params\":[\"same passphrase as above\", 9999999]}"
+
+#Save the file then run the following command:
+
+chmod +x wp
+
+#Run the file
+
+./wp
+
+#Get the btcpubkey key from the output and give it to James.
+
+3. create a text file SuperNET/iguana/myip.txt with just your ip address in it:
+
+pico myip.txt
+
+#Put your WAN IP of your node
+
+4. create a text file with the user home dir in it:
+
+pico userhome.txt
+root
+
+5. make a copy of SuperNET/iguana/wp -> SuperNET/iguana/wp_7776 and change port 7778 to port 7776
+
+cp wp wp_7776
+pico wp_7776
+
+#Then change the port to 7776 from within the new file.
+
+6. make a copy of SuperNET/iguana/tests/dpow_7776 to SuperNET/iguana/dpow_7776 and edit the pubkey to match your btcpubkey from above
+
+cp dpow_7776 ../
+pico dpow_7776
+
+7. make sure system clock is synchronized
+sudo service ntp stop
+sudo ntpdate -s time.nist.gov
+sudo service ntp start
+
+Now things should be ready. To update and run notary node:
+pkill iguana; ./m_LP; tests/notaryinit
+
+
+
+##Build for OSX distribution##
+Get OSX SDK 10.6 from https://github.com/ca333/MacOSX-SDKs/releases/tag/10.6
+
+Unpack & move the .sdk folder to Xcodes SDK folder:
+
+```cd DownloadDirectory```
+
+```mv MacOSX10.6.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/.```
+
+If you are using Xcode > 7.3 add the new SDK to XCode by changing MinimumSDKVersion in your Info.plist:
+
+```vi /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Info.plist```
+
+Change the value to:
+
+```
+MinimumSDKVersion
+10.6
+```
+Build crypto777 library and agents with OSX release makefile:
+
+```./m_onetime m_osx_release```
+
+Execute the OSX deploy script:
+
+```
+./osx_deploy.sh
+```
+The iguana binary and its linked libraries are in ```$HOME/tmp/iguana```.
diff --git a/README_decker.md b/README_decker.md
new file mode 100644
index 000000000..a9cccd878
--- /dev/null
+++ b/README_decker.md
@@ -0,0 +1,25 @@
+## What's this?
+
+This is a first build of **MarketMaker** app from barterDEX for Windows (64-bit) platform. This branch includes all that you need to build marketmaker for Windows. 64-bit build uses MSVC 2015 as a default C/C++ compiler, to build - simply open *marketmaker.sln* project file via File -> Open -> Project/Solution ... next choose Release / x64 configuration and build solution. Your binaries will be placed x64\Release folder. To run marketmaker you also need following dll libraries:
+
+- libcurl.dll
+- nanomsg.dll
+- curl.exe (win64 curl binary, used is scripts)
+
+It already included in this branch.
+
+## How to use?
+
+Please, refer to original barterDEX documentation and Komodo Platform + SuperNET resources to learn how to work this it. Later i will add some examples and useful links here.
+
+Important, coins.json on Windows shouldn't contain coins which haven't running daemons. Add to coins.json only coins that you plan to use, in other case starting marketmaker will too long: about 4 seconds on each not-running coin.
+
+Get the latest binary release from release section and step-by-step run cmd files:
+
+- 1-client.cmd - this runs marketmaker with passphrase taken from a passphrase file.
+- 2-getuserpass.cmd - this will save and output your userpass in userpass file for future use.
+- 3-orderbook.cmd - to get an orderbook (if u downloaded binary release from release section - it's have only REVS in coins.json and orderbook will be shown at KMD/REVS coins pair).
+
+Other scripts will be post later ... this is just for example that it works.
+
+
\ No newline at end of file
diff --git a/ReadMe.txt b/ReadMe.txt
new file mode 100644
index 000000000..3d1d8f0c5
--- /dev/null
+++ b/ReadMe.txt
@@ -0,0 +1,40 @@
+========================================================================
+ CONSOLE APPLICATION : ConsoleApplication3 Project Overview
+========================================================================
+
+AppWizard has created this ConsoleApplication3 application for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your ConsoleApplication3 application.
+
+
+ConsoleApplication3.vcxproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+ConsoleApplication3.vcxproj.filters
+ This is the filters file for VC++ projects generated using an Application Wizard.
+ It contains information about the association between the files in your project
+ and the filters. This association is used in the IDE to show grouping of files with
+ similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+ "Source Files" filter).
+
+ConsoleApplication3.cpp
+ This is the main application source file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named ConsoleApplication3.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/__TemplateIcon.ico b/__TemplateIcon.ico
new file mode 100644
index 000000000..aae70d3b8
Binary files /dev/null and b/__TemplateIcon.ico differ
diff --git a/basilisk/basilisk copy.c b/basilisk/basilisk copy.c
deleted file mode 100755
index 5b9a88c04..000000000
--- a/basilisk/basilisk copy.c
+++ /dev/null
@@ -1,1160 +0,0 @@
-/******************************************************************************
- * Copyright © 2014-2016 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. *
- * *
- ******************************************************************************/
-
-#include "../iguana/iguana777.h"
-
-typedef char *basilisk_coinfunc(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen);
-typedef char *basilisk_servicefunc(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk);
-typedef struct basilisk_item *basilisk_requestfunc(struct basilisk_item *Lptr,struct supernet_info *myinfo,bits256 hash,cJSON *valsobj,uint8_t *data,int32_t datalen);
-
-uint32_t basilisk_calcnonce(struct supernet_info *myinfo,uint8_t *data,int32_t datalen,uint32_t nBits)
-{
- int32_t i,numiters = 0; bits256 hash,hash2,threshold; uint32_t basilisktag;
- vcalc_sha256(0,hash.bytes,data,datalen);
- threshold = bits256_from_compact(nBits);
- for (i=0; i 0 )
- break;
- }
- iguana_rwnum(0,(void *)hash.uints,sizeof(basilisktag),&basilisktag);
- iguana_rwnum(1,&data[-sizeof(basilisktag)],sizeof(basilisktag),&basilisktag);
- char str[65],str2[65]; printf("found hash after numiters.%d %s vs %s basilisktag.%u\n",numiters,bits256_str(str,threshold),bits256_str(str2,hash2),basilisktag);
- return(basilisktag);
-}
-
-char *basilisk_addhexstr(char **ptrp,cJSON *valsobj,char *strbuf,int32_t strsize,uint8_t *data,int32_t datalen)
-{
- *ptrp = 0;
- if ( data != 0 && datalen > 0 )
- {
- if ( valsobj != 0 && jobj(valsobj,"data") != 0 )
- {
- printf("basilisk_addhexstr warning: already have data object\n");
- jdelete(valsobj,"data");
- }
- if ( (datalen<<1)+1 > strsize )
- {
- strbuf = calloc(1,(datalen << 1) + 1);
- *ptrp = (void *)strbuf;
- }
- init_hexbytes_noT(strbuf,data,datalen);
- if ( valsobj != 0 )
- jaddstr(valsobj,"data",strbuf);
- } else return(0);
- return(strbuf);
-}
-
-uint8_t *get_dataptr(int32_t hdroffset,uint8_t **ptrp,int32_t *datalenp,uint8_t *space,int32_t spacesize,char *hexstr)
-{
- *ptrp = 0; uint8_t *data = 0;
- if ( hexstr != 0 && (*datalenp= is_hexstr(hexstr,0)) > 0 )
- {
- *datalenp >>= 1;
- if ( (*datalenp+hdroffset) <= spacesize )
- {
- memset(space,0,hdroffset);
- data = &space[hdroffset];
- } else *ptrp = data = calloc(1,*datalenp + hdroffset);
- decode_hex(&data[hdroffset],*datalenp,hexstr);
- }
- if ( data != 0 )
- return(&data[hdroffset]);
- else return(data);
-}
-
-uint8_t *basilisk_jsondata(int32_t extraoffset,uint8_t **ptrp,uint8_t *space,int32_t spacesize,int32_t *datalenp,char *symbol,cJSON *sendjson,uint32_t basilisktag)
-{
- char *sendstr,*hexstr=0; uint8_t *data,hexspace[8192],*allocptr=0,*hexdata; int32_t datalen,hexlen=0;
- if ( jobj(sendjson,"symbol") == 0 )
- jaddstr(sendjson,"symbol",symbol);
- if ( (hexstr= jstr(sendjson,"data")) != 0 )
- {
- hexdata = get_dataptr(0,&allocptr,&hexlen,hexspace,sizeof(hexspace),hexstr);
- //printf("delete data.%s from sendjson\n",hexstr);
- jdelete(sendjson,"data");
- }
- *ptrp = 0;
- sendstr = jprint(sendjson,0);
- datalen = (int32_t)strlen(sendstr) + 1;
- if ( (datalen + extraoffset + BASILISK_HDROFFSET + hexlen) <= spacesize )
- data = space;
- else
- {
- data = calloc(1,datalen + extraoffset + BASILISK_HDROFFSET + hexlen);
- *ptrp = data;
- }
- data += extraoffset + BASILISK_HDROFFSET;
- memcpy(data,sendstr,datalen);
- //printf("jsondata.(%s) + hexlen.%d\n",sendstr,hexlen);
- free(sendstr);
- if ( hexlen > 0 )
- {
- memcpy(&data[datalen],hexdata,hexlen);
- datalen += hexlen;
- }
- *datalenp = datalen;
- if ( allocptr != 0 )
- free(allocptr);
- return(data);
-}
-
-char *basilisk_finish(struct basilisk_item *ptr,int32_t besti,char *errstr)
-{
- char *retstr = 0; struct basilisk_item *parent;
- if ( ptr->retstr != 0 )
- return(ptr->retstr);
- if ( besti >= 0 && besti < ptr->numresults )
- {
- retstr = ptr->results[besti];
- ptr->results[besti] = 0;
- } else printf("besti.%d vs numresults.%d retstr.%p\n",besti,ptr->numresults,retstr);
- if ( retstr == 0 )
- retstr = clonestr(errstr);
- ptr->retstr = retstr;
- ptr->finished = (uint32_t)time(NULL);
- if ( (parent= ptr->parent) != 0 )
- {
- ptr->parent = 0;
- parent->childrendone++;
- }
- return(retstr);
-}
-
-struct basilisk_item *basilisk_itemcreate(struct supernet_info *myinfo,char *CMD,char *symbol,uint32_t basilisktag,int32_t minresults,cJSON *vals,int32_t timeoutmillis,void *metricfunc)
-{
- struct basilisk_item *ptr;
- ptr = calloc(1,sizeof(*ptr));
- ptr->basilisktag = basilisktag;
- if ( (ptr->numrequired= minresults) == 0 )
- ptr->numrequired = 1;
- if ( (ptr->metricfunc= metricfunc) != 0 )
- ptr->vals = jduplicate(vals);
- strcpy(ptr->CMD,CMD);
- safecopy(ptr->symbol,symbol,sizeof(ptr->symbol));
- ptr->expiration = OS_milliseconds() + timeoutmillis;
- return(ptr);
-}
-
-int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *type,uint32_t *basilisktagp,int32_t encryptflag,int32_t delaymillis,uint8_t *data,int32_t datalen,int32_t fanout,uint32_t nBits) // data must be offset by sizeof(iguana_msghdr)+sizeof(basilisktag)
-{
- int32_t i,r,l,s,val,n=0,retval = -1; char cmd[12]; struct iguana_info *coin,*tmp; struct iguana_peer *addr; bits256 hash; uint32_t *alreadysent;
- if ( fanout <= 0 )
- fanout = BASILISK_MINFANOUT;
- else if ( fanout > BASILISK_MAXFANOUT )
- fanout = BASILISK_MAXFANOUT;
- if ( type == 0 )
- type = "BTCD";
- if ( strlen(type) > 3 )
- {
- printf("basilisk_sendcmd illegal type(%s)\n",type);
- return(-1);
- }
- if ( destipaddr != 0 )
- {
- if ( destipaddr[0] == 0 )
- destipaddr = 0; // broadcast
- else if ( strcmp(destipaddr,"127.0.0.1") == 0 )
- {
- printf("return after locally basilisk_msgprocess\n");
- hash = GENESIS_PUBKEY;
- basilisk_msgprocess(myinfo,0,0,type,*basilisktagp,data,datalen);
- return(0);
- }
- }
- alreadysent = calloc(IGUANA_MAXPEERS * IGUANA_MAXCOINS,sizeof(*alreadysent));
- iguana_rwnum(1,&data[-sizeof(*basilisktagp)],sizeof(*basilisktagp),basilisktagp);
- if ( *basilisktagp == 0 )
- {
- if ( nBits != 0 )
- *basilisktagp = basilisk_calcnonce(myinfo,data,datalen,nBits);
- else *basilisktagp = rand();
- iguana_rwnum(1,&data[-sizeof(*basilisktagp)],sizeof(*basilisktagp),basilisktagp);
- }
- data -= sizeof(*basilisktagp), datalen += sizeof(*basilisktagp);
- memset(cmd,0,sizeof(cmd));
- sprintf(cmd,"SuperNET%s",type);
- r = rand();
- //portable_mutex_lock(&Allcoins_mutex);
- HASH_ITER(hh,myinfo->allcoins,coin,tmp)
- {
- if ( coin->peers == 0 )
- continue;
- if ( coin->RELAYNODE == 0 && coin->VALIDATENODE == 0 )
- cmd[0] = 's';
- else cmd[0] = 'S';
- for (l=0; lpeers->active[i];
- if ( addr->usock >= 0 )
- {
- for (s=0; sipbits )
- break;
- //printf("%s s.%d vs n.%d\n",addr->ipaddr,s,n);
- if ( s == n && (addr->supernet != 0 || addr->basilisk != 0) && (destipaddr == 0 || strcmp(addr->ipaddr,destipaddr) == 0) )
- {
- //printf("[%s].tag%d send %s.(%s) [%x] datalen.%d addr->supernet.%u basilisk.%u to (%s).%d destip.%s\n",cmd,*(uint32_t *)data,type,(char *)&data[4],*(int32_t *)&data[datalen-4],datalen,addr->supernet,addr->basilisk,addr->ipaddr,addr->A.port,destipaddr!=0?destipaddr:"broadcast");
- if ( encryptflag != 0 && bits256_nonz(addr->pubkey) != 0 )
- {
- void *ptr; uint8_t *cipher,space[8192]; int32_t cipherlen; bits256 privkey;
- cmd[6] = 'e', cmd[7] = 't';
- memset(privkey.bytes,0,sizeof(privkey));
- if ( (cipher= SuperNET_ciphercalc(&ptr,&cipherlen,&privkey,&addr->pubkey,data,datalen,space,sizeof(space))) != 0 )
- {
- if ( (val= iguana_queue_send(addr,delaymillis,&cipher[-sizeof(struct iguana_msghdr)],cmd,cipherlen)) >= cipherlen )
- n++;
- if ( ptr != 0 )
- free(ptr);
- }
- }
- else
- {
- cmd[6] = 'E', cmd[7] = 'T';
- if ( (val= iguana_queue_send(addr,delaymillis,&data[-sizeof(struct iguana_msghdr)],cmd,datalen)) >= datalen )
- {
- alreadysent[n++] = (uint32_t)addr->ipbits;
- if ( n >= IGUANA_MAXPEERS*IGUANA_MAXCOINS )
- break;
- }
- }
- if ( destipaddr != 0 || (fanout > 0 && n >= fanout) )
- {
- free(alreadysent);
- return(val);
- }
- else if ( val > retval )
- retval = val;
- }
- }
- }
- if ( n >= IGUANA_MAXPEERS*IGUANA_MAXCOINS )
- break;
- }
- //portable_mutex_unlock(&Allcoins_mutex);
- free(alreadysent);
- return(n);
-}
-
-void basilisk_p2p(void *_myinfo,void *_addr,char *senderip,uint8_t *data,int32_t datalen,char *type,int32_t encrypted)
-{
- uint32_t ipbits,basilisktag; int32_t msglen,len=0; void *ptr = 0; uint8_t space[8192]; bits256 senderpub; struct supernet_info *myinfo = _myinfo;
- if ( encrypted != 0 )
- {
- printf("encrypted p2p\n");
- memset(senderpub.bytes,0,sizeof(senderpub));
- if ( (data= SuperNET_deciphercalc(&ptr,&msglen,myinfo->privkey,senderpub,data,datalen,space,sizeof(space))) == 0 )
- {
- printf("basilisk_p2p decrytion error\n");
- return;
- } else datalen = msglen;
- }
- if ( senderip != 0 && senderip[0] != 0 && strcmp(senderip,"127.0.0.1") != 0 )
- ipbits = (uint32_t)calc_ipbits(senderip);
- else ipbits = 0;
- len += iguana_rwnum(0,data,sizeof(basilisktag),&basilisktag);
- //int32_t i; for (i=0; ireceived.%d basilisk_p2p.(%s) from %s tag.%d\n",datalen,type,senderip!=0?senderip:"?",basilisktag);
- basilisk_msgprocess(myinfo,_addr,ipbits,type,basilisktag,&data[len],datalen - len);
- if ( ptr != 0 )
- free(ptr);
-}
-
-void basilisk_sendback(struct supernet_info *myinfo,char *origCMD,char *symbol,char *remoteaddr,uint32_t basilisktag,char *retstr)
-{
- uint8_t *data,space[4096],*allocptr; struct iguana_info *virt; cJSON *valsobj; int32_t datalen,encryptflag=0,delaymillis=0;
- //printf("%s retstr.(%s) -> remote.(%s) basilisktag.%u\n",origCMD,retstr,remoteaddr,basilisktag);
- if ( retstr != 0 && remoteaddr != 0 && remoteaddr[0] != 0 && strcmp(remoteaddr,"127.0.0.1") != 0 )
- {
- if ( (valsobj= cJSON_Parse(retstr)) != 0 )
- {
- jaddstr(valsobj,"origcmd",origCMD);
- jaddstr(valsobj,"symbol",symbol);
- if ( (virt= iguana_coinfind(symbol)) != 0 )
- {
- jaddnum(valsobj,"hwm",virt->blocks.hwmchain.height);
- jaddbits256(valsobj,"chaintip",virt->blocks.hwmchain.RO.hash2);
- }
- data = basilisk_jsondata(sizeof(struct iguana_msghdr),&allocptr,space,sizeof(space),&datalen,symbol,valsobj,basilisktag);
- basilisk_sendcmd(myinfo,remoteaddr,"RET",&basilisktag,encryptflag,delaymillis,data,datalen,0,0);
- if ( allocptr != 0 )
- free(allocptr);
- free_json(valsobj);
- }
- }
-}
-
-char *basilisk_waitresponse(struct supernet_info *myinfo,char *CMD,char *symbol,char *remoteaddr,struct basilisk_item *Lptr,struct basilisk_item *ptr)
-{
- char *retstr = 0;
- if ( ptr == Lptr )
- {
- if ( (retstr= Lptr->retstr) == 0 )
- retstr = clonestr("{\"result\":\"null return from local basilisk_issuecmd\"}");
- ptr = basilisk_itemcreate(myinfo,CMD,symbol,Lptr->basilisktag,Lptr->numrequired,Lptr->vals,OS_milliseconds() - Lptr->expiration,Lptr->metricfunc);
- queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
- }
- else
- {
- queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
- while ( OS_milliseconds() < ptr->expiration )
- {
- //if ( (retstr= basilisk_iscomplete(ptr)) != 0 )
- if ( (retstr= ptr->retstr) != 0 )
- break;
- usleep(50000);
- }
- if ( retstr == 0 )
- retstr = basilisk_finish(ptr,-1,"{\"error\":\"basilisk timeout\"}");
- }
- basilisk_sendback(myinfo,CMD,symbol,remoteaddr,ptr->basilisktag,retstr);
- return(retstr);
-}
-
-struct basilisk_item *basilisk_issueremote(struct supernet_info *myinfo,int32_t *numsentp,char *CMD,char *symbol,int32_t blockflag,cJSON *valsobj,int32_t fanout,int32_t minresults,uint32_t basilisktag,int32_t timeoutmillis,void *_metricfunc,char *retstr,int32_t encryptflag,int32_t delaymillis,uint32_t nBits)
-{
- struct basilisk_item *ptr; uint8_t *allocptr,*data,space[4096]; int32_t datalen; basilisk_metricfunc metricfunc = _metricfunc;
- ptr = basilisk_itemcreate(myinfo,CMD,symbol,basilisktag,minresults,valsobj,timeoutmillis,metricfunc);
- ptr->nBits = nBits;
- *numsentp = 0;
- if ( retstr != 0 )
- {
- ptr->results[0] = ptr->retstr = retstr;
- ptr->numresults = ptr->numrequired;
- ptr->metrics[0] = (*metricfunc)(myinfo,ptr,retstr);
- ptr->finished = (uint32_t)time(NULL);
- }
- else
- {
- data = basilisk_jsondata(sizeof(struct iguana_msghdr),&allocptr,space,sizeof(space),&datalen,symbol,valsobj,basilisktag);
- *numsentp = ptr->numsent = basilisk_sendcmd(myinfo,0,CMD,&ptr->basilisktag,encryptflag,delaymillis,data,datalen,1,ptr->nBits);
- if ( blockflag != 0 )
- queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
- else ptr->finished = (uint32_t)time(NULL);
- if ( allocptr != 0 )
- free(allocptr);
- }
- return(ptr);
-}
-
-struct basilisk_item *basilisk_requestservice(struct supernet_info *myinfo,char *CMD,int32_t blockflag,cJSON *valsobj,bits256 hash,uint8_t *data,int32_t datalen,uint32_t nBits)
-{
- int32_t minresults,timeoutmillis,numsent,delaymillis,encryptflag,fanout; struct basilisk_item *ptr; char buf[4096],*symbol,*str = 0; struct iguana_info *virt,*btcd;
- if ( (btcd= iguana_coinfind("BTCD")) != 0 && btcd->RELAYNODE != 0 )
- jaddnum(valsobj,"iamrelay",1);
- basilisk_addhexstr(&str,valsobj,buf,sizeof(buf),data,datalen);
- if ( bits256_cmp(hash,GENESIS_PUBKEY) != 0 && bits256_nonz(hash) != 0 )
- {
- if ( jobj(valsobj,"hash") != 0 )
- jdelete(valsobj,"hash");
- jaddbits256(valsobj,"hash",hash);
- }
- if ( (minresults= jint(valsobj,"minresults")) <= 0 )
- minresults = 1;
- if ( (timeoutmillis= jint(valsobj,"timeout")) == 0 )
- timeoutmillis = BASILISK_TIMEOUT;
- if ( jobj(valsobj,"fanout") == 0 )
- fanout = 1;
- else fanout = jint(valsobj,"fanout");
- if ( (symbol= jstr(valsobj,"coin")) != 0 || (symbol= jstr(valsobj,"symbol")) != 0 )
- {
- if ( (virt= iguana_coinfind(symbol)) != 0 )
- {
- jaddstr(valsobj,"symbol",symbol);
- jaddnum(valsobj,"longest",virt->longestchain);
- jaddnum(valsobj,"hwm",virt->blocks.hwmchain.height);
- }
- }
- encryptflag = jint(valsobj,"encrypt");
- delaymillis = jint(valsobj,"delay");
- ptr = basilisk_issueremote(myinfo,&numsent,CMD,"BTCD",blockflag,valsobj,fanout,minresults,0,timeoutmillis,0,0,encryptflag,delaymillis,nBits);
- return(ptr);
-}
-
-char *basilisk_standardservice(char *CMD,struct supernet_info *myinfo,bits256 hash,cJSON *valsobj,char *hexstr,int32_t blockflag) // client side
-{
- uint32_t nBits = 0; uint8_t space[8192],*allocptr=0,*data = 0; struct basilisk_item *ptr,Lptr; int32_t datalen = 0; cJSON *retjson;
- retjson = cJSON_CreateObject();
- data = get_dataptr(BASILISK_HDROFFSET,&allocptr,&datalen,space,sizeof(space),hexstr);
- ptr = basilisk_requestservice(myinfo,CMD,blockflag,valsobj,hash,data,datalen,nBits);
- if ( allocptr != 0 )
- free(allocptr);
- if ( ptr != 0 )
- {
- if ( blockflag != 0 )
- {
- if ( ptr->expiration <= OS_milliseconds() )
- ptr->expiration = OS_milliseconds() + BASILISK_TIMEOUT;
- ptr->vals = jduplicate(valsobj);
- strcpy(ptr->symbol,"BTCD");
- strcpy(ptr->CMD,CMD);
- return(basilisk_waitresponse(myinfo,CMD,"BTCD",0,&Lptr,ptr));
- }
- else if ( ptr->numsent > 0 )
- {
- queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
- jaddstr(retjson,"result","success");
- jaddnum(retjson,"numsent",ptr->numsent);
- } else jaddstr(retjson,"error","didnt find any nodes to send to");
- } else jaddstr(retjson,"error","couldnt create basilisk item");
- return(jprint(retjson,1));
-}
-
-#include "basilisk_bitcoin.c"
-#include "basilisk_nxt.c"
-#include "basilisk_ether.c"
-#include "basilisk_waves.c"
-#include "basilisk_lisk.c"
-#include "basilisk_CMD.c"
-
-void basilisk_functions(struct iguana_info *coin,int32_t protocol)
-{
- coin->protocol = protocol;
- switch ( protocol )
- {
- case IGUANA_PROTOCOL_BITCOIN:
- coin->basilisk_balances = basilisk_bitcoinbalances;
- coin->basilisk_rawtx = basilisk_bitcoinrawtx;
- coin->basilisk_rawtxmetric = basilisk_bitcoin_rawtxmetric;
- coin->basilisk_value = basilisk_bitcoinvalue;
- coin->basilisk_valuemetric = basilisk_bitcoin_valuemetric;
- break;
- /*case IGUANA_PROTOCOL_IOTA:
- coin->basilisk_balances = basilisk_iotabalances;
- coin->basilisk_rawtx = basilisk_iotarawtx;
- break;
- case IGUANA_PROTOCOL_NXT:
- coin->basilisk_balances = basilisk_nxtbalances;
- coin->basilisk_rawtx = basilisk_nxtrawtx;
- break;
- case IGUANA_PROTOCOL_ETHER:
- coin->basilisk_balances = basilisk_etherbalances;
- coin->basilisk_rawtx = basilisk_etherrawtx;
- break;
- case IGUANA_PROTOCOL_WAVES:
- coin->basilisk_balances = basilisk_wavesbalances;
- coin->basilisk_rawtx = basilisk_wavesrawtx;
- break;
- case IGUANA_PROTOCOL_LISK:
- coin->basilisk_balances = basilisk_liskbalances;
- coin->basilisk_rawtx = basilisk_liskrawtx;
- break;*/
- }
-}
-
-int32_t basilisk_besti(struct basilisk_item *ptr)
-{
- int32_t i,besti = -1; double metric,bestmetric=-1.;
- for (i=0; inumresults; i++)
- {
- if ( (metric= ptr->metrics[i]) > 0. )
- {
- if ( (ptr->metricdir < 0 && (bestmetric < 0. || metric < bestmetric)) || (ptr->metricdir > 0 && (bestmetric < 0. || metric > bestmetric)) || (ptr->metricdir == 0 && bestmetric < 0.) )
- {
- bestmetric = metric;
- besti = i;
- }
- }
- }
- if ( besti >= 0 )
- {
- for (ptr->numexact=i=0; inumresults; i++)
- if ( fabs(ptr->metrics[i] - bestmetric) < SMALLVAL )
- ptr->numexact++;
- }
- return(besti);
-}
-
-char *basilisk_iscomplete(struct basilisk_item *ptr)
-{
- int32_t i,numvalid,besti=-1; char *errstr = 0,*retstr = 0;
- if ( ptr->childrendone < ptr->numchildren )
- return(0);
- if ( ptr->retstr != 0 || ptr->finished != 0 )
- return(ptr->retstr);
- if ( (numvalid= ptr->numresults) >= ptr->numrequired )
- {
- for (i=numvalid=0; inumresults; i++)
- {
- if ( ptr->metrics[i] != 0. )
- numvalid++;
- }
- }
- if ( numvalid < ptr->numrequired )
- {
- //printf("%u: numvalid.%d < required.%d m %f\n",ptr->basilisktag,numvalid,ptr->numrequired,ptr->metrics[0]);
- return(0);
- }
- if ( ptr->uniqueflag == 0 && ptr->numexact != ptr->numresults && ptr->numexact < (ptr->numresults >> 1) )
- besti = -1, errstr = "{\"error\":\"basilisk non-consensus results\"}";
- else besti = basilisk_besti(ptr), errstr = "{\"error\":\"basilisk no valid results\"}";
- //printf("%u complete besti.%d\n",ptr->basilisktag,besti);
- retstr = basilisk_finish(ptr,besti,errstr);
- //printf("%u besti.%d numexact.%d numresults.%d -> (%s)\n",ptr->basilisktag,besti,ptr->numexact,ptr->numresults,retstr);
- return(retstr);
-}
-
-struct basilisk_item *basilisk_issuecmd(struct basilisk_item *Lptr,basilisk_func func,basilisk_metricfunc metricfunc,struct supernet_info *myinfo,char *remoteaddr,uint32_t basilisktag,char *symbol,int32_t timeoutmillis,cJSON *vals)
-{
- struct iguana_info *coin; struct basilisk_item *ptr;
- memset(Lptr,0,sizeof(*Lptr));
- if ( (coin= iguana_coinfind(symbol)) != 0 )
- {
- if ( func != 0 )
- {
- if ( (ptr= (*func)(Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 )
- {
- if ( (ptr->metricfunc= metricfunc) != 0 )
- ptr->vals = jduplicate(vals);
- strcpy(ptr->symbol,symbol);
- ptr->basilisktag = basilisktag;
- ptr->expiration = OS_milliseconds() + timeoutmillis;
- return(ptr);
- } else Lptr->retstr = clonestr("{\"error\":\"error issuing basilisk command\"}");
- } else Lptr->retstr = clonestr("{\"error\":\"null basilisk function\"}");
- } else Lptr->retstr = clonestr("{\"error\":\"error missing coin\"}");
- return(Lptr);
-}
-
-char *basilisk_check(int32_t *timeoutmillisp,uint32_t *basilisktagp,char *symbol,cJSON *vals)
-{
- if ( symbol != 0 && symbol[0] != 0 && vals != 0 )
- {
- if ( *basilisktagp == 0 )
- *basilisktagp = rand();
- if ( (*timeoutmillisp= jint(vals,"timeout")) < 0 )
- *timeoutmillisp = BASILISK_TIMEOUT;
- return(0);
- } else return(clonestr("{\"error\":\"missing activecoin or vals\"}"));
-}
-
-char *basilisk_standardcmd(struct supernet_info *myinfo,char *CMD,char *activecoin,char *remoteaddr,uint32_t basilisktag,cJSON *vals,basilisk_func func,basilisk_metricfunc metric)
-{
- char *retstr; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis; struct iguana_info *coin;
- if ( (retstr= basilisk_check(&timeoutmillis,&basilisktag,activecoin,vals)) == 0 )
- {
- if ( (coin= iguana_coinfind(activecoin)) != 0 )
- {
- if ( (ptr= basilisk_issuecmd(&Lptr,func,metric,myinfo,remoteaddr,basilisktag,activecoin,timeoutmillis,vals)) != 0 )
- {
- return(basilisk_waitresponse(myinfo,CMD,coin->symbol,remoteaddr,&Lptr,ptr));
- }
- else return(clonestr("{\"error\":\"null return from basilisk_issuecmd\"}"));
- } else return(clonestr("{\"error\":\"couldnt get coin\"}"));
- } else return(retstr);
-}
-
-char *_basilisk_value(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen)
-{
- return(basilisk_standardcmd(myinfo,"VAL",coin->symbol,remoteaddr,basilisktag,valsobj,coin->basilisk_value,coin->basilisk_valuemetric));
-}
-
-char *_basilisk_balances(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen)
-{
- return(basilisk_standardcmd(myinfo,"BAL",coin->symbol,remoteaddr,basilisktag,valsobj,coin->basilisk_balances,coin->basilisk_balancesmetric));
-}
-
-char *_basilisk_rawtx(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen)
-{
- char *retstr,strbuf[4096],*str = 0;
- printf("remote rawtx.(%s)\n",jprint(valsobj,0));
- basilisk_addhexstr(&str,valsobj,strbuf,sizeof(strbuf),data,datalen);
- retstr = basilisk_rawtx(myinfo,coin,0,remoteaddr,basilisktag,valsobj,coin->symbol);
- if ( str != 0 )
- free(str);
- return(retstr);
-}
-
-char *_basilisk_result(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen)
-{
- char strbuf[4096],*str = 0;
- basilisk_addhexstr(&str,valsobj,strbuf,sizeof(strbuf),data,datalen);
- return(basilisk_result(myinfo,coin,0,remoteaddr,basilisktag,valsobj));
-}
-
-char *basilisk_checkrawtx(int32_t *timeoutmillisp,uint32_t *basilisktagp,char *symbol,cJSON *vals)
-{
- cJSON *addresses=0; char *changeaddr,*spendscriptstr; int32_t i,n;
- *timeoutmillisp = -1;
- changeaddr = jstr(vals,"changeaddr");
- spendscriptstr = jstr(vals,"spendscript");
- addresses = jarray(&n,vals,"addresses");
- if ( addresses == 0 || changeaddr == 0 || changeaddr[0] == 0 )
- return(clonestr("{\"error\":\"invalid addresses[] or changeaddr\"}"));
- else
- {
- for (i=0; isymbol);
- if ( (retstr= basilisk_standardservice(CMD,myinfo,hash,vals,hexstr,0)) != 0 )
- free(retstr);
- free_json(vals);
- if ( allocptr != 0 )
- free(allocptr);
- }
- return(0);
- } else return(-1);
-}
-
-#include "../includes/iguana_apidefs.h"
-#include "../includes/iguana_apideclares.h"
-
-INT_ARRAY_STRING(basilisk,balances,basilisktag,vals,activecoin)
-{
- return(basilisk_standardcmd(myinfo,"BAL",activecoin,remoteaddr,basilisktag,vals,coin->basilisk_balances,coin->basilisk_balancesmetric));
-}
-
-INT_ARRAY_STRING(basilisk,value,basilisktag,vals,activecoin)
-{
- return(basilisk_standardcmd(myinfo,"VAL",activecoin,remoteaddr,basilisktag,vals,coin->basilisk_value,coin->basilisk_valuemetric));
-}
-
-INT_ARRAY_STRING(basilisk,rawtx,basilisktag,vals,activecoin)
-{
- char *retstr; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis;
- if ( (retstr= basilisk_checkrawtx(&timeoutmillis,(uint32_t *)&basilisktag,activecoin,vals)) == 0 )
- {
- coin = iguana_coinfind(activecoin);
- if ( coin != 0 && (ptr= basilisk_issuecmd(&Lptr,coin->basilisk_rawtx,coin->basilisk_rawtxmetric,myinfo,remoteaddr,basilisktag,activecoin,timeoutmillis,vals)) != 0 )
- {
- if ( (ptr->numrequired= juint(vals,"numrequired")) == 0 )
- ptr->numrequired = 1;
- ptr->uniqueflag = 1;
- ptr->metricdir = -1;
- return(basilisk_waitresponse(myinfo,"RAW",coin->symbol,remoteaddr,&Lptr,ptr));
- } else return(clonestr("{\"error\":\"error issuing basilisk rawtx\"}"));
- } else return(retstr);
-}
-
-INT_AND_ARRAY(basilisk,result,basilisktag,vals)
-{
- struct basilisk_item *ptr;
- if ( vals != 0 )
- {
- ptr = calloc(1,sizeof(*ptr));
- ptr->retstr = jprint(vals,0);
- ptr->basilisktag = basilisktag;
- strcpy(ptr->remoteaddr,remoteaddr);
- safecopy(ptr->CMD,jstr(vals,"origcmd"),sizeof(ptr->CMD));
- printf("(%s) -> Q.%u results vals.(%s)\n",ptr->CMD,basilisktag,ptr->retstr);
- queue_enqueue("resultsQ",&myinfo->basilisks.resultsQ,&ptr->DL,0);
- return(clonestr("{\"result\":\"queued basilisk return\"}"));
- } else printf("null vals.(%s) or no hexmsg.%p\n",jprint(vals,0),vals);
- return(clonestr("{\"error\":\"no hexmsg to return\"}"));
-}
-
-HASH_ARRAY_STRING(basilisk,addrelay,hash,vals,hexstr)
-{
- return(basilisk_standardservice("ADD",myinfo,hash,vals,hexstr,1));
-}
-
-HASH_ARRAY_STRING(basilisk,relays,hash,vals,hexstr)
-{
- return(basilisk_standardservice("RLY",myinfo,hash,vals,hexstr,1));
-}
-
-HASH_ARRAY_STRING(basilisk,dispatch,hash,vals,hexstr)
-{
- return(basilisk_standardservice("RUN",myinfo,hash,vals,hexstr,1));
-}
-
-HASH_ARRAY_STRING(basilisk,publish,hash,vals,hexstr)
-{
- return(basilisk_standardservice("PUB",myinfo,hash,vals,hexstr,1));
-}
-
-HASH_ARRAY_STRING(basilisk,subscribe,hash,vals,hexstr)
-{
- return(basilisk_standardservice("SUB",myinfo,hash,vals,hexstr,1));
-}
-
-HASH_ARRAY_STRING(basilisk,forward,hash,vals,hexstr)
-{
- return(basilisk_standardservice("HOP",myinfo,hash,vals,hexstr,0));
-}
-
-HASH_ARRAY_STRING(basilisk,mailbox,hash,vals,hexstr)
-{
- return(basilisk_standardservice("BOX",myinfo,hash,vals,hexstr,1));
-}
-
-HASH_ARRAY_STRING(basilisk,VPNcreate,hash,vals,hexstr)
-{
- return(basilisk_standardservice("VPN",myinfo,hash,vals,hexstr,1));
-}
-
-HASH_ARRAY_STRING(basilisk,VPNjoin,hash,vals,hexstr)
-{
- return(basilisk_standardservice("ARC",myinfo,hash,vals,hexstr,1));
-}
-
-HASH_ARRAY_STRING(basilisk,VPNmessage,hash,vals,hexstr)
-{
- return(basilisk_standardservice("GAB",myinfo,hash,vals,hexstr,0));
-}
-
-HASH_ARRAY_STRING(basilisk,VPNbroadcast,hash,vals,hexstr)
-{
- return(basilisk_standardservice("SAY",myinfo,hash,vals,hexstr,0));
-}
-
-HASH_ARRAY_STRING(basilisk,VPNreceive,hash,vals,hexstr)
-{
- return(basilisk_standardservice("EAR",myinfo,hash,vals,hexstr,1));
-}
-
-HASH_ARRAY_STRING(basilisk,VPNlogout,hash,vals,hexstr)
-{
- return(basilisk_standardservice("END",myinfo,hash,vals,hexstr,0));
-}
-
-#include "../includes/iguana_apiundefs.h"
-
-// set hwm, get headers, then blocks
-
-void basilisk_geckoresult(struct supernet_info *myinfo,struct basilisk_item *ptr)
-{
- uint8_t *data,space[16384],*allocptr = 0; struct iguana_info *virt; char *symbol,*str,*type; int32_t datalen; cJSON *retjson; bits256 hash2;
- if ( (retjson= cJSON_Parse(ptr->retstr)) != 0 )
- {
- if ( (symbol= jstr(retjson,"symbol")) != 0 && (virt= iguana_coinfind(symbol)) != 0 )
- {
- if ( (data= get_dataptr(0,&allocptr,&datalen,space,sizeof(space),jstr(retjson,"data"))) != 0 )
- {
- str = 0;
- if ( (type= jstr(retjson,"type")) != 0 )
- {
- hash2 = jbits256(retjson,"hash");
- if ( strcmp(type,"HDR") == 0 )
- str = gecko_headersarrived(myinfo,virt,ptr->remoteaddr,data,datalen,hash2);
- else if ( strcmp(type,"MEM") == 0 )
- str = gecko_mempoolarrived(myinfo,virt,ptr->remoteaddr,data,datalen,hash2);
- else if ( strcmp(type,"BLK") == 0 )
- str = gecko_blockarrived(myinfo,virt,ptr->remoteaddr,data,datalen,hash2);
- else if ( strcmp(type,"GTX") == 0 )
- str = gecko_txarrived(myinfo,virt,ptr->remoteaddr,data,datalen,hash2);
- }
- if ( str != 0 )
- free(str);
- if ( allocptr != 0 )
- free(allocptr);
- }
- }
- free_json(retjson);
- }
-}
-
-void basilisk_pending_result(struct supernet_info *myinfo,struct basilisk_item *ptr,struct basilisk_item *pending)
-{
- int32_t n; struct basilisk_item *parent; basilisk_metricfunc metricfunc;
- if ( (n= pending->numresults) < sizeof(pending->results)/sizeof(*pending->results) )
- {
- pending->numresults++;
- if ( (metricfunc= pending->metricfunc) == 0 )
- pending->metrics[n] = n + 1;
- else if ( (pending->metrics[n]= (*metricfunc)(myinfo,pending,ptr->retstr)) != 0. )
- pending->childrendone++;
- printf("%s.%u Add results[%d] <- metric %f\n",pending->CMD,pending->basilisktag,n,pending->metrics[n]);
- pending->results[n] = ptr->retstr, ptr->retstr = 0;
- /*if ( strcmp(ptr->CMD,"SEQ") == 0 )
- {
- if ( (retjson= cJSON_Parse(ptr->retstr)) != 0 )
- {
- gecko_seqresult(myinfo,ptr->retstr);
- free_json(retjson);
- }
- }
- else*/
- if ( strcmp(ptr->CMD,"RET") == 0 || strcmp(ptr->CMD,"GET") == 0 )
- {
- printf("got return for tag.%d parent.%p\n",pending->basilisktag,pending->parent);
- if ( (parent= pending->parent) != 0 )
- {
- pending->parent = 0;
- parent->childrendone++;
- }
- if ( strcmp(ptr->CMD,"GET") == 0 )
- basilisk_geckoresult(myinfo,ptr);
- }
- }
-}
-
-int32_t basilisk_issued_iteration(struct supernet_info *myinfo,struct basilisk_item *pending)
-{
- basilisk_metricfunc metricfunc; struct basilisk_item *parent; int32_t i,flag = 0;
- //printf("pending.%u numresults.%d m %f func.%p\n",pending->basilisktag,pending->numresults,pending->metrics[0],pending->metricfunc);
- if ( (metricfunc= pending->metricfunc) != 0 )
- {
- for (i=0; inumresults; i++)
- if ( pending->metrics[i] == 0. && pending->results[i] != 0 )
- {
- if ( (pending->metrics[i]= (*metricfunc)(myinfo,pending,pending->results[i])) != 0 )
- pending->childrendone++;
- // printf("iter.%d %p.[%d] poll metrics.%u metric %f\n",iter,pending,i,pending->basilisktag,pending->metrics[i]);
- flag++;
- }
- }
- basilisk_iscomplete(pending);
- if ( OS_milliseconds() > pending->expiration )
- {
- if ( pending->finished == 0 )
- {
- if ( (parent= pending->parent) != 0 )
- {
- pending->parent = 0;
- parent->childrendone++;
- }
- pending->finished = (uint32_t)time(NULL);
- if ( pending->retstr == 0 )
- pending->retstr = clonestr("{\"error\":\"basilisk timeout\"}");
- fprintf(stderr,"timeout.%s call metrics.%u lag %f - %f\n",pending->CMD,pending->basilisktag,OS_milliseconds(),pending->expiration);
- for (i=0; inumresults; i++)
- if ( (metricfunc= pending->metricfunc) != 0 && pending->metrics[i] == 0. )
- pending->metrics[i] = (*metricfunc)(myinfo,pending,pending->results[i]);
- flag++;
- }
- }
- //fprintf(stderr,"c");
- if ( pending->finished != 0 && time(NULL) > pending->finished+60 )
- {
- if ( pending->dependents == 0 || pending->childrendone >= pending->numchildren )
- {
- HASH_DELETE(hh,myinfo->basilisks.issued,pending);
- if ( pending->dependents != 0 )
- free(pending->dependents);
- fprintf(stderr,"HASH_DELETE free ptr.%u refcount.%d\n",pending->basilisktag,pending->refcount);
- for (i=0; inumresults; i++)
- if ( pending->results[i] != 0 )
- free(pending->results[i]), pending->results[i] = 0;
- if ( pending->vals != 0 )
- free_json(pending->vals), pending->vals = 0;
- free(pending);
- flag++;
- }
- }
- return(flag);
-}
-
-void basilisks_loop(void *arg)
-{
- struct iguana_info *btcd,*virt,*hhtmp; struct basilisk_item *ptr,*tmp,*pending; int32_t iter,maxmillis,flag; struct supernet_info *myinfo = arg;
- iter = 0;
- while ( 1 )
- {
- iter++;
- if ( (ptr= queue_dequeue(&myinfo->basilisks.submitQ,0)) != 0 )
- HASH_ADD(hh,myinfo->basilisks.issued,basilisktag,sizeof(ptr->basilisktag),ptr);
- //fprintf(stderr,"A");
- else if ( (ptr= queue_dequeue(&myinfo->basilisks.resultsQ,0)) != 0 )
- {
- HASH_FIND(hh,myinfo->basilisks.issued,&ptr->basilisktag,sizeof(ptr->basilisktag),pending);
- if ( pending != 0 )
- basilisk_pending_result(myinfo,ptr,pending);
- else printf("couldnt find issued.%u\n",ptr->basilisktag);
- free(ptr);
- }
- else
- {
- flag = 0;
- HASH_ITER(hh,myinfo->basilisks.issued,pending,tmp)
- {
- flag += basilisk_issued_iteration(myinfo,pending);
- }
- if ( flag == 0 && myinfo->allcoins_numvirts > 0 && (btcd= iguana_coinfind("BTCD")) != 0 )
- {
- maxmillis = (1000 / myinfo->allcoins_numvirts) + 1;
- //portable_mutex_lock(&Allcoins_mutex);
- HASH_ITER(hh,myinfo->allcoins,virt,hhtmp)
- {
- if ( virt->started != 0 && virt->active != 0 && virt->virtualchain != 0 )
- {
- //fprintf(stderr,"h");
- gecko_iteration(myinfo,btcd,virt,maxmillis);
- flag++;
- }
- }
- //portable_mutex_unlock(&Allcoins_mutex);
- }
- }
- //fprintf(stderr,"i ");
- //for (i=0; iRELAYNODE == 0 && coin->VALIDATENODE == 0 && coin->active != 0 && coin->chain->userpass[0] != 0 && coin->MAXPEERS == 1 )
- // basilisk_bitcoinscan(coin,blockspace,&RAWMEM);
- if ( flag == 0 )
- usleep(10000);
- }
-}
-
-void basilisks_init(struct supernet_info *myinfo)
-{
- iguana_initQ(&myinfo->basilisks.submitQ,"submitQ");
- iguana_initQ(&myinfo->basilisks.resultsQ,"resultsQ");
- portable_mutex_init(&myinfo->allcoins_mutex);
- portable_mutex_init(&myinfo->basilisk_mutex);
- portable_mutex_init(&myinfo->gecko_mutex);
- myinfo->basilisks.launched = iguana_launch(iguana_coinfind("BTCD"),"basilisks_loop",basilisks_loop,myinfo,IGUANA_PERMTHREAD);
-}
-
-void basilisk_wait(struct supernet_info *myinfo,struct iguana_info *coin)
-{
- if ( coin != 0 )
- {
- while ( coin->basilisk_busy != 0 )
- usleep(1000);
- }
- else
- {
- while ( myinfo->basilisk_busy != 0 )
- usleep(1000);
- }
-}
-
-void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t senderipbits,char *type,uint32_t basilisktag,uint8_t *data,int32_t datalen)
-{
- cJSON *valsobj; char *symbol,*retstr=0,remoteaddr[64],CMD[4],cmd[4]; int32_t height,origlen,from_basilisk,i,timeoutmillis,flag,numrequired,jsonlen; uint8_t *origdata; struct iguana_info *coin=0; bits256 hash; struct iguana_peer *addr = _addr;
- static basilisk_servicefunc *basilisk_services[][2] =
- {
- { (void *)"RUN", &basilisk_respond_dispatch }, // higher level protocol handler, pass through
- { (void *)"BYE", &basilisk_respond_goodbye }, // disconnect
-
- // gecko chains
- { (void *)"NEW", &basilisk_respond_newgeckochain }, // creates new virtual gecko chain
- { (void *)"GEN", &basilisk_respond_geckogenesis }, // returns genesis list
- { (void *)"GET", &basilisk_respond_geckoget }, // requests headers, block or tx
- { (void *)"HDR", &basilisk_respond_geckoheaders }, // reports headers
- { (void *)"BLK", &basilisk_respond_geckoblock }, // reports block
- { (void *)"MEM", &basilisk_respond_mempool }, // reports mempool
- { (void *)"GTX", &basilisk_respond_geckotx }, // reports tx
- //{ (void *)"SEQ", &basilisk_respond_hashstamps }, // BTCD and BTC recent hashes from timestamp
-
- // unencrypted low level functions, used by higher level protocols and virtual network funcs
- { (void *)"ADD", &basilisk_respond_addrelay }, // relays register with each other bus
- { (void *)"RLY", &basilisk_respond_relays },
- { (void *)"DEX", &basilisk_respond_instantdex },
-
- // encrypted data for jumblr
- { (void *)"HOP", &basilisk_respond_forward }, // message forwarding
- { (void *)"BOX", &basilisk_respond_mailbox }, // create/send/check mailbox pubkey
-
- // small virtual private network
- { (void *)"VPN", &basilisk_respond_VPNcreate }, // create virtual network's hub via privkey
- { (void *)"ARC", &basilisk_respond_VPNjoin }, // join
- { (void *)"GAB", &basilisk_respond_VPNmessage }, // private message
- { (void *)"SAY", &basilisk_respond_VPNbroadcast }, // broadcast
- { (void *)"EAR", &basilisk_respond_VPNreceive }, // network receive (via poll)
- { (void *)"END", &basilisk_respond_VPNlogout }, // logout
-
- // coin services
- { (void *)"RAW", &_basilisk_rawtx },
- { (void *)"VAL", &_basilisk_value },
- };
- /*static basilisk_coinfunc *basilisk_coinservices[][2] =
- {
- { (void *)"RAW", &_basilisk_rawtx },
- { (void *)"VAL", &_basilisk_value },
- { (void *)"BAL", &_basilisk_balances },
- };*/
- symbol = "BTCD";
- if ( (valsobj= cJSON_Parse((char *)data)) != 0 )
- {
- //printf("MSGVALS.(%s)\n",(char *)data);
- if ( jobj(valsobj,"coin") != 0 )
- coin = iguana_coinfind(jstr(valsobj,"coin"));
- else if ( jobj(valsobj,"symbol") != 0 )
- coin = iguana_coinfind(jstr(valsobj,"symbol"));
- if ( coin != 0 )
- {
- if ( (height= juint(valsobj,"hwm")) > 0 )
- {
- if ( height > addr->height )
- addr->height = height;
- if ( height > coin->longestchain )
- coin->longestchain = height;
- }
- }
- if ( strcmp(type,"RET") == 0 )
- {
- if ( (retstr= _basilisk_result(myinfo,coin,addr,remoteaddr,basilisktag,valsobj,data,datalen)) != 0 )
- free(retstr);
- return;
- }
- } else return;
- for (i=flag=0; ibasilisk_busy = 1;
- if ( valsobj != 0 )
- {
- jsonlen = (int32_t)strlen((char *)data) + 1;
- if ( datalen > jsonlen )
- data += jsonlen, datalen -= jsonlen;
- else data = 0, datalen = 0;
- if ( coin == 0 )
- coin = iguana_coinfind("BTCD");
- if ( coin != 0 )
- {
- symbol = coin->symbol;
- coin->basilisk_busy = 1;
- }
- hash = jbits256(valsobj,"hash");
- timeoutmillis = jint(valsobj,"timeout");
- if ( (numrequired= jint(valsobj,"numrequired")) == 0 )
- numrequired = 1;
- if ( senderipbits != 0 )
- expand_ipbits(remoteaddr,senderipbits);
- else remoteaddr[0] = 0;
- /*if ( valsobj != 0 && remoteaddr != 0 )
- {
- if ( from_basilisk == 0 )
- {
- if ( strcmp(CMD,"RLY") == 0 )
- {
- printf("add relay path\n");
- if ( juint(valsobj,"iamrelay") != 0 )
- {
- retstr = basilisk_respond_relays(myinfo,type,addr,remoteaddr,basilisktag,valsobj,data,datalen,hash,from_basilisk);
- }
- free_json(valsobj);
- if ( coin != 0 )
- coin->basilisk_busy = 0;
- myinfo->basilisk_busy = 0;
- return;
- }
- else if ( (retstr= basilisk_addrelay_info(myinfo,0,(uint32_t)calc_ipbits(remoteaddr),GENESIS_PUBKEY)) != 0 )
- free(retstr);
- }
- }*/
- for (i=0; iIAMRELAY != 0 ) // iguana node
- {
- if ( 0 && from_basilisk != 0 )
- {
- printf("echo to other relays\n");
- basilisk_sendcmd(myinfo,0,cmd,&basilisktag,0,0,origdata,origlen,-1,0); // to other iguanas
- }
- if ( (retstr= (*basilisk_services[i][1])(myinfo,type,addr,remoteaddr,basilisktag,valsobj,data,datalen,hash,from_basilisk)) != 0 )
- {
- //printf("from_basilisk.%d ret.(%s)\n",from_basilisk,retstr);
- if ( from_basilisk != 0 || strcmp(CMD,"GET") == 0 )
- basilisk_sendback(myinfo,CMD,symbol,remoteaddr,basilisktag,retstr);
- if ( retstr != 0 )
- free(retstr);
- } //else printf("services null return\n");
- } else printf("non-relay got unexpected.(%s)\n",type);
- /*free_json(valsobj);
- if ( coin != 0 )
- coin->basilisk_busy = 0;
- myinfo->basilisk_busy = 0;
- return;*/
- }
- }
- /*if ( coin != 0 )
- {
- if ( coin->RELAYNODE != 0 || coin->VALIDATENODE != 0 ) // iguana node
- {
- if ( 0 && from_basilisk != 0 )
- {
- printf("echo to other relays\n");
- basilisk_sendcmd(myinfo,0,cmd,&basilisktag,0,0,origdata,origlen,-1,0); // to other iguanas
- }
- for (i=0; ibasilisk_busy = 0;
- myinfo->basilisk_busy = 0;
-}
-
-
diff --git a/basilisk/basilisk.c b/basilisk/basilisk.c
index 28c03de01..a2a6d2200 100755
--- a/basilisk/basilisk.c
+++ b/basilisk/basilisk.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * Copyright © 2014-2016 The SuperNET Developers. *
+ * Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -14,13 +14,14 @@
******************************************************************************/
#include "../iguana/iguana777.h"
+#include "../iguana/exchanges777.h"
typedef char *basilisk_servicefunc(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk);
-int32_t basilisk_specialcmd(char *cmd)
+int32_t basilisk_notarycmd(char *cmd)
{
//&& strcmp(cmd,"DEX") != 0 && strcmp(cmd,"ACC") != 0 && strcmp(cmd,"RID") != 0 &&
- if ( strcmp(cmd,"PIN") != 0 && strcmp(cmd,"OUT") != 0 && strcmp(cmd,"MSG") != 0 )
+ if ( strcmp(cmd,"PIN") != 0 && strcmp(cmd,"OUT") != 0 && strcmp(cmd,"MSG") != 0 && strcmp(cmd,"VOT") != 0 )
return(0);
else return(1);
}
@@ -32,6 +33,55 @@ int32_t basilisk_specialcmd(char *cmd)
else return(0);
}*/
+cJSON *basilisk_utxosweep(struct supernet_info *myinfo,char *symbol,int64_t *satoshis,uint64_t limit,int32_t maxvins,char *coinaddr)
+{
+ int32_t i,n,numvins = 0; char *retstr; uint64_t value,biggest = 0; struct iguana_info *coin=0; cJSON *item,*biggestitem=0,*array,*utxos = 0;
+ coin = iguana_coinfind(symbol);
+ if ( (retstr= dex_listunspent(myinfo,coin,0,0,symbol,coinaddr)) != 0 )
+ {
+ //printf("(%s)\n",retstr);
+ if ( (array= cJSON_Parse(retstr)) != 0 )
+ {
+ n = cJSON_GetArraySize(array);
+ for (i=0; i biggest )
+ {
+ //fprintf(stderr,"biggest! ");
+ if ( biggestitem != 0 )
+ free_json(biggestitem);
+ biggestitem = jduplicate(item);
+ *satoshis = biggest = value;
+ } //else fprintf(stderr,"> ");
+ }
+ }
+ free_json(array);
+ if ( utxos == 0 && biggestitem != 0 )
+ {
+ fprintf(stderr,"add biggest.(%s)\n",jprint(biggestitem,0));
+ jaddi(utxos,biggestitem);
+ }
+ }
+ free(retstr);
+ }
+ return(utxos);
+}
+
uint32_t basilisk_calcnonce(struct supernet_info *myinfo,uint8_t *data,int32_t datalen,uint32_t nBits)
{
int32_t i,numiters = 0; bits256 hash,hash2,threshold; uint32_t basilisktag;
@@ -48,8 +98,8 @@ uint32_t basilisk_calcnonce(struct supernet_info *myinfo,uint8_t *data,int32_t d
break;
}
iguana_rwnum(0,(void *)hash.uints,sizeof(basilisktag),&basilisktag);
- iguana_rwnum(1,&data[-sizeof(basilisktag)],sizeof(basilisktag),&basilisktag);
- char str[65],str2[65]; printf("found hash after numiters.%d %s vs %s basilisktag.%u\n",numiters,bits256_str(str,threshold),bits256_str(str2,hash2),basilisktag);
+ iguana_rwnum(1,&data[-(int32_t)sizeof(basilisktag)],sizeof(basilisktag),&basilisktag);
+ //char str[65],str2[65]; printf("found hash after numiters.%d %s vs %s basilisktag.%u\n",numiters,bits256_str(str,threshold),bits256_str(str2,hash2),basilisktag);
return(basilisktag);
}
@@ -95,7 +145,7 @@ uint8_t *get_dataptr(int32_t hdroffset,uint8_t **ptrp,int32_t *datalenp,uint8_t
uint8_t *basilisk_jsondata(int32_t extraoffset,uint8_t **ptrp,uint8_t *space,int32_t spacesize,int32_t *datalenp,char *symbol,cJSON *sendjson,uint32_t basilisktag)
{
- char *sendstr,*hexstr=0; uint8_t *data,hexspace[4096],*allocptr=0,*hexdata; int32_t datalen,hexlen=0;
+ char *sendstr,*hexstr=0; uint8_t *data,hexspace[4096],*allocptr=0,*hexdata=0; int32_t datalen,hexlen=0;
if ( jobj(sendjson,"symbol") == 0 )
jaddstr(sendjson,"symbol",symbol);
if ( (hexstr= jstr(sendjson,"data")) != 0 )
@@ -118,7 +168,7 @@ uint8_t *basilisk_jsondata(int32_t extraoffset,uint8_t **ptrp,uint8_t *space,int
memcpy(data,sendstr,datalen);
//printf("jsondata.(%s) + hexlen.%d\n",sendstr,hexlen);
free(sendstr);
- if ( hexlen > 0 )
+ if ( hexlen > 0 && hexdata != 0 )
{
//int32_t i; for (i=0; ibasilisktag = basilisktag;
- if ( (ptr->numrequired= minresults) == 0 )
+ if ( (ptr->numrequired= numrequired) == 0 )
ptr->numrequired = 1;
strcpy(ptr->CMD,CMD);
safecopy(ptr->symbol,symbol,sizeof(ptr->symbol));
+ ptr->duration = timeoutmillis;
ptr->expiration = OS_milliseconds() + timeoutmillis;
+ //printf("itemcreate.%p %s %f timeout.%d\n",ptr,CMD,OS_milliseconds(),timeoutmillis);
return(ptr);
}
int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *type,uint32_t *basilisktagp,int32_t encryptflag,int32_t delaymillis,uint8_t *data,int32_t datalen,int32_t fanout,uint32_t nBits) // data must be offset by sizeof(iguana_msghdr)+sizeof(basilisktag)
{
- int32_t i,l,s,valid,val,n=0,retval = -1; char cmd[12]; struct iguana_info *coin,*tmp; struct iguana_peer *addr; bits256 hash; uint32_t *alreadysent,r,r2;
+ int32_t i,l,s,valid,val,n=0,retval = -1; char cmd[12]; struct iguana_info *coin,*tmp; struct iguana_peer *addr; bits256 hash; uint32_t *alreadysent,r;
if ( fanout <= 0 )
- fanout = sqrt(NUMRELAYS) + 1;
+ fanout = sqrt(myinfo->NOTARY.NUMRELAYS) + 1;
else if ( fanout > BASILISK_MAXFANOUT )
fanout = BASILISK_MAXFANOUT;
if ( type == 0 )
- type = "BTCD";
+ type = "INF";
if ( strlen(type) > 3 )
{
printf("basilisk_sendcmd illegal type(%s)\n",type);
@@ -162,7 +214,9 @@ int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *typ
if ( destipaddr != 0 )
{
if ( destipaddr[0] == 0 )
+ {
destipaddr = 0; // broadcast
+ }
else if ( strcmp(destipaddr,"127.0.0.1") == 0 || strcmp(destipaddr,myinfo->ipaddr) == 0 )
{
printf("return after locally basilisk_msgprocess\n");
@@ -171,27 +225,56 @@ int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *typ
return(0);
}
}
- alreadysent = calloc(IGUANA_MAXPEERS * IGUANA_MAXCOINS,sizeof(*alreadysent));
- iguana_rwnum(1,&data[-sizeof(*basilisktagp)],sizeof(*basilisktagp),basilisktagp);
+ iguana_rwnum(1,&data[-(int32_t)sizeof(*basilisktagp)],sizeof(*basilisktagp),basilisktagp);
if ( *basilisktagp == 0 )
{
if ( nBits != 0 )
*basilisktagp = basilisk_calcnonce(myinfo,data,datalen,nBits);
else *basilisktagp = rand();
- iguana_rwnum(1,&data[-sizeof(*basilisktagp)],sizeof(*basilisktagp),basilisktagp);
+ iguana_rwnum(1,&data[-(int32_t)sizeof(*basilisktagp)],sizeof(*basilisktagp),basilisktagp);
}
data -= sizeof(*basilisktagp), datalen += sizeof(*basilisktagp);
memset(cmd,0,sizeof(cmd));
sprintf(cmd,"SuperNET%s",type);
+ if ( destipaddr != 0 )
+ {
+ cmd[6] = 'E', cmd[7] = 'T';
+ HASH_ITER(hh,myinfo->allcoins,coin,tmp)
+ {
+ if ( coin->peers == 0 )
+ continue;
+ if ( coin->FULLNODE == 0 && coin->VALIDATENODE == 0 )
+ cmd[0] = 's';
+ else cmd[0] = 'S';
+ for (i=0; ipeers->active[i];
+ if ( addr->usock >= 0 && strcmp(addr->ipaddr,destipaddr) == 0 )
+ {
+ return(iguana_queue_send(addr,delaymillis,&data[-(int32_t)sizeof(struct iguana_msghdr)],cmd,datalen));
+ }
+ }
+ }
+ return(-1);
+ }
+ if ( basilisk_notarycmd(type) != 0 && myinfo->NOTARY.NUMRELAYS == 0 )
+ {
+ //printf("no notary nodes to send (%s) to\n",type);
+ return(-1);
+ }
//portable_mutex_lock(&myinfo->allcoins_mutex);
+ //dex_reqsend(myinfo,&data[-(int32_t)sizeof(struct iguana_msghdr)],datalen);
+ alreadysent = calloc(IGUANA_MAXPEERS * IGUANA_MAXCOINS,sizeof(*alreadysent));
HASH_ITER(hh,myinfo->allcoins,coin,tmp)
{
if ( coin->peers == 0 )
continue;
+ if ( basilisk_notarycmd(type) != 0 && strcmp(coin->symbol,"RELAY") != 0 )
+ continue;
if ( coin->FULLNODE == 0 && coin->VALIDATENODE == 0 )
cmd[0] = 's';
else cmd[0] = 'S';
- r = rand() % (coin->peers->numranked+1);
+ r = rand() % IGUANA_MAXPEERS;
for (l=0; lusock >= 0 )
{
s = 0;
- if ( NUMRELAYS > 0 && basilisk_specialcmd(type) != 0 )
+ valid = (addr->supernet != 0);
+ if ( basilisk_notarycmd(type) != 0 || (strcmp(type,"INF") == 0 && strcmp(coin->symbol,"RELAY") == 0) )
{
- OS_randombytes((void *)&r2,sizeof(r2));
- if ( (r2 % NUMRELAYS) >= sqrt(NUMRELAYS) )
+ valid = 0;
+ /*OS_randombytes((void *)&r2,sizeof(r2));
+ if ( (r2 % myinfo->NOTARY.NUMRELAYS) >= sqrt(myinfo->NOTARY.NUMRELAYS) )
{
- //printf("fanout.%d s.%d n.%d skip %s\n",fanout,s,n,addr->ipaddr);
+ printf("fanout.%d s.%d n.%d skip %s\n",fanout,s,n,addr->ipaddr);
continue;
- }
- for (s=0; sipbits != myinfo->myaddr.myipbits && RELAYS[s].ipbits == addr->ipbits )
+ }*/
+ for (s=0; sNOTARY.NUMRELAYS; s++)
+ if ( addr->ipbits != myinfo->myaddr.myipbits && myinfo->NOTARY.RELAYS[s].ipbits == addr->ipbits )
break;
- if ( s == NUMRELAYS )
+ if ( s == myinfo->NOTARY.NUMRELAYS )
{
//printf("skip non-relay.(%s)\n",addr->ipaddr);
continue;
}
- //printf("send to other relay.(%s)\n",addr->ipaddr);
valid = 1;
+ //printf("send to other relay.(%s)\n",addr->ipaddr);
}
for (s=0; sipbits )
{
- printf("already sent to %s\n",addr->ipaddr);
+ //printf("already sent to %s\n",addr->ipaddr);
continue;
}
if ( s == n && valid == 1 && (destipaddr == 0 || strcmp(addr->ipaddr,destipaddr) == 0) )
{
- //printf("n.%d/fanout.%d i.%d l.%d [%s].tag%d send %s.(%s) [%x] datalen.%d addr->supernet.%u basilisk.%u to (%s).%d destip.%s\n",n,fanout,i,l,cmd,*(uint32_t *)data,type,(char *)&data[4],*(int32_t *)&data[datalen-4],datalen,addr->supernet,addr->basilisk,addr->ipaddr,addr->A.port,destipaddr!=0?destipaddr:"broadcast");
+ val = 0;
+ //fprintf(stderr,">>> (%s).%u ",addr->ipaddr,coin->chain->portp2p);
+ //printf("n.%d/fanout.%d i.%d l.%d [%s].tag%u send %s [%x] datalen.%d addr->supernet.%u basilisk.%u to (%s).%d destip.%s\n",n,fanout,i,l,cmd,*(uint32_t *)data,type,*(int32_t *)&data[datalen-4],datalen,addr->supernet,addr->basilisk,addr->ipaddr,addr->A.port,destipaddr!=0?destipaddr:"broadcast");
if ( encryptflag != 0 && bits256_nonz(addr->pubkey) != 0 )
{
void *ptr; uint8_t *cipher,space[8192]; int32_t cipherlen; bits256 privkey;
@@ -237,7 +324,7 @@ int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *typ
memset(privkey.bytes,0,sizeof(privkey));
if ( (cipher= SuperNET_ciphercalc(&ptr,&cipherlen,&privkey,&addr->pubkey,data,datalen,space,sizeof(space))) != 0 )
{
- if ( (val= iguana_queue_send(addr,delaymillis,&cipher[-sizeof(struct iguana_msghdr)],cmd,cipherlen)) >= cipherlen )
+ if ( (val= iguana_queue_send(addr,delaymillis,&cipher[-(int32_t)sizeof(struct iguana_msghdr)],cmd,cipherlen)) >= cipherlen )
alreadysent[n++] = (uint32_t)addr->ipbits;
if ( ptr != 0 )
free(ptr);
@@ -246,7 +333,7 @@ int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *typ
else
{
cmd[6] = 'E', cmd[7] = 'T';
- if ( (val= iguana_queue_send(addr,delaymillis,&data[-sizeof(struct iguana_msghdr)],cmd,datalen)) >= datalen )
+ if ( (val= iguana_queue_send(addr,delaymillis,&data[-(int32_t)sizeof(struct iguana_msghdr)],cmd,datalen)) >= datalen )
{
alreadysent[n++] = (uint32_t)addr->ipbits;
if ( n >= IGUANA_MAXPEERS*IGUANA_MAXCOINS )
@@ -287,7 +374,8 @@ void basilisk_sendback(struct supernet_info *myinfo,char *origCMD,char *symbol,c
if ( (virt= iguana_coinfind(symbol)) != 0 )
{
jaddnum(valsobj,"hwm",virt->blocks.hwmchain.height);
- jaddbits256(valsobj,"chaintip",virt->blocks.hwmchain.RO.hash2);
+ if ( bits256_nonz(virt->blocks.hwmchain.RO.hash2) != 0 )
+ jaddbits256(valsobj,"chaintip",virt->blocks.hwmchain.RO.hash2);
}
data = basilisk_jsondata(sizeof(struct iguana_msghdr),&allocptr,space,sizeof(space),&datalen,symbol,valsobj,basilisktag);
//printf("sendback.%d -> %s\n",datalen,remoteaddr);
@@ -299,10 +387,10 @@ void basilisk_sendback(struct supernet_info *myinfo,char *origCMD,char *symbol,c
}
}
-struct basilisk_item *basilisk_issueremote(struct supernet_info *myinfo,struct iguana_peer *addr,int32_t *numsentp,char *CMD,char *symbol,int32_t blockflag,cJSON *valsobj,int32_t fanout,int32_t minresults,uint32_t basilisktag,int32_t timeoutmillis,void *deprecated_dontuse,char *retstr,int32_t encryptflag,int32_t delaymillis,uint32_t nBits)
+struct basilisk_item *basilisk_issueremote(struct supernet_info *myinfo,struct iguana_peer *addr,int32_t *numsentp,char *CMD,char *symbol,int32_t blockflag,cJSON *valsobj,int32_t fanout,int32_t numrequired,uint32_t basilisktag,int32_t timeoutmillis,void *deprecated_dontuse,char *retstr,int32_t encryptflag,int32_t delaymillis,uint32_t nBits)
{
- struct basilisk_item *pending; uint8_t *allocptr,*data,space[4096]; int32_t datalen; cJSON *retarray;
- pending = basilisk_itemcreate(myinfo,CMD,symbol,basilisktag,minresults,valsobj,timeoutmillis,0);
+ struct basilisk_item *pending; uint8_t *allocptr,*data,space[4096]; int32_t datalen;
+ pending = basilisk_itemcreate(myinfo,CMD,symbol,basilisktag,numrequired,valsobj,timeoutmillis,0);
pending->nBits = nBits;
*numsentp = 0;
if ( retstr != 0 )
@@ -319,32 +407,26 @@ struct basilisk_item *basilisk_issueremote(struct supernet_info *myinfo,struct i
if ( blockflag != 0 )
{
portable_mutex_lock(&myinfo->basilisk_mutex);
- //printf("HASH_ADD.%p\n",pending);
HASH_ADD(hh,myinfo->basilisks.issued,basilisktag,sizeof(basilisktag),pending);
portable_mutex_unlock(&myinfo->basilisk_mutex);
- //queue_enqueue("issuedQ",&myinfo->basilisks.issued,&pending->DL,0);
if ( pending->expiration <= OS_milliseconds() )
- pending->expiration = OS_milliseconds() + BASILISK_TIMEOUT;
- //ptr->vals = jduplicate(valsobj);
- strcpy(pending->symbol,"BTCD");
+ pending->expiration = OS_milliseconds() + pending->duration;
+ strcpy(pending->symbol,"RELAY");
strcpy(pending->CMD,CMD);
+ //printf("block for %f\n",pending->expiration - OS_milliseconds());
while ( OS_milliseconds() < pending->expiration )
{
- if ( pending->numresults >= pending->numrequired )//|| (retstr= pending->retstr) != 0 )
+ portable_mutex_lock(&myinfo->basilisk_mutex);
+ if ( pending->numresults >= pending->numrequired )
{
- //printf("numresults.%d vs numrequired.%d\n",pending->numresults,pending->numrequired);
+ portable_mutex_unlock(&myinfo->basilisk_mutex);
+ //printf("%p <<<<<<<<<<<<< numresults.%d vs numrequired.%d\n",pending,pending->numresults,pending->numrequired);
break;
}
+ portable_mutex_unlock(&myinfo->basilisk_mutex);
usleep(10000);
}
- if ( (retarray= pending->retarray) != 0 )
- {
- pending->retstr = jprint(retarray,0);
- pending->retarray = 0;
- free_json(retarray);
- }
- //return(basilisk_waitresponse(myinfo,CMD,"BTCD",0,&Lptr,valsobj,ptr));
- } else free(pending), pending = 0; //ptr->finished = (uint32_t)time(NULL);
+ }
if ( allocptr != 0 )
free(allocptr);
}
@@ -356,22 +438,26 @@ struct basilisk_item *basilisk_requestservice(struct supernet_info *myinfo,struc
int32_t minfanout,numrequired,timeoutmillis,numsent,delaymillis,encryptflag,fanout; struct basilisk_item *ptr; char buf[4096],*symbol,*str = 0; struct iguana_info *virt;
//printf("request.(%s)\n",jprint(valsobj,0));
basilisk_addhexstr(&str,valsobj,buf,sizeof(buf),data,datalen);
- if ( bits256_cmp(hash,GENESIS_PUBKEY) != 0 && bits256_nonz(hash) != 0 )
+ if ( str != 0 )
+ free(str);
+ if ( bits256_nonz(hash) == 0 || (bits256_cmp(hash,GENESIS_PUBKEY) != 0 && bits256_nonz(hash) != 0) )
{
if ( jobj(valsobj,"hash") != 0 )
jdelete(valsobj,"hash");
jaddbits256(valsobj,"hash",hash);
}
- if ( (numrequired= jint(valsobj,"numrequired")) <= 0 )
- numrequired = sqrt(NUMRELAYS);
if ( (timeoutmillis= jint(valsobj,"timeout")) == 0 )
timeoutmillis = BASILISK_TIMEOUT;
- minfanout = sqrt(NUMRELAYS)+1;
+ minfanout = sqrt(myinfo->NOTARY.NUMRELAYS)+1;
+ if ( minfanout < 8 )
+ minfanout = 8;
if ( jobj(valsobj,"fanout") == 0 )
fanout = minfanout;
else fanout = jint(valsobj,"fanout");
if ( fanout < minfanout )
fanout = minfanout;
+ if ( (numrequired= jint(valsobj,"numrequired")) <= 0 )
+ numrequired = MIN(fanout/2,sqrt(myinfo->NOTARY.NUMRELAYS)+1);
if ( (symbol= jstr(valsobj,"coin")) != 0 || (symbol= jstr(valsobj,"symbol")) != 0 )
{
if ( (virt= iguana_coinfind(symbol)) != 0 )
@@ -382,7 +468,7 @@ struct basilisk_item *basilisk_requestservice(struct supernet_info *myinfo,struc
}
}
if ( symbol == 0 )
- symbol = "BTCD";
+ symbol = "RELAY";
encryptflag = jint(valsobj,"encrypt");
delaymillis = jint(valsobj,"delay");
ptr = basilisk_issueremote(myinfo,addr,&numsent,CMD,symbol,blockflag,valsobj,fanout,numrequired,0,timeoutmillis,0,0,encryptflag,delaymillis,nBits);
@@ -391,31 +477,42 @@ struct basilisk_item *basilisk_requestservice(struct supernet_info *myinfo,struc
char *basilisk_standardservice(char *CMD,struct supernet_info *myinfo,void *_addr,bits256 hash,cJSON *valsobj,char *hexstr,int32_t blockflag) // client side
{
- uint32_t nBits = 0; uint8_t space[4096],*allocptr=0,*data = 0; struct basilisk_item *ptr; int32_t datalen = 0; cJSON *retjson; char *retstr=0;
- if ( RELAYID >= 0 && basilisk_specialcmd(CMD) == 0 )
+ uint32_t nBits = 0; uint8_t space[4096],*allocptr=0,*data = 0; struct basilisk_item *ptr; int32_t i,datalen = 0; cJSON *retjson; char *retstr=0;
+ if ( myinfo->IAMNOTARY != 0 && myinfo->NOTARY.RELAYID >= 0 && (strcmp(CMD,"INF") != 0 && basilisk_notarycmd(CMD) == 0) )
return(clonestr("{\"error\":\"unsupported special relay command\"}"));
data = get_dataptr(BASILISK_HDROFFSET,&allocptr,&datalen,space,sizeof(space),hexstr);
+//printf("request.(%s)\n",jprint(valsobj,0));
ptr = basilisk_requestservice(myinfo,_addr,CMD,blockflag,valsobj,hash,data,datalen,nBits);
if ( allocptr != 0 )
free(allocptr);
if ( ptr != 0 )
{
- if ( ptr->retstr != 0 )
- retstr = ptr->retstr, ptr->retstr = 0;
+ if ( (retstr= ptr->retstr) != 0 )
+ ptr->retstr = 0;
else
{
- retjson = cJSON_CreateObject();
- if ( ptr->numsent > 0 )
+ if ( ptr->numresults > 0 )
{
- //queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
- jaddstr(retjson,"result","success");
- jaddnum(retjson,"numsent",ptr->numsent);
- } else jaddstr(retjson,"error","didnt find any nodes to send to");
+ retjson = cJSON_CreateArray();
+ for (i=0; inumresults; i++)
+ jaddi(retjson,ptr->results[i]), ptr->results[i] = 0;
+ //printf("numresults.%d (%p)\n",ptr->numresults,ptr);
+ }
+ else
+ {
+ retjson = cJSON_CreateObject();
+ if ( ptr->numsent > 0 )
+ {
+ //queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
+ jaddstr(retjson,"result","error");
+ jaddnum(retjson,"packetsize",ptr->numsent);
+ } else jaddstr(retjson,"error","didnt find any nodes to send to");
+ }
retstr = jprint(retjson,1);
}
- ptr->finished = (uint32_t)time(NULL);
+ ptr->finished = OS_milliseconds() + 10000;
}
- if ( 1 && strcmp("RID",CMD) != 0 && strcmp("BAL",CMD) != 0 && strcmp("MSG",CMD) != 0 )
+ if ( (0) && strcmp("MSG",CMD) == 0 )
printf("%s.(%s) -> (%s)\n",CMD,jprint(valsobj,0),retstr!=0?retstr:"");
return(retstr);
}
@@ -423,8 +520,8 @@ char *basilisk_standardservice(char *CMD,struct supernet_info *myinfo,void *_add
int32_t basilisk_relayid(struct supernet_info *myinfo,uint32_t ipbits)
{
int32_t j;
- for (j=0; jNOTARY.NUMRELAYS; j++)
+ if ( myinfo->NOTARY.RELAYS[j].ipbits == ipbits )
return(j);
return(-1);
}
@@ -434,13 +531,18 @@ int32_t basilisk_relayid(struct supernet_info *myinfo,uint32_t ipbits)
#include "basilisk_ether.c"
#include "basilisk_waves.c"
#include "basilisk_lisk.c"
+#include "smartaddress.c"
#include "basilisk_MSG.c"
+#include "tradebots_marketmaker.c"
+#include "tradebots_liquidity.c"
#include "basilisk_tradebot.c"
#include "basilisk_swap.c"
#include "basilisk_DEX.c"
#include "basilisk_ping.c"
+#include "basilisk_vote.c"
#include "basilisk_CMD.c"
+#include "jumblr.c"
void basilisk_functions(struct iguana_info *coin,int32_t protocol)
{
@@ -479,7 +581,7 @@ void basilisk_functions(struct iguana_info *coin,int32_t protocol)
int32_t basilisk_hashes_send(struct supernet_info *myinfo,struct iguana_info *virt,struct iguana_peer *addr,char *CMD,bits256 *hashes,int32_t num)
{
- bits256 hash; uint8_t *serialized; int32_t i,len = 0; char *str=0,*retstr,*hexstr,*allocptr=0,space[4096]; bits256 txid; cJSON *vals;
+ bits256 hash; uint8_t *serialized; int32_t i,len = 0; char *str=0,*retstr,*hexstr,space[4096]; bits256 txid; cJSON *vals;
if ( virt != 0 && addr != 0 )
{
memset(hash.bytes,0,sizeof(hash));
@@ -496,8 +598,8 @@ int32_t basilisk_hashes_send(struct supernet_info *myinfo,struct iguana_info *vi
if ( (retstr= basilisk_standardservice(CMD,myinfo,addr,hash,vals,hexstr,0)) != 0 )
free(retstr);
free_json(vals);
- if ( allocptr != 0 )
- free(allocptr);
+ if ( str != 0 )
+ free(str);
}
return(0);
} else return(-1);
@@ -540,29 +642,30 @@ void basilisk_result(struct supernet_info *myinfo,char *remoteaddr,uint32_t basi
{
retstr = jprint(vals,0);
safecopy(CMD,jstr(vals,"origcmd"),sizeof(CMD));
- if ( 0 && strcmp("RID",CMD) != 0 )
- printf("(%s) -> Q.%u results vals.(%s)\n",CMD,basilisktag,retstr);
+ //if ( 0 && strcmp("RID",CMD) != 0 )
+ //printf("(%s) -> Q.%u results vals.(%s)\n",CMD,basilisktag,retstr);//(int32_t)strlen(retstr));
if ( strcmp(CMD,"GET") == 0 )
basilisk_geckoresult(myinfo,remoteaddr,retstr,data,datalen);
else
{
portable_mutex_lock(&myinfo->basilisk_mutex);
HASH_FIND(hh,myinfo->basilisks.issued,&basilisktag,sizeof(basilisktag),pending);
- //printf("HASH_FIND.%p\n",pending);
portable_mutex_unlock(&myinfo->basilisk_mutex);
if ( pending != 0 && retstr != 0 )
{
if ( (item= cJSON_Parse(retstr)) != 0 )
{
- if ( pending->retarray == 0 )
- pending->retarray = cJSON_CreateArray();
if ( jobj(item,"myip") == 0 )
- jaddstr(item,"myip",myinfo->ipaddr);
- jaddi(pending->retarray,item);
+ jaddstr(item,"myip",remoteaddr);
+ if ( pending->numresults < sizeof(pending->results)/sizeof(*pending->results) )
+ {
+ //printf("%p.(%s).%d\n",pending,jprint(item,0),pending->numresults);
+ pending->results[pending->numresults++] = item;
+ }
} else printf("couldnt parse.(%s)\n",retstr);
- pending->numresults++;
} //else printf("couldnt find issued.%u\n",basilisktag);
}
+ free(retstr);
}
}
@@ -588,7 +691,9 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende
{ (void *)"OUT", &basilisk_respond_OUT }, // send MSG to hash/id/num
{ (void *)"MSG", &basilisk_respond_MSG }, // get MSG (hash, id, num)
{ (void *)"ADD", &basilisk_respond_addrelay }, // relays register with each other bus
+ { (void *)"VOT", &basilisk_respond_VOT }, // VOTE handler for something
//{ (void *)"PIN", &basilisk_respond_PIN },
+
// encrypted data for jumblr
{ (void *)"HOP", &basilisk_respond_forward }, // message forwarding
{ (void *)"BOX", &basilisk_respond_mailbox }, // create/send/check mailbox pubkey
@@ -616,6 +721,7 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende
// coin services
{ (void *)"VAL", &basilisk_respond_value },
{ (void *)"BAL", &basilisk_respond_balances },
+ { (void *)"INF", &basilisk_respond_getinfo },
};
strncpy(CMD,type,3), CMD[3] = cmd[3] = 0;
if ( isupper((int32_t)CMD[0]) != 0 && isupper((int32_t)CMD[1]) != 0 && isupper((int32_t)CMD[2]) != 0 )
@@ -628,22 +734,18 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende
CMD[i] = toupper((int32_t)CMD[i]);
cmd[i] = tolower((int32_t)CMD[i]);
}
- //origcmd[0] = 0;
- if ( RELAYID >= 0 )
+ if ( myinfo->IAMNOTARY != 0 )//RELAYID >= 0 )
{
- if ( basilisk_specialcmd(CMD) == 0 )
+ if ( basilisk_notarycmd(CMD) == 0 && strcmp(CMD,"INF") != 0 )
return;
- //printf("MSGPROCESS %s.(%s) tag.%d\n",CMD,(char *)data,basilisktag);
- }
- symbol = "BTCD";
+ } else if ( basilisk_notarycmd(CMD) != 0 )
+ return;
+ symbol = "RELAY";
if ( senderipbits == 0 )
expand_ipbits(remoteaddr,myinfo->myaddr.myipbits);
else expand_ipbits(remoteaddr,senderipbits);
if ( (valsobj= cJSON_Parse((char *)data)) != 0 )
{
- //if ( origcmd[0] != 0 )
- // jaddstr(valsobj,"origcmd",origcmd);
- //printf("MSGVALS.(%s)\n",(char *)data);
if ( jobj(valsobj,"coin") != 0 )
coin = iguana_coinfind(jstr(valsobj,"coin"));
else if ( jobj(valsobj,"symbol") != 0 )
@@ -685,7 +787,7 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende
data += jsonlen, datalen -= jsonlen;
else data = 0, datalen = 0;
if ( coin == 0 )
- coin = iguana_coinfind("BTCD");
+ coin = iguana_coinfind(symbol);
if ( coin != 0 )
{
symbol = coin->symbol;
@@ -694,7 +796,7 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende
hash = jbits256(valsobj,"hash");
timeoutmillis = jint(valsobj,"timeout");
if ( (numrequired= jint(valsobj,"numrequired")) == 0 )
- numrequired = sqrt(NUMRELAYS);
+ numrequired = sqrt(myinfo->NOTARY.NUMRELAYS)+1;
if ( senderipbits != 0 )
expand_ipbits(remoteaddr,senderipbits);
else remoteaddr[0] = 0;
@@ -702,19 +804,19 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende
{
if ( strcmp((char *)basilisk_services[i][0],type) == 0 )
{
- if ( coin->FULLNODE != 0 || RELAYID >= 0 ) // iguana node
+ if ( (coin != 0 && coin->FULLNODE > 0) || myinfo->NOTARY.RELAYID >= 0 ) // iguana node
{
- //printf("services %s\n",type);
+ //printf("\n call %s from_basilisk.%d (%s)\n",addr->ipaddr,from_basilisk,type);
if ( (retstr= (*basilisk_services[i][1])(myinfo,type,addr,remoteaddr,basilisktag,valsobj,data,datalen,hash,from_basilisk)) != 0 )
{
- //printf("from_basilisk.%d ret.(%s)\n",from_basilisk,retstr);
+ //printf("%s from_basilisk.%d ret.(%s)\n",addr->ipaddr,from_basilisk,retstr);
//if ( from_basilisk != 0 || strcmp(CMD,"GET") == 0 )
basilisk_sendback(myinfo,CMD,symbol,remoteaddr,basilisktag,retstr);
if ( retstr != 0 )
free(retstr);
break;
} else printf("services null return\n");
- } else printf("non-relay got unhandled.(%s)\n",type);
+ } else printf("non-relay got %s unhandled.(%s)\n",coin!=0?coin->symbol:"",type);
}
}
free_json(valsobj);
@@ -724,9 +826,55 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende
myinfo->basilisk_busy = 0;
}
-void basilisk_p2p(void *_myinfo,void *_addr,char *senderip,uint8_t *data,int32_t datalen,char *type,int32_t encrypted)
+int32_t basilisk_p2pQ_process(struct supernet_info *myinfo,int32_t maxiters)
+{
+ struct basilisk_p2pitem *ptr; char senderip[64]; uint32_t n=0,basilisktag,len;
+ while ( n < maxiters && (ptr= queue_dequeue(&myinfo->p2pQ)) != 0 )
+ {
+ len = 0;
+ expand_ipbits(senderip,ptr->ipbits);
+ //printf("p2p.%d from.(%s) %c%c%c datalen.%d\n",n,senderip,ptr->type[0],ptr->type[1],ptr->type[2],ptr->datalen);
+ if ( ptr->type[0] == 'P' && ptr->type[1] == 'I' && ptr->type[2] == 'N' )
+ {
+ if ( myinfo->NOTARY.RELAYID >= 0 )
+ {
+ //printf("process ping\n");
+ basilisk_ping_process(myinfo,ptr->addr,ptr->ipbits,ptr->data,ptr->datalen);
+ //printf("done process ping\n");
+ }
+ }
+ else
+ {
+ len += iguana_rwnum(0,ptr->data,sizeof(basilisktag),&basilisktag);
+ if ( (0) && myinfo->IAMLP == 0 )
+ printf("RELAYID.%d ->received.%d basilisk_p2p.(%s) from %s tag.%u\n",myinfo->NOTARY.RELAYID,ptr->datalen,ptr->type,senderip,basilisktag);
+ basilisk_msgprocess(myinfo,ptr->addr,ptr->ipbits,ptr->type,basilisktag,&ptr->data[len],ptr->datalen - len);
+ if ( (0) && myinfo->IAMLP == 0 )
+ printf("processed.%s from %s\n",ptr->type,senderip);
+ }
+ free(ptr);
+ n++;
+ }
+ return(n);
+}
+
+struct basilisk_p2pitem *basilisk_p2pitem_create(struct iguana_info *coin,struct iguana_peer *addr,char *type,uint32_t ipbits,uint8_t *data,int32_t datalen)
+{
+ struct basilisk_p2pitem *ptr;
+ ptr = calloc(1,sizeof(*ptr) + datalen + 16);
+ ptr->coin = coin;
+ ptr->addr = addr;
+ ptr->ipbits = ipbits;
+ ptr->datalen = datalen;
+ safecopy(ptr->type,type,sizeof(ptr->type));
+ memcpy(ptr->data,data,datalen);
+ return(ptr);
+}
+
+void basilisk_p2p(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *senderip,uint8_t *data,int32_t datalen,char *type,int32_t encrypted)
{
- uint32_t ipbits,basilisktag; int32_t msglen,len=0; void *ptr = 0; uint8_t space[4096]; bits256 senderpub; struct supernet_info *myinfo = _myinfo;
+ uint32_t ipbits; int32_t msglen; void *ptr = 0; uint8_t space[4096]; bits256 senderpub;
+ ipbits = (uint32_t)calc_ipbits(senderip);
if ( encrypted != 0 )
{
printf("encrypted p2p\n");
@@ -736,141 +884,116 @@ void basilisk_p2p(void *_myinfo,void *_addr,char *senderip,uint8_t *data,int32_t
printf("basilisk_p2p decrytion error\n");
return;
} else datalen = msglen;
+ if ( ptr != 0 )
+ free(ptr);
}
if ( senderip != 0 && senderip[0] != 0 && strcmp(senderip,"127.0.0.1") != 0 )
ipbits = (uint32_t)calc_ipbits(senderip);
else ipbits = myinfo->myaddr.myipbits;
- if ( type[0] == 'P' && type[1] == 'I' && type[2] == 'N' )
- {
- if ( strcmp(type,"PIN") == 0 && RELAYID >= 0 )
- {
- basilisk_ping_process(myinfo,_addr,ipbits,data,datalen);
- }
- }
- else
- {
- len += iguana_rwnum(0,data,sizeof(basilisktag),&basilisktag);
- //int32_t i; for (i=0; i= 0 )
- printf(" ->received.%d basilisk_p2p.(%s) from %s tag.%d\n",datalen,type,senderip!=0?senderip:"?",basilisktag);
- basilisk_msgprocess(myinfo,_addr,ipbits,type,basilisktag,&data[len],datalen - len);
- }
- if ( ptr != 0 )
- free(ptr);
+ ptr = basilisk_p2pitem_create(coin,addr,type,ipbits,data,datalen);
+ queue_enqueue("p2pQ",&myinfo->p2pQ,ptr);
}
-void basilisk_requests_poll(struct supernet_info *myinfo)
+int32_t basilisk_issued_purge(struct supernet_info *myinfo,int32_t timepad)
{
- char *retstr; cJSON *outerarray; int32_t i,n; struct basilisk_request issueR; double hwm = 0.;
- memset(&issueR,0,sizeof(issueR));
- if ( (retstr= InstantDEX_incoming(myinfo,0,0,0,0)) != 0 )
- {
- //printf("poll.(%s)\n",retstr);
- if ( (outerarray= cJSON_Parse(retstr)) != 0 )
- {
- if ( is_cJSON_Array(outerarray) != 0 )
- {
- n = cJSON_GetArraySize(outerarray);
- for (i=0; i 0. )
+ struct basilisk_item *tmp,*pending; cJSON *item; int32_t i,n = 0; double startmilli = OS_milliseconds();
+ portable_mutex_lock(&myinfo->basilisk_mutex);
+ HASH_ITER(hh,myinfo->basilisks.issued,pending,tmp)
{
- if ( bits256_cmp(myinfo->myaddr.persistent,issueR.hash) == 0 ) // my request
+ if ( pending != 0 && ((pending->finished > 0 && startmilli > pending->finished) || startmilli > pending->expiration+timepad) )
{
- printf("my req hwm %f\n",hwm);
- if ( (retstr= InstantDEX_accept(myinfo,0,0,0,issueR.requestid,issueR.quoteid)) != 0 )
- free(retstr);
- if ( (retstr= basilisk_start(myinfo,&issueR,1)) != 0 )
- free(retstr);
+ HASH_DELETE(hh,myinfo->basilisks.issued,pending);
+ //printf("%f > %f (%d) clear pending.%p numresults.%d %p\n",startmilli,pending->expiration+timepad,timepad,pending,pending->numresults,pending->retstr);
+ for (i=0; inumresults; i++)
+ if ( (item= pending->results[i]) != 0 )
+ free_json(item);
+ if ( pending->retstr != 0 )
+ free(pending->retstr);
+ memset(pending,0,sizeof(*pending));
+ free(pending);
+ n++;
}
- else //if ( issueR.quoteid == 0 )
- {
- printf("other req hwm %f\n",hwm);
- issueR.quoteid = basilisk_quoteid(&issueR);
- issueR.desthash = myinfo->myaddr.persistent;
- if ( (retstr= basilisk_start(myinfo,&issueR,0)) != 0 )
- free(retstr);
- } //else printf("basilisk_requests_poll unexpected hwm issueR\n");
}
+ portable_mutex_unlock(&myinfo->basilisk_mutex);
+ return(n);
}
void basilisks_loop(void *arg)
{
- struct iguana_info *virt,*tmpcoin,*coin,*btcd; struct basilisk_message *msg,*tmpmsg; struct basilisk_item *tmp,*pending; uint32_t now; int32_t iter,maxmillis,flag=0; struct supernet_info *myinfo = arg;
+ static uint32_t counter;
+ struct iguana_info *relay; struct supernet_info *myinfo = arg; int32_t i,iter; double startmilli,endmilli; struct dpow_info *dp;
iter = 0;
+ relay = iguana_coinfind("RELAY");
+ printf("start basilisk loop\n");
while ( 1 )
{
- portable_mutex_lock(&myinfo->basilisk_mutex);
- HASH_ITER(hh,myinfo->basilisks.issued,pending,tmp)
+ if ( relay == 0 )
+ relay = iguana_coinfind("RELAY");
+ startmilli = OS_milliseconds();
+ endmilli = startmilli + 1000;
+ //fprintf(stderr,"A ");
+ basilisk_issued_purge(myinfo,600000);
+ //fprintf(stderr,"B ");
+ basilisk_p2pQ_process(myinfo,777);
+ //fprintf(stderr,"C ");
+ if ( myinfo->IAMNOTARY != 0 )
{
- if ( pending != 0 && (pending->finished != 0 || OS_milliseconds() > pending->expiration+600000) )
+ if ( relay != 0 )
{
- //printf("enable free for HASH_DELETE.(%p)\n",pending);
- HASH_DELETE(hh,myinfo->basilisks.issued,pending);
- memset(pending,0,sizeof(*pending));
- free(pending);
+ //fprintf(stderr,"D ");
+ basilisk_ping_send(myinfo,relay);
}
- }
- portable_mutex_unlock(&myinfo->basilisk_mutex);
- if ( (btcd= iguana_coinfind("BTCD")) != 0 )
- {
- maxmillis = (1000 / (myinfo->allcoins_numvirts + 1)) + 1;
- //portable_mutex_lock(&myinfo->allcoins_mutex);
- HASH_ITER(hh,myinfo->allcoins,virt,tmpcoin)
+ counter++;
+ //fprintf(stderr,"E ");
+ if ( myinfo->numdpows == 1 )
{
- if ( virt->started != 0 && virt->active != 0 && virt->virtualchain != 0 )
- {
- gecko_iteration(myinfo,btcd,virt,maxmillis), flag++;
- }
+ iguana_dPoWupdate(myinfo,&myinfo->DPOWS[0]);
+ endmilli = startmilli + 100;
}
- //portable_mutex_unlock(&myinfo->allcoins_mutex);
- if ( RELAYID >= 0 )
+ else if ( myinfo->numdpows > 1 )
{
- basilisk_ping_send(myinfo,btcd);
+ dp = &myinfo->DPOWS[counter % myinfo->numdpows];
+ iguana_dPoWupdate(myinfo,dp);
+ //if ( (counter % myinfo->numdpows) != 0 )
+ {
+ //fprintf(stderr,"F ");
+ iguana_dPoWupdate(myinfo,&myinfo->DPOWS[0]);
+ }
+ endmilli = startmilli + 30;
}
+ //fprintf(stderr,"F ");
}
- HASH_ITER(hh,myinfo->allcoins,coin,tmpcoin)
+ else
{
- if ( time(NULL) > coin->lastunspentsupdate+10 )
- {
- //printf(">>>>>>>>>>>>> update\n");
- basilisk_unspents_update(myinfo,coin);
- coin->lastunspentsupdate = (uint32_t)time(NULL);
- }
+ //fprintf(stderr,"G ");
+ dex_updateclient(myinfo);
+ if ( myinfo->IAMLP != 0 )
+ endmilli = startmilli + 500;
+ else endmilli = startmilli + 1000;
}
- if ( RELAYID < 0 )
- basilisk_requests_poll(myinfo);
- now = (uint32_t)time(NULL);
- portable_mutex_lock(&myinfo->messagemutex);
- HASH_ITER(hh,myinfo->messagetable,msg,tmpmsg)
+ if ( myinfo->expiration != 0 && (myinfo->dexsock >= 0 || myinfo->IAMLP != 0 || myinfo->DEXactive > time(NULL)) )
{
- if ( now > msg->expiration )
- {
- printf("delete expired message.%p QUEUEITEMS.%d\n",msg,QUEUEITEMS);
- HASH_DELETE(hh,myinfo->messagetable,msg);
- QUEUEITEMS--;
- free(msg);
- }
+ //fprintf(stderr,"H ");
+ for (i=0; i<100; i++)
+ if ( basilisk_requests_poll(myinfo) <= 0 )
+ break;
}
- portable_mutex_unlock(&myinfo->messagemutex);
- if ( RELAYID >= 0 )
- usleep(100000);
- else sleep(1);
+ //printf("RELAYID.%d endmilli %f vs now %f\n",myinfo->NOTARY.RELAYID,endmilli,startmilli);
+ while ( OS_milliseconds() < endmilli )
+ usleep(10000);
+ //printf("finished waiting numdpow.%d\n",myinfo->numdpows);
+ iter++;
}
}
void basilisks_init(struct supernet_info *myinfo)
{
+ iguana_initQ(&myinfo->p2pQ,"p2pQ");
iguana_initQ(&myinfo->msgQ,"messageQ");
portable_mutex_init(&myinfo->bu_mutex);
portable_mutex_init(&myinfo->allcoins_mutex);
portable_mutex_init(&myinfo->basilisk_mutex);
+ portable_mutex_init(&myinfo->smart_mutex);
portable_mutex_init(&myinfo->DEX_mutex);
portable_mutex_init(&myinfo->DEX_swapmutex);
portable_mutex_init(&myinfo->DEX_reqmutex);
@@ -882,46 +1005,519 @@ void basilisks_init(struct supernet_info *myinfo)
#include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h"
-HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr)
+#include "../includes/iguana_apideclares2.h"
+
+TWO_STRINGS(tradebot,gensvm,base,rel)
{
- char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis;
- if ( RELAYID >= 0 )
- return(clonestr("{\"error\":\"special relays only do OUT and MSG\"}"));
+#ifdef _WIN
+ return(clonestr("{\"error\":\"windows doesnt support SVM\"}"));
+#else
+ int32_t numfeatures = 317*61;
+ struct tradebot_arbpair *pair;
+ if ( base[0] != 0 && rel[0] != 0 && (pair= tradebots_arbpair_find(base,rel)) != 0 && pair->fp != 0 )
+ {
+ tradebots_calcanswers(pair);
+ ocas_gen(pair->refc,numfeatures,0,(int32_t)(ftell(pair->fp) / sizeof(pair->rawfeatures)));
+ return(clonestr("{\"result\":\"success\"}"));
+ } else return(clonestr("{\"error\":\"cant find arbpair\"}"));
+#endif
+}
+
+ZERO_ARGS(tradebot,openliquidity)
+{
+ int32_t i; cJSON *array = cJSON_CreateArray();
+ for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++)
+ {
+ if ( myinfo->linfos[i].base[0] != 0 )
+ jaddi(array,linfo_json(&myinfo->linfos[i]));
+ }
+ return(jprint(array,1));
+}
+
+ZERO_ARGS(tradebot,allbalances)
+{
+ int32_t i,n; double value,pending; char *base; cJSON *item,*balances = cJSON_CreateObject();
+ if ( myinfo->liquidity_currencies == 0 )
+ myinfo->liquidity_currencies = cJSON_Parse("[\"KMD\", \"BTC\"]");
+ if ( myinfo->liquidity_currencies != 0 && (n= cJSON_GetArraySize(myinfo->liquidity_currencies)) > 0 )
+ {
+ for (i=0; iliquidity_currencies,i);
+ value = tradebot_balance(myinfo,base);
+ pending = tradebot_pending(myinfo,base);
+ item = cJSON_CreateObject();
+ jaddnum(item,"value",value);
+ jaddnum(item,"pending",pending);
+ jadd(balances,base,item);
+ }
+ }
+ return(jprint(balances,1));
+}
+
+ZERO_ARGS(tradebot,anchor)
+{
+ FILE *fp; char *anchorstr,fname[512]; cJSON *anchor; int32_t retval = -1;
+ if ( (anchorstr= tradebot_allbalances(myinfo,0,0,0)) != 0 )
+ {
+ if ( (anchor= cJSON_Parse(anchorstr)) != 0 )
+ {
+ if ( jobj(anchor,"error") == 0 )
+ {
+ sprintf(fname,"%s/anchor",GLOBAL_DBDIR), OS_compatible_path(fname);
+ if ( (fp= fopen(fname,"wb")) != 0 )
+ {
+ if ( fwrite(anchorstr,1,strlen(anchorstr)+1,fp) == strlen(anchorstr)+1 )
+ retval = 0;
+ fclose(fp);
+ }
+ }
+ }
+ free(anchorstr);
+ }
+ if ( retval == 0 )
+ return(clonestr("{\"result\":\"success\"}"));
+ else return(clonestr("{\"error\":\"couldnt make anchor file\"}"));
+}
+
+ZERO_ARGS(tradebot,portfolio)
+{
+ char *currentstr,*anchorstr,fname[512]; long fsize; cJSON *current,*anchor=0,*portfolio=0;
+ if ( (currentstr= tradebot_allbalances(myinfo,0,0,0)) != 0 )
+ {
+ if ( (current= cJSON_Parse(currentstr)) != 0 )
+ {
+ sprintf(fname,"%s/anchor",GLOBAL_DBDIR), OS_compatible_path(fname);
+ if ( (anchorstr= OS_filestr(&fsize,fname)) != 0 )
+ {
+ anchor = cJSON_Parse(anchorstr);
+ free(anchorstr);
+ }
+ if ( anchor == 0 )
+ anchor = cJSON_Parse("{}");
+ portfolio = tradebot_balancesdiff(myinfo,current,anchor);
+ free_json(current);
+ }
+ free(currentstr);
+ }
+ if ( portfolio == 0 )
+ return(clonestr("{\"result\":\"success\"}"));
+ else return(jprint(portfolio,1));
+}
+
+ARRAY_OBJ_INT(tradebot,goals,currencies,vals,targettime)
+{
+ static bits256 zero; char *targetcoin; int32_t i,n;
+ if ( currencies != 0 && vals != 0 )
+ {
+ // init things so automatically updates refli.bid and refli.ask
+ // volume range with margin
+ // currency percentage value in BTC? target distribution, max percentage, min percentage`
+ // min price to sell, max price to buy, max volume
+ n = cJSON_GetArraySize(currencies);
+ for (i=0; imyaddr.persistent);
+ if ( (msgid= juint(vals,"msgid")) == 0 )
+ {
+ msgid = (uint32_t)time(NULL);
+ jdelete(vals,"msgid");
+ jaddnum(vals,"msgid",msgid);
+ }
+ if ( myinfo->NOTARY.RELAYID >= 0 || myinfo->dexsock >= 0 || myinfo->subsock >= 0 )
+ {
+ channel = juint(vals,"channel");
+ width = juint(vals,"width");
+ retstr = basilisk_iterate_MSG(myinfo,channel,msgid,jbits256(vals,"srchash"),jbits256(vals,"desthash"),width);
+ //printf("getmessage.(%s)\n",retstr);
+ return(retstr);
+ }
+ //printf("getmessage not relay.%d dexsock.%d subsock.%d\n",myinfo->NOTARY.RELAYID,myinfo->dexsock,myinfo->subsock);
+ return(basilisk_standardservice("MSG",myinfo,0,jbits256(vals,"desthash"),vals,hexstr,1));
+}
+
+HASH_ARRAY_STRING(basilisk,sendmessage,hash,vals,hexstr)
+{
+ int32_t keylen,datalen,allocsize = 65536; uint8_t key[BASILISK_KEYSIZE],*space,*space2,*data,*ptr = 0; char *retstr=0;
+ space = calloc(1,allocsize);
+ space2 = calloc(1,allocsize);
+ data = get_dataptr(BASILISK_HDROFFSET,&ptr,&datalen,&space[BASILISK_KEYSIZE],allocsize-BASILISK_KEYSIZE,hexstr);
+ if ( myinfo->subsock >= 0 || myinfo->dexsock >= 0 || (myinfo->IAMNOTARY != 0 && myinfo->NOTARY.RELAYID >= 0) )
+ {
+ keylen = basilisk_messagekey(key,juint(vals,"channel"),juint(vals,"msgid"),jbits256(vals,"srchash"),jbits256(vals,"desthash"));
+ if ( data != 0 )
+ {
+ retstr = basilisk_respond_addmessage(myinfo,key,keylen,data,datalen,0,juint(vals,"duration"));
+ } else printf("no get_dataptr\n");
+ if ( retstr != 0 )
+ free(retstr);
+ } //else printf("not notary.%d relayid.%d\n",myinfo->IAMNOTARY,myinfo->NOTARY.RELAYID);
+ if ( vals != 0 && juint(vals,"fanout") == 0 )
+ jaddnum(vals,"fanout",MAX(8,(int32_t)sqrt(myinfo->NOTARY.NUMRELAYS)+2));
+ if ( BASILISK_KEYSIZE+datalen < allocsize )
+ {
+ memcpy(space2,key,BASILISK_KEYSIZE);
+ if ( data != 0 && datalen != 0 )
+ memcpy(&space2[BASILISK_KEYSIZE],data,datalen);
+ dex_reqsend(myinfo,"DEX",space2,datalen+BASILISK_KEYSIZE,1,"");
+ } else printf("sendmessage space too small error for %d\n",datalen);
+ free(space);
+ free(space2);
+ if ( ptr != 0 )
+ free(ptr);
+ return(basilisk_standardservice("OUT",myinfo,0,jbits256(vals,"desthash"),vals,hexstr,0));
+}
+
+HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr)
+{
+ char *retstr=0,*symbol,*coinaddr,*infostr; cJSON *retjson,*sobj,*info,*addrs,*txoutjson,*txjson,*array; uint32_t basilisktag,blocktime,numtx=0; bits256 txid,blockhash; struct basilisk_item *ptr,Lptr; uint64_t value; int32_t timeoutmillis,vout,height,n,m;
if ( vals == 0 )
- return(clonestr("{\"error\":\"need vals object\"}"));
+ return(clonestr("{\"error\":\"null valsobj\"}"));
+ //if ( myinfo->IAMNOTARY != 0 || myinfo->NOTARY.RELAYID >= 0 )
+ // return(clonestr("{\"error\":\"special relays only do OUT and MSG\"}"));
//if ( coin == 0 )
{
if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 )
coin = iguana_coinfind(symbol);
}
if ( jobj(vals,"fanout") == 0 )
- jaddnum(vals,"fanout",(int32_t)sqrt(NUMRELAYS)+1);
- if ( jobj(vals,"numrequired") == 0 )
- jaddnum(vals,"numrequired",sqrt(NUMRELAYS));
+ jaddnum(vals,"fanout",MAX(5,(int32_t)sqrt(myinfo->NOTARY.NUMRELAYS)+1));
+ txid = jbits256(vals,"txid");
+ vout = jint(vals,"vout");
if ( coin != 0 )
{
- if ( jobj(vals,"addresses") == 0 )
+ if ( coin->FULLNODE < 0 )
+ {
+ if ( (txoutjson= dpow_gettxout(myinfo,coin,txid,vout)) != 0 )
+ {
+ if ( (value= SATOSHIDEN*jdouble(txoutjson,"value")) == 0 )
+ value = SATOSHIDEN*jdouble(txoutjson,"amount");
+ if ( (coinaddr= jstr(txoutjson,"address")) == 0 )
+ {
+ if ( (sobj= jobj(txoutjson,"scriptPubKey")) != 0 && (addrs= jarray(&n,sobj,"addresses")) != 0 && n > 0 )
+ coinaddr = jstri(addrs,0);
+ printf("no address, check addrs %p coinaddr.%p\n",sobj,coinaddr);
+ }
+ if ( coinaddr != 0 && value != 0 )
+ {
+ retjson = cJSON_CreateObject();
+ jaddstr(retjson,"result","success");
+ jaddstr(retjson,"address",coinaddr);
+ jadd64bits(retjson,"satoshis",value);
+ jaddnum(retjson,"value",dstr(value));
+ jaddnum(retjson,"amount",dstr(value));
+ height = dpow_getchaintip(myinfo,&blockhash,&blocktime,0,&numtx,coin);
+ jaddnum(retjson,"height",height);
+ jaddnum(retjson,"numconfirms",jint(txoutjson,"confirmations"));
+ jaddbits256(retjson,"txid",txid);
+ jaddnum(retjson,"vout",vout);
+ jaddstr(retjson,"coin",coin->symbol);
+ }
+ else
+ {
+ printf("missing fields.(%s)\n",jprint(txoutjson,0));
+ free_json(txoutjson);
+ return(clonestr("{\"error\":\"return from gettxout missing fields\"}"));
+ }
+ free_json(txoutjson);
+ return(jprint(retjson,1));
+ } //else return(clonestr("{\"error\":\"null return from gettxout\"}"));
+ }
+ else
+ {
+ if ( (basilisktag= juint(vals,"basilisktag")) == 0 )
+ basilisktag = rand();
+ if ( (timeoutmillis= juint(vals,"timeout")) <= 0 )
+ timeoutmillis = BASILISK_TIMEOUT;
+ if ( coin->FULLNODE > 0 && (ptr= basilisk_bitcoinvalue(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 )
+ {
+ retstr = ptr->retstr, ptr->retstr = 0;
+ ptr->finished = OS_milliseconds() + 10000;
+ return(retstr);
+ }
+ }
+ }
+ if ( myinfo->reqsock >= 0 )
+ {
+ if ( (retstr= _dex_getrawtransaction(myinfo,symbol,txid)) != 0 )
{
- jadd(vals,"addresses",iguana_getaddressesbyaccount(myinfo,coin,"*"));
- //printf("added all addresses: %s\n",jprint(vals,0));
- } //else printf("have addresses.(%s)\n",jprint(jobj(vals,"addresses"),0));
+ if ( (txoutjson= cJSON_Parse(retstr)) != 0 )
+ {
+ //printf("TX.(%s)\n",jprint(txoutjson,0));
+ retjson = cJSON_CreateObject();
+ jaddstr(retjson,"result","success");
+ jaddnum(retjson,"numconfirms",jint(txoutjson,"confirmations"));
+ if ( (height= jint(txoutjson,"height")) == 0 && coin != 0 )
+ height = coin->longestchain - jint(txoutjson,"confirmations");
+ jaddnum(retjson,"height",height);
+ if ( (array= jarray(&n,txoutjson,"vout")) != 0 && vout < n && (txjson= jitem(array,vout)) != 0 )
+ {
+ //printf("txjson.(%s)\n",jprint(txjson,0));
+ if ( (value= jdouble(txjson,"value") * SATOSHIDEN) != 0 )
+ {
+ if ( (sobj= jobj(txjson,"scriptPubKey")) != 0 && (addrs= jarray(&m,sobj,"addresses")) != 0 && (coinaddr= jstri(addrs,0)) != 0 )
+ jaddstr(retjson,"address",coinaddr);
+ jadd64bits(retjson,"satoshis",value);
+ jaddnum(retjson,"value",dstr(value));
+ if ( (infostr= _dex_getinfo(myinfo,symbol)) != 0 )
+ {
+ if ( (info= cJSON_Parse(infostr)) != 0 )
+ {
+ if ( (height= jint(info,"blocks")) > 0 )
+ {
+ height -= jint(txoutjson,"confirmations");
+ jaddnum(retjson,"height",height);
+ }
+ free_json(info);
+ }
+ free(infostr);
+ }
+ jaddbits256(retjson,"txid",txid);
+ jaddnum(retjson,"vout",vout);
+ jaddstr(retjson,"coin",symbol);
+ free(retstr);
+ free_json(txoutjson);
+ return(jprint(retjson,1));
+ }
+ }
+ free_json(txoutjson);
+ return(jprint(retjson,1));
+ }
+ return(retstr);
+ }
+ }
+ return(basilisk_standardservice("VAL",myinfo,0,hash,vals,hexstr,1));
+}
+
+HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr)
+{
+ char *retstr=0,*symbol; uint32_t basilisktag; int32_t timeoutmillis,i,retval = -1; uint64_t amount,txfee; cJSON *retarray;
+ if ( vals == 0 )
+ return(clonestr("{\"error\":\"null valsobj\"}"));
+ //if ( coin == 0 )
+ {
+ if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 )
+ coin = iguana_coinfind(symbol);
+ }
+ if ( jobj(vals,"numrequired") == 0 )
+ jaddnum(vals,"numrequired",MIN(3,(int32_t)sqrt(myinfo->NOTARY.NUMRELAYS)+1));
+ if ( jobj(vals,"fanout") == 0 )
+ jaddnum(vals,"fanout",MAX(3,(int32_t)sqrt(myinfo->NOTARY.NUMRELAYS)+1));
+ if ( coin != 0 )
+ {
+ //if ( juint(vals,"burn") == 0 )
+ // jaddnum(vals,"burn",0.0001);
if ( (basilisktag= juint(vals,"basilisktag")) == 0 )
basilisktag = rand();
if ( (timeoutmillis= juint(vals,"timeout")) <= 0 )
timeoutmillis = BASILISK_TIMEOUT;
- if ( (coin->FULLNODE != 0 || coin->VALIDATENODE != 0) && (ptr= basilisk_bitcoinbalances(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 )
+ if ( (retstr= basilisk_bitcoinrawtx(myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals,0)) != 0 )
{
- retstr = ptr->retstr, ptr->retstr = 0;
- ptr->finished = (uint32_t)time(NULL);
- return(retstr);
+ printf("rawtx.(%s)\n",retstr);
+ if ( (amount= j64bits(vals,"satoshis")) == 0 )
+ amount = jdouble(vals,"value") * SATOSHIDEN;
+ if ( (txfee= j64bits(vals,"txfee")) == 0 )
+ txfee = coin->chain->txfee;
+ if ( txfee == 0 )
+ txfee = 10000;
+ retval = -1;
+ if ( (retarray= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( is_cJSON_Array(retarray) != 0 )
+ {
+ for (i=0; iFULLNODE >= 0 )
+ return(clonestr("{\"error\":\"no passphrase or no native komodod\"}"));
+ else
+ {
+ safecopy(myinfo->jumblr_passphrase,passphrase,sizeof(myinfo->jumblr_passphrase));
+ retjson = cJSON_CreateObject();
+ jaddstr(retjson,"result","success");
+ privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,JUMBLR_DEPOSITPREFIX);
+ smartaddress_add(myinfo,privkey,"deposit","KMD",0.,0.);
+ myinfo->jumblr_depositkey = curve25519(privkey,curve25519_basepoint9());
+ bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype);
+ if ( coin->FULLNODE < 0 )
+ jumblr_importprivkey(myinfo,coin,wifstr);
+ jaddstr(retjson,"KMDdeposit",KMDaddr);
+ jaddstr(retjson,"BTCdeposit",BTCaddr);
+ if ( (coinbtc= iguana_coinfind("BTC")) != 0 )
+ {
+ bitcoin_priv2wif(wifstr,privkey,coinbtc->chain->wiftype);
+ if ( coinbtc->FULLNODE < 0 )
+ jumblr_importprivkey(myinfo,coinbtc,wifstr);
+ jaddnum(retjson,"BTCdeposits",dstr(jumblr_balance(myinfo,coinbtc,BTCaddr)));
+ }
+ privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,"");
+ smartaddress_add(myinfo,privkey,"jumblr","KMD",0.,0.);
+ myinfo->jumblr_pubkey = curve25519(privkey,curve25519_basepoint9());
+ jaddstr(retjson,"KMDjumblr",KMDaddr);
+ jaddstr(retjson,"BTCjumblr",BTCaddr);
+ if ( coinbtc != 0 )
+ jaddnum(retjson,"BTCjumbled",dstr(jumblr_balance(myinfo,coinbtc,BTCaddr)));
+ if ( (smartaddrs= InstantDEX_smartaddresses(myinfo,0,0,0)) != 0 )
+ {
+ if ( (tmp= cJSON_Parse(smartaddrs)) != 0 )
+ jadd(retjson,"smartaddresses",tmp);
+ free(smartaddrs);
+ }
+ return(jprint(retjson,1));
+ }
+}
+
+ZERO_ARGS(jumblr,runsilent)
+{
+ myinfo->runsilent = 1;
+ return(clonestr("{\"result\":\"success\",\"mode\":\"runsilent\"}"));
+}
+
+ZERO_ARGS(jumblr,totransparent)
+{
+ myinfo->runsilent = 0;
+ return(clonestr("{\"result\":\"success\",\"mode\":\"totransparent\"}"));
+}
+
+ZERO_ARGS(jumblr,status)
+{
+ cJSON *retjson; char KMDaddr[64],BTCaddr[64]; struct jumblr_item *ptr,*tmp; struct iguana_info *coinbtc; int64_t received,deposited,jumblred,step_t2z,step_z2z,step_z2t,finished,pending,maxval,minval;
+ if ( strcmp(coin->symbol,"KMD") == 0 && coin->FULLNODE < 0 && myinfo->jumblr_passphrase[0] != 0 )
+ {
+ jumblr_opidsupdate(myinfo,coin);
+ retjson = cJSON_CreateObject();
+ step_t2z = step_z2z = step_z2t = deposited = finished = pending = 0;
+ jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,JUMBLR_DEPOSITPREFIX);
+ jaddstr(retjson,"mode",myinfo->runsilent == 0 ? "totransparent" : "runsilent");
+ jaddstr(retjson,"KMDdeposit",KMDaddr);
+ jaddstr(retjson,"BTCdeposit",BTCaddr);
+ if ( (coinbtc= iguana_coinfind("BTC")) != 0 )
+ jaddnum(retjson,"BTCdeposits",dstr(jumblr_balance(myinfo,coinbtc,BTCaddr)));
+ received = jumblr_receivedby(myinfo,coin,KMDaddr);
+ deposited = jumblr_balance(myinfo,coin,KMDaddr);
+ jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,"");
+ jaddstr(retjson,"KMDjumblr",KMDaddr);
+ jaddstr(retjson,"BTCjumblr",BTCaddr);
+ if ( coinbtc != 0 )
+ jaddnum(retjson,"BTCjumbled",dstr(jumblr_balance(myinfo,coinbtc,BTCaddr)));
+ finished = jumblr_receivedby(myinfo,coin,KMDaddr);
+ jumblred = jumblr_balance(myinfo,coin,KMDaddr);
+ HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
+ {
+ if ( strlen(ptr->src) >= 40 )
+ {
+ if ( strlen(ptr->dest) >= 40 )
+ step_z2z += ptr->amount;
+ else step_z2t += ptr->amount;
+ } else step_t2z += ptr->amount;
+ }
+ jaddstr(retjson,"result","success");
+ jaddnum(retjson,"deposits",dstr(deposited));
+ jaddnum(retjson,"t_to_z",dstr(step_t2z));
+ jaddnum(retjson,"z_to_z",dstr(step_z2z));
+ jaddnum(retjson,"z_to_t",dstr(step_z2t));
+ maxval = MAX(step_t2z,MAX(step_z2z,step_z2t));
+ minval = MIN(step_t2z,MIN(step_z2z,step_z2t));
+ if ( maxval > minval )
+ {
+ pending = (maxval - minval);
+ if ( pending < finished*.1 )
+ pending = 0;
+ }
+ jaddnum(retjson,"pending",dstr(pending));
+ jaddnum(retjson,"jumbled",dstr(jumblred));
+ jaddnum(retjson,"received",dstr(received));
+ jaddnum(retjson,"finished",dstr(finished));
+ return(jprint(retjson,1));
+ }
+ else
+ {
+ printf("(%s) (%s) %d\n",coin->symbol,myinfo->jumblr_passphrase,coin->FULLNODE);
+ return(clonestr("{\"error\":\"jumblr status no passphrase or no native komodod\"}"));
+ }
+}
+
+HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr)
+{
+ char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis;
+ if ( myinfo->NOTARY.RELAYID >= 0 )
+ return(clonestr("{\"error\":\"special relays only do OUT and MSG\"}"));
+ if ( vals == 0 )
+ return(clonestr("{\"error\":\"need vals object\"}"));
+ if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 )
+ coin = iguana_coinfind(symbol);
+ if ( jobj(vals,"history") == 0 )
+ jaddnum(vals,"history",3);
+ if ( jobj(vals,"fanout") == 0 )
+ jaddnum(vals,"fanout",MAX(8,(int32_t)sqrt(myinfo->NOTARY.NUMRELAYS)+1));
+ if ( jobj(vals,"numrequired") == 0 )
+ jaddnum(vals,"numrequired",MIN(juint(vals,"fanout")/2,(int32_t)sqrt(myinfo->NOTARY.NUMRELAYS)));
+ if ( jobj(vals,"addresses") == 0 )
+ {
+ jadd(vals,"addresses",iguana_getaddressesbyaccount(myinfo,coin,"*"));
+ //printf("added all %s addresses: %s\n",coin->symbol,jprint(vals,0));
+ } //else printf("have addresses.(%s)\n",jprint(jobj(vals,"addresses"),0));
+ if ( (basilisktag= juint(vals,"basilisktag")) == 0 )
+ basilisktag = rand();
+ if ( (timeoutmillis= juint(vals,"timeout")) <= 0 )
+ timeoutmillis = BASILISK_TIMEOUT;
+ if ( coin != 0 )
+ {
+ if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 || coin->notarychain >= 0 )
+ {
+ if ( (ptr= basilisk_bitcoinbalances(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 )
+ {
+ retstr = ptr->retstr, ptr->retstr = 0;
+ ptr->finished = OS_milliseconds() + 10000;
+ return(retstr);
+ }
+ return(clonestr("{\"error\":\"no result\"}"));
}
} else printf("no coin\n");
- return(basilisk_standardservice("BAL",myinfo,0,hash,vals,hexstr,1));
+ if ( (retstr= basilisk_standardservice("BAL",myinfo,0,hash,vals,hexstr,1)) != 0 )
+ {
+ basilisk_unspents_process(myinfo,coin,retstr);
+ }
+ return(retstr);
}
HASH_ARRAY_STRING(basilisk,history,hash,vals,hexstr)
{
- struct basilisk_unspent *bu; int32_t i; int64_t totalspent=0,total = 0; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; char *symbol; cJSON *retjson,*array; struct basilisk_spend *s;
+ int64_t total = 0; int32_t i,n; char *symbol; cJSON *retjson,*unspents,*spends,*array; //struct basilisk_spend *s; struct basilisk_unspent *bu; int32_t i; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2;
if ( vals == 0 )
return(clonestr("{\"error\":\"need vals object\"}"));
//if ( coin == 0 )
@@ -931,44 +1527,461 @@ HASH_ARRAY_STRING(basilisk,history,hash,vals,hexstr)
}
if ( coin == 0 )
return(clonestr("{\"error\":\"couldnt find coin\"}"));
- //printf("history for (%s)\n",coin->symbol);
- basilisk_unspents_update(myinfo,coin);
- array = cJSON_CreateArray();
+ unspents = cJSON_CreateArray();
+ spends = cJSON_CreateArray();
portable_mutex_lock(&myinfo->bu_mutex);
- HASH_ITER(hh,myinfo->wallet,wacct,tmp)
+ //HASH_ITER(hh,myinfo->wallet,wacct,tmp)
{
- HASH_ITER(hh,wacct->waddr,waddr,tmp2)
+ //HASH_ITER(hh,wacct->waddr,waddr,tmp2)
{
- for (i=0; inumunspents; i++)
+ if ( myinfo->Cunspents != 0 )
{
- bu = &waddr->unspents[i];
- if ( strcmp(bu->symbol,coin->symbol) == 0 )
+ //printf("Cunspents.(%s)\n",jprint(waddr->Cunspents,0));
+ if ( (array= jobj(myinfo->Cunspents,coin->symbol)) != 0 )
{
- bitcoin_address(waddr->coinaddr,coin->chain->pubtype,waddr->rmd160,sizeof(waddr->rmd160));
- jaddi(array,basilisk_history_item(coin,&total,waddr->coinaddr,bu->value,bu->timestamp,bu->txid,"vout",bu->vout,bu->height,"spentheight",bu->spentheight,bu->relaymask,-1));
- //printf("%s %s i.%d numunspents.%d\n",coin->symbol,waddr->coinaddr,i,waddr->numunspents);
+ if ( (n= cJSON_GetArraySize(array)) > 0 )
+ {
+ for (i=0; inumspends > 0 )
- {
- //spends = cJSON_CreateArray();
- for (i=0; inumspends; i++)
- {
- s = &myinfo->spends[i];
- //struct basilisk_spend { bits256 txid; uint64_t relaymask,value; uint32_t timestamp; int32_t vini,height,unspentheight,ismine; char destaddr[64]; };
- if ( strcmp(s->symbol,coin->symbol) == 0 )
- jaddi(array,basilisk_history_item(coin,&totalspent,s->destaddr,s->value,s->timestamp,s->txid,"vin",s->vini,s->height,"unspentheight",s->unspentheight,s->relaymask,s->ismine));
+ if ( myinfo->Cspends != 0 )
+ {
+ //printf("Cspends.(%s)\n",jprint(waddr->Cspends,0));
+ if ( (array= jobj(myinfo->Cspends,coin->symbol)) != 0 )
+ jaddi(spends,jduplicate(array));
+ }
}
}
portable_mutex_unlock(&myinfo->bu_mutex);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
- jadd(retjson,"history",array);
+ jadd(retjson,"unspents",unspents);
+ jadd(retjson,"spends",spends);
jaddstr(retjson,"coin",coin->symbol);
jaddnum(retjson,"balance",dstr(total));
+ //printf("return history balance %s %.8f\n",coin->symbol,dstr(total));
+ return(jprint(retjson,1));
+}
+
+INT_ARG(passthru,paxfiats,mask)
+{
+ if ( mask == 0 )
+ mask = -1;
+ komodo_assetcoins(-1,mask);
+ return(clonestr("{\"result\":\"success\"}"));
+}
+
+INT_ARG(basilisk,paxfiats,mask)
+{
+ if ( mask == 0 )
+ mask = -1;
+ komodo_assetcoins(0,mask);
+ return(clonestr("{\"result\":\"success\"}"));
+}
+
+INT_ARG(iguana,paxfiats,mask)
+{
+ if ( mask == 0 )
+ mask = -1;
+ komodo_assetcoins(1,mask);
+ return(clonestr("{\"result\":\"success\"}"));
+}
+
+int32_t utxocmp(cJSON *utxo,cJSON *utxo2)
+{
+ bits256 txid,txid2; int32_t vout=-1,vout2=-1;
+ //printf("cmp (%s) vs (%s)\n",jprint(utxo,0),jprint(utxo2,0));
+ txid = jbits256(utxo,"txid");
+ vout = jint(utxo,"vout");
+ txid2 = jbits256(utxo2,"txid");
+ vout2 = jint(utxo2,"vout");
+ if ( bits256_cmp(txid,txid2) == 0 && vout == vout2 )
+ return(0);
+ else return(-1);
+}
+
+ZERO_ARGS(basilisk,cancelrefresh)
+{
+ myinfo->cancelrefresh = 1;
+ return(clonestr("{\"result\":\"refresh cancel started\"}"));
+}
+
+TWO_STRINGS(basilisk,refresh,symbol,address)
+{
+ cJSON *array=0,*array2=0,*array3,*item,*item2; char *retstr; int32_t i,j,n,m,vout; bits256 txid;
+ myinfo->cancelrefresh = 0;
+ if ( symbol != 0 && iguana_isnotarychain(symbol) >= 0 && address != 0 && address[0] != 0 )
+ {
+ if ( (retstr= _dex_listunspent(myinfo,symbol,address)) != 0 )
+ {
+ array = cJSON_Parse(retstr);
+ free(retstr);
+ }
+ if ( (retstr= _dex_listunspent2(myinfo,symbol,address)) != 0 )
+ {
+ if ( array == 0 )
+ array = cJSON_Parse(retstr);
+ else array2 = cJSON_Parse(retstr);
+ free(retstr);
+ }
+ if ( array != 0 && array2 != 0 ) // merge
+ {
+ m = cJSON_GetArraySize(array2);
+ array3 = jduplicate(array);
+ n = cJSON_GetArraySize(array3);
+ //printf("MERGE %s and %s\n",jprint(array,0),jprint(array2,0));
+ for (j=0; jcancelrefresh != 0 )
+ break;
+ item2 = jitem(array2,j);
+ for (i=0; icancelrefresh != 0 )
+ break;
+ item = jitem(array,i);
+ txid = jbits256(item,"txid");
+ vout = jint(item,"vout");
+ if ( (retstr= _dex_gettxout(myinfo,symbol,txid,vout)) != 0 )
+ {
+ if ( (item2= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( jdouble(item2,"value") > 0 )
+ {
+ jaddbits256(item2,"txid",txid);
+ jaddnum(item2,"vout",vout);
+ jaddnum(item2,"amount",jdouble(item2,"value"));
+ //printf("%s\n",jprint(item2,0));
+ jaddi(array3,item2);
+ }
+ else free_json(item2);
+ }
+ free(retstr);
+ }
+ }
+ free_json(array);
+ myinfo->cancelrefresh = 0;
+ return(jprint(array3,1));
+ } else return(clonestr("[]"));
+ }
+ myinfo->cancelrefresh = 0;
+ return(clonestr("{\"error\":\"invalid coin or address specified\"}"));
+}
+
+STRING_ARRAY_OBJ_STRING(basilisk,utxorawtx,symbol,utxos,vals,ignore)
+{
+ char *destaddr,*changeaddr; int64_t satoshis,txfee; int32_t completed,sendflag,timelock;
+ timelock = jint(vals,"timelock");
+ sendflag = jint(vals,"sendflag");
+ satoshis = jdouble(vals,"amount") * SATOSHIDEN;
+ destaddr = jstr(vals,"destaddr");
+ changeaddr = jstr(vals,"changeaddr");
+ if ( destaddr != 0 && changeaddr != 0 && symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 )
+ {
+ txfee = jdouble(vals,"txfee") * SATOSHIDEN;
+ return(iguana_utxorawtx(myinfo,coin,timelock,destaddr,changeaddr,&satoshis,1,txfee,&completed,sendflag,utxos,0));
+ }
+ return(clonestr("{\"error\":\"invalid coin or address specified\"}"));
+}
+
+HASH_ARRAY_STRING(basilisk,utxocombine,ignore,vals,symbol)
+{
+ char *coinaddr,*retstr=0; cJSON *utxos; int64_t satoshis,limit,txfee; int32_t maxvins,completed,sendflag,timelock;
+ timelock = 0;
+ if ( (maxvins= jint(vals,"maxvins")) == 0 )
+ maxvins = 20;
+ sendflag = jint(vals,"sendflag");
+ coinaddr = jstr(vals,"coinaddr");
+ limit = jdouble(vals,"maxamount") * SATOSHIDEN;
+ if ( limit > 0 && symbol != 0 && symbol[0] != 0 && (utxos= basilisk_utxosweep(myinfo,symbol,&satoshis,limit,maxvins,coinaddr)) != 0 && cJSON_GetArraySize(utxos) > 0 )
+ {
+ if ( coinaddr != 0 && symbol != 0 && (coin= iguana_coinfind(symbol)) != 0 )
+ {
+ txfee = jdouble(vals,"txfee") * SATOSHIDEN;
+ retstr = iguana_utxorawtx(myinfo,coin,timelock,coinaddr,coinaddr,&satoshis,1,txfee,&completed,sendflag,utxos,0);
+ }
+ free_json(utxos);
+ }
+ if ( retstr == 0 )
+ return(clonestr("{\"error\":\"invalid coin or address specified or no available utxos\"}"));
+ return(retstr);
+}
+
+//int64_t iguana_verifytimelock(struct supernet_info *myinfo,struct iguana_info *coin,uint32_t timelocked,char *destaddr,bits256 txid,int32_t vout)
+THREE_STRINGS_AND_DOUBLE(tradebot,aveprice,comment,base,rel,basevolume)
+{
+ double retvals[4],aveprice; cJSON *retjson = cJSON_CreateObject();
+ aveprice = instantdex_avehbla(myinfo,retvals,base,rel,basevolume);
+ jaddstr(retjson,"result","success");
+ jaddnum(retjson,"aveprice",aveprice);
+ jaddnum(retjson,"avebid",retvals[0]);
+ jaddnum(retjson,"bidvol",retvals[1]);
+ jaddnum(retjson,"aveask",retvals[2]);
+ jaddnum(retjson,"askvol",retvals[3]);
+ return(jprint(retjson,1));
+}
+
+ZERO_ARGS(InstantDEX,allcoins)
+{
+ struct iguana_info *tmp; cJSON *native,*notarychains,*basilisk,*virtual,*full,*retjson = cJSON_CreateObject();
+ full = cJSON_CreateArray();
+ native = cJSON_CreateArray();
+ basilisk = cJSON_CreateArray();
+ virtual = cJSON_CreateArray();
+ notarychains = cJSON_CreateArray();
+ HASH_ITER(hh,myinfo->allcoins,coin,tmp)
+ {
+ if ( coin->FULLNODE < 0 )
+ jaddistr(native,coin->symbol);
+ //else if ( coin->virtualchain != 0 )
+ // jaddistr(virtual,coin->symbol);
+ else if ( coin->FULLNODE > 0 )//|| coin->VALIDATENODE > 0 )
+ jaddistr(full,coin->symbol);
+ //else if ( coin->notarychain >= 0 )
+ // jaddistr(notarychains,coin->symbol);
+ else jaddistr(basilisk,coin->symbol);
+ }
+ jadd(retjson,"native",native);
+ jadd(retjson,"basilisk",basilisk);
+ jadd(retjson,"full",full);
+ //jadd(retjson,"virtual",virtual);
+ //jadd(retjson,"notarychains",notarychains);
+ return(jprint(retjson,1));
+}
+
+STRING_ARG(InstantDEX,available,source)
+{
+ uint64_t total = 0; int32_t i,n=0; char coinaddr[64]; cJSON *item,*unspents,*retjson = 0;
+ if ( source != 0 && source[0] != 0 && (coin= iguana_coinfind(source)) != 0 )
+ {
+ if ( myinfo->expiration != 0 )
+ {
+ bitcoin_address(coinaddr,coin->chain->pubtype,myinfo->persistent_pubkey33,33);
+ if ( (unspents= basilisk_unspents(myinfo,coin,coinaddr)) != 0 )
+ {
+ //printf("available.(%s)\n",jprint(unspents,0));
+ if ( (n= cJSON_GetArraySize(unspents)) > 0 )
+ {
+ for (i=0; i %.8f\n",jprint(item,0),dstr(total));
+ }
+ }
+ free_json(unspents);
+ }
+ retjson = cJSON_CreateObject();
+ jaddnum(retjson,"result",dstr(total));
+ printf(" n.%d total %.8f (%s)\n",n,dstr(total),jprint(retjson,0));
+ return(jprint(retjson,1));
+ }
+ printf("InstantDEX_available: need to unlock wallet\n");
+ return(clonestr("{\"error\":\"need to unlock wallet\"}"));
+ }
+ printf("InstantDEX_available: %s is not active\n",source!=0?source:"");
+ return(clonestr("{\"error\":\"specified coin is not active\"}"));
+}
+
+HASH_ARRAY_STRING(InstantDEX,request,hash,vals,hexstr)
+{
+ uint8_t serialized[512]; bits256 privkey; char buf[512],BTCaddr[64],KMDaddr[64]; struct basilisk_request R; int32_t jumblr,iambob,optionhours; cJSON *reqjson; uint32_t datalen=0,DEX_channel; struct iguana_info *bobcoin,*alicecoin;
+ myinfo->DEXactive = (uint32_t)time(NULL) + 3*BASILISK_TIMEOUT + 60;
+ jadd64bits(vals,"minamount",jdouble(vals,"minprice") * jdouble(vals,"amount") * SATOSHIDEN);
+ if ( jobj(vals,"desthash") == 0 )
+ jaddbits256(vals,"desthash",hash);
+ jadd64bits(vals,"satoshis",jdouble(vals,"amount") * SATOSHIDEN);
+ jadd64bits(vals,"destsatoshis",jdouble(vals,"destamount") * SATOSHIDEN);
+ jaddnum(vals,"timestamp",time(NULL));
+ if ( (jumblr= jint(vals,"usejumblr")) != 0 )
+ privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,jumblr == 1 ? JUMBLR_DEPOSITPREFIX : "");
+ else privkey = myinfo->persistent_priv;
+ hash = curve25519(privkey,curve25519_basepoint9());
+ if ( jobj(vals,"srchash") == 0 )
+ jaddbits256(vals,"srchash",hash);
+ printf("service.(%s)\n",jprint(vals,0));
+ memset(&R,0,sizeof(R));
+ if ( basilisk_request_create(&R,vals,hash,juint(vals,"timestamp"),juint(vals,"DEXselector")) == 0 )
+ {
+ iambob = bitcoin_coinptrs(hash,&bobcoin,&alicecoin,R.src,R.dest,privkey,GENESIS_PUBKEY);
+ if ( (optionhours= jint(vals,"optionhours")) != 0 )
+ {
+ printf("iambob.%d optionhours.%d R.requestid.%u vs calc %u, q.%u\n",iambob,R.optionhours,R.requestid,basilisk_requestid(&R),R.quoteid);
+ if ( iambob != 0 && optionhours > 0 )
+ {
+ sprintf(buf,"{\"error\":\"illegal call option request hours.%d when iambob.%d\"}",optionhours,iambob);
+ printf("ERROR.(%s)\n",buf);
+ return(clonestr(buf));
+ }
+ else if ( iambob == 0 && optionhours < 0 )
+ {
+ sprintf(buf,"{\"error\":\"illegal put option request hours.%d when iambob.%d\"}",optionhours,iambob);
+ printf("ERROR.(%s)\n",buf);
+ return(clonestr(buf));
+ }
+ }
+ //if ( myinfo->IAMNOTARY != 0 || myinfo->NOTARY.RELAYID >= 0 )
+ // R.relaybits = myinfo->myaddr.myipbits;
+ if ( (reqjson= basilisk_requestjson(&R)) != 0 )
+ free_json(reqjson);
+ datalen = basilisk_rwDEXquote(1,serialized,&R);
+ //int32_t i; for (i=0; i 0 )
+ {
+ uint32_t msgid;//,crc=0,crcs[2],numiters = 0; uint8_t buf[4096];
+ memset(hash.bytes,0,sizeof(hash));
+ msgid = (uint32_t)time(NULL);
+ DEX_channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16);
+ myinfo->DEXtrades++; // not exact but allows a one side initiated self-trade
+ basilisk_channelsend(myinfo,hash,hash,DEX_channel,msgid,serialized,datalen,60);
+ sleep(3);
+ /*while ( numiters < 10 && (crc= basilisk_crcsend(myinfo,0,buf,sizeof(buf),hash,myinfo->myaddr.persistent,DEX_channel,msgid,serialized,datalen,crcs)) == 0 )
+ {
+ //printf("didnt get back what was sent\n");
+ sleep(3);
+ basilisk_channelsend(myinfo,myinfo->myaddr.persistent,hash,DEX_channel,msgid,serialized,datalen,60);
+ numiters++;
+ }*/
+ //if ( crc != 0 )//basilisk_channelsend(myinfo,R.srchash,R.desthash,DEX_channel,(uint32_t)time(NULL),serialized,datalen,30) == 0 )
+ return(clonestr("{\"result\":\"DEX message sent\"}"));
+ //else return(clonestr("{\"error\":\"DEX message couldnt be sent\"}"));
+ }
+ return(clonestr("{\"error\":\"DEX message not sent\"}"));
+}
+
+INT_ARG(InstantDEX,automatched,requestid)
+{
+ // return quoteid
+ myinfo->DEXactive = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME;
+ return(clonestr("{\"result\":\"automatched not yet\"}"));
+}
+
+int32_t InstantDEX_incoming_func(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
+{
+ //int32_t i;
+ //for (i=0; inumsmartaddrs+1; int32_t retval,width,drift=3; bits256 pubkey; uint8_t data[32768];
+ now = (uint32_t)time(NULL);
+ memset(&zero,0,sizeof(zero));
+ width = (now - myinfo->DEXpoll) + 2*drift;
+ if ( width < (drift+1) )
+ width = 2*drift+1;
+ else if ( width > 64 )
+ width = 64;
+ if ( (counter % n) == n-1 )
+ pubkey = myinfo->myaddr.persistent;
+ else pubkey = myinfo->smartaddrs[counter % n].pubkey;
+ counter++;
+ myinfo->DEXpoll = now;
+ retjson = cJSON_CreateObject();
+ DEX_channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16);
+ msgid = (uint32_t)time(NULL) + drift;
+ if ( (retarray= basilisk_channelget(myinfo,zero,pubkey,DEX_channel,msgid,width)) != 0 )
+ {
+ //printf("GOT.(%s)\n",jprint(retarray,0));
+ if ( (retval= basilisk_process_retarray(myinfo,0,InstantDEX_process_channelget,data,sizeof(data),DEX_channel,msgid,retarray,InstantDEX_incoming_func)) > 0 )
+ {
+ jaddstr(retjson,"result","success");
+ } else jaddstr(retjson,"error","cant process InstantDEX retarray");
+ jadd(retjson,"responses",retarray);
+ }
+ else
+ {
+ jaddstr(retjson,"error","cant do InstantDEX channelget");
+ //char str[65]; printf("error channelget %s %x\n",bits256_str(str,pubkey),msgid);
+ }
return(jprint(retjson,1));
}
+/*TWO_INTS(InstantDEX,swapstatus,requestid,quoteid)
+ {
+ cJSON *vals; char *retstr;
+ myinfo->DEXactive = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME;
+ //if ( myinfo->IAMLP != 0 )
+ // return(basilisk_respond_swapstatus(myinfo,myinfo->myaddr.persistent,requestid,quoteid));
+ //else
+ {
+ vals = cJSON_CreateObject();
+ jaddnum(vals,"requestid",(uint32_t)requestid);
+ jaddnum(vals,"quoteid",(uint32_t)quoteid);
+ jaddbits256(vals,"hash",myinfo->myaddr.persistent);
+ retstr = basilisk_standardservice("SWP",myinfo,0,myinfo->myaddr.persistent,vals,"",1);
+ free_json(vals);
+ return(retstr);
+ }
+ }*/
+
+TWO_INTS(InstantDEX,accept,requestid,quoteid)
+{
+ cJSON *vals; char *retstr;
+ myinfo->DEXactive = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME;
+ if ( myinfo->IAMLP != 0 || myinfo->dexsock >= 0 || myinfo->subsock >= 0 )
+ return(basilisk_respond_accept(myinfo,myinfo->persistent_priv,requestid,quoteid,&myinfo->DEXaccept));
+ else
+ {
+ vals = cJSON_CreateObject();
+ jaddnum(vals,"quoteid",(uint32_t)quoteid);
+ jaddnum(vals,"requestid",(uint32_t)requestid);
+ retstr = basilisk_standardservice("ACC",myinfo,0,myinfo->myaddr.persistent,vals,"",1);
+ free_json(vals);
+ return(retstr);
+ }
+}
+
+ZERO_ARGS(InstantDEX,init)
+{
+ basilisk_swaps_init(myinfo);
+ return(clonestr("{\"result\":\"success\"}"));
+}
+
+ZERO_ARGS(InstantDEX,getswaplist)
+{
+ return(basilisk_swaplist(myinfo));
+}
+
+DOUBLE_ARG(InstantDEX,DEXratio,ratio)
+{
+ if ( ratio < 0.95 || ratio > 1.01 )
+ return(clonestr("{\"result\":\"error\",\"description\":\"DEXratio must be between 0.95 and 1.01\"}"));
+ myinfo->DEXratio = ratio;
+ return(clonestr("{\"result\":\"success\"}"));
+}
#include "../includes/iguana_apiundefs.h"
diff --git a/basilisk/basilisk.h b/basilisk/basilisk.h
index 3576eee12..8d0c3da9d 100755
--- a/basilisk/basilisk.h
+++ b/basilisk/basilisk.h
@@ -1,5 +1,5 @@
/******************************************************************************
- * Copyright © 2014-2016 The SuperNET Developers. *
+ * Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -16,20 +16,20 @@
#ifndef H_BASILISK_H
#define H_BASILISK_H
-#define BASILISK_DISABLETX
+//#define BASILISK_DISABLESENDTX
+//#define BASILISK_DISABLEWAITTX
#include "../iguana/iguana777.h"
-#define BASILISK_TIMEOUT 30000
+#define BASILISK_TIMEOUT 3000
#define BASILISK_MINFANOUT 8
#define BASILISK_MAXFANOUT 64
#define BASILISK_DEFAULTDIFF 0x1effffff
-#define BASILISK_MAXRELAYS 64
-#define BASILISK_DEXDURATION 180
-#define BASILISK_MSGDURATION 60
+#define BASILISK_DEXDURATION 300
+#define BASILISK_MSGDURATION 30
+#define BASILISK_AUCTION_DURATION 5
#define BASILISK_MAXFUTUREBLOCK 60
-//#define BASILISK_MAXBLOCKLAG 600
#define BASILISK_HDROFFSET ((int32_t)(sizeof(bits256)+sizeof(struct iguana_msghdr)+sizeof(uint32_t)))
#define INSTANTDEX_DECKSIZE 1000
@@ -37,38 +37,58 @@
#define INSTANTDEX_INSURANCEDIV 777
#define INSTANTDEX_PUBKEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06"
#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f"
+#define JUMBLR_RMD160 "5177f8b427e5f47342a4b8ab5dac770815d4389e"
#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146"
#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu"
#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf"
-struct basilisk_rawtx
+#define JUMBLR_INCR 99.65
+#define JUMBLR_FEE 0.001
+#define JUMBLR_TXFEE 0.01
+
+struct basilisk_swap;
+
+struct basilisk_rawtxinfo
{
+ char destaddr[64],coinstr[16];
bits256 txid,signedtxid,actualtxid;
- struct iguana_msgtx msgtx;
- struct iguana_info *coin;
uint64_t amount,change,inputsum;
int32_t redeemlen,datalen,completed,vintype,vouttype,numconfirms,spendlen,secretstart,suppress_pubkeys;
- uint32_t locktime;
- char destaddr[64],name[32];
- uint8_t addrtype,pubkey33[33],spendscript[512],redeemscript[1024],rmd160[20];
- uint8_t *txbytes,extraspace[1024];
+ uint32_t locktime,crcs[2];
+ uint8_t addrtype,pubkey33[33],rmd160[20];
+};
+
+struct basilisk_rawtx
+{
+ char name[32];
+ struct iguana_msgtx msgtx;
+ struct basilisk_rawtxinfo I;
+ struct iguana_info *coin;
+ char vinstr[8192],p2shaddr[64];
+ cJSON *vins;
+ uint8_t txbytes[16384],spendscript[512],redeemscript[1024],extraspace[4096];
};
-struct basilisk_swap
+struct basilisk_swapinfo
{
struct basilisk_request req;
- struct supernet_info *myinfo; bits256 myhash,otherhash;
- uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,locktime;
- struct iguana_info *bobcoin,*alicecoin; char bobstr[64],alicestr[64];
- int32_t bobconfirms,aliceconfirms,iambob,reclaimed;
+ char bobstr[64],alicestr[64];
+ bits256 myhash,otherhash,orderhash;
+ uint32_t statebits,otherstatebits,started,expiration,finished,dead,reftime,putduration,callduration;
+ int32_t bobconfirms,aliceconfirms,iambob,reclaimed,bobspent,alicespent,pad;
uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance;
- bits256 privkeys[INSTANTDEX_DECKSIZE],myprivs[2],mypubs[2],otherpubs[2],pubA0,pubA1,pubB0,pubB1,privAm,pubAm,privBn,pubBn;
- uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2];
- int32_t choosei,otherchoosei,cutverified,otherverifiedcut,numpubs,havestate,otherhavestate;
+ 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];
+ int32_t choosei,otherchoosei,cutverified,otherverifiedcut,numpubs,havestate,otherhavestate,pad2;
uint8_t secretAm[20],secretBn[20];
-
- struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim;
+ uint8_t secretAm256[32],secretBn256[32];
+ uint8_t userdata_aliceclaim[256],userdata_aliceclaimlen;
+ uint8_t userdata_alicereclaim[256],userdata_alicereclaimlen;
+ uint8_t userdata_alicespend[256],userdata_alicespendlen;
+ uint8_t userdata_bobspend[256],userdata_bobspendlen;
+ uint8_t userdata_bobreclaim[256],userdata_bobreclaimlen;
+ uint8_t userdata_bobrefund[256],userdata_bobrefundlen;
};
struct basilisk_value { bits256 txid; int64_t value; int32_t height; int16_t vout; char coinaddr[64]; };
@@ -76,8 +96,8 @@ struct basilisk_value { bits256 txid; int64_t value; int32_t height; int16_t vou
struct basilisk_item
{
struct queueitem DL; UT_hash_handle hh;
- double expiration; cJSON *retarray;
- uint32_t submit,finished,basilisktag,numresults,numsent,numrequired,nBits;
+ double expiration,finished; cJSON *results[64];
+ uint32_t submit,basilisktag,numresults,numsent,numrequired,nBits,duration;
char symbol[32],CMD[4],remoteaddr[64],*retstr;
};
@@ -85,8 +105,8 @@ struct basilisk_item
struct basilisk_message
{
struct queueitem DL; UT_hash_handle hh;
- uint32_t datalen,expiration,duration;
- uint8_t key[BASILISK_KEYSIZE],keylen;
+ uint32_t expiration,duration,datalen;
+ uint8_t keylen,broadcast,key[BASILISK_KEYSIZE];
uint8_t data[];
};
@@ -102,7 +122,7 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *addr,uint32_t sender
int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *type,uint32_t *basilisktagp,int32_t encryptflag,int32_t delaymillis,uint8_t *data,int32_t datalen,int32_t fanout,uint32_t nBits); // data must be offset by sizeof(iguana_msghdr)+sizeof(basilisktag)
void basilisks_init(struct supernet_info *myinfo);
-void basilisk_p2p(void *myinfo,void *_addr,char *ipaddr,uint8_t *data,int32_t datalen,char *type,int32_t encrypted);
+void basilisk_p2p(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *senderip,uint8_t *data,int32_t datalen,char *type,int32_t encrypted);
uint8_t *basilisk_jsondata(int32_t extraoffset,uint8_t **ptrp,uint8_t *space,int32_t spacesize,int32_t *datalenp,char *symbol,cJSON *sendjson,uint32_t basilisktag);
uint8_t *SuperNET_ciphercalc(void **ptrp,int32_t *cipherlenp,bits256 *privkeyp,bits256 *destpubkeyp,uint8_t *data,int32_t datalen,uint8_t *space2,int32_t space2size);
@@ -117,8 +137,15 @@ void basilisk_request_goodbye(struct supernet_info *myinfo);
int32_t basilisk_update(char *symbol,uint32_t reftimestamp);
void basilisk_seqresult(struct supernet_info *myinfo,char *retstr);
struct iguana_info *basilisk_geckochain(struct supernet_info *myinfo,char *symbol,char *chainname,cJSON *valsobj);
-void basilisk_alicepayment(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn);
-void basilisk_rawtx_setparms(char *name,struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33);
+void basilisk_alicepayment(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn);
+void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33,int32_t jumblrflag);
void basilisk_setmyid(struct supernet_info *myinfo);
+int32_t basilisk_rwDEXquote(int32_t rwflag,uint8_t *serialized,struct basilisk_request *rp);
+cJSON *basilisk_requestjson(struct basilisk_request *rp);
+int32_t basilisk_bobscripts_set(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t depositflag,int32_t genflag);
+void basilisk_txlog(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,int32_t delay);
+int32_t basilisk_messagekey(uint8_t *key,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash);
+cJSON *basilisk_unspents(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr);
+char *basilisk_sendrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *signedtx);
#endif
diff --git a/basilisk/basilisk_CMD.c b/basilisk/basilisk_CMD.c
index 695ee1c83..5696addc9 100755
--- a/basilisk/basilisk_CMD.c
+++ b/basilisk/basilisk_CMD.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * Copyright © 2014-2016 The SuperNET Developers. *
+ * Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -24,28 +24,33 @@
return(-1);
}*/
-struct iguana_peer *basilisk_ensurerelay(struct supernet_info *myinfo,struct iguana_info *btcd,uint32_t ipbits)
+void basilisk_ensurerelay(struct supernet_info *myinfo,struct iguana_info *notaries,uint32_t ipbits)
{
+ char ipaddr[64];
+ expand_ipbits(ipaddr,ipbits);
+//#if ISNOTARYNODE
+ //dpow_nanomsginit(myinfo,ipaddr);
+//#else
struct iguana_peer *addr; int32_t i;
- if ( btcd == 0 )
- return(0);
- if ( (addr= iguana_peerfindipbits(btcd,ipbits,0)) == 0 )
+ if ( notaries == 0 || ipbits == myinfo->myaddr.myipbits )
+ return;
+ if ( (addr= iguana_peerfindipbits(notaries,ipbits,0)) == 0 )
{
- if ( (addr= iguana_peerslot(btcd,ipbits,0)) != 0 )
+ if ( (addr= iguana_peerslot(notaries,ipbits,0)) != 0 && addr->isrelay == 0 )
{
- printf("launch peer for relay\n");
+ printf("launch peer.%s for relay vs (%s)\n",ipaddr,myinfo->ipaddr);
addr->isrelay = 1;
- RELAYID = -1;
- for (i=0; imyaddr.myipbits )
+ myinfo->NOTARY.RELAYID = -1;
+ for (i=0; iNOTARY.NUMRELAYS; i++)
+ if ( myinfo->NOTARY.RELAYS[i].ipbits == myinfo->myaddr.myipbits )
{
- RELAYID = i;
+ myinfo->NOTARY.RELAYID = i;
break;
}
- iguana_launch(btcd,"addrelay",iguana_startconnection,addr,IGUANA_CONNTHREAD);
+ iguana_launch(notaries,"addrelay",iguana_startconnection,addr,IGUANA_CONNTHREAD);
} else printf("error getting peerslot\n");
} else addr->isrelay = 1;
- return(addr);
+//#endif
}
static int _increasing_ipbits(const void *a,const void *b)
@@ -65,58 +70,59 @@ void basilisk_relay_remap(struct supernet_info *myinfo,struct basilisk_relay *rp
{
int32_t i; struct basilisk_relaystatus tmp[BASILISK_MAXRELAYS];
// need to verify this works
- for (i=0; iNOTARY.NUMRELAYS; i++)
tmp[i] = rp->reported[i];
- for (i=0; ireported[RELAYS[i].relayid] = tmp[RELAYS[i].oldrelayid];
+ for (i=0; iNOTARY.NUMRELAYS; i++)
+ rp->reported[myinfo->NOTARY.RELAYS[i].relayid] = tmp[myinfo->NOTARY.RELAYS[i].oldrelayid];
}
void basilisk_setmyid(struct supernet_info *myinfo)
{
- int32_t i; char ipaddr[64]; struct iguana_info *btcd = iguana_coinfind("BTCD");
- for (i=0; iNOTARY.NUMRELAYS; i++)
{
- expand_ipbits(ipaddr,RELAYS[i].ipbits);
- if ( myinfo->myaddr.myipbits == RELAYS[i].ipbits )
- RELAYID = i;
- basilisk_ensurerelay(myinfo,btcd,RELAYS[i].ipbits);
+ expand_ipbits(ipaddr,myinfo->NOTARY.RELAYS[i].ipbits);
+ if ( myinfo->myaddr.myipbits == myinfo->NOTARY.RELAYS[i].ipbits )
+ myinfo->NOTARY.RELAYID = i;
+ basilisk_ensurerelay(myinfo,notaries,myinfo->NOTARY.RELAYS[i].ipbits);
}
}
char *basilisk_addrelay_info(struct supernet_info *myinfo,uint8_t *pubkey33,uint32_t ipbits,bits256 pubkey)
{
int32_t i; struct basilisk_relay *rp;
- for (i=0; iNOTARY.NUMRELAYS; i++)
{
- rp = &RELAYS[i];
+ rp = &myinfo->NOTARY.RELAYS[i];
if ( ipbits == rp->ipbits )
{
if ( bits256_cmp(GENESIS_PUBKEY,pubkey) != 0 && bits256_nonz(pubkey) != 0 )
rp->pubkey = pubkey;
if ( pubkey33 != 0 && pubkey33[0] != 0 )
memcpy(rp->pubkey33,pubkey33,33);
- //printf("updated relay[%d] %x\n",i,ipbits);
+ basilisk_setmyid(myinfo);
+ //printf("updated relay[%d] %x vs mine.%x\n",i,ipbits,myinfo->myaddr.myipbits);
return(clonestr("{\"error\":\"relay already there\"}"));
}
}
- if ( i >= sizeof(RELAYS)/sizeof(*RELAYS) )
- i = (rand() % (sizeof(RELAYS)/sizeof(*RELAYS)));
+ if ( i >= sizeof(myinfo->NOTARY.RELAYS)/sizeof(*myinfo->NOTARY.RELAYS) )
+ i = (rand() % (sizeof(myinfo->NOTARY.RELAYS)/sizeof(*myinfo->NOTARY.RELAYS)));
printf("add relay[%d] <- %x\n",i,ipbits);
- for (i=0; iNOTARY.NUMRELAYS; i++)
+ myinfo->NOTARY.RELAYS[i].oldrelayid = i;
+ rp = &myinfo->NOTARY.RELAYS[i];
rp->ipbits = ipbits;
- rp->relayid = NUMRELAYS;
- basilisk_ensurerelay(myinfo,iguana_coinfind("BTCD"),rp->ipbits);
- if ( NUMRELAYS < sizeof(RELAYS)/sizeof(*RELAYS) )
- NUMRELAYS++;
- qsort(RELAYS,NUMRELAYS,sizeof(RELAYS[0]),_increasing_ipbits);
- for (i=0; irelayid = myinfo->NOTARY.NUMRELAYS;
+ basilisk_ensurerelay(myinfo,iguana_coinfind("RELAY"),rp->ipbits);
+ if ( myinfo->NOTARY.NUMRELAYS < sizeof(myinfo->NOTARY.RELAYS)/sizeof(*myinfo->NOTARY.RELAYS) )
+ myinfo->NOTARY.NUMRELAYS++;
+ qsort(myinfo->NOTARY.RELAYS,myinfo->NOTARY.NUMRELAYS,sizeof(myinfo->NOTARY.RELAYS[0]),_increasing_ipbits);
+ for (i=0; iNOTARY.NUMRELAYS; i++)
+ myinfo->NOTARY.RELAYS[i].relayid = i;
basilisk_setmyid(myinfo);
- printf("sorted MYRELAYID.%d\n",RELAYID);
- for (i=0; iNOTARY.RELAYID);
+ for (i=0; iNOTARY.NUMRELAYS; i++)
+ basilisk_relay_remap(myinfo,&myinfo->NOTARY.RELAYS[i]);
return(clonestr("{\"result\":\"relay added\"}"));
}
@@ -140,6 +146,8 @@ void basilisk_request_goodbye(struct supernet_info *myinfo)
char *basilisk_respond_addrelay(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
{
char *ipaddr,*retstr=0;
+ if ( valsobj == 0 )
+ return(clonestr("{\"error\":\"null valsobj\"}"));
if ( (ipaddr= jstr(valsobj,"ipaddr")) != 0 )
retstr = basilisk_addrelay_info(myinfo,0,(uint32_t)calc_ipbits(ipaddr),jbits256(valsobj,"pubkey"));
else retstr = clonestr("{\"error\":\"need rmd160, address and ipaddr\"}");
@@ -203,7 +211,7 @@ char *basilisk_respond_VPNmessage(struct supernet_info *myinfo,char *CMD,void *a
if ( coin != 0 && (ptr= basilisk_bitcoinrawtx(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,valsobj)) != 0 )
{
retstr = ptr->retstr;
- ptr->finished = (uint32_t)time(NULL);
+ ptr->finished = OS_milliseconds() + 10000;
} else retstr = clonestr("{\"error\":\"no coin specified or error bitcoinrawtx\"}");
return(retstr);
}*/
@@ -217,8 +225,8 @@ char *basilisk_respond_value(struct supernet_info *myinfo,char *CMD,void *addr,c
if ( coin != 0 && (ptr= basilisk_bitcoinvalue(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,valsobj)) != 0 )
{
retstr = ptr->retstr;
- ptr->finished = (uint32_t)time(NULL);
- } else retstr = clonestr("{\"error\":\"no coin specified or error bitcoinrawtx\"}");
+ ptr->finished = OS_milliseconds() + 10000;
+ } else retstr = clonestr("{\"error\":\"no coin specified or error bitcoin value\"}");
return(retstr);
}
@@ -231,14 +239,34 @@ char *basilisk_respond_balances(struct supernet_info *myinfo,char *CMD,void *add
if ( coin != 0 && (ptr= basilisk_bitcoinbalances(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,valsobj)) != 0 )
{
retstr = ptr->retstr;
- ptr->finished = (uint32_t)time(NULL);
- } else retstr = clonestr("{\"error\":\"no coin specified or error bitcoinrawtx\"}");
+ ptr->finished = OS_milliseconds() + 10000;
+ } else retstr = clonestr("{\"error\":\"no coin specified or error bitcoin balances\"}");
+ return(retstr);
+}
+
+char *basilisk_respond_getinfo(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
+{
+ char *symbol,*retstr=0; struct basilisk_item Lptr,*ptr; int32_t timeoutmillis; struct iguana_info *coin = 0;
+ if ( (timeoutmillis= jint(valsobj,"timeout")) <= 0 )
+ timeoutmillis = 5000;
+ if ( (symbol= jstr(valsobj,"coin")) != 0 || (symbol= jstr(valsobj,"symbol")) != 0 )
+ coin = iguana_coinfind(symbol);
+ if ( coin != 0 && (ptr= basilisk_getinfo(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,valsobj)) != 0 )
+ {
+ retstr = ptr->retstr;
+ ptr->finished = OS_milliseconds() + 10000;
+ } else retstr = clonestr("{\"error\":\"no coin specified or error bitcoin getinfo\"}");
return(retstr);
}
#include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h"
+HASH_ARRAY_STRING(basilisk,vote,hash,vals,hexstr)
+{
+ return(basilisk_standardservice("VOT",myinfo,0,hash,vals,hexstr,0));
+}
+
HASH_ARRAY_STRING(basilisk,addrelay,hash,vals,hexstr)
{
return(basilisk_standardservice("ADD",myinfo,0,hash,vals,hexstr,1));
diff --git a/basilisk/basilisk_DEX.c b/basilisk/basilisk_DEX.c
index 4921dee2a..17ed0816e 100755
--- a/basilisk/basilisk_DEX.c
+++ b/basilisk/basilisk_DEX.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * Copyright © 2014-2016 The SuperNET Developers. *
+ * Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -34,7 +34,7 @@ int32_t basilisk_ping_processDEX(struct supernet_info *myinfo,uint32_t senderipb
if ( relay->numrequests < relay->maxrequests )
{
memcpy(serialized,&data[len],clen);
- //printf("ping processDEX\n");
+ printf("ping processDEX\n");
n = basilisk_rwDEXquote(0,serialized,&R);
if ( n != clen )
printf("n.%d clen.%d\n",n,clen);
@@ -100,10 +100,10 @@ int32_t basilisk_rwDEXquote(int32_t rwflag,uint8_t *serialized,struct basilisk_r
len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->timestamp),&rp->timestamp); // must be 2nd
len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->quoteid),&rp->quoteid);
len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->quotetime),&rp->quotetime);
- len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->relaybits),&rp->relaybits);
+ len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->optionhours),&rp->optionhours);
len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->srcamount),&rp->srcamount);
len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->minamount),&rp->minamount);
- len += iguana_rwbignum(rwflag,&serialized[len],sizeof(rp->hash),rp->hash.bytes);
+ len += iguana_rwbignum(rwflag,&serialized[len],sizeof(rp->srchash),rp->srchash.bytes);
len += iguana_rwbignum(rwflag,&serialized[len],sizeof(rp->desthash),rp->desthash.bytes);
len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->destamount),&rp->destamount);
if ( rwflag != 0 )
@@ -116,16 +116,19 @@ int32_t basilisk_rwDEXquote(int32_t rwflag,uint8_t *serialized,struct basilisk_r
memcpy(rp->src,&serialized[len],sizeof(rp->src)), len += sizeof(rp->src);
memcpy(rp->dest,&serialized[len],sizeof(rp->dest)), len += sizeof(rp->dest);
}
+ //len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->DEXselector),&rp->DEXselector);
+ //len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->extraspace),&rp->extraspace);
if ( rp->quoteid != 0 && basilisk_quoteid(rp) != rp->quoteid )
- printf("basilisk_rwDEXquote.%d: quoteid.%u mismatch calc %u\n",rwflag,rp->quoteid,basilisk_quoteid(rp));
+ printf(" basilisk_rwDEXquote.%d: quoteid.%u mismatch calc %u rp.%p\n",rwflag,rp->quoteid,basilisk_quoteid(rp),rp);
if ( basilisk_requestid(rp) != rp->requestid )
- printf("basilisk_rwDEXquote.%d: requestid.%u mismatch calc %u\n",rwflag,rp->requestid,basilisk_requestid(rp));
+ printf(" basilisk_rwDEXquote.%d: requestid.%u mismatch calc %u rp.%p\n",rwflag,rp->requestid,basilisk_requestid(rp),rp);
return(len);
}
uint32_t basilisk_request_enqueue(struct supernet_info *myinfo,struct basilisk_request *rp)
{
uint8_t serialized[256]; int32_t len; struct queueitem *item;
+ //printf(" basilisk_request_enqueue\n");
len = basilisk_rwDEXquote(1,serialized+1,rp);
if ( (item= calloc(1,sizeof(*item) + len + 1)) != 0 )
{
@@ -134,7 +137,7 @@ uint32_t basilisk_request_enqueue(struct supernet_info *myinfo,struct basilisk_r
portable_mutex_lock(&myinfo->DEX_mutex);
DL_APPEND(myinfo->DEX_quotes,item);
portable_mutex_unlock(&myinfo->DEX_mutex);
- printf("ENQUEUE.%u calc.%u\n",rp->requestid,basilisk_requestid(rp));
+ //printf("ENQUEUE.%u calc.%u\n",rp->requestid,basilisk_requestid(rp));
return(rp->requestid);
}
return(0);
@@ -142,13 +145,13 @@ uint32_t basilisk_request_enqueue(struct supernet_info *myinfo,struct basilisk_r
cJSON *basilisk_requestjson(struct basilisk_request *rp)
{
- char ipaddr[64]; cJSON *item = cJSON_CreateObject();
- if ( rp->relaybits != 0 )
+ cJSON *item = cJSON_CreateObject();
+ /*if ( rp->relaybits != 0 )
{
expand_ipbits(ipaddr,rp->relaybits);
jaddstr(item,"relay",ipaddr);
- }
- jaddbits256(item,"hash",rp->hash);
+ }*/
+ jaddbits256(item,"srchash",rp->srchash);
if ( bits256_nonz(rp->desthash) != 0 )
jaddbits256(item,"desthash",rp->desthash);
jaddstr(item,"src",rp->src);
@@ -158,11 +161,18 @@ cJSON *basilisk_requestjson(struct basilisk_request *rp)
jadd64bits(item,"minamount",rp->minamount);
jaddstr(item,"dest",rp->dest);
if ( rp->destamount != 0 )
- jadd64bits(item,"destamount",rp->destamount);
+ {
+ //jadd64bits(item,"destamount",rp->destamount);
+ jadd64bits(item,"destsatoshis",rp->destamount);
+ //printf("DESTSATOSHIS.%llu\n",(long long)rp->destamount);
+ }
jaddnum(item,"quotetime",rp->quotetime);
jaddnum(item,"timestamp",rp->timestamp);
jaddnum(item,"requestid",rp->requestid);
jaddnum(item,"quoteid",rp->quoteid);
+ //jaddnum(item,"DEXselector",rp->DEXselector);
+ jaddnum(item,"optionhours",rp->optionhours);
+ jaddnum(item,"profit",(double)rp->profitmargin / 1000000.);
if ( rp->quoteid != 0 && basilisk_quoteid(rp) != rp->quoteid )
printf("quoteid mismatch %u vs %u\n",basilisk_quoteid(rp),rp->quoteid);
if ( basilisk_requestid(rp) != rp->requestid )
@@ -171,11 +181,11 @@ cJSON *basilisk_requestjson(struct basilisk_request *rp)
int32_t i; struct basilisk_request R;
if ( basilisk_parsejson(&R,item) != 0 )
{
- if ( memcmp(&R,rp,sizeof(*rp)) != 0 )
+ if ( memcmp(&R,rp,sizeof(*rp)-sizeof(uint32_t)) != 0 )
{
for (i=0; idestamount= j64bits(valsobj,"destsatoshis")) != 0 )
{
- rp->desthash = jbits256(valsobj,"desthash");
+ rp->desthash = desthash;
for (i=0; i<4; i++)
if ( rp->desthash.ulongs[i] != 0 )
break;
@@ -206,14 +216,20 @@ int32_t basilisk_request_create(struct basilisk_request *rp,cJSON *valsobj,bits2
}
rp->minamount = j64bits(valsobj,"minamount");
rp->timestamp = timestamp;
- rp->hash = hash;
+ rp->srchash = jbits256(valsobj,"srchash");
+ rp->optionhours = jint(valsobj,"optionhours");
+ rp->profitmargin = jdouble(valsobj,"profit") * 1000000;
+ //rp->DEXselector = DEXselector;
strncpy(rp->src,src,sizeof(rp->src)-1);
strncpy(rp->dest,dest,sizeof(rp->dest)-1);
+ //if ( jstr(valsobj,"relay") != 0 )
+ // rp->relaybits = (uint32_t)calc_ipbits(jstr(valsobj,"relay"));
rp->requestid = basilisk_requestid(rp);
+ //printf("set requestid <- %u\n",rp->requestid);
if ( rp->destamount != 0 && bits256_nonz(rp->desthash) != 0 )
{
rp->quoteid = basilisk_quoteid(rp);
- printf("set quoteid.%u\n",rp->quoteid);
+ //printf("set quoteid.%u\n",rp->quoteid);
}
//printf("create.%u calc.%u\n",rp->requestid,basilisk_requestid(rp));
return(0);
@@ -221,18 +237,42 @@ int32_t basilisk_request_create(struct basilisk_request *rp,cJSON *valsobj,bits2
return(-1);
}
-char *basilisk_start(struct supernet_info *myinfo,struct basilisk_request *rp,uint32_t statebits)
+char *basilisk_start(struct supernet_info *myinfo,bits256 privkey,struct basilisk_request *_rp,uint32_t statebits,int32_t optionduration)
{
- cJSON *retjson;
- if ( (bits256_cmp(rp->hash,myinfo->myaddr.persistent) == 0 || bits256_cmp(rp->desthash,myinfo->myaddr.persistent) == 0) )
+ cJSON *retjson; char typestr[64]; bits256 tmpprivkey; double bidasks[2]; struct basilisk_request *rp=0; int32_t i,srcmatch,destmatch;
+ if ( _rp->requestid == myinfo->lastdexrequestid )
+ {
+ printf("filter duplicate r%u\n",_rp->requestid);
+ return(clonestr("{\"error\":\"filter duplicate requestid\"}"));
+ }
+ srcmatch = smartaddress_pubkey(myinfo,typestr,bidasks,&tmpprivkey,_rp->src,_rp->srchash) >= 0;
+ destmatch = smartaddress_pubkey(myinfo,typestr,bidasks,&tmpprivkey,_rp->dest,_rp->desthash) >= 0;
+ char str[65],str2[65]; printf("%s srcmatch.%d %s destmatch.%d\n",bits256_str(str,_rp->srchash),srcmatch,bits256_str(str2,_rp->desthash),destmatch);
+ if ( srcmatch != 0 || destmatch != 0 )
{
- printf("START thread to complete %u/%u for (%s %.8f) <-> (%s %.8f) q.%u\n",rp->requestid,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount),rp->quoteid);
- if ( basilisk_thread_start(myinfo,rp) != 0 )
+ for (i=0; inumswaps; i++)
+ if ( myinfo->swaps[i]->I.req.requestid == _rp->requestid )
+ {
+ printf("basilisk_thread_start error trying to start requestid.%u which is already started\n",rp->requestid);
+ break;
+ }
+ if ( i == myinfo->numswaps )
+ {
+ rp = calloc(1,sizeof(*rp));
+ *rp = *_rp;
+ printf("START thread to complete %u/%u for (%s %.8f) <-> (%s %.8f) q.%u\n",rp->requestid,rp->quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount),rp->quoteid);
+ myinfo->lastdexrequestid = rp->requestid;
+ if ( basilisk_thread_start(myinfo,privkey,rp,statebits,optionduration,0) != 0 )
+ {
+ basilisk_request_enqueue(myinfo,rp);
+ return(clonestr("{\"result\":\"started atomic swap thread\"}"));
+ } else return(clonestr("{\"error\":\"couldnt atomic swap thread\"}"));
+ }
+ else
{
- basilisk_request_enqueue(myinfo,rp);
- return(clonestr("{\"result\":\"started atomic swap thread\"}"));
+ printf("trying to start already pending swap.r%u\n",rp->requestid);
+ return(clonestr("{\"error\":\"cant start pending swap\"}"));
}
- else return(clonestr("{\"error\":\"couldnt atomic swap thread\"}"));
}
else if ( myinfo->IAMLP != 0 )
{
@@ -242,12 +282,69 @@ char *basilisk_start(struct supernet_info *myinfo,struct basilisk_request *rp,ui
} else return(clonestr("{\"error\":\"unexpected basilisk_start not mine and amrelay\"}"));
}
+int32_t basilisk_requests_poll(struct supernet_info *myinfo)
+{
+ static uint32_t lastpoll;
+ char *retstr,typestr[64]; uint8_t data[32768]; cJSON *outerarray,*retjson; uint32_t msgid,channel; int32_t datalen,i,n,retval = 0; struct basilisk_request issueR; bits256 privkey; double bidasks[2],hwm = 0.;
+ if ( myinfo->IAMNOTARY != 0 || time(NULL) < lastpoll+5 || (myinfo->IAMLP == 0 && myinfo->DEXactive < time(NULL)) )
+ return(retval);
+ lastpoll = (uint32_t)time(NULL);
+ memset(&issueR,0,sizeof(issueR));
+ memset(&myinfo->DEXaccept,0,sizeof(myinfo->DEXaccept));
+ //printf("Call incoming\n");
+ if ( (retstr= InstantDEX_incoming(myinfo,0,0,0,0)) != 0 )
+ {
+ //printf("poll.(%s)\n",retstr);
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( (outerarray= jarray(&n,retjson,"responses")) != 0 )
+ {
+ retval++;
+ for (i=0; i 0. )
+ {
+ myinfo->DEXaccept = issueR;
+ if ( smartaddress_pubkey(myinfo,typestr,bidasks,&privkey,issueR.src,issueR.srchash) >= 0 )
+ {
+ if ( myinfo->DEXtrades > 0 )
+ {
+ dex_channelsend(myinfo,issueR.srchash,issueR.desthash,channel,0x4000000,(void *)&issueR.requestid,sizeof(issueR.requestid)); // 60
+ dpow_nanomsg_update(myinfo);
+ dex_updateclient(myinfo);
+ if ( (retstr= basilisk_start(myinfo,privkey,&issueR,1,issueR.optionhours * 3600)) != 0 )
+ free(retstr);
+ }
+ }
+ else if ( myinfo->IAMLP != 0 && issueR.requestid != myinfo->lastdexrequestid )//if ( issueR.quoteid == 0 )
+ {
+ issueR.quoteid = basilisk_quoteid(&issueR);
+ issueR.desthash = myinfo->myaddr.persistent;
+ datalen = basilisk_rwDEXquote(1,data,&issueR);
+ msgid = (uint32_t)time(NULL);
+ printf("other req hwm %f >>>>>>>>>>> send response (%llx -> %llx) last.%u r.%u quoteid.%u\n",hwm,(long long)issueR.desthash.txid,(long long)issueR.srchash.txid,myinfo->lastdexrequestid,issueR.requestid,issueR.quoteid);
+ dex_channelsend(myinfo,issueR.desthash,issueR.srchash,channel,msgid,data,datalen); //INSTANTDEX_LOCKTIME*2
+ dpow_nanomsg_update(myinfo);
+ dex_updateclient(myinfo);
+ if ( (retstr= basilisk_start(myinfo,myinfo->persistent_priv,&issueR,0,issueR.optionhours * 3600)) != 0 )
+ free(retstr);
+ } //else printf("basilisk_requests_poll unexpected hwm issueR\n");
+ }
+ return(retval);
+}
+
struct basilisk_relay *basilisk_request_ensure(struct supernet_info *myinfo,uint32_t senderipbits,int32_t numrequests)
{
int32_t j; struct basilisk_relay *relay = 0;
if ( (j= basilisk_relayid(myinfo,senderipbits)) >= 0 )
{
- relay = &RELAYS[j];
+ relay = &myinfo->NOTARY.RELAYS[j];
if ( numrequests > relay->maxrequests )
{
relay->maxrequests = numrequests;
@@ -281,17 +378,30 @@ static int _cmp_requests(const void *a,const void *b)
#undef uint32_b
}
-struct basilisk_request *_basilisk_requests_uniq(struct supernet_info *myinfo,int32_t *nump,uint8_t *space,int32_t spacesize)
+struct basilisk_request *_basilisk_requests_uniq(struct supernet_info *myinfo,int32_t *nump,uint8_t *space,int32_t spacesize,struct basilisk_request *refrp)
{
int32_t i,j,n,k,m; struct basilisk_relay *relay; struct basilisk_request *requests,*rp;
- for (j=m=0; jNOTARY.NUMRELAYS; j++)
+ m += myinfo->NOTARY.RELAYS[j].numrequests;
if ( m*sizeof(*requests) <= spacesize )
requests = (void *)space;
else requests = calloc(m,sizeof(*requests));
- for (j=m=0; jNOTARY.NUMRELAYS; j++)
+ {
+ relay = &myinfo->NOTARY.RELAYS[j];
if ( (n= relay->numrequests) > 0 )
{
for (i=0; iipbits;
+ //requests[m].relaybits = relay->ipbits;
requests[m++] = *rp;
}
}
@@ -322,20 +432,22 @@ struct basilisk_request *_basilisk_requests_uniq(struct supernet_info *myinfo,in
return(jprint(retjson,1));
}*/
-char *basilisk_respond_requests(struct supernet_info *myinfo,bits256 hash,uint32_t requestid,uint32_t quoteid)
+char *basilisk_respond_requests(struct supernet_info *myinfo,bits256 hash,uint32_t requestid,uint32_t quoteid,struct basilisk_request *refrp)
{
int32_t i,qflag,num=0; cJSON *retjson,*array; struct basilisk_request *requests,*rp; uint8_t space[4096];
array = cJSON_CreateArray();
portable_mutex_lock(&myinfo->DEX_reqmutex);
- if ( (requests= _basilisk_requests_uniq(myinfo,&num,space,sizeof(space))) != 0 )
+ if ( (requests= _basilisk_requests_uniq(myinfo,&num,space,sizeof(space),refrp)) != 0 )
{
- //printf("numrequests.%d r.%u q.%u\n",num,requestid,quoteid);
for (i=0; iquoteid && (bits256_cmp(hash,rp->hash) == 0 || bits256_cmp(hash,rp->desthash) == 0)) )
+ if ( quoteid == 0 || (quoteid == rp->quoteid && (bits256_cmp(hash,rp->srchash) == 0 || bits256_cmp(hash,rp->desthash) == 0)) )
qflag = 1;
else qflag = 0;
+ //int32_t j; for (j=0; jrequestid == requestid && qflag != 0) )
jaddi(array,basilisk_requestjson(rp));
}
@@ -348,11 +460,11 @@ char *basilisk_respond_requests(struct supernet_info *myinfo,bits256 hash,uint32
return(jprint(retjson,1));
}
-char *basilisk_respond_accept(struct supernet_info *myinfo,uint32_t requestid,uint32_t quoteid)
+char *basilisk_respond_accept(struct supernet_info *myinfo,bits256 privkey,uint32_t requestid,uint32_t quoteid,struct basilisk_request *refrp)
{
int32_t i,num=0; char *retstr=0; struct basilisk_request *requests,*rp; uint8_t space[4096];
portable_mutex_lock(&myinfo->DEX_reqmutex);
- if ( (requests= _basilisk_requests_uniq(myinfo,&num,space,sizeof(space))) != 0 )
+ if ( (requests= _basilisk_requests_uniq(myinfo,&num,space,sizeof(space),refrp)) != 0 )
{
for (i=0; irequestid == requestid && rp->quoteid == quoteid )
{
printf("start from accept\n");
- retstr = basilisk_start(myinfo,rp,1);
+ retstr = basilisk_start(myinfo,privkey,rp,1,0);
break;
}
}
@@ -373,181 +485,54 @@ char *basilisk_respond_accept(struct supernet_info *myinfo,uint32_t requestid,ui
return(retstr);
}
-// respond to incoming RID, ACC, DEX, QST
-
-/*char *basilisk_respond_RID(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
-{
- return(basilisk_respond_requests(myinfo,hash,juint(valsobj,"requestid"),0));
-}
-
-char *basilisk_respond_SWP(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
-{
-return(basilisk_respond_swapstatus(myinfo,hash,juint(valsobj,"requestid"),juint(valsobj,"quoteid")));
-}
-
-char *basilisk_respond_ACC(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
-{
- uint32_t requestid,quoteid;
- if ( (requestid= juint(valsobj,"requestid")) != 0 && (quoteid= juint(valsobj,"quoteid")) != 0 )
- return(basilisk_respond_accept(myinfo,requestid,quoteid));
- else return(clonestr("{\"error\":\"need nonzero requestid and quoteid\"}"));
-}
-
-char *basilisk_respond_DEX(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
+cJSON *basilisk_unspents(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr)
{
- char *retstr=0,buf[256]; struct basilisk_request R;
- if ( basilisk_request_create(&R,valsobj,hash,juint(valsobj,"timestamp")) == 0 )
+ cJSON *unspents=0,*array=0,*json,*ismine; char *retstr; int32_t valid = 0;
+ if ( coin->FULLNODE > 0 )
{
- char str[65]; printf("DEX.(%s %.8f) -> %s %s\n",R.src,dstr(R.srcamount),R.dest,bits256_str(str,hash));
- if ( basilisk_request_enqueue(myinfo,&R) != 0 )
- {
- sprintf(buf,"{\"result\":\"DEX request added\",\"requestid\":%u}",R.requestid);
- retstr = clonestr(buf);
- } else retstr = clonestr("{\"error\":\"DEX quote couldnt be created\"}");
- } else retstr = clonestr("{\"error\":\"missing or invalid fields\"}");
- return(retstr);
-}*/
-
-#include "../includes/iguana_apidefs.h"
-#include "../includes/iguana_apideclares.h"
-
-THREE_STRINGS_AND_DOUBLE(tradebot,aveprice,comment,base,rel,basevolume)
-{
- double retvals[4],aveprice; cJSON *retjson = cJSON_CreateObject();
- aveprice = instantdex_avehbla(myinfo,retvals,base,rel,basevolume);
- jaddstr(retjson,"result","success");
- jaddnum(retjson,"aveprice",aveprice);
- jaddnum(retjson,"avebid",retvals[0]);
- jaddnum(retjson,"bidvol",retvals[1]);
- jaddnum(retjson,"aveask",retvals[2]);
- jaddnum(retjson,"askvol",retvals[3]);
- return(jprint(retjson,1));
-}
-
-ZERO_ARGS(InstantDEX,allcoins)
-{
- struct iguana_info *tmp; cJSON *basilisk,*virtual,*full,*retjson = cJSON_CreateObject();
- full = cJSON_CreateArray();
- basilisk = cJSON_CreateArray();
- virtual = cJSON_CreateArray();
- HASH_ITER(hh,myinfo->allcoins,coin,tmp)
- {
- if ( coin->virtualchain != 0 )
- jaddistr(virtual,coin->symbol);
- if ( coin->FULLNODE != 0 || coin->VALIDATENODE != 0 )
- jaddistr(full,coin->symbol);
- else jaddistr(basilisk,coin->symbol);
+ array = cJSON_CreateArray();
+ jaddistr(array,coinaddr);
+ unspents = iguana_listunspents(myinfo,coin,array,0,0,"");
+ free_json(array);
}
- jadd(retjson,"basilisk",basilisk);
- jadd(retjson,"full",full);
- jadd(retjson,"virtual",virtual);
- return(jprint(retjson,1));
-}
-
-STRING_ARG(InstantDEX,available,source)
-{
- if ( source != 0 && source[0] != 0 && (coin= iguana_coinfind(source)) != 0 )
- {
- if ( myinfo->expiration != 0 )
- return(bitcoinrpc_getbalance(myinfo,coin,json,remoteaddr,"*",coin->chain->minconfirms,1,1<<30));
- else return(clonestr("{\"error\":\"need to unlock wallet\"}"));
- } else return(clonestr("{\"error\":\"specified coin is not active\"}"));
-}
-
-HASH_ARRAY_STRING(InstantDEX,request,hash,vals,hexstr)
-{
- uint8_t serialized[512]; struct basilisk_request R; cJSON *reqjson; uint32_t datalen=0,DEX_channel;
- myinfo->DEXactive = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME;
- jadd64bits(vals,"minamount",jdouble(vals,"minprice") * jdouble(vals,"amount") * SATOSHIDEN);
- if ( jobj(vals,"desthash") == 0 )
- jaddbits256(vals,"desthash",hash);
- jadd64bits(vals,"satoshis",jdouble(vals,"amount") * SATOSHIDEN);
- jadd64bits(vals,"destsatoshis",jdouble(vals,"destamount") * SATOSHIDEN);
- jaddnum(vals,"timestamp",time(NULL));
- hash = myinfo->myaddr.persistent;
- printf("service.(%s)\n",jprint(vals,0));
+ else
{
- memset(&R,0,sizeof(R));
- if ( basilisk_request_create(&R,vals,hash,juint(vals,"timestamp")) == 0 )
+ if ( coin->FULLNODE < 0 && (retstr= dpow_validateaddress(myinfo,coin,coinaddr)) != 0 )
{
- printf("R.requestid.%u vs calc %u, q.%u\n",R.requestid,basilisk_requestid(&R),R.quoteid);
- if ( RELAYID >= 0 )
- R.relaybits = myinfo->myaddr.myipbits;
- if ( (reqjson= basilisk_requestjson(&R)) != 0 )
- free_json(reqjson);
- datalen = basilisk_rwDEXquote(1,serialized,&R);
- printf("R.requestid.%u vs calc %u, q.%u datalen.%d\n",R.requestid,basilisk_requestid(&R),R.quoteid,datalen);
- basilisk_rwDEXquote(0,serialized,&R);
- } else printf("error creating request\n");
- }
- if ( datalen > 0 )
- {
- memset(hash.bytes,0,sizeof(hash));
- DEX_channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16);
- if ( basilisk_channelsend(myinfo,hash,DEX_channel,(uint32_t)time(NULL),serialized,datalen,30) == 0 )
- return(clonestr("{\"result\":\"DEX message sent\"}"));
- else return(clonestr("{\"error\":\"DEX message couldnt be sent\"}"));
- }
- return(clonestr("{\"error\":\"DEX message not sent\"}"));
- //return(basilisk_standardservice("DEX",myinfo,0,myinfo->myaddr.persistent,vals,"",1));
-}
-
-INT_ARG(InstantDEX,automatched,requestid)
-{
- // return quoteid
- myinfo->DEXactive = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME;
- return(clonestr("{\"result\":\"automatched not yet\"}"));
-}
-
-INT_ARG(InstantDEX,incoming,requestid)
-{
- cJSON *vals; char *retstr;
- myinfo->DEXactive = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME;
- //if ( myinfo->IAMLP != 0 )
- // return(basilisk_respond_requests(myinfo,myinfo->myaddr.persistent,requestid,0));
- //else
- {
- vals = cJSON_CreateObject();
- jaddnum(vals,"requestid",(uint32_t)requestid);
- jaddbits256(vals,"hash",myinfo->myaddr.persistent);
- retstr = basilisk_standardservice("RID",myinfo,0,myinfo->myaddr.persistent,vals,"",1);
- free_json(vals);
- return(retstr);
+ json = cJSON_Parse(retstr);
+ if ( (ismine= jobj(json,"ismine")) != 0 && is_cJSON_True(ismine) != 0 )
+ valid = 1;
+ free(retstr);
+ }
+ if ( coin->FULLNODE == 0 || valid == 0 )
+ {
+ if ( (retstr= dex_listunspent(myinfo,coin,0,0,coin->symbol,coinaddr)) != 0 )
+ {
+ unspents = cJSON_Parse(retstr);
+ free(retstr);
+ }
+ } else unspents = dpow_listunspent(myinfo,coin,coinaddr);
}
+ return(unspents);
}
-/*TWO_INTS(InstantDEX,swapstatus,requestid,quoteid)
+char *basilisk_sendrawtransaction(struct supernet_info *myinfo,struct iguana_info *coin,char *signedtx)
{
- cJSON *vals; char *retstr;
- myinfo->DEXactive = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME;
- //if ( myinfo->IAMLP != 0 )
- // return(basilisk_respond_swapstatus(myinfo,myinfo->myaddr.persistent,requestid,quoteid));
- //else
+ char *retstr,buf[65]; bits256 txid;
+ if ( coin->FULLNODE > 0 )
{
- vals = cJSON_CreateObject();
- jaddnum(vals,"requestid",(uint32_t)requestid);
- jaddnum(vals,"quoteid",(uint32_t)quoteid);
- jaddbits256(vals,"hash",myinfo->myaddr.persistent);
- retstr = basilisk_standardservice("SWP",myinfo,0,myinfo->myaddr.persistent,vals,"",1);
- free_json(vals);
- return(retstr);
+ txid = iguana_sendrawtransaction(myinfo,coin,signedtx);
+ if ( bits256_nonz(txid) )
+ {
+ bits256_str(buf,txid);
+ retstr = clonestr(buf);
+ } else retstr = clonestr("{\"error\":\"couldnt validate or send signedtx\"}");
}
-}*/
-
-TWO_INTS(InstantDEX,accept,requestid,quoteid)
-{
- cJSON *vals; char *retstr;
- myinfo->DEXactive = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME;
- //if ( myinfo->IAMLP != 0 )
- // return(basilisk_respond_accept(myinfo,requestid,quoteid));
- //else
+ else if ( coin->FULLNODE == 0 )
{
- vals = cJSON_CreateObject();
- jaddnum(vals,"quoteid",(uint32_t)quoteid);
- jaddnum(vals,"requestid",(uint32_t)requestid);
- retstr = basilisk_standardservice("ACC",myinfo,0,myinfo->myaddr.persistent,vals,"",1);
- free_json(vals);
- return(retstr);
+ retstr = _dex_sendrawtransaction(myinfo,coin->symbol,signedtx);
}
+ else retstr = dpow_sendrawtransaction(myinfo,coin,signedtx);
+ return(retstr);
}
-#include "../includes/iguana_apiundefs.h"
+
diff --git a/basilisk/basilisk_MSG.c b/basilisk/basilisk_MSG.c
index c64269041..0fba54c91 100755
--- a/basilisk/basilisk_MSG.c
+++ b/basilisk/basilisk_MSG.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * Copyright © 2014-2016 The SuperNET Developers. *
+ * Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -15,68 +15,16 @@
// included from basilisk.c
-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)
+int32_t basilisk_messagekeyread(uint8_t *key,uint32_t *channelp,uint32_t *msgidp,bits256 *srchashp,bits256 *desthashp)
{
- struct basilisk_message *msg; int32_t i;
- HASH_FIND(hh,myinfo->messagetable,key,keylen,msg);
- if ( msg == 0 && keylen == BASILISK_KEYSIZE )
- {
- msg = calloc(1,sizeof(*msg) + datalen);
- if ( duration == 0 )
- duration = BASILISK_MSGDURATION;
- else if ( duration > INSTANTDEX_LOCKTIME*2 )
- duration = INSTANTDEX_LOCKTIME*2;
- msg->duration = duration;
- msg->expiration = (uint32_t)time(NULL) + duration;
- msg->keylen = keylen;
- memcpy(msg->key,key,keylen);
- msg->datalen = datalen;
- memcpy(msg->data,data,datalen);
- portable_mutex_lock(&myinfo->messagemutex);
- HASH_ADD_KEYPTR(hh,myinfo->messagetable,msg->key,msg->keylen,msg);
- for (i=0; imessagemutex);
- if ( sendping != 0 )
- {
- queue_enqueue("basilisk_message",&myinfo->msgQ,&msg->DL,0);
- return(clonestr("{\"result\":\"message added to hashtable\"}"));
- } else return(0);
- } else return(0);
-}
-
-cJSON *basilisk_respond_getmessage(struct supernet_info *myinfo,uint8_t *key,int32_t keylen)
-{
- cJSON *msgjson=0; struct basilisk_message *msg; char *ptr = 0,strbuf[32768];
- portable_mutex_lock(&myinfo->messagemutex);
- HASH_FIND(hh,myinfo->messagetable,key,keylen,msg);
- if ( msg != 0 )
- {
- msgjson = cJSON_CreateObject();
- if ( basilisk_addhexstr(&ptr,msgjson,strbuf,sizeof(strbuf),msg->data,msg->datalen) != 0 )
- {
- //retjson = cJSON_CreateObject();
- jaddnum(msgjson,"expiration",msg->expiration);
- jaddnum(msgjson,"duration",msg->duration);
- //jadd(retjson,"message",msgjson);
- printf("havemessage len.%d\n",msg->datalen);
- }
- else
- {
- //jaddstr(retjson,"error","couldnt add message");
- printf("couldnt add message\n");
- free_json(msgjson);
- msgjson = 0;
- }
- }
- portable_mutex_unlock(&myinfo->messagemutex);
- return(msgjson);
+ int32_t keylen = 0;
+ keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),channelp);
+ keylen += iguana_rwnum(0,&key[keylen],sizeof(uint32_t),msgidp);
+ keylen += iguana_rwbignum(0,&key[keylen],sizeof(*srchashp),srchashp->bytes);
+ keylen += iguana_rwbignum(0,&key[keylen],sizeof(*desthashp),desthashp->bytes);
+ return(keylen);
}
-// respond to incoming OUT, MSG
-
int32_t basilisk_messagekey(uint8_t *key,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash)
{
int32_t keylen = 0;
@@ -87,116 +35,291 @@ int32_t basilisk_messagekey(uint8_t *key,uint32_t channel,uint32_t msgid,bits256
return(keylen);
}
-char *basilisk_respond_OUT(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
+cJSON *basilisk_msgjson(struct basilisk_message *msg,uint8_t *key,int32_t keylen)
{
- int32_t keylen,duration; uint8_t key[BASILISK_KEYSIZE]; bits256 senderhash;
- senderhash = jbits256(valsobj,"sender");
- duration = juint(valsobj,"duration");
- keylen = basilisk_messagekey(key,juint(valsobj,"channel"),juint(valsobj,"msgid"),senderhash,hash);
- if( bits256_nonz(senderhash) == 0 && bits256_nonz(hash) == 0 && duration > BASILISK_MSGDURATION )
- duration = BASILISK_MSGDURATION;
- // printf("OUT keylen.%d datalen.%d\n",keylen,datalen);
- // char str[65]; printf("add message.[%d] channel.%u msgid.%x %s\n",datalen,juint(valsobj,"channel"),juint(valsobj,"msgid"),bits256_str(str,hash));
- return(basilisk_respond_addmessage(myinfo,key,keylen,data,datalen,1,duration));
+ cJSON *msgjson=0; char *str = 0,strbuf[32768],keystr[BASILISK_KEYSIZE*2+1];
+ msgjson = cJSON_CreateObject();
+ if ( basilisk_addhexstr(&str,msgjson,strbuf,sizeof(strbuf),msg->data,msg->datalen) != 0 )
+ {
+ init_hexbytes_noT(keystr,key,keylen);
+ jaddstr(msgjson,"key",keystr);
+ jaddnum(msgjson,"expiration",msg->expiration);
+ jaddnum(msgjson,"duration",msg->duration);
+ if ( str != 0 )
+ free(str);
+ }
+ else
+ {
+ printf("basilisk_respond_getmessage: couldnt basilisk_addhexstr data.[%d]\n",msg->datalen);
+ free_json(msgjson);
+ msgjson = 0;
+ }
+ return(msgjson);
}
-char *basilisk_iterate_MSG(struct supernet_info *myinfo,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash,int32_t width)
+cJSON *_basilisk_respond_getmessage(struct supernet_info *myinfo,uint8_t *key,int32_t keylen)
{
- uint8_t key[BASILISK_KEYSIZE]; int32_t i,keylen; cJSON *item,*retjson,*array; bits256 zero;
+ cJSON *msgjson = 0; struct basilisk_message *msg;
+ HASH_FIND(hh,myinfo->messagetable,key,keylen,msg);
+ if ( msg != 0 && msg->broadcast == 0 )
+ msgjson = basilisk_msgjson(msg,key,keylen);
+ return(msgjson);
+}
+
+int32_t basilisk_msgcmp(struct basilisk_message *msg,int32_t width,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash)
+{
+ uint32_t keychannel,keymsgid,n=0; bits256 keysrc,keydest;
+ basilisk_messagekeyread(msg->key,&keychannel,&keymsgid,&keysrc,&keydest);
+ if ( bits256_nonz(srchash) == 0 || bits256_cmp(srchash,keysrc) == 0 )
+ {
+ if ( bits256_nonz(desthash) == 0 || bits256_cmp(desthash,keydest) == 0 )
+ {
+ while ( width >= 0 && n < 60 )
+ {
+ if ( (keymsgid == 0 || msgid == keymsgid) && (keychannel == 0 || keychannel == channel) )
+ return(0);
+ msgid--;
+ n++;
+ }
+ return(-1);
+ } else return(-2);
+ } else return(-3);
+}
+
+char *basilisk_iterate_MSG(struct supernet_info *myinfo,uint32_t channel,uint32_t msgid,bits256 srchash,bits256 desthash,int32_t origwidth)
+{
+ uint8_t key[BASILISK_KEYSIZE]; int32_t i,keylen,width; cJSON *msgjson,*item,*retjson,*array; bits256 zero; struct basilisk_message *msg,*tmpmsg; uint32_t origmsgid,now = (uint32_t)time(NULL);
+ origmsgid = msgid;
memset(zero.bytes,0,sizeof(zero));
- array = cJSON_CreateArray();
- if ( width > 3600 )
+ if ( (width= origwidth) > 3600 )
width = 3600;
else if ( width < 1 )
width = 1;
+ // char str[65],str2[65]; printf("MSGiterate (%s) -> (%s)\n",bits256_str(str,srchash),bits256_str(str2,desthash));
+ array = cJSON_CreateArray();
+ portable_mutex_lock(&myinfo->messagemutex);
+ //printf("iterate_MSG width.%d channel.%d msgid.%d src.%llx -> %llx\n",origwidth,channel,msgid,(long long)srchash.txid,(long long)desthash.txid);
for (i=0; i 0 )
+ }
+ //keylen = basilisk_messagekey(key,channel,msgid,desthash,srchash);
+ //if ( (item= _basilisk_respond_getmessage(myinfo,key,keylen)) != 0 )
+ // jaddi(array,item);//, printf("gotmsg0.(%s)\n",jprint(item,0));
+ if ( origwidth > 0 )
{
if ( bits256_nonz(srchash) != 0 )
{
keylen = basilisk_messagekey(key,channel,msgid,zero,desthash);
- if ( (item= basilisk_respond_getmessage(myinfo,key,keylen)) != 0 )
+ if ( (item= _basilisk_respond_getmessage(myinfo,key,keylen)) != 0 )
+ {
+ jaddbits256(item,"src",srchash);
+ jaddbits256(item,"dest",desthash);
jaddi(array,item);
+ }
+ //keylen = basilisk_messagekey(key,channel,msgid,desthash,zero);
+ //if ( (item= _basilisk_respond_getmessage(myinfo,key,keylen)) != 0 )
+ // jaddi(array,item);//, printf("gotmsg1.(%s)\n",jprint(item,0));
}
if ( bits256_nonz(desthash) != 0 )
{
keylen = basilisk_messagekey(key,channel,msgid,srchash,zero);
- if ( (item= basilisk_respond_getmessage(myinfo,key,keylen)) != 0 )
+ if ( (item= _basilisk_respond_getmessage(myinfo,key,keylen)) != 0 )
+ {
+ jaddbits256(item,"src",srchash);
+ jaddbits256(item,"dest",desthash);
jaddi(array,item);
+ }
+ //keylen = basilisk_messagekey(key,channel,msgid,zero,srchash);
+ //if ( (item= _basilisk_respond_getmessage(myinfo,key,keylen)) != 0 )
+ // jaddi(array,item);//, printf("gotmsg2.(%s)\n",jprint(item,0));
}
- if ( bits256_nonz(srchash) != 0 || bits256_nonz(desthash) != 0 )
+ if ( bits256_nonz(srchash) != 0 && bits256_nonz(desthash) != 0 )
{
keylen = basilisk_messagekey(key,channel,msgid,zero,zero);
- if ( (item= basilisk_respond_getmessage(myinfo,key,keylen)) != 0 )
+ if ( (item= _basilisk_respond_getmessage(myinfo,key,keylen)) != 0 )
+ {
+ jaddbits256(item,"src",srchash);
+ jaddbits256(item,"dest",desthash);
jaddi(array,item);
+ }
}
}
msgid--;
- iguana_rwnum(1,&key[0],sizeof(uint32_t),&msgid);
}
+ HASH_ITER(hh,myinfo->messagetable,msg,tmpmsg)
+ {
+ if ( bits256_nonz(srchash) == 0 )
+ {
+ if ( basilisk_msgcmp(msg,origwidth,channel,origmsgid,zero,zero) == 0 )
+ {
+ if ( (msgjson= basilisk_msgjson(msg,msg->key,msg->keylen)) != 0 )
+ {
+ jaddbits256(msgjson,"src",srchash);
+ jaddbits256(msgjson,"dest",desthash);
+ jaddi(array,msgjson);
+ }
+ }
+ }
+ if ( now > msg->expiration+60 )
+ {
+ printf("delete expired message.%p QUEUEITEMS.%d\n",msg,QUEUEITEMS);
+ HASH_DELETE(hh,myinfo->messagetable,msg);
+ QUEUEITEMS--;
+ free(msg);
+ }
+ }
+ portable_mutex_unlock(&myinfo->messagemutex);
if ( cJSON_GetArraySize(array) > 0 )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jadd(retjson,"messages",array);
+ //printf("MESSAGES.(%s)\n",jprint(array,0));
return(jprint(retjson,1));
- } else return(clonestr("{\"error\":\"no messages\"}"));
+ }
+ //printf("no matching messages\n");
+ return(clonestr("{\"error\":\"no messages\"}"));
}
-char *basilisk_respond_MSG(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
+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)
{
- int32_t width; uint32_t msgid,channel;
- width = juint(valsobj,"width");
- msgid = juint(valsobj,"msgid");
- channel = juint(valsobj,"channel");
- char str[65]; printf("%s channel.%u msgid.%x datalen.%d width.%d\n",bits256_str(str,hash),juint(valsobj,"channel"),msgid,datalen,width);
- return(basilisk_iterate_MSG(myinfo,channel,msgid,jbits256(valsobj,"sender"),hash,width));
+ struct basilisk_message *msg; bits256 desthash;
+ if ( keylen != BASILISK_KEYSIZE )
+ {
+ printf("basilisk_respond_addmessage keylen.%d != %d\n",keylen,BASILISK_KEYSIZE);
+ return(0);
+ }
+ if ( duration == 0 )
+ duration = BASILISK_MSGDURATION;
+ else if ( duration > INSTANTDEX_LOCKTIME*2 )
+ duration = INSTANTDEX_LOCKTIME*2;
+ portable_mutex_lock(&myinfo->messagemutex);
+ HASH_FIND(hh,myinfo->messagetable,key,keylen,msg);
+ if ( msg != 0 )
+ {
+ if ( msg->datalen != datalen )
+ {
+ //printf("overwrite delete of msg.[%d]\n",msg->datalen);
+ HASH_DELETE(hh,myinfo->messagetable,msg);
+ QUEUEITEMS--;
+ free(msg);
+ msg = 0;
+ }
+ else
+ {
+ if ( memcmp(msg->data,data,datalen) != 0 )
+ {
+ //printf("overwrite update of msg.[%d] <- datalen.%d\n",msg->datalen,datalen);
+ memcpy(msg->data,data,datalen);
+ if ( sendping != 0 )
+ queue_enqueue("basilisk_message",&myinfo->msgQ,&msg->DL);
+ }
+ portable_mutex_unlock(&myinfo->messagemutex);
+ return(clonestr("{\"result\":\"message updated\"}"));
+ }
+ }
+ msg = calloc(1,sizeof(*msg) + datalen + 16);
+ msg->keylen = keylen;
+ memcpy(msg->key,key,keylen);
+ msg->datalen = datalen;
+ memcpy(msg->data,data,datalen);
+ memcpy(desthash.bytes,&key[BASILISK_KEYSIZE - sizeof(desthash)],sizeof(desthash));
+ if ( bits256_nonz(desthash) == 0 )
+ msg->broadcast = 1;
+ msg->duration = duration;
+ msg->expiration = (uint32_t)time(NULL) + duration;
+ HASH_ADD_KEYPTR(hh,myinfo->messagetable,msg->key,msg->keylen,msg);
+ QUEUEITEMS++;
+ portable_mutex_unlock(&myinfo->messagemutex);
+ {
+ bits256 srchash,desthash; uint32_t channel,msgid;
+ basilisk_messagekeyread(key,&channel,&msgid,&srchash,&desthash);
+ //printf("add message keylen.%d [%d] msgid.%x channel.%x\n",msg->keylen,datalen,msgid,channel);
+ }
+ //if ( myinfo->NOTARY.RELAYID >= 0 )
+ // dpow_handler(myinfo,msg);
+ if ( sendping != 0 )
+ queue_enqueue("basilisk_message",&myinfo->msgQ,&msg->DL);
+ return(clonestr("{\"result\":\"message added to hashtable\"}"));
}
-#include "../includes/iguana_apidefs.h"
-#include "../includes/iguana_apideclares.h"
+// respond to incoming OUT, MSG
-HASH_ARRAY_STRING(basilisk,getmessage,hash,vals,hexstr)
+char *basilisk_respond_OUT(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
{
- uint32_t msgid,width,channel;
- if ( (msgid= juint(vals,"msgid")) == 0 )
+ int32_t keylen,duration; uint8_t key[BASILISK_KEYSIZE]; bits256 desthash,senderhash; char *retstr;
+ senderhash = jbits256(valsobj,"srchash");
+ desthash = jbits256(valsobj,"desthash");
+ duration = juint(valsobj,"duration");
+ keylen = basilisk_messagekey(key,juint(valsobj,"channel"),juint(valsobj,"msgid"),senderhash,desthash);
+ if ( bits256_nonz(hash) == 0 )
{
- msgid = (uint32_t)time(NULL);
- jdelete(vals,"msgid");
- jaddnum(vals,"msgid",msgid);
+ if ( duration > BASILISK_MSGDURATION )
+ duration = BASILISK_MSGDURATION;
}
- if ( RELAYID >= 0 )
+ //char str[65]; printf("add message.[%d] %s from.%s\n",datalen,bits256_str(str,hash),remoteaddr);
+ retstr = basilisk_respond_addmessage(myinfo,key,keylen,data,datalen,0,duration);
+ // printf("OUT keylen.%d datalen.%d\n",keylen,datalen);
+ return(retstr);
+}
+
+char *basilisk_respond_MSG(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
+{
+ int32_t width; uint32_t msgid,channel; char *retstr=0;
+ if ( valsobj != 0 )
{
- channel = juint(vals,"channel");
- width = juint(vals,"width");
- return(basilisk_iterate_MSG(myinfo,channel,msgid,hash,myinfo->myaddr.persistent,width));
- } else return(basilisk_standardservice("MSG",myinfo,0,myinfo->myaddr.persistent,vals,hexstr,1));
+ width = juint(valsobj,"width");
+ msgid = juint(valsobj,"msgid");
+ channel = juint(valsobj,"channel");
+ //char str[65],str2[65]; printf("%s -> %s channel.%u msgid.%x width.%d from.%s\n",bits256_str(str,jbits256(valsobj,"sender")),bits256_str(str2,jbits256(valsobj,"desthash")),juint(valsobj,"channel"),msgid,width,remoteaddr);
+ retstr = basilisk_iterate_MSG(myinfo,channel,msgid,jbits256(valsobj,"srchash"),jbits256(valsobj,"desthash"),width);
+ }
+ return(retstr);
}
-HASH_ARRAY_STRING(basilisk,sendmessage,hash,vals,hexstr)
+cJSON *dpow_getmessage(struct supernet_info *myinfo,char *jsonstr)
{
- int32_t keylen,datalen; uint8_t key[BASILISK_KEYSIZE],space[16384],*data,*ptr = 0; char *retstr=0;
- if ( RELAYID >= 0 )
+ cJSON *valsobj,*retjson = 0; char *retstr;
+ if ( (valsobj= cJSON_Parse(jsonstr)) != 0 )
{
- keylen = basilisk_messagekey(key,juint(vals,"channel"),juint(vals,"msgid"),jbits256(vals,"sender"),hash);
- if ( (data= get_dataptr(BASILISK_HDROFFSET,&ptr,&datalen,space,sizeof(space),hexstr)) != 0 )
- retstr = basilisk_respond_addmessage(myinfo,key,keylen,data,datalen,0,juint(vals,"duration"));
- if ( ptr != 0 )
- free(ptr);
+ retstr = basilisk_iterate_MSG(myinfo,juint(valsobj,"channel"),juint(valsobj,"msgid"),jbits256(valsobj,"srchash"),jbits256(valsobj,"desthash"),juint(valsobj,"width"));
+ retjson = cJSON_Parse(retstr);
+ free(retstr);
+ }
+ return(retjson);
+}
+
+cJSON *dpow_addmessage(struct supernet_info *myinfo,char *jsonstr)
+{
+ cJSON *vals,*retjson=0; char *retstr=0,*datastr; int32_t datalen,keylen; uint8_t *data=0,key[BASILISK_KEYSIZE];
+ if ( (vals= cJSON_Parse(jsonstr)) != 0 )
+ {
+ keylen = basilisk_messagekey(key,juint(vals,"channel"),juint(vals,"msgid"),jbits256(vals,"srchash"),jbits256(vals,"desthash"));
+ if ( (datastr= jstr(vals,"data")) != 0 )
+ {
+ datalen = (int32_t)strlen(datastr) >> 1;
+ data = malloc(datalen);
+ decode_hex(data,datalen,datastr);
+ if ( (retstr= basilisk_respond_addmessage(myinfo,key,keylen,data,datalen,0,juint(vals,"duration"))) != 0 )
+ retjson = cJSON_Parse(retstr);
+ }
if ( retstr != 0 )
free(retstr);
+ if ( data != 0 )
+ free(data);
}
- if ( vals != 0 && juint(vals,"fanout") == 0 )
- jaddnum(vals,"fanout",(int32_t)sqrt(NUMRELAYS)+2);
- return(basilisk_standardservice("OUT",myinfo,0,hash,vals,hexstr,0));
+ if ( retjson == 0 )
+ retjson = cJSON_Parse("{\"error\":\"couldnt add message\"}");
+ return(retjson);
}
-#include "../includes/iguana_apiundefs.h"
-int32_t basilisk_channelsend(struct supernet_info *myinfo,bits256 hash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t duration)
+int32_t basilisk_channelsend(struct supernet_info *myinfo,bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t duration)
{
char *retstr,*hexstr,strbuf[4096],*ptr = 0; int32_t retval = -1; cJSON *valsobj;
if ( (hexstr= basilisk_addhexstr(&ptr,0,strbuf,sizeof(strbuf),data,datalen)) != 0 )
@@ -205,12 +328,14 @@ int32_t basilisk_channelsend(struct supernet_info *myinfo,bits256 hash,uint32_t
jaddnum(valsobj,"channel",channel);
if ( msgid == 0 )
msgid = (uint32_t)time(NULL);
- jaddnum(valsobj,"fanout",(int32_t)sqrt(NUMRELAYS)+2);
+ jaddnum(valsobj,"fanout",1);//MAX(8,(int32_t)sqrt(myinfo->NOTARY.NUMRELAYS)+2));
jaddnum(valsobj,"msgid",msgid);
jaddnum(valsobj,"duration",duration);
- jaddbits256(valsobj,"sender",myinfo->myaddr.persistent);
- char str[65]; printf("sendmessage.[%d] channel.%u msgid.%x -> %s numrelays.%d:%d\n",datalen,channel,msgid,bits256_str(str,hash),NUMRELAYS,juint(valsobj,"fanout"));
- if ( (retstr= basilisk_sendmessage(myinfo,0,0,0,hash,valsobj,hexstr)) != 0 )
+ jaddnum(valsobj,"timeout",1000);
+ jaddbits256(valsobj,"srchash",srchash);
+ jaddbits256(valsobj,"desthash",desthash);
+ //char str[65]; printf("sendmessage.[%d] channel.%u msgid.%x -> %s numrelays.%d\n",datalen,channel,msgid,bits256_str(str,desthash),myinfo->NOTARY.NUMRELAYS);
+ if ( (retstr= basilisk_sendmessage(myinfo,0,0,0,desthash,valsobj,hexstr)) != 0 )
free(retstr);
free_json(valsobj);
if ( ptr != 0 )
@@ -220,26 +345,31 @@ int32_t basilisk_channelsend(struct supernet_info *myinfo,bits256 hash,uint32_t
return(retval);
}
-int32_t basilisk_message_returned(uint8_t *data,int32_t maxlen,cJSON *item)
+int32_t basilisk_message_returned(uint8_t *key,uint8_t *data,int32_t maxlen,cJSON *json)
{
- char *hexstr=0; cJSON *msgobj; int32_t datalen=0,retval = -1;
- if ( (msgobj= jobj(item,"message")) != 0 )
+ char *keystr=0,*hexstr=0; int32_t i,n,datalen=0,retval = -1; cJSON *item,*msgobj;
+ if ( (msgobj= jarray(&n,json,"messages")) != 0 )
{
- if ( (hexstr= jstr(msgobj,"data")) != 0 && (datalen= is_hexstr(hexstr,0)) > 0 )
+ for (i=0; i>= 1;
- if ( datalen < maxlen )
+ item = jitem(msgobj,i);
+ if ( (keystr= jstr(item,"key")) != 0 && is_hexstr(keystr,0) == BASILISK_KEYSIZE*2 && (hexstr= jstr(item,"data")) != 0 && (datalen= is_hexstr(hexstr,0)) > 0 )
{
- decode_hex(data,datalen,hexstr);
- //printf("decoded hexstr.[%d]\n",datalen);
- retval = datalen;
- } else printf("datalen.%d < maxlen.%d\n",datalen,maxlen);
- } else printf("no hexstr.%p or datalen.%d\n",hexstr,datalen);
- } //else printf("no msgobj\n");
+ decode_hex(key,BASILISK_KEYSIZE,keystr);
+ datalen >>= 1;
+ if ( datalen <= maxlen )
+ {
+ decode_hex(data,datalen,hexstr);
+ //printf("decoded hexstr.[%d]\n",datalen);
+ retval = datalen;
+ } else printf("datalen.%d >= maxlen.%d\n",datalen,maxlen);
+ }
+ }
+ } //else printf("no hexstr.%p or datalen.%d (%s)\n",hexstr,datalen,jprint(json,0));
return(retval);
}
-cJSON *basilisk_channelget(struct supernet_info *myinfo,bits256 hash,uint32_t channel,uint32_t msgid,int32_t width)
+cJSON *basilisk_channelget(struct supernet_info *myinfo,bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgid,int32_t width)
{
char *retstr; cJSON *valsobj,*retarray=0,*item;
valsobj = cJSON_CreateObject();
@@ -248,10 +378,21 @@ cJSON *basilisk_channelget(struct supernet_info *myinfo,bits256 hash,uint32_t ch
msgid = (uint32_t)time(NULL);
jaddnum(valsobj,"msgid",msgid);
jaddnum(valsobj,"width",width);
- jaddnum(valsobj,"fanout",1);
- if ( (retstr= basilisk_getmessage(myinfo,0,0,0,hash,valsobj,0)) != 0 )
+ jaddnum(valsobj,"timeout",BASILISK_TIMEOUT);
+ jaddnum(valsobj,"fanout",1);//MAX(8,(int32_t)sqrt(myinfo->NOTARY.NUMRELAYS)+1));
+ jaddnum(valsobj,"numrequired",1);
+ jaddbits256(valsobj,"srchash",srchash);
+ jaddbits256(valsobj,"desthash",desthash);
+ if ( myinfo->IAMNOTARY != 0 )
+ retstr = basilisk_getmessage(myinfo,0,0,0,desthash,valsobj,0);
+ else
+ {
+ //char str[65],str2[65];
+ retstr = _dex_getmessage(myinfo,jprint(valsobj,0));
+ //printf("channel.%u msgid.%u gotmessage.(%d) %s %s %s\n",channel,msgid,(int32_t)strlen(retstr),strlen(retstr) < 100 ? retstr : "(too long)",bits256_str(str,srchash),bits256_str(str2,desthash));
+ }
+ if ( retstr != 0 )
{
- printf("channel.%u msgid.%u gotmessage.(%s)\n",channel,msgid,retstr);
if ( (retarray= cJSON_Parse(retstr)) != 0 )
{
if ( is_cJSON_Array(retarray) == 0 )
@@ -269,22 +410,153 @@ cJSON *basilisk_channelget(struct supernet_info *myinfo,bits256 hash,uint32_t ch
int32_t basilisk_process_retarray(struct supernet_info *myinfo,void *ptr,int32_t (*process_func)(struct supernet_info *myinfo,void *ptr,int32_t (*internal_func)(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen),uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t expiration,uint32_t duration),uint8_t *data,int32_t maxlen,uint32_t channel,uint32_t msgid,cJSON *retarray,int32_t (*internal_func)(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen))
{
- cJSON *item; uint32_t duration,expiration; int32_t i,n,datalen,errs = 0;
+ cJSON *item; uint32_t duration,expiration; char *retstr; uint8_t key[BASILISK_KEYSIZE]; int32_t i,n,datalen,havedata = 0,errs = 0;
if ( (n= cJSON_GetArraySize(retarray)) > 0 )
{
for (i=0; i 0 )
+ if ( jobj(item,"error") != 0 )
+ continue;
+ //printf("(%s).%d ",jprint(item,0),i);
+ if ( (datalen= basilisk_message_returned(key,data,maxlen,item)) > 0 )
{
duration = juint(item,"duration");
expiration = juint(item,"expiration");
- if ( (*process_func)(myinfo,ptr,internal_func,channel,msgid,data,datalen,expiration,duration) < 0 )
- errs++;
+ if ( (retstr= basilisk_respond_addmessage(myinfo,key,BASILISK_KEYSIZE,data,datalen,0,duration)) != 0 )
+ {
+ if ( (*process_func)(myinfo,ptr,internal_func,channel,msgid,data,datalen,expiration,duration) < 0 )
+ errs++;
+ else havedata++;
+ free(retstr);
+ } // else printf("duplicate.%d skipped\n",datalen);
}
}
+ //printf("n.%d maxlen.%d\n",n,maxlen);
}
- if ( errs > 0 )
+ if ( havedata == 0 )
+ return(-1);
+ else if ( errs > 0 )
return(-errs);
- else return(n);
+ else return(havedata);
+}
+
+uint32_t basilisk_majority32(int32_t *datalenp,uint32_t rawcrcs[64],int32_t datalens[64],int32_t numcrcs)
+{
+ int32_t tally[64],candlens[64],i,j,mintally,numcandidates = 0; uint32_t candidates[64];
+ *datalenp = 0;
+ mintally = (numcrcs >> 1) + 1;
+ memset(tally,0,sizeof(tally));
+ memset(candlens,0,sizeof(candlens));
+ memset(candidates,0,sizeof(candidates));
+ if ( numcrcs > 0 )
+ {
+ for (i=0; i numcandidates.%d\n",i,numcandidates);
+ if ( numcandidates > 0 )
+ {
+ for (j=0; j= mintally )
+ {
+ *datalenp = candlens[j];
+ //printf("tally[%d] %d >= mintally.%d numcrcs.%d crc %08x datalen.%d\n",j,tally[j],mintally,numcrcs,candidates[j],*datalenp);
+ return(candidates[j]);
+ }
+ }
+ }
+ return(0);
+}
+
+uint32_t basilisk_crcrecv(struct supernet_info *myinfo,int32_t width,uint8_t *verifybuf,int32_t maxlen,int32_t *datalenp,bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgbits)
+{
+ cJSON *retarray,*obj,*item,*msgarray; char *hexstr,*keystr,*retstr; uint32_t rawcrcs[64],crc=0; int32_t numcrcs=0,i,j,m,n,datalen,datalens[64]; uint8_t key[BASILISK_KEYSIZE];
+ *datalenp = 0;
+ memset(rawcrcs,0,sizeof(rawcrcs));
+ memset(datalens,0,sizeof(datalens));
+ if ( (retarray= basilisk_channelget(myinfo,srchash,desthash,channel,msgbits,width)) != 0 )
+ {
+ //printf("retarray.(%s)\n",jprint(retarray,0));
+ if ( (n= cJSON_GetArraySize(retarray)) > 0 )
+ {
+ for (i=0; i 0 )
+ {
+ decode_hex(key,BASILISK_KEYSIZE,keystr);
+ datalen >>= 1;
+ if ( datalen < maxlen )
+ {
+ decode_hex(verifybuf,datalen,hexstr);
+ if ( (retstr= basilisk_respond_addmessage(myinfo,key,BASILISK_KEYSIZE,verifybuf,datalen,juint(item,"expiration"),juint(item,"duration"))) != 0 )
+ {
+ if ( numcrcs < sizeof(rawcrcs)/sizeof(*rawcrcs) )
+ {
+ rawcrcs[numcrcs] = calc_crc32(0,verifybuf,datalen);
+ datalens[numcrcs] = datalen;
+ numcrcs++;
+ }
+ free(retstr);
+ }
+ } else printf("datalen.%d >= maxlen.%d\n",datalen,maxlen);
+ } else printf("not keystr.%p or no data.%p or bad datalen.%d\n",keystr,hexstr,datalen);
+ }
+ }
+ }
+ //printf("n.%d maxlen.%d\n",n,maxlen);
+ }
+ free_json(retarray);
+ if ( (crc= basilisk_majority32(datalenp,rawcrcs,datalens,numcrcs)) != 0 )
+ {
+ //printf("have majority crc.%08x\n",crc);
+ }
+ //else printf("no majority from rawcrcs.%d\n",numcrcs);
+ }
+ return(crc);
+}
+
+uint32_t basilisk_crcsend(struct supernet_info *myinfo,int32_t width,uint8_t *verifybuf,int32_t maxlen,bits256 srchash,bits256 desthash,uint32_t channel,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t crcs[2])
+{
+ uint32_t crc; int32_t recvlen=0;
+ if ( crcs != 0 )
+ {
+ crc = calc_crc32(0,data,datalen);
+ if ( crcs[0] != crc )
+ crcs[0] = crc, crcs[1] = 0;
+ else
+ {
+ if ( crcs[1] == 0 )
+ crcs[1] = basilisk_crcrecv(myinfo,width,verifybuf,maxlen,&recvlen,srchash,desthash,channel,msgbits);
+ if ( crcs[0] == crcs[1] && datalen == recvlen )
+ return(crcs[0]);
+ }
+ }
+ return(0);
}
diff --git a/basilisk/basilisk_bitcoin.c b/basilisk/basilisk_bitcoin.c
index 159e972c1..942539260 100755
--- a/basilisk/basilisk_bitcoin.c
+++ b/basilisk/basilisk_bitcoin.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * Copyright © 2014-2016 The SuperNET Developers. *
+ * Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -22,36 +22,6 @@
};*/
#ifdef bitcoincancalculatebalances
-int64_t bitcoin_value(struct iguana_info *coin,bits256 txid,int16_t vout,char *coinaddr)
-{
- char params[512],str[65]; char *curlstr; cJSON *txobj,*vouts,*item,*sobj,*addrs; int32_t j,m,n; int64_t value = 0;
- sprintf(params,"[\"%s\", 1]",bits256_str(str,txid));
- if ( (curlstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getrawtransaction",params)) != 0 )
- {
- if ( (txobj= cJSON_Parse(curlstr)) != 0 )
- {
- if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n )
- {
- item = jitem(vouts,vout);
- if ( (sobj= jobj(item,"scriptPubKey")) != 0 && (addrs= jarray(&m,sobj,"addresses")) != 0 )
- {
- for (j=0; jsymbol,coin->chain->serverport,coin->chain->userpass,"getrawtransaction",params)) != 0 )
+ {
+ if ( (txobj= cJSON_Parse(curlstr)) != 0 )
+ {
+ if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n )
+ {
+ item = jitem(vouts,vout);
+ if ( (sobj= jobj(item,"scriptPubKey")) != 0 && (addrs= jarray(&m,sobj,"addresses")) != 0 )
+ {
+ for (j=0; jVALIDATENODE != 0 || coin->FULLNODE != 0 )
+ if ( coin->VALIDATENODE > 0 || coin->FULLNODE > 0 )
return(1);
//else if ( coin->chain->serverport[0] != 0 )
// return(1);
@@ -299,7 +299,7 @@ int32_t basilisk_bitcoinavail(struct iguana_info *coin)
void *basilisk_bitcoinbalances(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *vals)
{
- int64_t balance,total = 0; int32_t i,n,hist; cJSON *spends,*unspents,*retjson,*item,*addresses,*array = cJSON_CreateArray();
+ int64_t balance,total = 0; int32_t i,j,n,hist; char *str; cJSON *spends,*unspents,*retjson,*item,*addresses,*array = cJSON_CreateArray();
spends = unspents = 0;
if ( (hist= juint(vals,"history")) != 0 )
{
@@ -313,13 +313,20 @@ void *basilisk_bitcoinbalances(struct basilisk_item *Lptr,struct supernet_info *
{
for (i=0; iRTheight > 0 )
- balance = iguana_addressreceived(myinfo,coin,vals,remoteaddr,0,0,unspents,spends,jstri(addresses,i),juint(vals,"minconf"),juint(vals,"firstheight"));
- //else balance = 0;
- item = cJSON_CreateObject();
- jaddnum(item,jstri(addresses,i),dstr(balance));
- jaddi(array,item);
- total += balance;
+ if ( (str= jstri(addresses,i)) != 0 )
+ {
+ for (j=0; jipaddr);
jaddnum(retjson,"total",dstr(total));
+ jaddnum(retjson,"balance",dstr(total));
jadd(retjson,"addresses",array);
if ( unspents != 0 )
jadd(retjson,"unspents",unspents);
@@ -335,6 +343,7 @@ void *basilisk_bitcoinbalances(struct basilisk_item *Lptr,struct supernet_info *
jaddnum(retjson,"RTheight",coin->RTheight);
jaddnum(retjson,"longest",coin->longestchain);
jaddnum(retjson,"lag",coin->longestchain- coin->RTheight);
+//printf("BAL.(%s)\n",jprint(retjson,0));
Lptr->retstr = jprint(retjson,1);
return(Lptr);
}
@@ -345,6 +354,7 @@ char *basilisk_valuestr(struct iguana_info *coin,char *coinaddr,uint64_t value,i
jaddstr(retjson,"result","success");
jaddstr(retjson,"address",coinaddr);
jadd64bits(retjson,"satoshis",value);
+ jaddnum(retjson,"amount",dstr(value));
jaddnum(retjson,"value",dstr(value));
jaddnum(retjson,"height",height);
jaddnum(retjson,"numconfirms",coin->blocks.hwmchain.height - height + 1);
@@ -374,16 +384,18 @@ double basilisk_bitcoin_valuemetric(struct supernet_info *myinfo,struct basilisk
void *basilisk_bitcoinvalue(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj)
{
- int32_t i,height,vout,numsent; struct basilisk_item *ptr; char coinaddr[64],str[64]; struct basilisk_value *v; uint64_t value = 0; bits256 txid;
- if ( RELAYID >= 0 )
+ int32_t i,j,height,vout,numsent; cJSON *retjson; struct basilisk_item *ptr; char coinaddr[64],str[65]; struct basilisk_value *v; uint64_t value = 0; bits256 txid; struct iguana_outpoint outpt;
+ if ( valsobj == 0 )
+ return(clonestr("{\"error\":\"null valsobj\"}"));
+ if ( myinfo->IAMNOTARY != 0 && myinfo->NOTARY.RELAYID >= 0 )
return(0);
txid = jbits256(valsobj,"txid");
vout = jint(valsobj,"vout");
if ( coin != 0 && basilisk_bitcoinavail(coin) != 0 )
{
- if ( (coin->VALIDATENODE != 0 || coin->FULLNODE != 0) )//&& coinaddr != 0 && coinaddr[0] != 0 )
+ if ( (coin->VALIDATENODE > 0 || coin->FULLNODE > 0) )//&& coinaddr != 0 && coinaddr[0] != 0 )
{
- if ( iguana_RTunspentindfind(myinfo,coin,coinaddr,0,0,&value,&height,txid,vout,coin->bundlescount,0) > 0 )
+ if ( iguana_RTunspentindfind(myinfo,coin,&outpt,coinaddr,0,0,&value,&height,txid,vout,coin->bundlescount,0) == 0 )
{
//printf("bitcoinvalue found iguana\n");
Lptr->retstr = basilisk_valuestr(coin,coinaddr,value,height,txid,vout);
@@ -401,18 +413,83 @@ void *basilisk_bitcoinvalue(struct basilisk_item *Lptr,struct supernet_info *myi
if ( v->vout == vout && bits256_cmp(txid,v->txid) == 0 && strcmp(v->coinaddr,coinaddr) == 0 )
{
printf("bitcoinvalue local ht.%d %s %.8f\n",v->height,v->coinaddr,dstr(v->value));
- ptr = basilisk_issueremote(myinfo,0,&numsent,"VAL",coin->symbol,1,valsobj,juint(valsobj,"fanout"),juint(valsobj,"minresults"),basilisktag,timeoutmillis,0,basilisk_valuestr(coin,v->coinaddr,v->value,v->height,txid,vout),0,0,BASILISK_DEFAULTDIFF); // this completes immediate
+ ptr = basilisk_issueremote(myinfo,0,&numsent,"VAL",coin->symbol,1,valsobj,juint(valsobj,"fanout"),juint(valsobj,"numrequired"),basilisktag,timeoutmillis,0,basilisk_valuestr(coin,v->coinaddr,v->value,v->height,txid,vout),0,0,BASILISK_DEFAULTDIFF); // this completes immediate
//queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
+ if ( ptr->numresults > 0 )
+ {
+ retjson = cJSON_CreateArray();
+ for (j=0; jnumresults; j++)
+ jaddi(retjson,ptr->results[j]), ptr->results[j] = 0;
+ ptr->retstr = jprint(retjson,1);
+ //printf("numresults.%d (%p)\n",ptr->numresults,ptr);
+ }
return(ptr);
}
}
}
printf("bitcoinvalue issue remote tag.%u\n",basilisktag);
- ptr = basilisk_issueremote(myinfo,0,&numsent,"VAL",coin->symbol,1,valsobj,juint(valsobj,"fanout"),juint(valsobj,"minresults"),basilisktag,timeoutmillis,0,0,0,0,BASILISK_DEFAULTDIFF);
+ ptr = basilisk_issueremote(myinfo,0,&numsent,"VAL",coin->symbol,1,valsobj,juint(valsobj,"fanout"),juint(valsobj,"numrequired"),basilisktag,timeoutmillis,0,0,0,0,BASILISK_DEFAULTDIFF);
+ if ( ptr->numresults > 0 )
+ {
+ retjson = cJSON_CreateArray();
+ for (j=0; jnumresults; j++)
+ jaddi(retjson,ptr->results[j]), ptr->results[j] = 0;
+ ptr->retstr = jprint(retjson,1);
+ //printf("numresults.%d (%p)\n",ptr->numresults,ptr);
+ }
//queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
return(ptr);
}
+void *basilisk_getinfo(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj)
+{
+ struct basilisk_item *ptr; cJSON *infojson,*retjson; int32_t j,numsent,fanout,numrequired;
+ if ( valsobj == 0 )
+ return(clonestr("{\"error\":\"null valsobj\"}"));
+ if ( (myinfo->IAMNOTARY != 0 || myinfo->NOTARY.RELAYID >= 0) && strcmp(coin->symbol,"RELAY") != 0 )
+ return(0);
+ if ( coin->VALIDATENODE > 0 || coin->FULLNODE > 0 || coin->notarychain >= 0 )
+ {
+ infojson = iguana_getinfo(myinfo,coin);
+ Lptr->retstr = jprint(infojson,1);
+ return(Lptr);
+ }
+ if ( (fanout= juint(valsobj,"fanout")) < 8 )
+ fanout = 8;
+ if ( (numrequired= juint(valsobj,"numrequired")) < fanout )
+ {
+ jaddnum(valsobj,"numrequired",fanout);
+ numrequired = 1;
+ }
+ ptr = basilisk_issueremote(myinfo,0,&numsent,"INF",coin->symbol,1,valsobj,fanout,numrequired,basilisktag,timeoutmillis,0,0,0,0,BASILISK_DEFAULTDIFF);
+ if ( ptr->numresults > 0 )
+ {
+ retjson = cJSON_CreateArray();
+ for (j=0; jnumresults; j++)
+ jaddi(retjson,ptr->results[j]), ptr->results[j] = 0;
+ ptr->retstr = jprint(retjson,1);
+ //printf("numresults.%d (%p)\n",ptr->numresults,ptr);
+ }
+ return(ptr);
+}
+
+int64_t iguana_getestimatedfee(struct supernet_info *myinfo,struct iguana_info *coin)
+{
+ char *retstr; cJSON *retjson; double x; int64_t txfeeperbyte = 200;
+ if ( (retstr= _dex_getinfo(myinfo,coin->symbol)) != 0 )
+ {
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( (x= jdouble(retjson,"estimatefee")) > SMALLVAL )
+ txfeeperbyte = 1 + (x * SATOSHIDEN) / 1024;
+ printf("SET txfeeperbyte %lld (%s)\n",(long long)txfeeperbyte,retstr);
+ free(retjson);
+ }
+ free(retstr);
+ }
+ return(txfeeperbyte);
+}
+
int32_t basilisk_voutvin_validate(struct iguana_info *coin,char *rawtx,uint64_t inputsum,uint64_t amount,uint64_t txfee)
{
//static int counter;
@@ -483,19 +560,219 @@ int32_t basilisk_vins_validate(struct supernet_info *myinfo,struct iguana_info *
return(retval);
}
-char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj)
+int64_t iguana_esttxfee(struct supernet_info *myinfo,struct iguana_info *coin,char *rawtx,char *signedtx,int32_t numvins)
+{
+ int64_t txfee = 0;
+ if ( coin->estimatedfee == 0 )
+ coin->estimatedfee = iguana_getestimatedfee(myinfo,coin);
+ if ( signedtx != 0 )
+ {
+ txfee = coin->estimatedfee * (strlen(signedtx)/2 + numvins);
+ free(signedtx);
+ }
+ else if ( rawtx != 0 )
+ {
+ txfee = coin->estimatedfee * (strlen(rawtx)/2 + numvins * 110);
+ free(rawtx);
+ }
+ return(txfee);
+}
+
+char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *pubkey33,uint64_t satoshis,int32_t duplicates,int32_t *completedp,bits256 *signedtxidp,int32_t sendflag,cJSON *addresses)
+{
+ uint8_t script[35]; int64_t txfee; int32_t i,spendlen; cJSON *txobj=0,*vins=0; char *rawtx=0,*signedtx=0,changeaddr[64];
+ *completedp = 0;
+ if ( signedtxidp != 0 )
+ memset(signedtxidp,0,sizeof(*signedtxidp));
+ bitcoin_address(changeaddr,coin->chain->pubtype,myinfo->persistent_pubkey33,33);
+ txfee = (coin->txfee + duplicates*coin->txfee*2);
+ if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,0,1,0)) != 0 )
+ {
+ if ( duplicates <= 0 )
+ duplicates = 1;
+ spendlen = bitcoin_pubkeyspend(script,0,pubkey33);
+ for (i=0; ichain->symbol,"BTC") == 0 && cJSON_GetArraySize(vins) > duplicates/2 )
+ {
+ free(rawtx);
+ rawtx = 0;
+ fprintf(stderr,"No point to recycle utxo when trying to create utxo duplicates, numvins.%d vs duplicates.%d\n",cJSON_GetArraySize(vins),duplicates);
+ free_json(vins);
+ return(rawtx);
+ }
+ printf("%s splitfunds tx.(%s) vins.(%s)\n",coin->symbol,rawtx,jprint(vins,0));
+ if ( signedtxidp != 0 )
+ {
+ if ( (signedtx= iguana_signrawtx(myinfo,coin,0,signedtxidp,completedp,vins,rawtx,0,0)) != 0 )
+ {
+ if ( *completedp != 0 )
+ {
+ printf("splitfunds signedtx.(%s)\n",signedtx);
+ if ( sendflag != 0 )
+ iguana_sendrawtransaction(myinfo,coin,signedtx);
+ free(rawtx);
+ rawtx = signedtx, signedtx = 0;
+ }
+ } else printf("error signing raw %s utxoduplicates tx\n",coin->symbol);
+ }
+ }
+ if ( vins != 0 )
+ free_json(vins);
+ if ( txobj != 0 )
+ free_json(txobj);
+ return(rawtx);
+}
+
+int64_t iguana_verifytimelock(struct supernet_info *myinfo,struct iguana_info *coin,uint32_t timelocked,char *destaddr,bits256 txid,int32_t vout)
+{
+ uint8_t script[35],script2[35],p2shscript[128],rmd160[20],addrtype; char *retstr,*spendscriptstr; int32_t p2shlen,spendlen; cJSON *sobj,*txout=0; int64_t value = 0;
+ bitcoin_addr2rmd160(&addrtype,rmd160,destaddr);
+ if ( addrtype != coin->chain->pubtype )
+ return(-1);
+ p2shlen = bitcoin_timelockspend(p2shscript,0,rmd160,timelocked);
+ calc_rmd160(0,rmd160,p2shscript,p2shlen);
+ spendlen = bitcoin_p2shspend(script,0,rmd160);
+ if ( coin->FULLNODE != 0 )
+ txout = dpow_gettxout(myinfo,coin,txid,vout);
+ else if ( (retstr= _dex_gettxout(myinfo,coin->symbol,txid,vout)) != 0 )
+ {
+ txout = cJSON_Parse(retstr);
+ free(retstr);
+ }
+ if ( txout != 0 )
+ {
+ if ( (sobj= jobj(txout,"scriptPubKey")) != 0 && (spendscriptstr= jstr(sobj,"hex")) == 0 )
+ {
+ if ( strlen(spendscriptstr) == spendlen*2 )
+ {
+ decode_hex(script2,spendlen,spendscriptstr);
+ if ( memcmp(script,script2,spendlen) != 0 )
+ return(-2);
+ value = SATOSHIDEN * jdouble(txout,"value");
+ } else return(-4);
+ }
+ free_json(txout);
+ return(value);
+ } return(-2);
+}
+
+char *iguana_utxorawtx(struct supernet_info *myinfo,struct iguana_info *coin,int32_t timelock,char *destaddr,char *changeaddr,int64_t *satoshis,int32_t numoutputs,uint64_t txfee,int32_t *completedp,int32_t sendflag,cJSON *utxos,cJSON *privkeys)
+{
+ uint8_t script[35],p2shscript[128],rmd160[20],addrtype; bits256 txid; int32_t i,p2shlen,iter,spendlen; cJSON *retjson,*txcopy,*txobj=0,*vins=0; char *rawtx=0,*signedtx=0; uint32_t timelocked = 0;
+ *completedp = 0;
+ if ( iguana_addressvalidate(coin,&addrtype,destaddr) < 0 || iguana_addressvalidate(coin,&addrtype,changeaddr) < 0 )
+ return(clonestr("{\"error\":\"invalid coin address\"}"));
+ bitcoin_addr2rmd160(&addrtype,rmd160,changeaddr);
+ if ( addrtype != coin->chain->pubtype )
+ return(clonestr("{\"error\":\"invalid changeaddr type\"}"));
+ bitcoin_addr2rmd160(&addrtype,rmd160,destaddr);
+ if ( addrtype != coin->chain->pubtype )
+ return(clonestr("{\"error\":\"invalid dest address type\"}"));
+ if ( txfee == 0 && strcmp(coin->symbol,"BTC") != 0 && (txfee= coin->txfee) == 0 )
+ txfee = coin->chain->txfee;
+ retjson = cJSON_CreateObject();
+ if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,0,1,0)) != 0 )
+ {
+ if ( timelock == 0 )
+ spendlen = bitcoin_standardspend(script,0,rmd160);
+ else
+ {
+ timelocked = (uint32_t)(time(NULL)+timelock);
+ if ( (timelocked % 3600) != 0 )
+ timelocked += (3600 - (timelocked % 3600));
+ p2shlen = bitcoin_timelockspend(p2shscript,0,rmd160,timelocked);
+ calc_rmd160(0,rmd160,p2shscript,p2shlen);
+ spendlen = bitcoin_p2shspend(script,0,rmd160);
+ printf("timelock.%d spend timelocked %u\n",timelock,timelocked);
+ }
+ for (i=0; i 0 )
+ bitcoin_txoutput(txobj,script,spendlen,satoshis[i]);
+ for (iter=0; iter<2; iter++)
+ {
+ txcopy = jduplicate(txobj);
+ if ( (rawtx= iguana_calcutxorawtx(myinfo,coin,&vins,txobj,satoshis,numoutputs,changeaddr,txfee,utxos,"",0,0)) != 0 )
+ {
+ if ( iter == 1 || txfee != 0 )
+ jaddstr(retjson,"rawtx",rawtx);
+ if ( (signedtx= iguana_signrawtx(myinfo,coin,0,&txid,completedp,vins,rawtx,privkeys,0)) != 0 )
+ {
+ if ( (iter == 1 || txfee != 0) && *completedp != 0 )
+ {
+ jaddbits256(retjson,"txid",txid);
+ jaddstr(retjson,"signedtx",signedtx);
+ if ( sendflag != 0 )
+ {
+ txid = iguana_sendrawtransaction(myinfo,coin,signedtx);
+ jaddbits256(retjson,"sent",txid);
+ } else printf("dont send signedtx.(%s)\n",signedtx);
+ }
+ } else printf("error signing raw utxorawtx tx\n");
+ } else printf("null rawtx from calcutxorawtx\n");
+ if ( txfee != 0 )
+ {
+ free_json(txcopy);
+ break;
+ }
+ else // must be BTC and txfee == 0
+ {
+ txfee = iguana_esttxfee(myinfo,coin,rawtx,signedtx,cJSON_GetArraySize(vins));
+ free_json(vins);
+ rawtx = signedtx = 0;
+ vins = 0;
+ *completedp = 0;
+ txobj = txcopy;
+ }
+ }
+ }
+ if ( timelock != 0 )
+ {
+ jaddnum(retjson,"timelock",timelock);
+ jaddnum(retjson,"timelocked",timelocked);
+ }
+ jaddstr(retjson,"result","success");
+ if ( *completedp != 0 )
+ jadd(retjson,"completed",jtrue());
+ else jadd(retjson,"completed",jfalse());
+ if ( vins != 0 )
+ free_json(vins);
+ if ( txobj != 0 )
+ free_json(txobj);
+ if ( rawtx != 0 )
+ {
+ jaddstr(retjson,"rawtx",rawtx);
+ free(rawtx);
+ }
+ if ( signedtx != 0 )
+ {
+ jaddstr(retjson,"signedtx",signedtx);
+ free(signedtx);
+ }
+ return(jprint(retjson,1));
+}
+
+char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj,struct vin_info *V)
{
uint8_t buf[4096]; int32_t oplen,offset,minconf,spendlen; cJSON *vins,*addresses,*txobj = 0; uint32_t locktime; char *opreturn,*spendscriptstr,*changeaddr,*rawtx = 0; int64_t amount,txfee,burnamount;
- if ( RELAYID >= 0 )
- return(clonestr("{\"error\":\"special relays only do OUT and MSG\"}"));
+ if ( valsobj == 0 )
+ return(clonestr("{\"error\":\"null valsobj\"}"));
+ //if ( myinfo->IAMNOTARY != 0 || myinfo->NOTARY.RELAYID >= 0 )
+ // return(clonestr("{\"error\":\"special relays only do OUT and MSG\"}"));
vins = 0;
changeaddr = jstr(valsobj,"changeaddr");
if ( (amount= j64bits(valsobj,"satoshis")) == 0 )
amount = jdouble(valsobj,"value") * SATOSHIDEN;
if ( (txfee= j64bits(valsobj,"txfee")) == 0 )
- txfee = coin->chain->txfee;
- if ( txfee == 0 )
- txfee = 10000;
+ {
+ //if ( strcmp(coin->symbol,"BTC") != 0 )
+ {
+ txfee = coin->chain->txfee;
+ if ( txfee < 50000 )
+ txfee = 50000;
+ }
+ }
spendscriptstr = jstr(valsobj,"spendscript");
minconf = juint(valsobj,"minconf");
locktime = jint(valsobj,"locktime");
@@ -504,13 +781,13 @@ char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coi
addresses = iguana_getaddressesbyaccount(myinfo,coin,"*");
jadd(valsobj,"addresses",addresses);
}
- //printf("use addresses.(%s)\n",jprint(addresses,0));
+ printf("use addresses.(%s) (%s)\n",jprint(addresses,0),spendscriptstr!=0?spendscriptstr:"no script");
//printf("(%s) vals.(%s) change.(%s) spend.%s\n",coin->symbol,jprint(valsobj,0),changeaddr,spendscriptstr);
if ( changeaddr == 0 || changeaddr[0] == 0 || spendscriptstr == 0 || spendscriptstr[0] == 0 )
return(clonestr("{\"error\":\"invalid changeaddr or spendscript or addresses\"}"));
- if ( coin != 0 )//&& basilisk_bitcoinavail(coin) != 0 )
+ if ( coin != 0 )
{
- if ( (txobj= bitcoin_txcreate(coin->chain->isPoS,locktime,locktime==0?coin->chain->normal_txversion:coin->chain->locktime_txversion)) != 0 )
+ if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,locktime,locktime==0?coin->chain->normal_txversion:coin->chain->locktime_txversion,juint(valsobj,"timestamp"))) != 0 )
{
spendlen = (int32_t)strlen(spendscriptstr) >> 1;
decode_hex(buf,spendlen,spendscriptstr);
@@ -519,17 +796,28 @@ char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coi
if ( (opreturn= jstr(valsobj,"opreturn")) != 0 && (oplen= is_hexstr(opreturn,0)) > 0 )
{
oplen >>= 1;
- if ( (strcmp("BTC",coin->symbol) == 0 && oplen < 77) || coin->chain->do_opreturn == 0 )
+ if ( (strcmp("BTC",coin->symbol) == 0 && oplen < 76) || coin->chain->do_opreturn == 0 )
{
decode_hex(&buf[sizeof(buf) - oplen],oplen,opreturn);
spendlen = datachain_datascript(coin,buf,&buf[sizeof(buf) - oplen],oplen);
if ( (burnamount= SATOSHIDEN * jdouble(valsobj,"burn")) < 10000 )
- burnamount = 10000;
+ {
+ //burnamount = 10000;
+ printf("low burnamount %.8f\n",dstr(burnamount));
+ }
bitcoin_txoutput(txobj,buf,spendlen,burnamount);
oplen = 0;
} else oplen = datachain_opreturnscript(coin,buf,opreturn,oplen);
}
- rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,amount,changeaddr,txfee,addresses,minconf,oplen!=0?buf:0,oplen+offset,burnamount,remoteaddr);
+ rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,amount,changeaddr,txfee,addresses,minconf,oplen!=0?buf:0,oplen+offset,burnamount,remoteaddr,V,1);
+ if ( txfee == 0 )
+ {
+ txfee = iguana_esttxfee(myinfo,coin,rawtx,0,vins != 0 ? cJSON_GetArraySize(vins): 0);
+ if ( vins != 0 )
+ free_json(vins), vins = 0;
+ rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,amount,changeaddr,txfee,addresses,minconf,oplen!=0?buf:0,oplen+offset,burnamount,remoteaddr,V,1);
+ printf("new txfee %.8f (%s)\n",dstr(txfee),rawtx);
+ }
//printf("generated.(%s) vins.(%s)\n",rawtx!=0?rawtx:"",vins!=0?jprint(vins,0):"");
}
if ( rawtx != 0 )
@@ -552,7 +840,6 @@ char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coi
return(clonestr("{\"error\":\"couldnt create rawtx\"}"));
}
return(clonestr("{\"error\":\"dont have coin to create rawtx\"}"));
- //return(basilisk_issueremote(myinfo,0,&numsent,"RAW",coin->symbol,1,valsobj,juint(valsobj,"fanout"),juint(valsobj,"minresults"),basilisktag,timeoutmillis,0,0,0,0,BASILISK_DEFAULTDIFF));
}
/*
@@ -585,7 +872,7 @@ char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coi
*/
-#ifdef later
+#ifdef oldway
int32_t instantdex_feetxverify(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_swap *swap,cJSON *argjson)
{
@@ -776,131 +1063,9 @@ cJSON *BTC_makeclaimfunc(struct supernet_info *myinfo,struct exchange_info *exch
}
#endif
-
-#include "../includes/iguana_apidefs.h"
-#include "../includes/iguana_apideclares.h"
-
-HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr)
-{
- char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis;
- if ( RELAYID >= 0 )
- return(clonestr("{\"error\":\"special relays only do OUT and MSG\"}"));
- //if ( coin == 0 )
- {
- if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 )
- coin = iguana_coinfind(symbol);
- }
- if ( jobj(vals,"fanout") == 0 )
- jaddnum(vals,"fanout",(int32_t)sqrt(NUMRELAYS)+1);
- if ( coin != 0 )
- {
- if ( (basilisktag= juint(vals,"basilisktag")) == 0 )
- basilisktag = rand();
- if ( (timeoutmillis= juint(vals,"timeout")) <= 0 )
- timeoutmillis = BASILISK_TIMEOUT;
- if ( coin->FULLNODE != 0 && (ptr= basilisk_bitcoinvalue(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 )
- {
- retstr = ptr->retstr, ptr->retstr = 0;
- ptr->finished = (uint32_t)time(NULL);
- return(retstr);
- }
- }
- return(basilisk_standardservice("VAL",myinfo,0,hash,vals,hexstr,1));
-}
-
-/*HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr)
-{
- char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis,i,retval = -1; uint64_t amount,txfee; cJSON *retarray;
- //if ( coin == 0 )
- {
- if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 )
- coin = iguana_coinfind(symbol);
- }
- if ( jobj(vals,"numrequired") == 0 )
- jaddnum(vals,"numrequired",myinfo->numrelays);
- if ( jobj(vals,"fanout") == 0 )
- jaddnum(vals,"fanout",(int32_t)sqrt(myinfo->numrelays));
- if ( coin != 0 )
- {
- if ( juint(vals,"burn") == 0 )
- jaddnum(vals,"burn",0.0001);
- if ( (basilisktag= juint(vals,"basilisktag")) == 0 )
- basilisktag = rand();
- if ( (timeoutmillis= juint(vals,"timeout")) <= 0 )
- timeoutmillis = BASILISK_TIMEOUT;
- if ( (ptr= basilisk_bitcoinrawtx(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 )
- {
- if ( (retstr= ptr->retstr) != 0 )
- {
- if ( (amount= j64bits(vals,"satoshis")) == 0 )
- amount = jdouble(vals,"value") * SATOSHIDEN;
- if ( (txfee= j64bits(vals,"txfee")) == 0 )
- txfee = coin->chain->txfee;
- if ( txfee == 0 )
- txfee = 10000;
- retval = -1;
- if ( (retarray= cJSON_Parse(retstr)) != 0 )
- {
- if ( is_cJSON_Array(retarray) != 0 )
- {
- for (i=0; iretstr = 0;
- ptr->finished = (uint32_t)time(NULL);
- }
- }
- }
- return(retstr);
-}*/
-
-cJSON *basilisk_history_item(struct iguana_info *coin,int64_t *totalp,char *coinaddr,int64_t value,uint32_t timestamp,bits256 txid,char *vinvoutstr,int32_t vinvout,int32_t height,char *otherheightstr,int32_t otherheight,uint64_t relaymask,int32_t ismine)
-{
- cJSON *item,*details;
- item = cJSON_CreateObject();
- jaddstr(item,"address",coinaddr);
- jaddnum(item,"amount",dstr(value));
- jaddnum(item,"numseconds",time(NULL) - timestamp);
- details = cJSON_CreateObject();
- if ( ismine > 0 )
- {
- jaddnum(details,"ismine",ismine);
- if ( strcmp(vinvoutstr,"spentheight") == 0 )
- jaddstr(details,"category","sent");
- else jaddstr(details,"category","received");
- }
- jaddbits256(details,"txid",txid);
- jaddnum(details,vinvoutstr,vinvout);
- jaddnum(details,"height",height);
- if ( coin->blocks.hwmchain.height > 0 )
- jaddnum(details,"confirms",coin->blocks.hwmchain.height - height);
- jaddnum(details,"height",height);
- if ( otherheight != 0 )
- jaddnum(details,otherheightstr,otherheight);
- else *totalp += value;
- jaddnum(details,"relays",bitweight(relaymask));
- jadd(item,"details",details);
- return(item);
-}
-
-#include "../includes/iguana_apiundefs.h"
-
int32_t basilisk_unspentfind(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,uint8_t *spendscript,struct iguana_outpoint outpt,int64_t value)
{
- struct basilisk_unspent *bu; int32_t i,spendlen; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; char str[65];
+ struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2;
memset(txidp,0,sizeof(*txidp));
*voutp = -1;
portable_mutex_lock(&myinfo->bu_mutex);
@@ -908,223 +1073,115 @@ int32_t basilisk_unspentfind(struct supernet_info *myinfo,struct iguana_info *co
{
HASH_ITER(hh,wacct->waddr,waddr,tmp2)
{
- for (i=0; inumunspents; i++)
- {
- bu = &waddr->unspents[i];
- if ( bu->hdrsi == outpt.hdrsi && bu->unspentind == outpt.unspentind && bu->value == value )
- {
- if ( bu->status == 0 )
- {
- *txidp = bu->txid;
- *voutp = bu->vout;
- memcpy(spendscript,bu->script,bu->spendlen);
- spendlen = bu->spendlen;
- portable_mutex_unlock(&myinfo->bu_mutex);
- return(spendlen);
- } else printf("unspentfind skip %s/v%d\n",bits256_str(str,bu->txid),bu->vout);
- }
- }
+ printf("need to port basilisk_unspentfind\n");
}
}
portable_mutex_unlock(&myinfo->bu_mutex);
return(-1);
}
-struct basilisk_spend *basilisk_addspend(struct supernet_info *myinfo,char *symbol,bits256 txid,uint16_t vout,int32_t addflag)
+cJSON *basilisk_jsonmerge(char *symbol,cJSON *array)
{
- int32_t i; struct basilisk_spend *s;
- // mutex
- if ( myinfo->numspends > 0 )
+ int32_t i,j,n,m; cJSON *jobj,*iobj,*dest = cJSON_CreateArray();
+ if ( dest != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
- for (i=0; inumspends; i++)
+ for (i=0; ispends[i].vout == vout && bits256_cmp(txid,myinfo->spends[i].txid) == 0 )
+ m = cJSON_GetArraySize(dest);
+ iobj = jitem(array,i);
+ for (j=0; jspends[i]);
+ jobj = jitem(dest,j);
+ if ( bits256_cmp(jbits256(jobj,"txid"),jbits256(iobj,"txid")) == 0 && jint(jobj,"vout") == jint(iobj,"vout") )
+ {
+ //printf("(%s) == (%s)\n",jprint(iobj,0),jprint(jobj,0));
+ break;
+ }
}
+ if ( j == m )
+ {
+ jaddi(dest,jduplicate(iobj));
+ //printf("add.(%s) ",jprint(iobj,0));
+ } //else printf("j.%d != m.%d\n",j,m);
}
}
- if ( addflag != 0 && i == myinfo->numspends )
- {
- printf("realloc spends.[%d] %p\n",myinfo->numspends,myinfo->spends);
- myinfo->spends = realloc(myinfo->spends,sizeof(*myinfo->spends) * (myinfo->numspends+1));
- printf("allocated spends.[%d] %p\n",myinfo->numspends+1,myinfo->spends);
- s = &myinfo->spends[myinfo->numspends++];
- memset(s,0,sizeof(*s));
- s->txid = txid;
- s->vout = vout;
- strcpy(s->symbol,symbol);
- //char str[65]; printf("ADDSPEND.%s %s/v%d\n",symbol,bits256_str(str,txid),vout);
- // mutex
- return(s);
- }
- // mutex
- return(0);
+ return(dest);
}
-void basilisk_unspent_update(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *item,int32_t spentheight,int32_t relayid,int32_t RTheight)
+void basilisk_unspent_update(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json)
{
- //{"txid":"4814dc8a357f93f16271eb43806a69416ec41ab1956b128d170402b0a1b37c7f","vout":2,"address":"RSyKVKNxrSDc1Vwvh4guYb9ZDEpvMFz2rm","scriptPubKey":"76a914c210f6711e98fe9971757ede2b2dcb0507f3f25e88ac","amount":9.99920000,"timestamp":1466684518,"height":1160306,"confirmations":22528,"checkind":1157,"spent":{"hdrsi":2320,"pkind":168,"unspentind":1157,"prevunspentind":0,"satoshis":"999920000","txidind":619,"vout":2,"type":2,"fileid":0,"scriptpos":0,"scriptlen":25},"spentheight":1161800,"dest":{"error":"couldnt find spent info"}}
- int32_t i,n,j,m,already_spent=0; struct basilisk_unspent bu,bu2; char *address,*script=0,*destaddr; struct iguana_waccount *wacct; struct iguana_waddress *waddr=0; cJSON *dest,*vouts,*vitem; double ratio;
- if ( (address= jstr(item,"address")) != 0 && (script= jstr(item,"scriptPubKey")) != 0 && (waddr= iguana_waddresssearch(myinfo,&wacct,address)) != 0 )
+ cJSON *unspents,*spends,*item; int32_t n; char *address; //struct iguana_waccount *wacct; struct iguana_waddress *waddr=0;
+ if ( (spends= jarray(&n,json,"spends")) != 0 && n > 0 )
{
- if ( relayid >= 64 )
- relayid = 0;
- memset(&bu,0,sizeof(bu));
- bu.spendlen = (int32_t)strlen(script) >> 1;
- if ( bu.spendlen > sizeof(bu.script) )
+ item = jitem(spends,0);
+ if ( (address= jstr(item,"address")) != 0 )//&& (waddr= iguana_waddresssearch(myinfo,&wacct,address)) != 0 )
{
- printf("spendscript too big.%d\n",bu.spendlen);
- return;
- }
- strcpy(bu.symbol,coin->symbol);
- bu.txid = jbits256(item,"txid");
- bu.vout = jint(item,"vout");
- bu.value = jdouble(item,"amount") * SATOSHIDEN;
- bu.height = jint(item,"height");
- bu.hdrsi = (bu.height / coin->chain->bundlesize);
- bu.unspentind = juint(item,"checkind");
- bu.timestamp = juint(item,"timestamp");
- decode_hex(bu.script,bu.spendlen,script);
- //printf("unspentupdate.(%s)\n",jprint(item,0));
- n = waddr->numunspents;
- for (i=0; iunspents[i];
- bu2.status = 0;
- bu2.RTheight = bu2.spentheight = 0;
- bu2.relaymask = 0;
- if ( memcmp(&bu,&bu2,sizeof(bu)) == 0 )
- {
- if ( waddr->unspents[i].RTheight > RTheight )
- RTheight = waddr->unspents[i].RTheight;
- already_spent = waddr->unspents[i].spentheight;
- bu.relaymask = waddr->unspents[i].relaymask;
- if ( (bu.status= waddr->unspents[i].status) != 0 )
- {
- //printf("mempool spend for %s/%d\n",bits256_str(str,bu.txid),bu.vout);
- }
- break;
- }
- }
- bu.RTheight = RTheight;
- bu.relaymask |= ((uint64_t)1 << relayid);
- //printf("relayid.%d -> %llx wt.%d\n",relayid,(long long)bu.relaymask,bitweight(bu.relaymask));
- if ( spentheight != 0 )
- already_spent = spentheight;
- if ( (bu.spentheight= already_spent) != 0 )
- bu.status = 1;
- //printf("i.%d n.%d\n",i,n);
- if ( i == n )
- {
- if ( i >= waddr->maxunspents )
- {
- waddr->maxunspents += 16;
- waddr->unspents = realloc(waddr->unspents,sizeof(*waddr->unspents) * waddr->maxunspents);
- //printf("allocate max.%d for %s\n",waddr->maxunspents,waddr->coinaddr);
- }
- waddr->numunspents++;
- //printf("new unspent.%s %d script.%p [%d]\n",waddr->coinaddr,waddr->numunspents,bu.script,bu.spendlen);
+ if ( myinfo->Cspends == 0 )
+ myinfo->Cspends = cJSON_CreateObject();
+ if ( jobj(myinfo->Cspends,coin->symbol) != 0 )
+ jdelete(myinfo->Cspends,coin->symbol);
+ jadd(myinfo->Cspends,coin->symbol,basilisk_jsonmerge(coin->symbol,spends));
+ //printf("S.(%s)\n",jprint(waddr->Cspends,0));
}
- waddr->unspents[i] = bu;
- //PREVENT DOUBLE SPENDS!!! and use p2sh
- if ( i == n && bu.spentheight != 0 && (dest= jobj(item,"dest")) != 0 )
+ //printf("merge spends.(%s)\n",jprint(spends,0));
+ }
+ if ( (unspents= jarray(&n,json,"unspents")) != 0 && n > 0 )
+ {
+ item = jitem(unspents,0);
+ if ( (address= jstr(item,"address")) != 0 )//&& (waddr= iguana_waddresssearch(myinfo,&wacct,address)) != 0 )
{
- struct basilisk_spend *s;
- //{"txid":"cd4fb72f871d481c534f15d7f639883958936d49e965f58276f0925798e762df","vin":1,"height":,"unspentheight":,"relays":2}},
- if ( (s= basilisk_addspend(myinfo,coin->symbol,bu.txid,bu.vout,1)) != 0 )
- {
- s->spentfrom = jbits256(dest,"spentfrom");
- s->vini = jint(dest,"vin");
- s->height = bu.spentheight;
- s->timestamp = juint(dest,"timestamp");
- s->unspentheight = bu.height;
- s->relaymask = bu.relaymask;
- ratio = jdouble(dest,"ratio");
- if ( (vouts= jobj(dest,"vouts")) != 0 && (m= cJSON_GetArraySize(vouts)) > 0 )
- {
- for (j=0; jdestaddr,destaddr,sizeof(s->destaddr));
- s->ismine = (iguana_waddresssearch(myinfo,&wacct,destaddr) != 0);
- s->value = jdouble(vitem,jfieldname(vitem)) * SATOSHIDEN;
- //printf("(%s %.8f) ",s->destaddr,dstr(s->value));
- }
- }
- //char str[65]; printf("SPEND dest.(%s) ratio %.8f (%s/v%d)\n",jprint(dest,0),ratio,bits256_str(str,s->txid),s->vini);
- }
- }
+ if ( myinfo->Cunspents == 0 )
+ myinfo->Cunspents = cJSON_CreateObject();
+ if ( jobj(myinfo->Cunspents,coin->symbol) != 0 )
+ jdelete(myinfo->Cunspents,coin->symbol);
+ jadd(myinfo->Cunspents,coin->symbol,basilisk_jsonmerge(coin->symbol,unspents));
+ //printf("U.(%s)\n",jprint(myinfo->Cunspents,0));
}
- } else printf("waddr.%p script.%p address.%p %s\n",waddr,script,address,address!=0?address:"");
+ //printf("merge unspents.(%s)\n",jprint(unspents,0));
+ }
}
-void basilisk_relay_unspentsprocess(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *relayjson)
+void basilisk_unspents_process(struct supernet_info *myinfo,struct iguana_info *coin,char *retstr)
{
- int32_t RTheight,relayid,num,j; cJSON *unspents,*spends;
- RTheight = jint(relayjson,"RTheight");
- if ( (relayid= basilisk_relayid(myinfo,(uint32_t)calc_ipbits(jstr(relayjson,"relay")))) < BASILISK_MAXRELAYS )
- {
- coin->relay_RTheights[relayid] = RTheight;
- }
- //printf("basilisk_relay_unspentsprocess relayid.%d RT.%d (%s)\n",relayid,RTheight,jprint(relayjson,0));
- if ( (unspents= jarray(&num,relayjson,"unspents")) != 0 )
- {
- for (j=0; jbu_mutex);
+ if ( myinfo->Cspends != 0 )
+ free_json(myinfo->Cspends), myinfo->Cspends = 0;
+ if ( myinfo->Cunspents != 0 )
+ free_json(myinfo->Cunspents), myinfo->Cunspents = 0;
+ if ( (retarray= cJSON_Parse(retstr)) != 0 )
{
- for (j=0; jbu_mutex);
+}
+
+cJSON *basilisk_balance_valsobj(struct supernet_info *myinfo,struct iguana_info *coin)
+{
+ int32_t oldest,i,RTheight; cJSON *vals;
+ for (i=oldest=0; irelay_RTheights[i]) != 0 && (oldest == 0 || RTheight < oldest) )
+ oldest = RTheight;
+ vals = cJSON_CreateObject();
+ jaddnum(vals,"firstheight",oldest);
+ jaddnum(vals,"history",3);
+ jaddstr(vals,"coin",coin->symbol);
+ return(vals);
}
void basilisk_unspents_update(struct supernet_info *myinfo,struct iguana_info *coin)
{
- char *retstr; cJSON *retarray,*vals; int32_t oldest,i,n,RTheight;
- //if ( coin->FULLNODE == 0 && coin->VALIDATENODE == 0 )
+ char *retstr; cJSON *vals;
+ if ( (vals= basilisk_balance_valsobj(myinfo,coin)) != 0 && (retstr= basilisk_balances(myinfo,coin,0,0,GENESIS_PUBKEY,vals,"")) != 0 )
{
- vals = cJSON_CreateObject();
- for (i=oldest=0; irelay_RTheights[i]) != 0 && (oldest == 0 || RTheight < oldest) )
- oldest = RTheight;
- jaddnum(vals,"firstheight",oldest);
- jaddnum(vals,"history",3);
- jaddstr(vals,"coin",coin->symbol);
- if ( (retstr= basilisk_balances(myinfo,coin,0,0,GENESIS_PUBKEY,vals,"")) != 0 )
- {
- portable_mutex_lock(&myinfo->bu_mutex);
- if ( (retarray= cJSON_Parse(retstr)) != 0 )
- {
- //printf("%s UNSPENTS_UPDATE.(%s)\n",coin->symbol,retstr);
- if ( jobj(retarray,"error") == 0 )
- {
- if ( (jstr(retarray,"ipaddr") == 0 || strcmp(jstr(retarray,"ipaddr"),myinfo->ipaddr) != 0) && (n= cJSON_GetArraySize(retarray)) > 0 )
- {
- for (i=0; ibu_mutex);
- }
- free_json(vals);
+ basilisk_unspents_process(myinfo,coin,retstr);
+ free(retstr);
}
+ free_json(vals);
}
diff --git a/basilisk/basilisk_ping.c b/basilisk/basilisk_ping.c
index 404bb7095..7533cd2cd 100755
--- a/basilisk/basilisk_ping.c
+++ b/basilisk/basilisk_ping.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * Copyright © 2014-2016 The SuperNET Developers. *
+ * Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -16,7 +16,7 @@
// included from basilisk.c
#ifdef ENABLE_VIRTPING
-int32_t basilisk_blocksend(struct supernet_info *myinfo,struct iguana_info *btcd,struct iguana_info *virt,struct iguana_peer *addr,int32_t height)
+int32_t basilisk_blocksend(struct supernet_info *myinfo,struct iguana_info *notary,struct iguana_info *virt,struct iguana_peer *addr,int32_t height)
{
int32_t blocklen; bits256 hash2; uint8_t *data = 0; char str[65],strbuf[4096],*blockstr,*allocptr = 0; struct iguana_block *block;
hash2 = iguana_blockhash(virt,height);
@@ -42,7 +42,7 @@ int32_t basilisk_blocksend(struct supernet_info *myinfo,struct iguana_info *btcd
{
blockstr = basilisk_addhexstr(&allocptr,0,strbuf,sizeof(strbuf),data,blocklen);
printf("RELAYID.%d send block.%d %s -> (%s) %s\n",myinfo->RELAYID,height,blockstr,addr->ipaddr,bits256_str(str,hash2));
- basilisk_blocksubmit(myinfo,btcd,virt,addr,blockstr,hash2,height);
+ basilisk_blocksubmit(myinfo,notary,virt,addr,blockstr,hash2,height);
if ( allocptr != 0 )
free(allocptr);
return(0);
@@ -50,7 +50,7 @@ int32_t basilisk_blocksend(struct supernet_info *myinfo,struct iguana_info *btcd
return(-1);
}
-int32_t basilisk_ping_processvirts(struct supernet_info *myinfo,struct iguana_info *btcd,struct iguana_peer *addr,uint8_t *data,int32_t datalen)
+int32_t basilisk_ping_processvirts(struct supernet_info *myinfo,struct iguana_info *notary,struct iguana_peer *addr,uint8_t *data,int32_t datalen)
{
int32_t diff,i,j,len = 0; struct iguana_info *virt; char symbol[7]; uint32_t numvirts,height;
len += iguana_rwvarint32(0,&data[len],&numvirts);
@@ -72,7 +72,7 @@ int32_t basilisk_ping_processvirts(struct supernet_info *myinfo,struct iguana_in
if ( (rand() % diff) == 0 )
{
for (j=1; height+jblocks.hwmchain.height && j<3; j++)
- basilisk_blocksend(myinfo,btcd,virt,addr,height+j);
+ basilisk_blocksend(myinfo,notary,virt,addr,height+j);
}
}
}
@@ -107,7 +107,7 @@ int32_t basilisk_ping_genvirts(struct supernet_info *myinfo,uint8_t *data,int32_
int32_t basilisk_ping_processMSG(struct supernet_info *myinfo,uint32_t senderipbits,uint8_t *data,int32_t datalen)
{
- int32_t i,msglen,len=0; uint8_t num,keylen,*msg,*key; uint32_t duration;
+ int32_t i,msglen=0,len=0; uint8_t num,keylen,*message,*key; uint32_t duration;
if ( (num= data[len++]) > 0 )
{
//printf("processMSG num.%d datalen.%d\n",num,datalen);
@@ -127,14 +127,14 @@ int32_t basilisk_ping_processMSG(struct supernet_info *myinfo,uint32_t senderipb
}
len += iguana_rwnum(0,&data[len],sizeof(msglen),&msglen);
len += iguana_rwnum(0,&data[len],sizeof(duration),&duration);
- msg = &data[len], len += msglen;
+ message = &data[len], len += msglen;
if ( msglen <= 0 || len > datalen )
{
printf("illegal msglen.%d or len.%d > %d\n",msglen,len,datalen);
return(0);
}
//printf("i.%d: keylen.%d msglen.%d\n",i,keylen,msglen);
- basilisk_respond_addmessage(myinfo,key,keylen,msg,msglen,0,duration);
+ basilisk_respond_addmessage(myinfo,key,keylen,message,msglen,0,duration);
}
}
return(len);
@@ -143,7 +143,7 @@ int32_t basilisk_ping_processMSG(struct supernet_info *myinfo,uint32_t senderipb
int32_t basilisk_ping_genMSG(struct supernet_info *myinfo,uint8_t *data,int32_t maxlen)
{
struct basilisk_message *msg; int32_t datalen = 0;
- if ( maxlen > sizeof(msg->key) && (msg= queue_dequeue(&myinfo->msgQ,0)) != 0 ) // oneshot ping
+ if ( maxlen > sizeof(msg->key) && (msg= queue_dequeue(&myinfo->msgQ)) != 0 ) // oneshot ping
{
data[datalen++] = 1;
data[datalen++] = msg->keylen;
@@ -188,7 +188,7 @@ int32_t baslisk_relay_report(struct supernet_info *myinfo,uint8_t *data,int32_t
int32_t basilisk_ping_processrelay(struct supernet_info *myinfo,uint8_t *data,int32_t maxlen,struct basilisk_relay *rp,int32_t i)
{
- uint8_t pingdelay; int32_t j,datalen = 0; uint32_t ipbits;
+ uint8_t pingdelay; int32_t j,datalen = 0; uint32_t ipbits; char ipaddr[64];
ipbits = rp->ipbits;
if ( maxlen < sizeof(ipbits)+1 )
{
@@ -202,19 +202,21 @@ int32_t basilisk_ping_processrelay(struct supernet_info *myinfo,uint8_t *data,in
datalen += baslisk_relay_report(myinfo,&data[datalen],maxlen-datalen,&rp->reported[j],pingdelay);
return(datalen);
}
- printf("notified about unknown relay\n"); // parse it to match bytes sent
datalen += baslisk_relay_report(myinfo,&data[datalen],maxlen-datalen,0,pingdelay);
+ expand_ipbits(ipaddr,ipbits);
+ printf("notified about unknown relay (%s)\n",ipaddr); // parse it to match bytes sent
+ basilisk_addrelay_info(myinfo,0,ipbits,GENESIS_PUBKEY);
return(datalen);
}
void basilisk_ping_process(struct supernet_info *myinfo,struct iguana_peer *addr,uint32_t senderipbits,uint8_t *data,int32_t datalen)
{
- int32_t diff,i,n,len = 0; struct iguana_info *btcd; char ipbuf[64]; struct basilisk_relay *rp; uint8_t numrelays; uint16_t sn; uint32_t now = (uint32_t)time(NULL);
+ int32_t diff,i,n,len = 0; struct iguana_info *notary; char ipbuf[64]; struct basilisk_relay *rp; uint8_t numrelays; uint16_t sn; uint32_t now = (uint32_t)time(NULL);
expand_ipbits(ipbuf,senderipbits);
- btcd = iguana_coinfind("BTCD");
- for (i=0; iNOTARY.NUMRELAYS; i++)
{
- rp = &RELAYS[i];
+ rp = &myinfo->NOTARY.RELAYS[i];
rp->direct.pingdelay = 0;
if ( rp->ipbits == senderipbits )
rp->lastping = now;
@@ -228,9 +230,10 @@ void basilisk_ping_process(struct supernet_info *myinfo,struct iguana_peer *addr
}
}
numrelays = data[len++];
- //len += basilisk_ping_processvirts(myinfo,btcd,addr,&data[len],datalen - len);
+ //len += basilisk_ping_processvirts(myinfo,notary,addr,&data[len],datalen - len);
for (i=0; iNOTARY.RELAYS[i];
if ( len > datalen )
break;
if ( (n= basilisk_ping_processrelay(myinfo,&data[len],datalen-len,rp,i)) < 0 )
@@ -246,54 +249,58 @@ void basilisk_ping_process(struct supernet_info *myinfo,struct iguana_peer *addr
//else printf("\n");
//for (i=0; iRELAYID,QUEUEITEMS);
+ //printf("<<<<<<<<<<< input ping from.(%s) rel.%d numrelays.%d datalen.%d relay.%d Q.%d\n",ipbuf,basilisk_relayid(myinfo,(uint32_t)calc_ipbits(ipbuf)),numrelays,datalen,myinfo->NOTARY.RELAYID,QUEUEITEMS);
+ //basilisk_addrelay_info(myinfo,0,(uint32_t)calc_ipbits(ipbuf),GENESIS_PUBKEY);
}
int32_t basilisk_ping_gen(struct supernet_info *myinfo,uint8_t *data,int32_t maxlen)
{
int32_t i,datalen = 0;
- data[datalen++] = NUMRELAYS;
+ data[datalen++] = myinfo->NOTARY.NUMRELAYS;
//datalen += basilisk_ping_genvirts(myinfo,&data[datalen],maxlen - datalen);
- for (i=0; iNOTARY.NUMRELAYS; i++)
+ datalen += basilisk_ping_genrelay(myinfo,&data[datalen],maxlen - datalen,&myinfo->NOTARY.RELAYS[i]);
//datalen += basilisk_ping_genDEX(myinfo,&data[datalen],maxlen - datalen);
datalen += basilisk_ping_genMSG(myinfo,&data[datalen],maxlen - datalen);
//for (i=0; i>>>>>>>>> Q.%d\n",datalen,myinfo->RELAYID,QUEUEITEMS);
+ //printf(" output ping datalen.%d relay.%d >>>>>>>>>> Q.%d\n",datalen,myinfo->NOTARY.RELAYID,QUEUEITEMS);
return(datalen);
}
// encapsulate other messages inside msgQ for onetime ping
// filter out duplicates
-void basilisk_ping_send(struct supernet_info *myinfo,struct iguana_info *btcd)
+void basilisk_ping_send(struct supernet_info *myinfo,struct iguana_info *notary)
{
struct iguana_peer *addr; char ipaddr[64]; struct basilisk_relay *rp; uint32_t r; int32_t i,j,incr,datalen=0; uint64_t alreadysent;
- if ( btcd == 0 || NUMRELAYS <= 0 )
+ if ( notary == 0 || myinfo->NOTARY.NUMRELAYS <= 0 || myinfo->IAMNOTARY == 0 )
+ {
+ printf("skip ping send %p %d %d\n",notary,myinfo->NOTARY.NUMRELAYS,myinfo->IAMNOTARY);
return;
+ }
if ( myinfo->pingbuf == 0 )
myinfo->pingbuf = malloc(IGUANA_MAXPACKETSIZE);
datalen = basilisk_ping_gen(myinfo,&myinfo->pingbuf[sizeof(struct iguana_msghdr)],IGUANA_MAXPACKETSIZE-sizeof(struct iguana_msghdr));
- incr = sqrt(NUMRELAYS) + 1;
+ incr = sqrt(myinfo->NOTARY.NUMRELAYS) + 1;
+ OS_randombytes((void *)&r,sizeof(r));
for (alreadysent=j=0; j<=incr; j++)
{
- OS_randombytes((void *)&r,sizeof(r));
- i = (j == 0) ? RELAYID : (r % NUMRELAYS);
- if ( j != 0 && i == RELAYID )
- i = (RELAYID + 1) % NUMRELAYS;
+ i = (j == 0) ? myinfo->NOTARY.RELAYID : ((r+j) % myinfo->NOTARY.NUMRELAYS);
+ if ( j != 0 && i == myinfo->NOTARY.RELAYID )
+ i = (myinfo->NOTARY.RELAYID + 1) % myinfo->NOTARY.NUMRELAYS;
if ( (((uint64_t)1 << i) & alreadysent) != 0 )
{
j--;
- continue;
+ break;
}
alreadysent |= ((uint64_t)1 << i);
- rp = &RELAYS[i];
+ rp = &myinfo->NOTARY.RELAYS[i];
addr = 0;
expand_ipbits(ipaddr,rp->ipbits);
if ( rp->ipbits == myinfo->myaddr.myipbits )
basilisk_ping_process(myinfo,0,myinfo->myaddr.myipbits,&myinfo->pingbuf[sizeof(struct iguana_msghdr)],datalen);
- else if ( (addr= iguana_peerfindipbits(btcd,rp->ipbits,1)) != 0 && addr->usock >= 0 )
+ else if ( (addr= iguana_peerfindipbits(notary,rp->ipbits,1)) != 0 && addr->usock >= 0 )
{
if ( iguana_queue_send(addr,0,myinfo->pingbuf,"SuperNETPIN",datalen) <= 0 )
printf("error sending %d to (%s)\n",datalen,addr->ipaddr);
@@ -301,6 +308,7 @@ void basilisk_ping_send(struct supernet_info *myinfo,struct iguana_info *btcd)
fprintf(stderr,"+(%s).%d ",ipaddr,i);
} //else fprintf(stderr,"-(%s).%d ",ipaddr,i);
}
- //printf("my RELAYID.%d of %d\n",myinfo->RELAYID,NUMRELAYS);
+ if ( 0 && datalen > 200 )
+ printf("my RELAYID.%d of %d\n",myinfo->NOTARY.RELAYID,myinfo->NOTARY.NUMRELAYS);
}
diff --git a/basilisk/basilisk_swap.c b/basilisk/basilisk_swap.c
index 625e9d4f0..a142f8a12 100755
--- a/basilisk/basilisk_swap.c
+++ b/basilisk/basilisk_swap.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * Copyright © 2014-2016 The SuperNET Developers. *
+ * Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -13,35 +13,71 @@
* *
******************************************************************************/
+/*
+ resume handling: list of tx broadcast, tx pending + required items, reconnect state machine or have statemachine assume off by one or state/otherstate specific handling
+make sure to broadcast deposit before claiming refund, or to just skip it if neither is done
+*/
+
+#define DEX_SLEEP 10
+#define BASILISK_DEFAULT_NUMCONFIRMS 5
+
+// Todo: monitor blockchains, ie complete extracting scriptsig
+// mode to autocreate required outputs
+// more better LP commands
+
+// depends on just three external functions:
+// - basilisk_sendrawtransaction(myinfo,coin,signedtx);
+// - basilisk_value(myinfo,rawtx->coin,0,0,myinfo->myaddr.persistent,argjson,0)
+// basilisk_bitcoinrawtx(myinfo,rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V)
+
+
// included from basilisk.c
/* https://bitcointalk.org/index.php?topic=1340621.msg13828271#msg13828271
https://bitcointalk.org/index.php?topic=1364951
Tier Nolan's approach is followed with the following changes:
a) instead of cutting 1000 keypairs, only INSTANTDEX_DECKSIZE are a
b) instead of sending the entire 256 bits, it is truncated to 64 bits. With odds of collision being so low, it is dwarfed by the ~0.1% insurance factor.
- c) D is set to 100x the insurance rate of 1/777 12.87% + BTC amount
+ c) D is set to ~100x the insurance rate of 1/777 12.87% + BTC amount
d) insurance is added to Bob's payment, which is after the deposit and bailin
e) BEFORE Bob broadcasts deposit, Alice broadcasts BTC denominated fee in cltv so if trade isnt done fee is reclaimed
*/
+//#define DISABLE_CHECKSIG // unsolved MITM (evil peer)
+
/*
both fees are standard payments: OP_DUP OP_HASH160 FEE_RMD160 OP_EQUALVERIFY OP_CHECKSIG
Alice altpayment: OP_2 OP_2 OP_CHECKMULTISIG
Bob deposit:
+ #ifndef DISABLE_CHECKSIG
OP_IF
OP_CLTV OP_DROP OP_CHECKSIG
OP_ELSE
OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF
+ #else
+ OP_IF
+ OP_CLTV OP_DROP OP_SHA256 OP_EQUAL
+ OP_ELSE
+ OP_HASH160 OP_EQUALVERIFY OP_SHA256 OP_EQUAL
+ OP_ENDIF
+#endif
Bob paytx:
+ #ifndef DISABLE_CHECKSIG
OP_IF
OP_CLTV OP_DROP OP_CHECKSIG
OP_ELSE
OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF
+ #else
+ OP_IF
+ OP_CLTV OP_DROP OP_SHA256 OP_EQUAL
+ OP_ELSE
+ OP_HASH160 OP_EQUALVERIFY OP_SHA256 OP_EQUAL
+ OP_ENDIF
+ #endif
Naming convention are pubAi are alice's pubkeys (seems only pubA0 and not pubA1)
pubBi are Bob's pubkeys
@@ -53,31 +89,118 @@
Alice timeout event is triggered if INSTANTDEX_LOCKTIME elapses from the start of a FSM instance. Bob timeout event is triggered after INSTANTDEX_LOCKTIME*2
*/
+/*
+Bob sends bobdeposit and waits for alicepayment to confirm before sending bobpayment
+Alice waits for bobdeposit to confirm and sends alicepayment
+
+Alice spends bobpayment immediately divulging privAm
+Bob spends alicepayment immediately after getting privAm and divulges privBn
+
+Bob will spend bobdeposit after end of trade or INSTANTDEX_LOCKTIME, divulging privBn
+Alice spends alicepayment as soon as privBn is seen
+
+Bob will spend bobpayment after INSTANTDEX_LOCKTIME
+Alice spends bobdeposit in 2*INSTANTDEX_LOCKTIME
+*/
+
+//Bobdeposit includes a covered put option for alicecoin, duration INSTANTDEX_LOCKTIME
+//alicepayment includes a covered call option for alicecoin, duration (2*INSTANTDEX_LOCKTIME - elapsed)
+
+
+/* in case of following states, some funds remain unclaimable, but all identified cases are due to one or both sides not spending when they were the only eligible party:
+
+ Bob failed to claim deposit during exclusive period and since alice put in the claim, the alicepayment is unspendable. if alice is nice, she can send privAm to Bob.
+Apaymentspent.(0000000000000000000000000000000000000000000000000000000000000000) alice.0 bob.0
+paymentspent.(f91da4e001360b95276448e7b01904d9ee4d15862c5af7f5c7a918df26030315) alice.0 bob.1
+depositspent.(f34e04ad74e290f63f3d0bccb7d0d50abfa54eea58de38816fdc596a19767add) alice.1 bob.0
+
+ */
+
+int32_t basilisk_istrustedbob(struct supernet_info *myinfo,struct basilisk_swap *swap)
+{
+ // for BTC and if trusted LP
+ return(0);
+}
+
+int32_t basilisk_priviextract(struct supernet_info *myinfo,struct iguana_info *coin,char *name,bits256 *destp,uint8_t secret160[20],bits256 srctxid,int32_t srcvout)
+{
+ bits256 txid,privkey; char str[65]; int32_t i,vini,scriptlen; uint8_t rmd160[20],scriptsig[IGUANA_MAXSCRIPTSIZE];
+ memset(privkey.bytes,0,sizeof(privkey));
+ // use dex_listtransactions!
+ if ( (vini= iguana_vinifind(myinfo,coin,&txid,srctxid,srcvout)) >= 0 )
+ {
+ if ( (scriptlen= iguana_scriptsigextract(myinfo,coin,scriptsig,sizeof(scriptsig),txid,vini)) > 32 )
+ {
+ for (i=0; i<32; i++)
+ privkey.bytes[i] = scriptsig[scriptlen - 33 + i];
+ revcalc_rmd160_sha256(rmd160,privkey);//.bytes,sizeof(privkey));
+ if ( memcmp(secret160,rmd160,sizeof(rmd160)) == sizeof(rmd160) )
+ {
+ *destp = privkey;
+ printf("basilisk_priviextract found privi %s (%s)\n",name,bits256_str(str,privkey));
+ return(0);
+ }
+ }
+ }
+ return(-1);
+}
+
+void revcalc_rmd160_sha256(uint8_t rmd160[20],bits256 revhash)
+{
+ bits256 hash; int32_t i;
+ for (i=0; i<32; i++)
+ hash.bytes[i] = revhash.bytes[31-i];
+ calc_rmd160_sha256(rmd160,hash.bytes,sizeof(hash));
+}
+
+bits256 revcalc_sha256(bits256 revhash)
+{
+ bits256 hash,dest; int32_t i;
+ for (i=0; i<32; i++)
+ hash.bytes[i] = revhash.bytes[31-i];
+ vcalc_sha256(0,dest.bytes,hash.bytes,sizeof(hash));
+ return(dest);
+}
+
#define SCRIPT_OP_IF 0x63
#define SCRIPT_OP_ELSE 0x67
#define SCRIPT_OP_ENDIF 0x68
-int32_t basilisk_bobscript(uint8_t *rmd160,uint8_t *redeemscript,int32_t *redeemlenp,uint8_t *script,int32_t n,uint32_t *locktimep,int32_t *secretstartp,struct basilisk_swap *swap,int32_t depositflag)
+bits256 basilisk_revealkey(bits256 privkey,bits256 pubkey)
+{
+ bits256 reveal;
+#ifdef DISABLE_CHECKSIG
+ vcalc_sha256(0,reveal.bytes,privkey.bytes,sizeof(privkey));
+ //reveal = revcalc_sha256(privkey);
+ char str[65],str2[65]; printf("priv.(%s) -> reveal.(%s)\n",bits256_str(str,privkey),bits256_str(str2,reveal));
+#else
+ reveal = pubkey;
+#endif
+ return(reveal);
+}
+
+int32_t basilisk_swap_bobredeemscript(int32_t depositflag,int32_t *secretstartp,uint8_t *redeemscript,uint32_t locktime,bits256 pubA0,bits256 pubB0,bits256 pubB1,bits256 privAm,bits256 privBn,uint8_t *secretAm,uint8_t *secretAm256,uint8_t *secretBn,uint8_t *secretBn256)
{
- uint8_t pubkeyA[33],pubkeyB[33],*secret160; bits256 cltvpub,destpub; int32_t i;
- *locktimep = swap->locktime;
+ int32_t i,n=0; bits256 cltvpub,destpub,privkey; uint8_t pubkeyA[33],pubkeyB[33],secret160[20],secret256[32];
if ( depositflag != 0 )
{
- *locktimep += INSTANTDEX_LOCKTIME;
- cltvpub = swap->pubA0;
- destpub = swap->pubB0;
- secret160 = swap->secretBn;
- pubkeyA[0] = 0x02;
- pubkeyB[0] = 0x03;
+ pubkeyA[0] = 0x02, cltvpub = pubA0;
+ pubkeyB[0] = 0x03, destpub = pubB0;
+ privkey = privBn;
+ memcpy(secret160,secretBn,20);
+ memcpy(secret256,secretBn256,32);
}
else
{
- cltvpub = swap->pubB1;
- destpub = swap->pubA0;
- secret160 = swap->secretAm;
- pubkeyA[0] = 0x03;
- pubkeyB[0] = 0x02;
+ pubkeyA[0] = 0x03, cltvpub = pubB1;
+ pubkeyB[0] = 0x02, destpub = pubA0;
+ privkey = privAm;
+ memcpy(secret160,secretAm,20);
+ memcpy(secret256,secretAm256,32);
}
+ //for (i=0; i<32; i++)
+ // printf("%02x",secret256[i]);
+ //printf(" <- secret256 depositflag.%d nonz.%d\n",depositflag,bits256_nonz(privkey));
if ( bits256_nonz(cltvpub) == 0 || bits256_nonz(destpub) == 0 )
return(-1);
for (i=0; i<20; i++)
@@ -88,26 +211,73 @@ int32_t basilisk_bobscript(uint8_t *rmd160,uint8_t *redeemscript,int32_t *redeem
memcpy(pubkeyA+1,cltvpub.bytes,sizeof(cltvpub));
memcpy(pubkeyB+1,destpub.bytes,sizeof(destpub));
redeemscript[n++] = SCRIPT_OP_IF;
- n = bitcoin_checklocktimeverify(redeemscript,n,*locktimep);
+ n = bitcoin_checklocktimeverify(redeemscript,n,locktime);
+#ifdef DISABLE_CHECKSIG
+ n = bitcoin_secret256spend(redeemscript,n,cltvpub);
+#else
n = bitcoin_pubkeyspend(redeemscript,n,pubkeyA);
+#endif
redeemscript[n++] = SCRIPT_OP_ELSE;
if ( secretstartp != 0 )
*secretstartp = n + 2;
- n = bitcoin_revealsecret160(redeemscript,n,secret160);
+ if ( 1 )
+ {
+ if ( 1 && bits256_nonz(privkey) != 0 )
+ {
+ uint8_t bufA[20],bufB[20];
+ revcalc_rmd160_sha256(bufA,privkey);
+ calc_rmd160_sha256(bufB,privkey.bytes,sizeof(privkey));
+ /*if ( memcmp(bufA,secret160,sizeof(bufA)) == 0 )
+ printf("MATCHES BUFA\n");
+ else if ( memcmp(bufB,secret160,sizeof(bufB)) == 0 )
+ printf("MATCHES BUFB\n");
+ else printf("secret160 matches neither\n");
+ for (i=0; i<20; i++)
+ printf("%02x",bufA[i]);
+ printf(" <- revcalc\n");
+ for (i=0; i<20; i++)
+ printf("%02x",bufB[i]);
+ printf(" <- calc\n");*/
+ memcpy(secret160,bufB,20);
+ }
+ n = bitcoin_secret160verify(redeemscript,n,secret160);
+ }
+ else
+ {
+ redeemscript[n++] = 0xa8;//IGUANA_OP_SHA256;
+ redeemscript[n++] = 0x20;
+ memcpy(&redeemscript[n],secret256,0x20), n += 0x20;
+ redeemscript[n++] = 0x88; //SCRIPT_OP_EQUALVERIFY;
+ }
+#ifdef DISABLE_CHECKSIG
+ n = bitcoin_secret256spend(redeemscript,n,destpub);
+#else
n = bitcoin_pubkeyspend(redeemscript,n,pubkeyB);
+#endif
redeemscript[n++] = SCRIPT_OP_ENDIF;
- *redeemlenp = n;
- calc_rmd160_sha256(rmd160,redeemscript,n);
- n = bitcoin_p2shspend(script,0,rmd160);
- for (i=0; istarted + swap->putduration + swap->callduration;
+ else *locktimep = swap->started + swap->putduration;
+ *redeemlenp = n = basilisk_swap_bobredeemscript(depositflag,secretstartp,redeemscript,*locktimep,swap->pubA0,swap->pubB0,swap->pubB1,swap->privAm,swap->privBn,swap->secretAm,swap->secretAm256,swap->secretBn,swap->secretBn256);
+ if ( n > 0 )
+ {
+ calc_rmd160_sha256(rmd160,redeemscript,n);
+ n = bitcoin_p2shspend(script,0,rmd160);
+ //for (i=0; i 0 && numconfirms >= 0 )
return(numconfirms);
+ printf("basilisk_confirmsobj height.%d numconfirms.%d (%s)\n",height,numconfirms,jprint(item,0));
return(-1);
}
-int32_t basilisk_numconfirms(struct supernet_info *myinfo,struct basilisk_rawtx *rawtx)
+int32_t basilisk_numconfirms(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx)
{
cJSON *argjson,*valuearray=0; char *valstr; int32_t i,n,retval = -1;
-#ifdef BASILISK_DISABLETX
- return(10);
+#ifdef BASILISK_DISABLEWAITTX
+ return(100);
#endif
argjson = cJSON_CreateObject();
- jaddbits256(argjson,"txid",rawtx->actualtxid);
+ jaddbits256(argjson,"txid",rawtx->I.actualtxid);
jaddnum(argjson,"vout",0);
jaddstr(argjson,"coin",rawtx->coin->symbol);
- if ( (valstr= basilisk_value(myinfo,rawtx->coin,0,0,myinfo->myaddr.persistent,argjson,0)) != 0 )
+ if ( (valstr= basilisk_value(myinfo,rawtx->coin,0,0,swap->persistent_pubkey,argjson,0)) != 0 )
{
- //char str[65]; printf("%s %s valstr.(%s)\n",rawtx->name,bits256_str(str,rawtx->actualtxid),valstr);
+ char str[65]; printf("basilisk_numconfirms required.%d %s %s valstr.(%s)\n",rawtx->I.numconfirms,rawtx->name,bits256_str(str,rawtx->I.actualtxid),valstr);
+ //basilisk_numconfirms required.0 alicespend 29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85 valstr.({"result":"success","numconfirms":0,"address":"1JGvZ67oTdM7kCya4J8kj1uErbSRAoq3wH","satoshis":"1413818","value":0.01413818,"height":462440,"txid":"29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85","vout":0,"coin":"BTC"})
+
if ( (valuearray= cJSON_Parse(valstr)) != 0 )
{
- if ( is_cJSON_Array(valuearray) != 0 )
+ if ( valstr[0] == '[' && is_cJSON_Array(valuearray) != 0 )
{
n = cJSON_GetArraySize(valuearray);
for (i=0; i= 0 )
break;
}
@@ -160,109 +334,313 @@ int32_t basilisk_numconfirms(struct supernet_info *myinfo,struct basilisk_rawtx
free(valstr);
}
free_json(argjson);
+ printf("numconfirms.%d returned\n",retval);
return(retval);
}
bits256 basilisk_swap_broadcast(char *name,struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,uint8_t *data,int32_t datalen)
{
- bits256 txid; char *signedtx;
+ bits256 txid; char *signedtx,*retstr; int32_t i;
memset(txid.bytes,0,sizeof(txid));
if ( data != 0 && datalen != 0 )
{
char str[65];
-#ifdef BASILISK_DISABLETX
+#ifdef BASILISK_DISABLESENDTX
txid = bits256_doublesha256(0,data,datalen);
printf("%s <- dont sendrawtransaction (%s)\n",name,bits256_str(str,txid));
return(txid);
#endif
signedtx = malloc(datalen*2 + 1);
init_hexbytes_noT(signedtx,data,datalen);
- txid = iguana_sendrawtransaction(myinfo,coin,signedtx);
- printf("%s <- sendrawtransaction %s.(%s)\n",name,signedtx,bits256_str(str,txid));
+ for (i=0; i<3; i++)
+ {
+ if ( (retstr= basilisk_sendrawtransaction(myinfo,coin,signedtx)) != 0 )
+ {
+ if ( is_hexstr(retstr,0) == 64 )
+ {
+ decode_hex(txid.bytes,32,retstr);
+ free(retstr);
+ printf("sendrawtransaction %s.(%s)\n",name,bits256_str(str,txid));
+ break;
+ }
+ else
+ {
+ printf("sendrawtransaction %s error.(%s)\n",name,retstr);
+ free(retstr);
+ }
+ } else printf("sendrawtransaction %s got null return\n",name);
+ }
free(signedtx);
}
return(txid);
}
-int32_t basilisk_rawtx_sign(struct supernet_info *myinfo,int32_t height,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen)
+int32_t _basilisk_rawtx_sign(struct supernet_info *myinfo,int32_t height,uint32_t timestamp,uint32_t locktime,uint32_t sequenceid,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr)
{
- char *rawtxbytes,*signedtx,hexstr[999],wifstr[128]; cJSON *txobj,*vins,*item,*sobj,*privkeys; int32_t retval = -1; struct vin_info V; uint32_t locktime=0;
- memset(&V,0,sizeof(V));
- if ( dest == &swap->aliceclaim )
- locktime = swap->locktime + INSTANTDEX_LOCKTIME;
- V.signers[0].privkey = privkey;
- bitcoin_pubkey33(myinfo->ctx,V.signers[0].pubkey,privkey);
+ char *rawtxbytes=0,*signedtx=0,hexstr[999],wifstr[128]; cJSON *txobj,*vins,*item,*sobj,*privkeys; int32_t needsig=1,retval = -1; struct vin_info *V;
+ V = calloc(256,sizeof(*V));
+ V[0].signers[0].privkey = privkey;
+ bitcoin_pubkey33(myinfo->ctx,V[0].signers[0].pubkey,privkey);
privkeys = cJSON_CreateArray();
bitcoin_priv2wif(wifstr,privkey,rawtx->coin->chain->wiftype);
jaddistr(privkeys,wifstr);
if ( privkey2 != 0 )
{
- V.signers[1].privkey = *privkey2;
- bitcoin_pubkey33(myinfo->ctx,V.signers[1].pubkey,*privkey2);
+ V[0].signers[1].privkey = *privkey2;
+ bitcoin_pubkey33(myinfo->ctx,V[0].signers[1].pubkey,*privkey2);
bitcoin_priv2wif(wifstr,*privkey2,rawtx->coin->chain->wiftype);
jaddistr(privkeys,wifstr);
- V.N = V.M = 2;
- char str[65]; printf("add second privkey.(%s) %s\n",jprint(privkeys,0),bits256_str(str,*privkey2));
- } else V.N = V.M = 1;
- V.suppress_pubkeys = dest->suppress_pubkeys;
- if ( dest->redeemlen != 0 )
- memcpy(V.p2shscript,dest->redeemscript,dest->redeemlen), V.p2shlen = dest->redeemlen;
- txobj = bitcoin_txcreate(rawtx->coin->chain->isPoS,locktime,rawtx->coin->chain->locktime_txversion);
+ V[0].N = V[0].M = 2;
+ //char str[65]; printf("add second privkey.(%s) %s\n",jprint(privkeys,0),bits256_str(str,*privkey2));
+ } else V[0].N = V[0].M = 1;
+ V[0].suppress_pubkeys = dest->I.suppress_pubkeys;
+ V[0].ignore_cltverr = ignore_cltverr;
+ if ( dest->I.redeemlen != 0 )
+ memcpy(V[0].p2shscript,dest->redeemscript,dest->I.redeemlen), V[0].p2shlen = dest->I.redeemlen;
+ txobj = bitcoin_txcreate(rawtx->coin->symbol,rawtx->coin->chain->isPoS,locktime,userdata == 0 ? 1 : 1,timestamp);//rawtx->coin->chain->locktime_txversion);
vins = cJSON_CreateArray();
item = cJSON_CreateObject();
if ( userdata != 0 && userdatalen > 0 )
{
- memcpy(V.userdata,userdata,userdatalen);
- V.userdatalen = userdatalen;
+ memcpy(V[0].userdata,userdata,userdatalen);
+ V[0].userdatalen = userdatalen;
init_hexbytes_noT(hexstr,userdata,userdatalen);
jaddstr(item,"userdata",hexstr);
+#ifdef DISABLE_CHECKSIG
+ needsig = 0;
+#endif
}
- if ( bits256_nonz(rawtx->actualtxid) != 0 )
- jaddbits256(item,"txid",rawtx->actualtxid);
- else jaddbits256(item,"txid",rawtx->signedtxid);
+ //printf("rawtx B\n");
+ if ( bits256_nonz(rawtx->I.actualtxid) != 0 )
+ jaddbits256(item,"txid",rawtx->I.actualtxid);
+ else jaddbits256(item,"txid",rawtx->I.signedtxid);
jaddnum(item,"vout",0);
sobj = cJSON_CreateObject();
- init_hexbytes_noT(hexstr,rawtx->spendscript,rawtx->spendlen);
+ init_hexbytes_noT(hexstr,rawtx->spendscript,rawtx->I.spendlen);
jaddstr(sobj,"hex",hexstr);
jadd(item,"scriptPubKey",sobj);
- jaddnum(item,"suppress",dest->suppress_pubkeys);
- if ( locktime != 0 )
- jaddnum(item,"sequence",0);
- if ( (dest->redeemlen= rawtx->redeemlen) != 0 )
+ jaddnum(item,"suppress",dest->I.suppress_pubkeys);
+ jaddnum(item,"sequence",sequenceid);
+ if ( (dest->I.redeemlen= rawtx->I.redeemlen) != 0 )
{
- init_hexbytes_noT(hexstr,rawtx->redeemscript,rawtx->redeemlen);
- memcpy(dest->redeemscript,rawtx->redeemscript,rawtx->redeemlen);
+ init_hexbytes_noT(hexstr,rawtx->redeemscript,rawtx->I.redeemlen);
+ memcpy(dest->redeemscript,rawtx->redeemscript,rawtx->I.redeemlen);
jaddstr(item,"redeemScript",hexstr);
}
jaddi(vins,item);
jdelete(txobj,"vin");
jadd(txobj,"vin",vins);
- printf("basilisk_rawtx_sign locktime.%u/%u for %s spendscript.%s -> %s, suppress.%d\n",rawtx->locktime,dest->locktime,rawtx->name,hexstr,dest->name,dest->suppress_pubkeys);
- txobj = bitcoin_txoutput(txobj,dest->spendscript,dest->spendlen,dest->amount);
- if ( (rawtxbytes= bitcoin_json2hex(myinfo,rawtx->coin,&dest->txid,txobj,&V)) != 0 )
+ //printf("basilisk_rawtx_sign locktime.%u/%u for %s spendscript.%s -> %s, suppress.%d\n",rawtx->I.locktime,dest->I.locktime,rawtx->name,hexstr,dest->name,dest->I.suppress_pubkeys);
+ txobj = bitcoin_txoutput(txobj,dest->spendscript,dest->I.spendlen,dest->I.amount);
+ if ( (rawtxbytes= bitcoin_json2hex(myinfo,rawtx->coin,&dest->I.txid,txobj,V)) != 0 )
{
- printf("(%s) spend.%s rawtx.(%s) userdatalen.%d p2shlen.%d\n",jprint(txobj,0),rawtx->name,rawtxbytes,userdatalen,dest->redeemlen);
- if ( (signedtx= iguana_signrawtx(myinfo,rawtx->coin,height,&dest->signedtxid,&dest->completed,vins,rawtxbytes,privkeys,&V)) != 0 )
+ //printf("rawtx.(%s) vins.%p\n",rawtxbytes,vins);
+ if ( needsig == 0 )
+ signedtx = rawtxbytes;
+ if ( signedtx != 0 || (signedtx= iguana_signrawtx(myinfo,rawtx->coin,height,&dest->I.signedtxid,&dest->I.completed,vins,rawtxbytes,privkeys,V)) != 0 )
{
- printf("rawtx spend signedtx.(%s)\n",signedtx);
- dest->datalen = (int32_t)strlen(signedtx) >> 1;
- dest->txbytes = calloc(1,dest->datalen);
- decode_hex(dest->txbytes,dest->datalen,signedtx);
- free(signedtx);
- retval = 0;
+ dest->I.datalen = (int32_t)strlen(signedtx) >> 1;
+ if ( dest->I.datalen <= sizeof(dest->txbytes) )
+ decode_hex(dest->txbytes,dest->I.datalen,signedtx);
+ else printf("DEX tx is too big %d vs %d\n",dest->I.datalen,(int32_t)sizeof(dest->txbytes));
+ if ( signedtx != rawtxbytes )
+ free(signedtx);
+ if ( dest->I.completed != 0 )
+ retval = 0;
+ else printf("couldnt complete sign transaction %s\n",rawtx->name);
} else printf("error signing\n");
free(rawtxbytes);
} else printf("error making rawtx\n");
free_json(privkeys);
free_json(txobj);
+ free(V);
+ return(retval);
+}
+
+int32_t basilisk_rawtx_sign(struct supernet_info *myinfo,int32_t height,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr)
+{
+ uint32_t timestamp,locktime=0,sequenceid = 0xffffffff;
+ timestamp = swap->I.started;
+ if ( dest == &swap->aliceclaim )
+ locktime = swap->bobdeposit.I.locktime + 1, sequenceid = 0;
+ else if ( dest == &swap->bobreclaim )
+ locktime = swap->bobpayment.I.locktime + 1, sequenceid = 0;
+ return(_basilisk_rawtx_sign(myinfo,height,timestamp,locktime,sequenceid,dest,rawtx,privkey,privkey2,userdata,userdatalen,ignore_cltverr));
+}
+
+cJSON *basilisk_privkeyarray(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins)
+{
+ cJSON *privkeyarray,*item,*sobj; struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],account[128],wifstr[64],str[65],typestr[64],*hexstr; uint8_t script[1024]; int32_t i,n,len,vout; bits256 txid,privkey; double bidasks[2];
+ privkeyarray = cJSON_CreateArray();
+ //printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr);
+ if ( (n= cJSON_GetArraySize(vins)) > 0 )
+ {
+ for (i=0; i= 0 )
+ {
+ iguana_txidcategory(myinfo,coin,account,coinaddr,txid,vout);
+ if ( coinaddr[0] == 0 && (sobj= jobj(item,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && is_hexstr(hexstr,0) > 0 )
+ {
+ len = (int32_t)strlen(hexstr) >> 1;
+ if ( len < (sizeof(script) << 1) )
+ {
+ decode_hex(script,len,hexstr);
+ if ( len == 25 && script[0] == 0x76 && script[1] == 0xa9 && script[2] == 0x14 )
+ bitcoin_address(coinaddr,coin->chain->pubtype,script+3,20);
+ }
+ }
+ if ( coinaddr[0] != 0 )
+ {
+ if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 )
+ {
+ bitcoin_priv2wif(wifstr,waddr->privkey,coin->chain->wiftype);
+ jaddistr(privkeyarray,waddr->wifstr);
+ }
+ else if ( smartaddress(myinfo,typestr,bidasks,&privkey,coin->symbol,coinaddr) >= 0 )
+ {
+ bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype);
+ jaddistr(privkeyarray,wifstr);
+ }
+ else printf("cant find (%s) in wallet\n",coinaddr);
+ } else printf("cant coinaddr from (%s).v%d\n",bits256_str(str,txid),vout);
+ } else printf("invalid txid/vout %d of %d\n",i,n);
+ }
+ }
+ return(privkeyarray);
+}
+
+int32_t basilisk_rawtx_return(struct supernet_info *myinfo,int32_t height,struct basilisk_rawtx *rawtx,cJSON *item,int32_t lockinputs,struct vin_info *V)
+{
+ char *signedtx,*txbytes; cJSON *vins,*privkeyarray; int32_t i,n,retval = -1;
+ if ( (txbytes= jstr(item,"rawtx")) != 0 && (vins= jobj(item,"vins")) != 0 )
+ {
+ privkeyarray = basilisk_privkeyarray(myinfo,rawtx->coin,vins);
+ if ( (signedtx= iguana_signrawtx(myinfo,rawtx->coin,height,&rawtx->I.signedtxid,&rawtx->I.completed,vins,txbytes,privkeyarray,V)) != 0 )
+ {
+ if ( lockinputs != 0 )
+ {
+ //printf("lockinputs\n");
+ iguana_RTunspentslock(myinfo,rawtx->coin,vins);
+ if ( (n= cJSON_GetArraySize(vins)) != 0 )
+ {
+ bits256 txid; int32_t vout;
+ for (i=0; iI.datalen = (int32_t)strlen(signedtx) >> 1;
+ //rawtx->txbytes = calloc(1,rawtx->I.datalen);
+ decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx);
+ //printf("%s SIGNEDTX.(%s)\n",rawtx->name,signedtx);
+ free(signedtx);
+ retval = 0;
+ } else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll
+ free_json(privkeyarray);
+ }
+ return(retval);
+}
+
+int32_t _basilisk_rawtx_gen(char *str,struct supernet_info *myinfo,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)
+{
+ char *retstr,*jsonstr,scriptstr[1024],coinaddr[64]; uint32_t basilisktag; int32_t flag,i,n,retval = -1; cJSON *addresses,*valsobj,*retarray=0; struct vin_info *V;
+ //bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33);
+ if ( rawtx->coin->changeaddr[0] == 0 )
+ {
+ bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->chain->pubtype,pubkey33,33);
+ printf("set change address.(%s)\n",rawtx->coin->changeaddr);
+ }
+ init_hexbytes_noT(scriptstr,script,scriptlen);
+ basilisktag = (uint32_t)rand();
+ valsobj = cJSON_CreateObject();
+ jaddstr(valsobj,"coin",rawtx->coin->symbol);
+ jaddstr(valsobj,"spendscript",scriptstr);
+ jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr);
+ jadd64bits(valsobj,"satoshis",rawtx->I.amount);
+ if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 )
+ txfee = 50000;
+ jadd64bits(valsobj,"txfee",txfee);
+ jaddnum(valsobj,"minconf",minconf);
+ if ( locktime == 0 )
+ locktime = (uint32_t)time(NULL) - 777;
+ jaddnum(valsobj,"locktime",locktime);
+ jaddnum(valsobj,"timeout",30000);
+ jaddnum(valsobj,"timestamp",swapstarted+delay);
+ addresses = cJSON_CreateArray();
+ bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,pubkey33,33);
+ jaddistr(addresses,coinaddr);
+ jadd(valsobj,"addresses",addresses);
+ rawtx->I.locktime = locktime;
+ printf("%s locktime.%u\n",rawtx->name,locktime);
+ V = calloc(256,sizeof(*V));
+ if ( (retstr= basilisk_bitcoinrawtx(myinfo,rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V)) != 0 )
+ {
+ printf("%s %s basilisk_bitcoinrawtx.(%s) txfee %.8f\n",rawtx->name,str,retstr,dstr(txfee));
+ flag = 0;
+ if ( (retarray= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( is_cJSON_Array(retarray) != 0 )
+ {
+ n = cJSON_GetArraySize(retarray);
+ for (i=0; icoin->longestchain,rawtx,jitem(retarray,i),lockinputs,V)) == 0 )
+ {
+ rawtx->vins = jduplicate(jobj(jitem(retarray,i),"vins"));
+ jsonstr = jprint(rawtx->vins,0);
+ safecopy(rawtx->vinstr,jsonstr,sizeof(rawtx->vinstr));
+ free(jsonstr);
+ break;
+ }
+ }
+ }
+ else
+ {
+ retval = basilisk_rawtx_return(myinfo,rawtx->coin->longestchain,rawtx,retarray,lockinputs,V);
+ rawtx->vins = jduplicate(jobj(retarray,"vins"));
+ jsonstr = jprint(rawtx->vins,0);
+ safecopy(rawtx->vinstr,jsonstr,sizeof(rawtx->vinstr));
+ free(jsonstr);
+ }
+ free(retarray);
+ } else printf("error parsing.(%s)\n",retstr);
+ free(retstr);
+ } else printf("error creating %s %s\n",iambob != 0 ? "BOB" : "ALICE",rawtx->name);
+ free_json(valsobj);
+ free(V);
+ return(retval);
+}
+
+int32_t basilisk_rawtx_gen(char *str,struct supernet_info *myinfo,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)
+{
+ int32_t retval,len; uint64_t newtxfee; struct iguana_info *coin;
+ if ( (coin= rawtx->coin) == 0 || strcmp(coin->symbol,"BTC") != 0 )
+ return(_basilisk_rawtx_gen(str,myinfo,swapstarted,pubkey33,iambob,lockinputs,rawtx,locktime,script,scriptlen,txfee,minconf,delay));
+ retval = _basilisk_rawtx_gen(str,myinfo,swapstarted,pubkey33,iambob,0,rawtx,locktime,script,scriptlen,txfee,minconf,delay);
+ len = rawtx->I.datalen;
+ if ( coin->estimatedfee == 0 )
+ coin->estimatedfee = iguana_getestimatedfee(myinfo,coin);
+ newtxfee = coin->estimatedfee * len;
+ if ( newtxfee > txfee )
+ {
+ retval = _basilisk_rawtx_gen(str,myinfo,swapstarted,pubkey33,iambob,lockinputs,rawtx,locktime,script,scriptlen,newtxfee,minconf,delay);
+ printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee));
+ }
return(retval);
}
struct basilisk_rawtx *basilisk_swapdata_rawtx(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx)
{
- if ( rawtx->txbytes != 0 && rawtx->datalen <= maxlen )
+ if ( rawtx->I.datalen != 0 && rawtx->I.datalen <= maxlen )
{
- memcpy(data,rawtx->txbytes,rawtx->datalen);
+ memcpy(data,rawtx->txbytes,rawtx->I.datalen);
return(rawtx);
}
return(0);
@@ -271,41 +649,65 @@ struct basilisk_rawtx *basilisk_swapdata_rawtx(struct supernet_info *myinfo,stru
int32_t basilisk_verify_otherfee(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
{
struct basilisk_swap *swap = ptr;
- // add verification
- swap->otherfee.txbytes = calloc(1,datalen);
+ // add verification and broadcast
+ //swap->otherfee.txbytes = calloc(1,datalen);
memcpy(swap->otherfee.txbytes,data,datalen);
- swap->otherfee.actualtxid = swap->otherfee.signedtxid = bits256_doublesha256(0,data,datalen);
+ swap->otherfee.I.datalen = datalen;
+ swap->otherfee.I.actualtxid = swap->otherfee.I.signedtxid = bits256_doublesha256(0,data,datalen);
+ basilisk_txlog(myinfo,swap,&swap->otherfee,-1);
return(0);
}
-int32_t basilisk_rawtx_spendscript(struct supernet_info *myinfo,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *data,int32_t datalen,int32_t suppress_pubkeys)
+int32_t basilisk_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys)
{
- int32_t retval=-1,hexlen,n; cJSON *txobj,*skey,*vouts,*vout; char *hexstr;
- if ( rawtx->txbytes == 0 )
+ int32_t datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr; bits256 txid;
+ datalen = recvbuf[0];
+ datalen += (int32_t)recvbuf[1] << 8;
+ if ( datalen > 65536 )
+ return(-1);
+ rawtx->I.redeemlen = recvbuf[2];
+ data = &recvbuf[3];
+ if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 )
+ memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen);
+ //printf("recvlen.%d datalen.%d redeemlen.%d\n",recvlen,datalen,rawtx->redeemlen);
+ if ( rawtx->I.datalen == 0 )
{
- rawtx->txbytes = calloc(1,datalen);
+ //rawtx->txbytes = calloc(1,datalen);
memcpy(rawtx->txbytes,data,datalen);
- rawtx->datalen = datalen;
+ rawtx->I.datalen = datalen;
}
- else if ( datalen != rawtx->datalen || memcmp(rawtx->txbytes,data,datalen) != 0 )
+ else if ( datalen != rawtx->I.datalen || memcmp(rawtx->txbytes,data,datalen) != 0 )
{
- printf("%s rawtx data compare error, len %d vs %d\n",rawtx->name,rawtx->datalen,datalen);
+ int32_t i; for (i=0; iI.datalen; i++)
+ printf("%02x",rawtx->txbytes[i]);
+ printf(" <- rawtx\n");
+ printf("%s rawtx data compare error, len %d vs %d <<<<<<<<<< warning\n",rawtx->name,rawtx->I.datalen,datalen);
return(-1);
}
- if ( (txobj= bitcoin_data2json(rawtx->coin,height,&rawtx->signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),rawtx->txbytes,rawtx->datalen,0,suppress_pubkeys)) != 0 )
+ txid = bits256_doublesha256(0,data,datalen);
+ char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid));
+ if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 )
+ rawtx->I.actualtxid = txid;
+ if ( (txobj= bitcoin_data2json(rawtx->coin,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 )
{
- rawtx->actualtxid = rawtx->signedtxid;
- char str[65]; printf("got txid.%s\n",bits256_str(str,rawtx->signedtxid));
- rawtx->locktime = rawtx->msgtx.lock_time;
+ rawtx->I.actualtxid = rawtx->I.signedtxid;
+ //char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,rawtx->signedtxid),jprint(txobj,0));
+ rawtx->I.locktime = rawtx->msgtx.lock_time;
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n )
{
vout = jitem(vouts,v);
- if ( j64bits(vout,"satoshis") == rawtx->amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 )
+ if ( j64bits(vout,"satoshis") == rawtx->I.amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 )
{
if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) )
{
decode_hex(rawtx->spendscript,hexlen,hexstr);
- rawtx->spendlen = hexlen;
+ rawtx->I.spendlen = hexlen;
+ bitcoin_address(rawtx->p2shaddr,rawtx->coin->chain->p2shtype,rawtx->spendscript,hexlen);
+ if ( swap != 0 )
+ basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment
retval = 0;
}
} else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0));
@@ -315,21 +717,44 @@ int32_t basilisk_rawtx_spendscript(struct supernet_info *myinfo,int32_t height,s
return(retval);
}
-int32_t basilisk_swapuserdata(uint8_t *userdata,int32_t pushpriv,bits256 privkey,uint8_t addrtype,bits256 pubkey,int32_t ifpath)
+void basilisk_swap_coinaddr(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,char *coinaddr,uint8_t *data,int32_t datalen)
{
- int32_t i,len = 0;
- if ( 0 )
+ cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[8192]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0;
+ if ( (txobj= bitcoin_data2json(coin,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 )
{
- userdata[len++] = 33;
- userdata[len++] = addrtype;
- for (i=0; i 0 )
+ {
+ vout = jitem(vouts,0);
+ //printf("VOUT.(%s)\n",jprint(vout,0));
+ if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 )
+ {
+ item = jitem(addresses,0);
+ //printf("item.(%s)\n",jprint(item,0));
+ if ( (addr= jstr(item,0)) != 0 )
+ {
+ safecopy(coinaddr,addr,64);
+ //printf("extracted.(%s)\n",coinaddr);
+ }
+ }
+ }
+ free_json(txobj);
}
- if ( pushpriv != 0 )
+}
+
+int32_t basilisk_swapuserdata(uint8_t *userdata,bits256 privkey,int32_t ifpath,bits256 signpriv,uint8_t *redeemscript,int32_t redeemlen)
+{
+ int32_t i,len = 0;
+#ifdef DISABLE_CHECKSIG
+ userdata[len++] = sizeof(signpriv);
+ for (i=0; i if path, 0 -> else path
return(len);
@@ -342,25 +767,246 @@ int32_t basilisk_swapuserdata(uint8_t *userdata,int32_t pushpriv,bits256 privkey
OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF*/
+void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,int32_t scriptlen)
+{
+ int32_t i; char scriptstr[513];
+ if ( scriptlen != 0 )
+ {
+ for (i=0; iI.req.requestid,swap->I.req.quoteid,rawtx->name), OS_compatible_path(fname);
+ coinaddr[0] = secretAmstr[0] = secretAm256str[0] = secretBnstr[0] = secretBn256str[0] = 0;
+ memset(zeroes,0,sizeof(zeroes));
+ if ( rawtx != 0 && (fp= fopen(fname,"wb")) != 0 )
+ {
+ fprintf(fp,"{\"name\":\"%s\",\"coin\":\"%s\"",rawtx->name,rawtx->coin->symbol);
+ if ( rawtx->I.datalen > 0 )
+ {
+ fprintf(fp,",\"tx\":\"");
+ for (i=0; iI.datalen; i++)
+ fprintf(fp,"%02x",rawtx->txbytes[i]);
+ fprintf(fp,"\",\"txid\":\"%s\"",bits256_str(str,bits256_doublesha256(0,rawtx->txbytes,rawtx->I.datalen)));
+ if ( rawtx == &swap->bobdeposit || rawtx == &swap->bobpayment )
+ {
+ basilisk_swap_coinaddr(myinfo,swap,swap->bobcoin,coinaddr,rawtx->txbytes,rawtx->I.datalen);
+ if ( coinaddr[0] != 0 )
+ {
+ if ( swap->bobcoin != 0 && swap->bobcoin->FULLNODE < 0 )
+ {
+ if ( (tmp= dpow_importaddress(myinfo,swap->bobcoin,coinaddr)) != 0 )
+ free(tmp);
+ }
+ if ( rawtx == &swap->bobdeposit )
+ safecopy(swap->Bdeposit,coinaddr,sizeof(swap->Bdeposit));
+ else safecopy(swap->Bpayment,coinaddr,sizeof(swap->Bpayment));
+ }
+ }
+ }
+ if ( swap->Bdeposit[0] != 0 )
+ fprintf(fp,",\"%s\":\"%s\"","Bdeposit",swap->Bdeposit);
+ if ( swap->Bpayment[0] != 0 )
+ fprintf(fp,",\"%s\":\"%s\"","Bpayment",swap->Bpayment);
+ fprintf(fp,",\"expiration\":%u",swap->I.expiration);
+ fprintf(fp,",\"iambob\":%d",swap->I.iambob);
+ fprintf(fp,",\"bobcoin\":\"%s\"",swap->bobcoin->symbol);
+ fprintf(fp,",\"alicecoin\":\"%s\"",swap->alicecoin->symbol);
+ fprintf(fp,",\"lock\":%u",locktime);
+ fprintf(fp,",\"amount\":%.8f",dstr(rawtx->I.amount));
+ if ( bits256_nonz(triggertxid) != 0 )
+ fprintf(fp,",\"trigger\":\"%s\"",bits256_str(str,triggertxid));
+ if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 )
+ {
+ basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin->chain->p2shtype,swap->I.pubAm,swap->I.pubBn);
+ if ( swap->alicecoin != 0 && swap->alicecoin->FULLNODE < 0 )
+ {
+ if ( (tmp= dpow_importaddress(myinfo,swap->alicecoin,coinaddr)) != 0 )
+ free(tmp);
+ }
+ fprintf(fp,",\"Apayment\":\"%s\"",coinaddr);
+ }
+ /*basilisk_dontforget_userdata("Aclaim",fp,swap->I.userdata_aliceclaim,swap->I.userdata_aliceclaimlen);
+ basilisk_dontforget_userdata("Areclaim",fp,swap->I.userdata_alicereclaim,swap->I.userdata_alicereclaimlen);
+ basilisk_dontforget_userdata("Aspend",fp,swap->I.userdata_alicespend,swap->I.userdata_alicespendlen);
+ basilisk_dontforget_userdata("Bspend",fp,swap->I.userdata_bobspend,swap->I.userdata_bobspendlen);
+ basilisk_dontforget_userdata("Breclaim",fp,swap->I.userdata_bobreclaim,swap->I.userdata_bobreclaimlen);
+ basilisk_dontforget_userdata("Brefund",fp,swap->I.userdata_bobrefund,swap->I.userdata_bobrefundlen);*/
+ fprintf(fp,"}\n");
+ fclose(fp);
+ }
+ sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname);
+ if ( (fp= fopen(fname,"wb")) != 0 )
+ {
+ fprintf(fp,"{\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u",swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime);
+ if ( memcmp(zeroes,swap->I.secretAm,20) != 0 )
+ {
+ init_hexbytes_noT(secretAmstr,swap->I.secretAm,20);
+ fprintf(fp,",\"secretAm\":\"%s\"",secretAmstr);
+ }
+ if ( memcmp(zeroes,swap->I.secretAm256,32) != 0 )
+ {
+ init_hexbytes_noT(secretAm256str,swap->I.secretAm256,32);
+ fprintf(fp,",\"secretAm256\":\"%s\"",secretAm256str);
+ }
+ if ( memcmp(zeroes,swap->I.secretBn,20) != 0 )
+ {
+ init_hexbytes_noT(secretBnstr,swap->I.secretBn,20);
+ fprintf(fp,",\"secretBn\":\"%s\"",secretBnstr);
+ }
+ if ( memcmp(zeroes,swap->I.secretBn256,32) != 0 )
+ {
+ init_hexbytes_noT(secretBn256str,swap->I.secretBn256,32);
+ fprintf(fp,",\"secretBn256\":\"%s\"",secretBn256str);
+ }
+ for (i=0; i<2; i++)
+ if ( bits256_nonz(swap->I.myprivs[i]) != 0 )
+ fprintf(fp,",\"myprivs%d\":\"%s\"",i,bits256_str(str,swap->I.myprivs[i]));
+ if ( bits256_nonz(swap->I.privAm) != 0 )
+ fprintf(fp,",\"privAm\":\"%s\"",bits256_str(str,swap->I.privAm));
+ if ( bits256_nonz(swap->I.privBn) != 0 )
+ fprintf(fp,",\"privBn\":\"%s\"",bits256_str(str,swap->I.privBn));
+ if ( bits256_nonz(swap->I.pubA0) != 0 )
+ fprintf(fp,",\"pubA0\":\"%s\"",bits256_str(str,swap->I.pubA0));
+ if ( bits256_nonz(swap->I.pubB0) != 0 )
+ fprintf(fp,",\"pubB0\":\"%s\"",bits256_str(str,swap->I.pubB0));
+ if ( bits256_nonz(swap->I.pubB1) != 0 )
+ fprintf(fp,",\"pubB1\":\"%s\"",bits256_str(str,swap->I.pubB1));
+ if ( bits256_nonz(swap->bobdeposit.I.actualtxid) != 0 )
+ fprintf(fp,",\"Bdeposit\":\"%s\"",bits256_str(str,swap->bobdeposit.I.actualtxid));
+ if ( bits256_nonz(swap->bobrefund.I.actualtxid) != 0 )
+ fprintf(fp,",\"Brefund\":\"%s\"",bits256_str(str,swap->bobrefund.I.actualtxid));
+ if ( bits256_nonz(swap->aliceclaim.I.actualtxid) != 0 )
+ fprintf(fp,",\"Aclaim\":\"%s\"",bits256_str(str,swap->aliceclaim.I.actualtxid));
+
+ if ( bits256_nonz(swap->bobpayment.I.actualtxid) != 0 )
+ fprintf(fp,",\"Bpayment\":\"%s\"",bits256_str(str,swap->bobpayment.I.actualtxid));
+ if ( bits256_nonz(swap->alicespend.I.actualtxid) != 0 )
+ fprintf(fp,",\"Aspend\":\"%s\"",bits256_str(str,swap->alicespend.I.actualtxid));
+ if ( bits256_nonz(swap->bobreclaim.I.actualtxid) != 0 )
+ fprintf(fp,",\"Breclaim\":\"%s\"",bits256_str(str,swap->bobreclaim.I.actualtxid));
+
+ if ( bits256_nonz(swap->alicepayment.I.actualtxid) != 0 )
+ fprintf(fp,",\"Apayment\":\"%s\"",bits256_str(str,swap->alicepayment.I.actualtxid));
+ if ( bits256_nonz(swap->bobspend.I.actualtxid) != 0 )
+ fprintf(fp,",\"Bspend\":\"%s\"",bits256_str(str,swap->bobspend.I.actualtxid));
+ if ( bits256_nonz(swap->alicereclaim.I.actualtxid) != 0 )
+ fprintf(fp,",\"Areclaim\":\"%s\"",bits256_str(str,swap->alicereclaim.I.actualtxid));
+
+ if ( bits256_nonz(swap->otherfee.I.actualtxid) != 0 )
+ fprintf(fp,",\"otherfee\":\"%s\"",bits256_str(str,swap->otherfee.I.actualtxid));
+ if ( bits256_nonz(swap->myfee.I.actualtxid) != 0 )
+ fprintf(fp,",\"myfee\":\"%s\"",bits256_str(str,swap->myfee.I.actualtxid));
+ fprintf(fp,",\"dest33\":\"");
+ for (i=0; i<33; i++)
+ fprintf(fp,"%02x",swap->persistent_pubkey33[i]);
+ fprintf(fp,"\"}\n");
+ fclose(fp);
+ }
+}
+
+void basilisk_dontforget_update(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx)
+{
+ bits256 triggertxid;
+ memset(triggertxid.bytes,0,sizeof(triggertxid));
+ if ( rawtx == 0 )
+ {
+ basilisk_dontforget(myinfo,swap,0,0,triggertxid);
+ return;
+ }
+ if ( rawtx == &swap->myfee )
+ basilisk_dontforget(myinfo,swap,&swap->myfee,0,triggertxid);
+ else if ( rawtx == &swap->otherfee )
+ basilisk_dontforget(myinfo,swap,&swap->otherfee,0,triggertxid);
+ else if ( rawtx == &swap->bobdeposit )
+ {
+ basilisk_dontforget(myinfo,swap,&swap->bobdeposit,0,triggertxid);
+ basilisk_dontforget(myinfo,swap,&swap->bobrefund,swap->bobdeposit.I.locktime,triggertxid);
+ }
+ else if ( rawtx == &swap->bobrefund )
+ basilisk_dontforget(myinfo,swap,&swap->bobrefund,swap->bobdeposit.I.locktime,triggertxid);
+ else if ( rawtx == &swap->aliceclaim )
+ {
+ basilisk_dontforget(myinfo,swap,&swap->bobrefund,0,triggertxid);
+ basilisk_dontforget(myinfo,swap,&swap->aliceclaim,0,swap->bobrefund.I.actualtxid);
+ }
+ else if ( rawtx == &swap->alicepayment )
+ {
+ basilisk_dontforget(myinfo,swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid);
+ }
+ else if ( rawtx == &swap->bobspend )
+ {
+ basilisk_dontforget(myinfo,swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid);
+ basilisk_dontforget(myinfo,swap,&swap->bobspend,0,swap->alicepayment.I.actualtxid);
+ }
+ else if ( rawtx == &swap->alicereclaim )
+ {
+ basilisk_dontforget(myinfo,swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid);
+ basilisk_dontforget(myinfo,swap,&swap->alicereclaim,0,swap->bobrefund.I.actualtxid);
+ }
+ else if ( rawtx == &swap->bobpayment )
+ {
+ basilisk_dontforget(myinfo,swap,&swap->bobpayment,0,triggertxid);
+ basilisk_dontforget(myinfo,swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid);
+ }
+ else if ( rawtx == &swap->alicespend )
+ {
+ basilisk_dontforget(myinfo,swap,&swap->bobpayment,0,triggertxid);
+ basilisk_dontforget(myinfo,swap,&swap->alicespend,0,triggertxid);
+ }
+ else if ( rawtx == &swap->bobreclaim )
+ basilisk_dontforget(myinfo,swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid);
+}
+
int32_t basilisk_verify_bobdeposit(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
{
- uint8_t userdata[512]; int32_t len = 0; struct basilisk_swap *swap = ptr;
- if ( basilisk_rawtx_spendscript(myinfo,swap->bobcoin->blocks.hwmchain.height,&swap->bobdeposit,0,data,datalen,0) == 0 )
+ uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero; struct basilisk_swap *swap = ptr;
+ if ( basilisk_rawtx_spendscript(swap,swap->bobcoin->longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 )
{
- //len = basilisk_swapuserdata(userdata,0,GENESIS_PRIVKEY,0x02,swap->pubA0,1);
- userdata[len++] = 0x51;
- return(basilisk_rawtx_sign(myinfo,swap->bobcoin->blocks.hwmchain.height,swap,&swap->aliceclaim,&swap->bobdeposit,swap->myprivs[0],0,userdata,len));
+ swap->bobdeposit.I.signedtxid = basilisk_swap_broadcast(swap->bobdeposit.name,myinfo,swap,swap->bobdeposit.coin,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen);
+ if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 )
+ swap->depositunconf = 1;
+ basilisk_dontforget_update(myinfo,swap,&swap->bobdeposit);
+ len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
+ memcpy(swap->I.userdata_aliceclaim,userdata,len);
+ swap->I.userdata_aliceclaimlen = len;
+ if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1)) == 0 )
+ {
+ for (i=0; ibobdeposit.I.datalen; i++)
+ printf("%02x",swap->bobdeposit.txbytes[i]);
+ printf(" <- bobdeposit\n");
+ for (i=0; ialiceclaim.I.datalen; i++)
+ printf("%02x",swap->aliceclaim.txbytes[i]);
+ printf(" <- aliceclaim\n");
+ basilisk_txlog(myinfo,swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration);
+ return(retval);
+ }
}
printf("error with bobdeposit\n");
return(-1);
}
-int32_t basilisk_bobdeposit_refund(struct supernet_info *myinfo,struct basilisk_swap *swap)
+int32_t basilisk_bobdeposit_refund(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t delay)
{
- uint8_t userdata[512]; int32_t len = 0;
- printf("basilisk_bobdeposit_refund\n");
- len = basilisk_swapuserdata(userdata,1,swap->privBn,0x03,swap->pubB0,0);
- return(basilisk_rawtx_sign(myinfo,swap->bobcoin->blocks.hwmchain.height,swap,&swap->bobrefund,&swap->bobdeposit,swap->myprivs[0],0,userdata,len));
+ uint8_t userdata[512]; int32_t i,retval,len = 0; char str[65];
+ len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
+ memcpy(swap->I.userdata_bobrefund,userdata,len);
+ swap->I.userdata_bobrefundlen = len;
+ if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0)) == 0 )
+ {
+ for (i=0; ibobrefund.I.datalen; i++)
+ printf("%02x",swap->bobrefund.txbytes[i]);
+ printf(" <- bobrefund.(%s)\n",bits256_str(str,swap->bobrefund.I.txid));
+ basilisk_txlog(myinfo,swap,&swap->bobrefund,delay);
+ return(retval);
+ }
+ return(-1);
}
/*Bob paytx:
@@ -370,55 +1016,108 @@ int32_t basilisk_bobdeposit_refund(struct supernet_info *myinfo,struct basilisk_
OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF*/
-int32_t basilisk_bobpayment_reclaim(struct supernet_info *myinfo,struct basilisk_swap *swap)
+int32_t basilisk_bobpayment_reclaim(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t delay)
{
- uint8_t userdata[512]; int32_t len = 0;
+ uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero;
printf("basilisk_bobpayment_reclaim\n");
- userdata[len++] = 0x51;
- //len = basilisk_swapuserdata(userdata,0,GENESIS_PRIVKEY,0x03,swap->pubB1,1);
- return(basilisk_rawtx_sign(myinfo,swap->bobcoin->blocks.hwmchain.height,swap,&swap->bobreclaim,&swap->bobpayment,swap->myprivs[1],0,userdata,len));
+ len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
+ memcpy(swap->I.userdata_bobreclaim,userdata,len);
+ swap->I.userdata_bobreclaimlen = len;
+ if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1)) == 0 )
+ {
+ for (i=0; ibobreclaim.I.datalen; i++)
+ printf("%02x",swap->bobreclaim.txbytes[i]);
+ printf(" <- bobreclaim\n");
+ basilisk_txlog(myinfo,swap,&swap->bobreclaim,delay);
+ return(retval);
+ }
+ return(-1);
}
int32_t basilisk_verify_bobpaid(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
{
- uint8_t userdata[512]; int32_t len = 0; struct basilisk_swap *swap = ptr;
- if ( basilisk_rawtx_spendscript(myinfo,swap->bobcoin->blocks.hwmchain.height,&swap->bobpayment,0,data,datalen,0) == 0 )
+ uint8_t userdata[512]; int32_t i,retval,len = 0; bits256 revAm; struct basilisk_swap *swap = ptr;
+ memset(revAm.bytes,0,sizeof(revAm));
+ if ( basilisk_rawtx_spendscript(swap,swap->bobcoin->longestchain,&swap->bobpayment,0,data,datalen,0) == 0 )
{
- len = basilisk_swapuserdata(userdata,1,swap->privAm,0x02,swap->pubA0,0);
- char str[65]; printf("bobpaid.(%s)\n",bits256_str(str,swap->privAm));
- return(basilisk_rawtx_sign(myinfo,swap->bobcoin->blocks.hwmchain.height,swap,&swap->alicespend,&swap->bobpayment,swap->myprivs[0],0,userdata,len));
- } else return(-1);
+ swap->bobpayment.I.signedtxid = basilisk_swap_broadcast(swap->bobpayment.name,myinfo,swap,swap->bobpayment.coin,swap->bobpayment.txbytes,swap->bobpayment.I.datalen);
+ if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 )
+ swap->paymentunconf = 1;
+ basilisk_dontforget_update(myinfo,swap,&swap->bobpayment);
+ for (i=0; i<32; i++)
+ revAm.bytes[i] = swap->I.privAm.bytes[31-i];
+ len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
+ memcpy(swap->I.userdata_alicespend,userdata,len);
+ swap->I.userdata_alicespendlen = len;
+ char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0]));
+ if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1)) == 0 )
+ {
+ for (i=0; ibobpayment.I.datalen; i++)
+ printf("%02x",swap->bobpayment.txbytes[i]);
+ printf(" <- bobpayment\n");
+ for (i=0; ialicespend.I.datalen; i++)
+ printf("%02x",swap->alicespend.txbytes[i]);
+ printf(" <- alicespend\n\n");
+ swap->I.alicespent = 1;
+ basilisk_txlog(myinfo,swap,&swap->alicespend,-1);
+ return(retval);
+ }
+ }
+ return(-1);
+}
+
+void basilisk_alicepayment(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn)
+{
+ alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->chain->p2shtype,pubAm,pubBn);
+ basilisk_rawtx_gen("alicepayment",myinfo,swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,coin->chain->txfee,1,0);
}
int32_t basilisk_alicepayment_spend(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *dest)
{
+ int32_t i,retval;
printf("alicepayment_spend\n");
- return(basilisk_rawtx_sign(myinfo,swap->alicecoin->blocks.hwmchain.height,swap,dest,&swap->alicepayment,swap->privAm,&swap->privBn,0,0));
+ swap->alicepayment.I.spendlen = basilisk_alicescript(swap->alicepayment.redeemscript,&swap->alicepayment.I.redeemlen,swap->alicepayment.spendscript,0,swap->alicepayment.I.destaddr,swap->alicecoin->chain->p2shtype,swap->I.pubAm,swap->I.pubBn);
+ printf("alicepayment_spend len.%d\n",swap->alicepayment.I.spendlen);
+ if ( swap->I.iambob == 0 )
+ {
+ memcpy(swap->I.userdata_alicereclaim,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen);
+ swap->I.userdata_alicereclaimlen = swap->alicepayment.I.spendlen;
+ }
+ else
+ {
+ memcpy(swap->I.userdata_bobspend,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen);
+ swap->I.userdata_bobspendlen = swap->alicepayment.I.spendlen;
+ }
+ if ( (retval= basilisk_rawtx_sign(myinfo,swap->alicecoin->longestchain,swap,dest,&swap->alicepayment,swap->I.privAm,&swap->I.privBn,0,0,1)) == 0 )
+ {
+ for (i=0; iI.datalen; i++)
+ printf("%02x",dest->txbytes[i]);
+ printf(" <- msigspend\n\n");
+ if ( dest == &swap->bobspend )
+ swap->I.bobspent = 1;
+ basilisk_txlog(myinfo,swap,dest,0); // bobspend or alicereclaim
+ return(retval);
+ }
+ return(-1);
}
int32_t basilisk_verify_alicepaid(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
{
struct basilisk_swap *swap = ptr;
- if ( basilisk_rawtx_spendscript(myinfo,swap->alicecoin->blocks.hwmchain.height,&swap->alicepayment,0,data,datalen,0) == 0 )
- return(0);
- else return(-1);
-}
-
-int32_t basilisk_privAm_extract(struct supernet_info *myinfo,struct basilisk_swap *swap)
-{
- // need to scan blockchain for alicespend of bobpayment
- // search for swap->bobpayment.actualtxid in spends
- if ( bits256_nonz(swap->privAm) != 0 && swap->bobspend.txbytes == 0 )
+ if ( basilisk_rawtx_spendscript(swap,swap->alicecoin->longestchain,&swap->alicepayment,0,data,datalen,0) == 0 )
{
- char str[65]; printf("have privAm.%s\n",bits256_str(str,swap->privAm));
- return(basilisk_alicepayment_spend(myinfo,swap,&swap->bobspend));
+ swap->alicepayment.I.signedtxid = basilisk_swap_broadcast(swap->alicepayment.name,myinfo,swap,swap->alicepayment.coin,swap->alicepayment.txbytes,swap->alicepayment.I.datalen);
+ if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 )
+ swap->aliceunconf = 1;
+ basilisk_dontforget_update(myinfo,swap,&swap->alicepayment);
+ return(0);
}
- return(-1);
+ else return(-1);
}
int32_t basilisk_verify_pubpair(int32_t *wrongfirstbytep,struct basilisk_swap *swap,int32_t ind,uint8_t pub0,bits256 pubi,uint64_t txid)
{
- if ( pub0 != (swap->iambob ^ 1) + 0x02 )
+ if ( pub0 != (swap->I.iambob ^ 1) + 0x02 )
{
(*wrongfirstbytep)++;
printf("wrongfirstbyte[%d] %02x\n",ind,pub0);
@@ -437,21 +1136,113 @@ int32_t basilisk_verify_pubpair(int32_t *wrongfirstbytep,struct basilisk_swap *s
return(0);
}
+int32_t basilisk_bobscripts_set(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t depositflag,int32_t genflag)
+{
+ int32_t i,j; //char str[65];
+ if ( genflag != 0 && swap->I.iambob == 0 )
+ printf("basilisk_bobscripts_set WARNING: alice generating BOB tx\n");
+ if ( depositflag == 0 )
+ {
+ swap->bobpayment.I.spendlen = basilisk_bobscript(swap->bobpayment.I.rmd160,swap->bobpayment.redeemscript,&swap->bobpayment.I.redeemlen,swap->bobpayment.spendscript,0,&swap->bobpayment.I.locktime,&swap->bobpayment.I.secretstart,&swap->I,0);
+ bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin->chain->p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
+ //for (i=0; ibobpayment.redeemlen; i++)
+ // printf("%02x",swap->bobpayment.redeemscript[i]);
+ //printf(" <- bobpayment.%d\n",i);
+ if ( genflag != 0 && bits256_nonz(*(bits256 *)swap->I.secretBn256) != 0 && swap->bobpayment.I.datalen == 0 )
+ {
+ for (i=0; i<3; i++)
+ {
+ //if ( swap->bobpayment.txbytes != 0 && swap->bobpayment.I.spendlen != 0 )
+ // break;
+ basilisk_rawtx_gen("payment",myinfo,swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobpayment,swap->bobpayment.I.locktime,swap->bobpayment.spendscript,swap->bobpayment.I.spendlen,swap->bobpayment.coin->chain->txfee,1,0);
+ if ( swap->bobpayment.I.spendlen == 0 || swap->bobpayment.I.datalen == 0 )
+ {
+ printf("error bob generating %p payment.%d\n",swap->bobpayment.txbytes,swap->bobpayment.I.spendlen);
+ sleep(DEX_SLEEP);
+ }
+ else
+ {
+ for (j=0; jbobpayment.I.datalen; j++)
+ printf("%02x",swap->bobpayment.txbytes[j]);
+ //printf(" <- bobpayment.%d\n",swap->bobpayment.datalen);
+ //for (j=0; jbobpayment.redeemlen; j++)
+ // printf("%02x",swap->bobpayment.redeemscript[j]);
+ //printf(" <- redeem.%d\n",swap->bobpayment.redeemlen);
+ printf(" <- GENERATED BOB PAYMENT.%d\n",swap->bobpayment.I.datalen);
+ iguana_unspents_mark(myinfo,swap->bobcoin,swap->bobpayment.vins);
+ basilisk_bobpayment_reclaim(myinfo,swap,swap->I.callduration);
+ printf("bobscripts set completed\n");
+ return(0);
+ }
+ }
+ }
+ }
+ else
+ {
+ swap->bobdeposit.I.spendlen = basilisk_bobscript(swap->bobdeposit.I.rmd160,swap->bobdeposit.redeemscript,&swap->bobdeposit.I.redeemlen,swap->bobdeposit.spendscript,0,&swap->bobdeposit.I.locktime,&swap->bobdeposit.I.secretstart,&swap->I,1);
+ bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin->chain->p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
+ if ( genflag != 0 && (swap->bobdeposit.I.datalen == 0 || swap->bobrefund.I.datalen == 0) )
+ {
+ for (i=0; i<3; i++)
+ {
+ //if ( swap->bobdeposit.txbytes != 0 && swap->bobdeposit.I.spendlen != 0 )
+ // break;
+ basilisk_rawtx_gen("deposit",myinfo,swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobdeposit,swap->bobdeposit.I.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.I.spendlen,swap->bobdeposit.coin->chain->txfee,1,0);
+ if ( swap->bobdeposit.I.datalen == 0 || swap->bobdeposit.I.spendlen == 0 )
+ {
+ printf("error bob generating %p deposit.%d\n",swap->bobdeposit.txbytes,swap->bobdeposit.I.spendlen);
+ sleep(DEX_SLEEP);
+ }
+ else
+ {
+ for (j=0; jbobdeposit.I.datalen; j++)
+ printf("%02x",swap->bobdeposit.txbytes[j]);
+ printf(" <- GENERATED BOB DEPOSIT.%d\n",swap->bobdeposit.I.datalen);
+ //for (j=0; jbobdeposit.redeemlen; j++)
+ // printf("%02x",swap->bobdeposit.redeemscript[j]);
+ //printf(" <- redeem.%d\n",swap->bobdeposit.redeemlen);
+ //printf("GENERATED BOB DEPOSIT\n");
+ iguana_unspents_mark(myinfo,swap->bobcoin,swap->bobdeposit.vins);
+ basilisk_bobdeposit_refund(myinfo,swap,swap->I.putduration);
+ printf("bobscripts set completed\n");
+ return(0);
+ }
+ }
+ }
+ //for (i=0; ibobdeposit.redeemlen; i++)
+ // printf("%02x",swap->bobdeposit.redeemscript[i]);
+ //printf(" <- bobdeposit.%d\n",i);
+ }
+ return(0);
+}
+
int32_t basilisk_verify_privi(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
{
- int32_t j,wrongfirstbyte,len = 0; bits256 privkey,pubi; uint8_t secret160[20],pubkey33[33]; uint64_t txid; struct basilisk_swap *swap = ptr;
+ int32_t j,wrongfirstbyte,len = 0; bits256 privkey,pubi; char str[65],str2[65]; uint8_t secret160[20],pubkey33[33]; uint64_t txid; struct basilisk_swap *swap = ptr;
+ memset(privkey.bytes,0,sizeof(privkey));
if ( datalen == sizeof(bits256) )
{
for (j=0; j<32; j++)
privkey.bytes[j] = data[len++];
- calc_rmd160_sha256(secret160,privkey.bytes,sizeof(privkey));
+ revcalc_rmd160_sha256(secret160,privkey);//.bytes,sizeof(privkey));
memcpy(&txid,secret160,sizeof(txid));
pubi = bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey);
- if ( basilisk_verify_pubpair(&wrongfirstbyte,swap,swap->choosei,pubkey33[0],pubi,txid) == 0 )
+ if ( basilisk_verify_pubpair(&wrongfirstbyte,swap,swap->I.choosei,pubkey33[0],pubi,txid) == 0 )
{
- if ( swap->iambob != 0 )
- swap->privAm = privkey;
- else swap->privBn = privkey;
+ if ( swap->I.iambob != 0 )
+ {
+ swap->I.privAm = privkey;
+ vcalc_sha256(0,swap->I.secretAm256,privkey.bytes,sizeof(privkey));
+ printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256));
+ basilisk_bobscripts_set(myinfo,swap,0,1);
+ }
+ else
+ {
+ swap->I.privBn = privkey;
+ vcalc_sha256(0,swap->I.secretBn256,privkey.bytes,sizeof(privkey));
+ printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256));
+ }
+ basilisk_dontforget_update(myinfo,swap,0);
char str[65]; printf("privi verified.(%s)\n",bits256_str(str,privkey));
return(0);
}
@@ -459,390 +1250,626 @@ int32_t basilisk_verify_privi(struct supernet_info *myinfo,void *ptr,uint8_t *da
return(-1);
}
-int32_t basilisk_process_swapget(struct supernet_info *myinfo,void *ptr,int32_t (*internal_func)(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen),uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t expiration,uint32_t duration)
+int32_t basilisk_process_swapverify(struct supernet_info *myinfo,void *ptr,int32_t (*internal_func)(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen),uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t expiration,uint32_t duration)
{
struct basilisk_swap *swap = ptr;
- return((*internal_func)(myinfo,swap,data,datalen));
+ if ( internal_func != 0 )
+ return((*internal_func)(myinfo,swap,data,datalen));
+ else return(0);
+}
+
+void basilisk_swapgotdata(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t crc32,bits256 srchash,bits256 desthash,uint32_t quoteid,uint32_t msgbits,uint8_t *data,int32_t datalen,int32_t reinit)
+{
+ int32_t i; struct basilisk_swapmessage *mp;
+ for (i=0; inummessages; i++)
+ if ( crc32 == swap->messages[i].crc32 && msgbits == swap->messages[i].msgbits && bits256_cmp(srchash,swap->messages[i].srchash) == 0 && bits256_cmp(desthash,swap->messages[i].desthash) == 0 )
+ return;
+ //printf(" new message.[%d] datalen.%d Q.%x msg.%x [%llx]\n",swap->nummessages,datalen,quoteid,msgbits,*(long long *)data);
+ swap->messages = realloc(swap->messages,sizeof(*swap->messages) * (swap->nummessages + 1));
+ mp = &swap->messages[swap->nummessages++];
+ mp->crc32 = crc32;
+ mp->srchash = srchash;
+ mp->desthash = desthash;
+ mp->msgbits = msgbits;
+ mp->quoteid = quoteid;
+ mp->data = malloc(datalen);
+ mp->datalen = datalen;
+ memcpy(mp->data,data,datalen);
+ if ( reinit == 0 && swap->fp != 0 )
+ {
+ fwrite(mp,1,sizeof(*mp),swap->fp);
+ fwrite(data,1,datalen,swap->fp);
+ fflush(swap->fp);
+ }
+}
+
+FILE *basilisk_swap_save(struct supernet_info *myinfo,struct basilisk_swap *swap,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit)
+{
+ FILE *fp=0; /*char fname[512];
+ sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,rp->requestid,rp->quoteid), OS_compatible_path(fname);
+ if ( (fp= fopen(fname,"rb+")) == 0 )
+ {
+ if ( (fp= fopen(fname,"wb+")) != 0 )
+ {
+ fwrite(privkey.bytes,1,sizeof(privkey),fp);
+ fwrite(rp,1,sizeof(*rp),fp);
+ fwrite(&statebits,1,sizeof(statebits),fp);
+ fwrite(&optionduration,1,sizeof(optionduration),fp);
+ fflush(fp);
+ }
+ }
+ else if ( reinit != 0 )
+ {
+ }*/
+ return(fp);
+}
+
+int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp)
+{
+ FILE *fp=0; char fname[512]; int32_t retval = -1;
+ sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname);
+ if ( (fp= fopen(fname,"rb+")) != 0 )
+ {
+ if ( fread(privkeyp,1,sizeof(*privkeyp),fp) == sizeof(*privkeyp) &&
+ fread(rp,1,sizeof(*rp),fp) == sizeof(*rp) &&
+ fread(statebitsp,1,sizeof(*statebitsp),fp) == sizeof(*statebitsp) &&
+ fread(optiondurationp,1,sizeof(*optiondurationp),fp) == sizeof(*optiondurationp) )
+ retval = 0;
+ fclose(fp);
+ }
+ return(retval);
+}
+
+struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit);
+
+void basilisk_swaps_init(struct supernet_info *myinfo)
+{
+ char fname[512]; uint32_t iter,swapcompleted,requestid,quoteid,optionduration,statebits; FILE *fp; bits256 privkey;struct basilisk_request R; struct basilisk_swapmessage M; struct basilisk_swap *swap = 0;
+ sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
+ if ( (myinfo->swapsfp= fopen(fname,"rb+")) != 0 )
+ {
+ while ( fread(&requestid,1,sizeof(requestid),myinfo->swapsfp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),myinfo->swapsfp) == sizeof(quoteid) )
+ {
+ sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname);
+ printf("%s\n",fname);
+ if ( (fp= fopen(fname,"rb+")) != 0 ) // check to see if completed
+ {
+ memset(&M,0,sizeof(M));
+ swapcompleted = 1;
+ for (iter=0; iter<2; iter++)
+ {
+ if ( fread(privkey.bytes,1,sizeof(privkey),fp) == sizeof(privkey) &&
+ fread(&R,1,sizeof(R),fp) == sizeof(R) &&
+ fread(&statebits,1,sizeof(statebits),fp) == sizeof(statebits) &&
+ fread(&optionduration,1,sizeof(optionduration),fp) == sizeof(optionduration) )
+ {
+ while ( 0 && fread(&M,1,sizeof(M),fp) == sizeof(M) )
+ {
+ M.data = 0;
+ //printf("entry iter.%d crc32.%x datalen.%d\n",iter,M.crc32,M.datalen);
+ if ( M.datalen < 100000 )
+ {
+ M.data = malloc(M.datalen);
+ if ( fread(M.data,1,M.datalen,fp) == M.datalen )
+ {
+ if ( calc_crc32(0,M.data,M.datalen) == M.crc32 )
+ {
+ if ( iter == 1 )
+ {
+ if ( swap == 0 )
+ {
+ swap = basilisk_thread_start(myinfo,privkey,&R,statebits,optionduration,1);
+ swap->I.choosei = swap->I.otherchoosei = -1;
+ }
+ if ( swap != 0 )
+ basilisk_swapgotdata(myinfo,swap,M.crc32,M.srchash,M.desthash,M.quoteid,M.msgbits,M.data,M.datalen,1);
+ }
+ } else printf("crc mismatch %x vs %x\n",calc_crc32(0,M.data,M.datalen),M.crc32);
+ } else printf("error reading M.datalen %d\n",M.datalen);
+ free(M.data), M.data = 0;
+ }
+ }
+ }
+ if ( swapcompleted != 0 )
+ break;
+ rewind(fp);
+ }
+ }
+ }
+ } else myinfo->swapsfp = fopen(fname,"wb+");
}
+void basilisk_psockinit(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t amlp);
+
int32_t basilisk_swapget(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,int32_t (*basilisk_verify_func)(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen))
{
- int32_t retval; cJSON *retarray;
- if ( (retarray= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,msgbits,0)) != 0 )
+ uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0;
+ while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 )
{
- retval = basilisk_process_retarray(myinfo,swap,basilisk_process_swapget,data,maxlen,swap->req.quoteid,msgbits,retarray,basilisk_verify_func);
- if ( retval > 0 )
- return(0);
- //return((*basilisk_verify_func)(myinfo,swap,data,datalen));
+ swap->lasttime = (uint32_t)time(NULL);
+ memset(srchash.bytes,0,sizeof(srchash));
+ memset(desthash.bytes,0,sizeof(desthash));
+ //printf("gotmsg.[%d] crc.%x\n",size,crc32);
+ offset = 0;
+ for (i=0; i<32; i++)
+ srchash.bytes[i] = ptr[offset++];
+ for (i=0; i<32; i++)
+ desthash.bytes[i] = ptr[offset++];
+ offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),"eid);
+ offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),&_msgbits);
+ if ( size > offset )
+ {
+ crc32 = calc_crc32(0,&ptr[offset],size-offset);
+ if ( size > offset )
+ {
+ //printf("size.%d offset.%d datalen.%d\n",size,offset,size-offset);
+ basilisk_swapgotdata(myinfo,swap,crc32,srchash,desthash,quoteid,_msgbits,&ptr[offset],size-offset,0);
+ }
+ }
+ else if ( bits256_nonz(srchash) == 0 && bits256_nonz(desthash) == 0 )
+ {
+ if ( swap->aborted == 0 )
+ {
+ swap->aborted = (uint32_t)time(NULL);
+ printf("got abort signal from other side\n");
+ }
+ } else printf("basilisk_swapget: got strange packet\n");
+ if ( ptr != 0 )
+ nn_freemsg(ptr), ptr = 0;
}
- return(-1);
+ //char str[65],str2[65];
+ for (i=0; inummessages; i++)
+ {
+ //printf("%d: %s vs %s\n",i,bits256_str(str,swap->messages[i].srchash),bits256_str(str2,swap->messages[i].desthash));
+ if ( bits256_cmp(swap->messages[i].desthash,swap->I.myhash) == 0 )
+ {
+ if ( swap->messages[i].msgbits == msgbits )
+ {
+ if ( swap->I.iambob == 0 && swap->lasttime != 0 && time(NULL) > swap->lasttime+360 )
+ {
+ printf("nothing received for a while from Bob, try new sockets\n");
+ if ( swap->pushsock >= 0 ) //
+ nn_close(swap->pushsock), swap->pushsock = -1;
+ if ( swap->subsock >= 0 ) //
+ nn_close(swap->subsock), swap->subsock = -1;
+ swap->connected = 0;
+ basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
+ }
+ mp = &swap->messages[i];
+ if ( msgbits != 0x80000000 )
+ break;
+ }
+ }
+ }
+ if ( mp != 0 )
+ retval = (*basilisk_verify_func)(myinfo,swap,mp->data,mp->datalen);
+ //printf("mine/other %s vs %s\n",bits256_str(str,swap->I.myhash),bits256_str(str2,swap->I.otherhash));
+ return(retval);
}
-int32_t basilisk_privBn_extract(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
+uint32_t basilisk_swapsend(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits,uint32_t crcs[2])
+{
+ uint8_t *buf; int32_t sentbytes,offset=0,i;
+ buf = malloc(datalen + sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2);
+ for (i=0; i<32; i++)
+ buf[offset++] = swap->I.myhash.bytes[i];
+ for (i=0; i<32; i++)
+ buf[offset++] = swap->I.otherhash.bytes[i];
+ offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid);
+ offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits);
+ if ( datalen > 0 )
+ memcpy(&buf[offset],data,datalen), offset += datalen;
+ if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset )
+ {
+ printf("sentbytes.%d vs offset.%d\n",sentbytes,offset);
+ if ( sentbytes < 0 )
+ {
+ if ( swap->pushsock >= 0 )
+ nn_close(swap->pushsock), swap->pushsock = -1; //,
+ if ( swap->subsock >= 0 ) //
+ nn_close(swap->subsock), swap->subsock = -1;
+ swap->connected = swap->I.iambob != 0 ? -1 : 0;
+ swap->aborted = (uint32_t)time(NULL);
+ }
+ }
+ //else printf("send.[%d] %x offset.%d datalen.%d [%llx]\n",sentbytes,msgbits,offset,datalen,*(long long *)data);
+ free(buf);
+ return(nextbits);
+}
+
+void basilisk_swap_sendabort(struct supernet_info *myinfo,struct basilisk_swap *swap)
{
- // need to scan blockchain for bobrefund
- // search for swap->bobrefund.actualtxid in spends
- if ( basilisk_swapget(myinfo,swap,0x40000000,data,maxlen,basilisk_verify_privi) == 0 )
+ uint32_t msgbits = 0; uint8_t buf[sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2]; int32_t sentbytes,offset=0;
+ memset(buf,0,sizeof(buf));
+ offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid);
+ offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits);
+ if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset )
{
- if ( bits256_nonz(swap->privBn) != 0 && swap->alicereclaim.txbytes == 0 )
+ if ( sentbytes < 0 )
{
- char str[65]; printf("have privBn.%s\n",bits256_str(str,swap->privBn));
- return(basilisk_alicepayment_spend(myinfo,swap,&swap->alicereclaim));
+ if ( swap->pushsock >= 0 ) //
+ nn_close(swap->pushsock), swap->pushsock = -1;
+ if ( swap->subsock >= 0 ) //
+ nn_close(swap->subsock), swap->subsock = -1;
+ swap->connected = 0;
}
+ } else printf("basilisk_swap_sendabort\n");
+}
+
+int32_t basilisk_privBn_extract(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
+{
+ if ( basilisk_priviextract(myinfo,swap->bobcoin,"privBn",&swap->I.privBn,swap->I.secretBn,swap->bobrefund.I.actualtxid,0) == 0 )
+ {
+ printf("extracted privBn from blockchain\n");
+ }
+ else if ( basilisk_swapget(myinfo,swap,0x40000000,data,maxlen,basilisk_verify_privi) == 0 )
+ {
+ }
+ if ( bits256_nonz(swap->I.privBn) != 0 && swap->alicereclaim.I.datalen == 0 )
+ {
+ char str[65]; printf("got privBn.%s\n",bits256_str(str,swap->I.privBn));
+ return(basilisk_alicepayment_spend(myinfo,swap,&swap->alicereclaim));
+ }
+ return(-1);
+}
+
+int32_t basilisk_privAm_extract(struct supernet_info *myinfo,struct basilisk_swap *swap)
+{
+ if ( basilisk_priviextract(myinfo,swap->bobcoin,"privAm",&swap->I.privAm,swap->I.secretAm,swap->bobpayment.I.actualtxid,0) == 0 )
+ {
+ printf("extracted privAm from blockchain\n");
+ }
+ if ( bits256_nonz(swap->I.privAm) != 0 && swap->bobspend.I.datalen == 0 )
+ {
+ char str[65]; printf("got privAm.%s\n",bits256_str(str,swap->I.privAm));
+ return(basilisk_alicepayment_spend(myinfo,swap,&swap->bobspend));
}
return(-1);
}
-// end of coin protocol dependent
-bits256 instantdex_derivekeypair(struct supernet_info *myinfo,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash)
+bits256 instantdex_derivekeypair(void *ctx,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash)
{
bits256 sharedsecret;
sharedsecret = curve25519_shared(privkey,orderhash);
vcalc_sha256cat(newprivp->bytes,orderhash.bytes,sizeof(orderhash),sharedsecret.bytes,sizeof(sharedsecret));
- return(bitcoin_pubkey33(myinfo->ctx,pubkey,*newprivp));
+ return(bitcoin_pubkey33(ctx,pubkey,*newprivp));
}
-int32_t instantdex_pubkeyargs(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte)
+int32_t instantdex_pubkeyargs(void *ctx,struct basilisk_swap *swap,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte)
{
- char buf[3]; int32_t i,n,m,len=0; bits256 pubi; uint64_t txid; uint8_t secret160[20],pubkey[33];
+ char buf[3]; int32_t i,n,m,len=0; bits256 pubi,reveal; uint64_t txid; uint8_t secret160[20],pubkey[33];
sprintf(buf,"%c0",'A' - 0x02 + firstbyte);
if ( numpubs > 2 )
{
- if ( swap->numpubs+2 >= numpubs )
+ if ( swap->I.numpubs+2 >= numpubs )
return(numpubs);
- printf(">>>>>> start generating %s\n",buf);
+ //fprintf(stderr,">>>>>> start generating %s\n",buf);
}
for (i=n=m=0; imypubs[n]) == 0 )
+ if ( bits256_nonz(swap->I.mypubs[n]) == 0 )
{
- swap->myprivs[n] = privkey;
- memcpy(swap->mypubs[n].bytes,pubkey+1,sizeof(bits256));
- if ( swap->iambob != 0 )
+ swap->I.myprivs[n] = privkey;
+ memcpy(swap->I.mypubs[n].bytes,pubkey+1,sizeof(bits256));
+ reveal = basilisk_revealkey(privkey,swap->I.mypubs[n]);
+ if ( swap->I.iambob != 0 )
{
if ( n == 0 )
- swap->pubB0 = swap->mypubs[n];
+ swap->I.pubB0 = reveal;
else if ( n == 1 )
- swap->pubB1 = swap->mypubs[n];
+ swap->I.pubB1 = reveal;
}
- else if ( swap->iambob == 0 )
+ else if ( swap->I.iambob == 0 )
{
if ( n == 0 )
- swap->pubA0 = swap->mypubs[n];
+ swap->I.pubA0 = reveal;
else if ( n == 1 )
- swap->pubA1 = swap->mypubs[n];
+ swap->I.pubA1 = reveal;
}
}
}
if ( m < INSTANTDEX_DECKSIZE )
{
swap->privkeys[m] = privkey;
- calc_rmd160_sha256(secret160,privkey.bytes,sizeof(privkey));
+ revcalc_rmd160_sha256(secret160,privkey);//.bytes,sizeof(privkey));
memcpy(&txid,secret160,sizeof(txid));
len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][0],sizeof(txid),&txid);
len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][1],sizeof(pubi.txid),&pubi.txid);
m++;
- if ( m > swap->numpubs )
- swap->numpubs = m;
+ if ( m > swap->I.numpubs )
+ swap->I.numpubs = m;
}
n++;
}
if ( n > 2 || m > 2 )
- printf("n.%d m.%d len.%d numpubs.%d\n",n,m,len,swap->numpubs);
+ printf("n.%d m.%d len.%d numpubs.%d\n",n,m,len,swap->I.numpubs);
return(n);
}
-int32_t basilisk_rawtx_return(struct supernet_info *myinfo,int32_t height,struct basilisk_rawtx *rawtx,cJSON *item,cJSON *privkeyarray,int32_t lockinputs)
+void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33,int32_t jumblrflag)
{
- char *signedtx,*txbytes; cJSON *vins; int32_t i,n,retval = -1;
- if ( (txbytes= jstr(item,"rawtx")) != 0 && (vins= jobj(item,"vins")) != 0 )
+ strcpy(rawtx->name,name);
+ rawtx->coin = coin;
+ strcpy(rawtx->I.coinstr,coin->symbol);
+ rawtx->I.numconfirms = numconfirms;
+ if ( (rawtx->I.amount= satoshis) < 50000 )
+ rawtx->I.amount = 50000;
+ rawtx->I.vintype = vintype; // 0 -> std, 2 -> 2of2, 3 -> spend bobpayment, 4 -> spend bobdeposit
+ rawtx->I.vouttype = vouttype; // 0 -> fee, 1 -> std, 2 -> 2of2, 3 -> bobpayment, 4 -> bobdeposit
+ if ( rawtx->I.vouttype == 0 )
{
- if ( (signedtx= iguana_signrawtx(myinfo,rawtx->coin,height,&rawtx->signedtxid,&rawtx->completed,vins,txbytes,privkeyarray,0)) != 0 )
- {
- if ( lockinputs != 0 )
- {
- iguana_RTunspentslock(myinfo,rawtx->coin,vins);
- if ( (n= cJSON_GetArraySize(vins)) != 0 )
- {
- bits256 txid; int32_t vout;
- for (i=0; icoin->symbol,txid,vout,1);
- }
- }
- }
- }
- rawtx->datalen = (int32_t)strlen(signedtx) >> 1;
- rawtx->txbytes = calloc(1,rawtx->datalen);
- decode_hex(rawtx->txbytes,rawtx->datalen,signedtx);
- //printf("SIGNEDTX.(%s)\n",signedtx);
- free(signedtx);
- retval = 0;
- } else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll
+ if ( strcmp(coin->symbol,"BTC") == 0 && (quoteid % 10) == 0 )
+ decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160);
+ else decode_hex(rawtx->I.rmd160,20,INSTANTDEX_RMD160);
+ bitcoin_address(rawtx->I.destaddr,rawtx->coin->chain->pubtype,rawtx->I.rmd160,20);
}
- return(retval);
+ if ( pubkey33 != 0 )
+ {
+ memcpy(rawtx->I.pubkey33,pubkey33,33);
+ bitcoin_address(rawtx->I.destaddr,rawtx->coin->chain->pubtype,rawtx->I.pubkey33,33);
+ bitcoin_addr2rmd160(&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr);
+ }
+ if ( rawtx->I.vouttype <= 1 && rawtx->I.destaddr[0] != 0 )
+ {
+ rawtx->I.spendlen = bitcoin_standardspend(rawtx->spendscript,0,rawtx->I.rmd160);
+ printf("%s spendlen.%d %s <- %.8f\n",name,rawtx->I.spendlen,rawtx->I.destaddr,dstr(rawtx->I.amount));
+ } else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr);
}
-int32_t basilisk_rawtx_gen(char *str,struct supernet_info *myinfo,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 bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct iguana_info **alicecoinp,char *src,char *dest,bits256 srchash,bits256 desthash)
{
- struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],wifstr[64],*retstr,scriptstr[1024]; uint32_t basilisktag; int32_t flag,i,n,retval = -1; cJSON *valsobj,*retarray=0,*privkeyarray,*addresses;
- //if ( (waddr= iguana_getaccountaddress(myinfo,rawtx->coin,0,0,rawtx->coin->changeaddr,"change")) == 0 )
- if ( rawtx->coin->changeaddr[0] == 0 )
+ struct iguana_info *coin = iguana_coinfind(src);
+ if ( coin == 0 || iguana_coinfind(dest) == 0 )
+ return(0);
+ *bobcoinp = *alicecoinp = 0;
+ *bobcoinp = iguana_coinfind(dest);
+ *alicecoinp = iguana_coinfind(src);
+ if ( bits256_cmp(pubkey,srchash) == 0 )
{
- bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33);
- printf("set change address.(%s)\n",rawtx->coin->changeaddr);
+ if ( strcmp(src,(*bobcoinp)->symbol) == 0 )
+ return(1);
+ else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 )
+ return(-1);
+ else return(0);
}
- init_hexbytes_noT(scriptstr,script,scriptlen);
- privkeyarray = cJSON_CreateArray();
- addresses = cJSON_CreateArray();
- bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33);
- //printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr);
- if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 )
+ else if ( bits256_cmp(pubkey,desthash) == 0 )
{
- bitcoin_priv2wif(wifstr,waddr->privkey,rawtx->coin->chain->wiftype);
- jaddistr(privkeyarray,waddr->wifstr);
+ if ( strcmp(src,(*bobcoinp)->symbol) == 0 )
+ return(-1);
+ else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 )
+ return(1);
+ else return(0);
}
- basilisktag = (uint32_t)rand();
- jaddistr(addresses,coinaddr);
- valsobj = cJSON_CreateObject();
- //jadd(valsobj,"addresses",addresses);
- jaddstr(valsobj,"coin",rawtx->coin->symbol);
- jaddstr(valsobj,"spendscript",scriptstr);
- jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr);
- jadd64bits(valsobj,"satoshis",rawtx->amount);
- jadd64bits(valsobj,"txfee",txfee);
- jaddnum(valsobj,"minconf",minconf);
- jaddnum(valsobj,"locktime",locktime);
- jaddnum(valsobj,"timeout",30000);
- rawtx->locktime = locktime;
- printf("%s locktime.%u\n",rawtx->name,locktime);
- if ( (retstr= basilisk_bitcoinrawtx(myinfo,rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj)) != 0 )
- {
- printf("%s got.(%s)\n",str,retstr);
- flag = 0;
- if ( (retarray= cJSON_Parse(retstr)) != 0 )
- {
- if ( is_cJSON_Array(retarray) != 0 )
- {
- n = cJSON_GetArraySize(retarray);
- for (i=0; icoin->blocks.hwmchain.height,rawtx,jitem(retarray,i),privkeyarray,lockinputs)) == 0 )
- break;
- }
- } else retval = basilisk_rawtx_return(myinfo,rawtx->coin->blocks.hwmchain.height,rawtx,retarray,privkeyarray,lockinputs);
- free(retarray);
- } else printf("error parsing.(%s)\n",retstr);
- free(retstr);
- } else printf("error creating %s feetx\n",iambob != 0 ? "BOB" : "ALICE");
- free_json(privkeyarray);
- free_json(valsobj);
- printf("rawtx retval.%d\n",retval);
- return(retval);
+ return(0);
}
-void basilisk_rawtx_setparms(char *name,struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33)
+void basilisk_swap_saveupdate(struct supernet_info *myinfo,struct basilisk_swap *swap)
{
- strcpy(rawtx->name,name);
- rawtx->coin = coin;
- rawtx->numconfirms = numconfirms;
- if ( (rawtx->amount= satoshis) < 10000 )
- rawtx->amount = 10000;
- rawtx->vintype = vintype; // 0 -> std, 2 -> 2of2, 3 -> spend bobpayment, 4 -> spend bobdeposit
- rawtx->vouttype = vouttype; // 0 -> fee, 1 -> std, 2 -> 2of2, 3 -> bobpayment, 4 -> bobdeposit
- if ( rawtx->vouttype == 0 )
- {
- if ( strcmp(coin->symbol,"BTC") == 0 && (swap->req.quoteid % 10) == 0 )
- decode_hex(rawtx->rmd160,20,TIERNOLAN_RMD160);
- else decode_hex(rawtx->rmd160,20,INSTANTDEX_RMD160);
- bitcoin_address(rawtx->destaddr,rawtx->coin->chain->pubtype,rawtx->rmd160,20);
- }
- if ( pubkey33 != 0 )
+ FILE *fp; char fname[512];
+ sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname);
+ if ( (fp= fopen(fname,"wb")) != 0 )
{
- memcpy(rawtx->pubkey33,pubkey33,33);
- bitcoin_address(rawtx->destaddr,rawtx->coin->chain->pubtype,rawtx->pubkey33,33);
- bitcoin_addr2rmd160(&rawtx->addrtype,rawtx->rmd160,rawtx->destaddr);
+ fwrite(&swap->I,1,sizeof(swap->I),fp);
+ /*fwrite(&swap->bobdeposit,1,sizeof(swap->bobdeposit),fp);
+ fwrite(&swap->bobpayment,1,sizeof(swap->bobpayment),fp);
+ fwrite(&swap->alicepayment,1,sizeof(swap->alicepayment),fp);
+ fwrite(&swap->myfee,1,sizeof(swap->myfee),fp);
+ fwrite(&swap->otherfee,1,sizeof(swap->otherfee),fp);
+ fwrite(&swap->aliceclaim,1,sizeof(swap->aliceclaim),fp);
+ fwrite(&swap->alicespend,1,sizeof(swap->alicespend),fp);
+ fwrite(&swap->bobreclaim,1,sizeof(swap->bobreclaim),fp);
+ fwrite(&swap->bobspend,1,sizeof(swap->bobspend),fp);
+ fwrite(&swap->bobrefund,1,sizeof(swap->bobrefund),fp);
+ fwrite(&swap->alicereclaim,1,sizeof(swap->alicereclaim),fp);*/
+ fwrite(swap->privkeys,1,sizeof(swap->privkeys),fp);
+ fwrite(swap->otherdeck,1,sizeof(swap->otherdeck),fp);
+ fwrite(swap->deck,1,sizeof(swap->deck),fp);
+ fclose(fp);
}
- if ( rawtx->vouttype <= 1 && rawtx->destaddr[0] != 0 )
- {
- rawtx->spendlen = bitcoin_standardspend(rawtx->spendscript,0,rawtx->rmd160);
- printf("%s spendlen.%d %s <- %.8f\n",name,rawtx->spendlen,rawtx->destaddr,dstr(rawtx->amount));
- } else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->vouttype,rawtx->destaddr);
}
-struct basilisk_swap *bitcoin_swapinit(struct supernet_info *myinfo,struct basilisk_swap *swap)
+int32_t basilisk_swap_loadtx(struct basilisk_rawtx *rawtx,FILE *fp,char *bobcoinstr,char *alicecoinstr)
{
- struct iguana_info *coin; uint8_t *alicepub33=0,*bobpub33=0; int32_t x = -1;
- if ( strcmp("BTC",swap->req.src) == 0 )
+ if ( fread(rawtx,1,sizeof(*rawtx),fp) == sizeof(*rawtx) )
{
- swap->bobcoin = iguana_coinfind("BTC");
- swap->bobsatoshis = swap->req.srcamount;
- swap->bobconfirms = (1 + sqrt(dstr(swap->bobsatoshis) * .1));
- swap->alicecoin = iguana_coinfind(swap->req.dest);
- swap->alicesatoshis = swap->req.destamount;
- swap->aliceconfirms = swap->bobconfirms * 3;
+ rawtx->coin = 0;
+ rawtx->vins = 0;
+ if ( strcmp(rawtx->I.coinstr,bobcoinstr) == 0 || strcmp(rawtx->I.coinstr,alicecoinstr) == 0 )
+ {
+ rawtx->coin = iguana_coinfind(rawtx->I.coinstr);
+ if ( rawtx->vinstr[0] != 0 )
+ rawtx->vins = cJSON_Parse(rawtx->vinstr);
+ printf("loaded.%s len.%d\n",rawtx->name,rawtx->I.datalen);
+ return(0);
+ }
}
- else if ( strcmp("BTC",swap->req.dest) == 0 )
+ return(-1);
+}
+
+struct basilisk_swap *bitcoin_swapinit(struct supernet_info *myinfo,bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,int32_t reinit)
+{
+ FILE *fp; char fname[512]; uint8_t *alicepub33=0,*bobpub33=0; int32_t errs=0,jumblrflag,x = -1;
+ if ( reinit != 0 )
{
- swap->bobcoin = iguana_coinfind("BTC");
- swap->bobsatoshis = swap->req.destamount;
- swap->bobconfirms = (1 + sqrt(dstr(swap->bobsatoshis) * .1));
- swap->alicecoin = iguana_coinfind(swap->req.src);
- swap->alicesatoshis = swap->req.srcamount;
- swap->aliceconfirms = swap->bobconfirms * 3;
+ sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname);
+ printf("reinit.(%s)\n",fname);
+ if ( (fp= fopen(fname,"rb")) != 0 )
+ {
+ if ( fread(&swap->I,1,sizeof(swap->I),fp) != sizeof(swap->I) )
+ errs++;
+ if ( swap->bobcoin == 0 )
+ swap->bobcoin = iguana_coinfind(swap->I.req.dest);
+ if ( swap->alicecoin == 0 )
+ swap->alicecoin = iguana_coinfind(swap->I.req.src);
+ if ( swap->alicecoin != 0 && swap->bobcoin != 0 )
+ {
+ /*basilisk_swap_loadtx(&swap->bobdeposit,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->bobpayment,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->alicepayment,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->myfee,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->otherfee,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->aliceclaim,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->alicespend,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->bobreclaim,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->bobspend,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->bobrefund,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
+ basilisk_swap_loadtx(&swap->alicereclaim,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);*/
+ } else printf("missing coins (%p %p)\n",swap->bobcoin,swap->alicecoin);
+ if ( fread(swap->privkeys,1,sizeof(swap->privkeys),fp) != sizeof(swap->privkeys) )
+ errs++;
+ if ( fread(swap->otherdeck,1,sizeof(swap->otherdeck),fp) != sizeof(swap->otherdeck) )
+ errs++;
+ if ( fread(swap->deck,1,sizeof(swap->deck),fp) != sizeof(swap->deck) )
+ errs++;
+ fclose(fp);
+ } else printf("cant find.(%s)\n",fname);
}
else
{
- if ( (coin= iguana_coinfind(swap->req.src)) != 0 )
+ swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME;
+ if ( optionduration < 0 )
+ swap->I.putduration -= optionduration;
+ else if ( optionduration > 0 )
+ swap->I.callduration += optionduration;
+ swap->I.bobsatoshis = swap->I.req.destamount;
+ swap->I.alicesatoshis = swap->I.req.srcamount;
+ if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 )
+ swap->I.bobinsurance = 50000;
+ if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 )
+ swap->I.aliceinsurance = 50000;
+ strcpy(swap->I.bobstr,swap->I.req.dest);
+ strcpy(swap->I.alicestr,swap->I.req.src);
+ swap->I.started = (uint32_t)time(NULL);
+ swap->I.expiration = swap->I.req.timestamp + swap->I.putduration + swap->I.callduration;
+ OS_randombytes((uint8_t *)&swap->I.choosei,sizeof(swap->I.choosei));
+ if ( swap->I.choosei < 0 )
+ swap->I.choosei = -swap->I.choosei;
+ swap->I.choosei %= INSTANTDEX_DECKSIZE;
+ swap->I.otherchoosei = -1;
+ swap->I.myhash = pubkey25519;
+ if ( statebits != 0 )
{
- if ( coin->chain->havecltv != 0 )
- {
- swap->bobcoin = coin;
- swap->bobsatoshis = swap->req.srcamount;
- swap->alicecoin = iguana_coinfind(swap->req.dest);
- swap->alicesatoshis = swap->req.destamount;
- }
- else if ( (coin= iguana_coinfind(swap->req.dest)) != 0 )
- {
- if ( coin->chain->havecltv != 0 )
- {
- swap->bobcoin = coin;
- swap->bobsatoshis = swap->req.destamount;
- swap->alicecoin = iguana_coinfind(swap->req.src);
- swap->alicesatoshis = swap->req.srcamount;
- }
- }
+ swap->I.iambob = 0;
+ swap->I.otherhash = swap->I.req.desthash;
+ }
+ else
+ {
+ swap->I.iambob = 1;
+ swap->I.otherhash = swap->I.req.srchash;
+ }
+ if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(myinfo->ctx,swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE )
+ {
+ char str[65]; printf("couldnt generate privkeys %d %s\n",x,bits256_str(str,privkey));
+ return(0);
}
}
+ swap->bobcoin = iguana_coinfind(swap->I.req.dest);
+ swap->alicecoin = iguana_coinfind(swap->I.req.src);
if ( swap->bobcoin == 0 || swap->alicecoin == 0 )
{
- printf("missing BTC.%p or missing alicecoin.%p\n",swap->bobcoin,swap->alicecoin);
+ printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",swap->bobcoin,swap->alicecoin,iguana_coinfind(swap->I.req.src),iguana_coinfind(swap->I.req.dest));
free(swap);
return(0);
}
- if ( swap->bobconfirms == 0 )
- swap->bobconfirms = swap->bobcoin->chain->minconfirms;
- if ( swap->aliceconfirms == 0 )
- swap->aliceconfirms = swap->alicecoin->chain->minconfirms;
- if ( (swap->bobinsurance= (swap->bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 )
- swap->bobinsurance = 10000;
- if ( (swap->aliceinsurance= (swap->alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 )
- swap->aliceinsurance = 10000;
- strcpy(swap->bobstr,swap->bobcoin->symbol);
- strcpy(swap->alicestr,swap->alicecoin->symbol);
- swap->started = (uint32_t)time(NULL);
- swap->expiration = swap->req.timestamp + INSTANTDEX_LOCKTIME*2;
- swap->locktime = swap->req.timestamp + INSTANTDEX_LOCKTIME;
- OS_randombytes((uint8_t *)&swap->choosei,sizeof(swap->choosei));
- if ( swap->choosei < 0 )
- swap->choosei = -swap->choosei;
- swap->choosei %= INSTANTDEX_DECKSIZE;
- swap->otherchoosei = -1;
- swap->myhash = myinfo->myaddr.persistent;
- if ( bits256_cmp(swap->myhash,swap->req.hash) == 0 )
- {
- swap->otherhash = swap->req.desthash;
- if ( strcmp(swap->req.src,swap->bobstr) == 0 )
- swap->iambob = 1;
- else if ( strcmp(swap->req.dest,swap->alicestr) == 0 )
- {
- printf("neither bob nor alice error\n");
- return(0);
- }
- }
- else if ( bits256_cmp(swap->myhash,swap->req.desthash) == 0 )
+ if ( strcmp("BTC",swap->bobcoin->symbol) == 0 )
{
- swap->otherhash = swap->req.hash;
- if ( strcmp(swap->req.dest,swap->bobstr) == 0 )
- swap->iambob = 1;
- else if ( strcmp(swap->req.src,swap->alicestr) != 0 )
- {
- printf("neither alice nor bob error\n");
- return(0);
- }
+ swap->I.bobconfirms = (1*0 + sqrt(dstr(swap->I.bobsatoshis) * .1));
+ swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3);
}
- else
+ else if ( strcmp("BTC",swap->alicecoin->symbol) == 0 )
{
- printf("neither src nor dest error\n");
- return(0);
+ swap->I.aliceconfirms = (1*0 + sqrt(dstr(swap->I.alicesatoshis) * .1));
+ swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3);
}
- if ( bits256_nonz(myinfo->persistent_priv) == 0 || (x= instantdex_pubkeyargs(myinfo,swap,2 + INSTANTDEX_DECKSIZE,myinfo->persistent_priv,swap->myhash,0x02+swap->iambob)) != 2 + INSTANTDEX_DECKSIZE )
+ else
{
- printf("couldnt generate privkeys %d\n",x);
- return(0);
+ swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
+ swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
}
- if ( swap->iambob != 0 )
+ /*if ( swap->I.bobconfirms == 0 )
+ swap->I.bobconfirms = swap->bobcoin->chain->minconfirms;
+ if ( swap->I.aliceconfirms == 0 )
+ swap->I.aliceconfirms = swap->alicecoin->chain->minconfirms;*/
+ jumblrflag = (bits256_cmp(pubkey25519,myinfo->jumblr_pubkey) == 0 || bits256_cmp(pubkey25519,myinfo->jumblr_depositkey) == 0);
+ printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms);
+ if ( swap->I.iambob != 0 )
{
- basilisk_rawtx_setparms("myfee",myinfo,swap,&swap->myfee,swap->bobcoin,0,0,swap->bobsatoshis/INSTANTDEX_DECKSIZE,0,0);
- basilisk_rawtx_setparms("otherfee",myinfo,swap,&swap->otherfee,swap->alicecoin,0,0,swap->alicesatoshis/INSTANTDEX_DECKSIZE,0,0);
- bobpub33 = myinfo->persistent_pubkey33;
+ basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag);
+ basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag);
+ bobpub33 = pubkey33;
}
else
{
- basilisk_rawtx_setparms("otherfee",myinfo,swap,&swap->otherfee,swap->bobcoin,0,0,swap->bobsatoshis/INSTANTDEX_DECKSIZE,0,0);
- basilisk_rawtx_setparms("myfee",myinfo,swap,&swap->myfee,swap->alicecoin,0,0,swap->alicesatoshis/INSTANTDEX_DECKSIZE,0,0);
- alicepub33 = myinfo->persistent_pubkey33;
- }
- basilisk_rawtx_setparms("bobdeposit",myinfo,swap,&swap->bobdeposit,swap->bobcoin,swap->bobconfirms,0,swap->bobsatoshis*1.1,4,0);
- basilisk_rawtx_setparms("bobrefund",myinfo,swap,&swap->bobrefund,swap->bobcoin,1,4,swap->bobsatoshis*1.1-swap->bobcoin->txfee,1,bobpub33);
- swap->bobrefund.suppress_pubkeys = 1;
- basilisk_rawtx_setparms("aliceclaim",myinfo,swap,&swap->aliceclaim,swap->bobcoin,1,4,swap->bobsatoshis*1.1-swap->bobcoin->txfee,1,alicepub33);
- swap->aliceclaim.suppress_pubkeys = 1;
-
- basilisk_rawtx_setparms("bobpayment",myinfo,swap,&swap->bobpayment,swap->bobcoin,swap->bobconfirms,0,swap->bobsatoshis,3,0);
- basilisk_rawtx_setparms("alicespend",myinfo,swap,&swap->alicespend,swap->bobcoin,swap->bobconfirms,3,swap->bobsatoshis - swap->bobcoin->txfee,1,alicepub33);
- swap->alicespend.suppress_pubkeys = 1;
- basilisk_rawtx_setparms("bobreclaim",myinfo,swap,&swap->bobreclaim,swap->bobcoin,swap->bobconfirms,3,swap->bobsatoshis - swap->bobcoin->txfee,1,bobpub33);
- swap->bobreclaim.suppress_pubkeys = 1;
-
- basilisk_rawtx_setparms("alicepayment",myinfo,swap,&swap->alicepayment,swap->alicecoin,swap->aliceconfirms,0,swap->alicesatoshis,2,0);
- basilisk_rawtx_setparms("bobspend",myinfo,swap,&swap->bobspend,swap->alicecoin,swap->aliceconfirms,2,swap->alicesatoshis-swap->alicecoin->txfee,1,bobpub33);
- swap->bobspend.suppress_pubkeys = 1;
- basilisk_rawtx_setparms("alicereclaim",myinfo,swap,&swap->alicereclaim,swap->alicecoin,swap->aliceconfirms,2,swap->alicesatoshis-swap->alicecoin->txfee,1,alicepub33);
- swap->alicereclaim.suppress_pubkeys = 1;
+ basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag);
+ basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_INSURANCEDIV,0,0,jumblrflag);
+ alicepub33 = pubkey33;
+ }
+ basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3) + swap->bobcoin->txfee,4,0,jumblrflag);
+ basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,bobpub33,jumblrflag);
+ swap->bobrefund.I.suppress_pubkeys = 1;
+ basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,alicepub33,jumblrflag);
+ swap->aliceclaim.I.suppress_pubkeys = 1;
+ swap->aliceclaim.I.locktime = swap->I.started + swap->I.putduration+swap->I.callduration + 1;
+
+ basilisk_rawtx_setparms("bobpayment",swap->I.req.quoteid,&swap->bobpayment,swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + swap->bobcoin->txfee,3,0,jumblrflag);
+ basilisk_rawtx_setparms("alicespend",swap->I.req.quoteid,&swap->alicespend,swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,alicepub33,jumblrflag);
+ swap->alicespend.I.suppress_pubkeys = 1;
+ basilisk_rawtx_setparms("bobreclaim",swap->I.req.quoteid,&swap->bobreclaim,swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,bobpub33,jumblrflag);
+ swap->bobreclaim.I.suppress_pubkeys = 1;
+ swap->bobreclaim.I.locktime = swap->I.started + swap->I.putduration + 1;
+ basilisk_rawtx_setparms("alicepayment",swap->I.req.quoteid,&swap->alicepayment,swap->alicecoin,swap->I.aliceconfirms,0,swap->I.alicesatoshis+swap->alicecoin->txfee,2,0,jumblrflag);
+ basilisk_rawtx_setparms("bobspend",swap->I.req.quoteid,&swap->bobspend,swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,bobpub33,jumblrflag);
+ swap->bobspend.I.suppress_pubkeys = 1;
+ basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag);
+ swap->alicereclaim.I.suppress_pubkeys = 1;
+ printf("IAMBOB.%d\n",swap->I.iambob);
+
return(swap);
}
// end of alice/bob code
void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx)
{
- if ( rawtx->txbytes != 0 )
- free(rawtx->txbytes), rawtx->txbytes = 0;
+ if ( rawtx->vins != 0 )
+ free_json(rawtx->vins);
+ //if ( rawtx->txbytes != 0 )
+ // free(rawtx->txbytes), rawtx->txbytes = 0;
}
void basilisk_swap_finished(struct supernet_info *myinfo,struct basilisk_swap *swap)
{
- swap->finished = (uint32_t)time(NULL);
+ int32_t i;
+ swap->I.finished = (uint32_t)time(NULL);
// save to permanent storage
basilisk_rawtx_purge(&swap->bobdeposit);
basilisk_rawtx_purge(&swap->bobpayment);
basilisk_rawtx_purge(&swap->alicepayment);
basilisk_rawtx_purge(&swap->myfee);
basilisk_rawtx_purge(&swap->otherfee);
- basilisk_rawtx_purge(&swap->alicereclaim);
+ basilisk_rawtx_purge(&swap->aliceclaim);
basilisk_rawtx_purge(&swap->alicespend);
basilisk_rawtx_purge(&swap->bobreclaim);
basilisk_rawtx_purge(&swap->bobspend);
basilisk_rawtx_purge(&swap->bobrefund);
+ basilisk_rawtx_purge(&swap->alicereclaim);
+ for (i=0; inummessages; i++)
+ if ( swap->messages[i].data != 0 )
+ free(swap->messages[i].data), swap->messages[i].data = 0;
+ free(swap->messages), swap->messages = 0;
+ swap->nummessages = 0;
}
void basilisk_swap_purge(struct supernet_info *myinfo,struct basilisk_swap *swap)
{
int32_t i,n;
// while still in orderbook, wait
- return;
+ //return;
portable_mutex_lock(&myinfo->DEX_swapmutex);
n = myinfo->numswaps;
for (i=0; iotherstatebits) )
- return(iguana_rwnum(0,data,sizeof(swap->otherstatebits),&swap->otherstatebits));
- else return(-1);
+ int32_t retval; struct basilisk_swap *swap = ptr;
+ if ( datalen == sizeof(swap->I.otherstatebits) )
+ {
+ retval = iguana_rwnum(0,data,sizeof(swap->I.otherstatebits),&swap->I.otherstatebits);
+ return(retval);
+ } else return(-1);
}
-
-int32_t basilisk_verify_choosei(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
+
+int32_t basilisk_verify_statebits(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
{
- int32_t otherchoosei=-1,i,len = 0; struct basilisk_swap *swap = ptr;
- if ( datalen == sizeof(otherchoosei)+sizeof(bits256)*2 )
+ int32_t retval = -1; uint32_t statebits; struct basilisk_swap *swap = ptr;
+ if ( datalen == sizeof(swap->I.statebits) )
{
- len += iguana_rwnum(0,data,sizeof(otherchoosei),&otherchoosei);
- if ( otherchoosei >= 0 && otherchoosei < INSTANTDEX_DECKSIZE )
+ retval = iguana_rwnum(0,data,sizeof(swap->I.statebits),&statebits);
+ if ( statebits != swap->I.statebits )
{
- printf("otherchoosei.%d\n",otherchoosei);
- swap->otherchoosei = otherchoosei;
- if ( swap->iambob != 0 )
- {
+ printf("statebits.%x != %x\n",statebits,swap->I.statebits);
+ return(-1);
+ }
+ }
+ return(retval);
+}
+
+int32_t basilisk_verify_choosei(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
+{
+ int32_t otherchoosei=-1,i,len = 0; struct basilisk_swap *swap = ptr;
+ if ( datalen == sizeof(otherchoosei)+sizeof(bits256)*2 )
+ {
+ len += iguana_rwnum(0,data,sizeof(otherchoosei),&otherchoosei);
+ if ( otherchoosei >= 0 && otherchoosei < INSTANTDEX_DECKSIZE )
+ {
+ //printf("otherchoosei.%d\n",otherchoosei);
+ swap->I.otherchoosei = otherchoosei;
+ if ( swap->I.iambob != 0 )
+ {
for (i=0; i<32; i++)
- swap->pubA0.bytes[i] = data[len++];
+ swap->I.pubA0.bytes[i] = data[len++];
for (i=0; i<32; i++)
- swap->pubA1.bytes[i] = data[len++];
- char str[65]; printf("GOT pubA0/1 %s\n",bits256_str(str,swap->pubA0));
+ swap->I.pubA1.bytes[i] = data[len++];
+ char str[65]; printf("GOT pubA0/1 %s\n",bits256_str(str,swap->I.pubA0));
}
else
{
for (i=0; i<32; i++)
- swap->pubB0.bytes[i] = data[len++];
+ swap->I.pubB0.bytes[i] = data[len++];
for (i=0; i<32; i++)
- swap->pubB1.bytes[i] = data[len++];
+ swap->I.pubB1.bytes[i] = data[len++];
}
return(0);
}
@@ -915,62 +1959,91 @@ int32_t basilisk_verify_otherdeck(struct supernet_info *myinfo,void *ptr,uint8_t
int32_t basilisk_verify_privkeys(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
{
int32_t i,j,wrongfirstbyte=0,errs=0,len = 0; bits256 otherpriv,pubi; uint8_t secret160[20],otherpubkey[33]; uint64_t txid; struct basilisk_swap *swap = ptr;
- printf("verify privkeys choosei.%d otherchoosei.%d datalen.%d vs %d\n",swap->choosei,swap->otherchoosei,datalen,(int32_t)sizeof(swap->privkeys)+20+32);
- if ( swap->cutverified == 0 && swap->otherchoosei >= 0 && datalen == sizeof(swap->privkeys)+20+32 )
+ //printf("verify privkeys choosei.%d otherchoosei.%d datalen.%d vs %d\n",swap->choosei,swap->otherchoosei,datalen,(int32_t)sizeof(swap->privkeys)+20+32);
+ memset(otherpriv.bytes,0,sizeof(otherpriv));
+ if ( swap->I.cutverified == 0 && swap->I.otherchoosei >= 0 && datalen == sizeof(swap->privkeys)+20+2*32 )
{
for (i=errs=0; iprivkeys)/sizeof(*swap->privkeys); i++)
{
for (j=0; j<32; j++)
otherpriv.bytes[j] = data[len++];
- if ( i != swap->choosei )
+ if ( i != swap->I.choosei )
{
pubi = bitcoin_pubkey33(myinfo->ctx,otherpubkey,otherpriv);
- calc_rmd160_sha256(secret160,otherpriv.bytes,sizeof(otherpriv));
+ revcalc_rmd160_sha256(secret160,otherpriv);//.bytes,sizeof(otherpriv));
memcpy(&txid,secret160,sizeof(txid));
errs += basilisk_verify_pubpair(&wrongfirstbyte,swap,i,otherpubkey[0],pubi,txid);
}
}
if ( errs == 0 && wrongfirstbyte == 0 )
{
- swap->cutverified = 1, printf("CUT VERIFIED\n");
- if ( swap->iambob != 0 )
+ swap->I.cutverified = 1, printf("CUT VERIFIED\n");
+ if ( swap->I.iambob != 0 )
{
for (i=0; i<32; i++)
- swap->pubAm.bytes[i] = data[len++];
+ swap->I.pubAm.bytes[i] = data[len++];
for (i=0; i<20; i++)
- swap->secretAm[i] = data[len++];
+ swap->I.secretAm[i] = data[len++];
+ for (i=0; i<32; i++)
+ swap->I.secretAm256[i] = data[len++];
+ basilisk_bobscripts_set(myinfo,swap,1,1);
}
else
{
for (i=0; i<32; i++)
- swap->pubBn.bytes[i] = data[len++];
+ swap->I.pubBn.bytes[i] = data[len++];
for (i=0; i<20; i++)
- swap->secretBn[i] = data[len++];
+ swap->I.secretBn[i] = data[len++];
+ for (i=0; i<32; i++)
+ swap->I.secretBn256[i] = data[len++];
+ //basilisk_bobscripts_set(myinfo,swap,0);
}
} else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs);
}
- printf("privkeys errs.%d wrongfirstbyte.%d\n",errs,wrongfirstbyte);
+ //printf("privkeys errs.%d wrongfirstbyte.%d\n",errs,wrongfirstbyte);
return(errs);
}
-uint32_t basilisk_swapsend(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits)
-{
- if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,msgbits,data,datalen,INSTANTDEX_LOCKTIME*2) == 0 )
- return(nextbits);
- printf("ERROR basilisk_channelsend\n");
- return(0);
-}
-
-uint32_t basilisk_swapdata_rawtxsend(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits)
+uint32_t basilisk_swapdata_rawtxsend(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend)
{
+ uint8_t sendbuf[32768]; int32_t sendlen;
if ( basilisk_swapdata_rawtx(myinfo,swap,data,maxlen,rawtx) != 0 )
{
- rawtx->actualtxid = basilisk_swap_broadcast(rawtx->name,myinfo,swap,rawtx->coin,rawtx->txbytes,rawtx->datalen);
- char str[65],str2[65]; printf("rawtxsend %s vs %s\n",bits256_str(str,rawtx->signedtxid),bits256_str(str2,rawtx->actualtxid));
- if ( bits256_nonz(rawtx->actualtxid) != 0 && msgbits != 0 )
- return(basilisk_swapsend(myinfo,swap,msgbits,rawtx->txbytes,rawtx->datalen,nextbits));
- else return(nextbits);
- } else printf("error from basilisk_swapdata_rawtx %p len.%d\n",rawtx->txbytes,rawtx->datalen);
+ if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 )
+ {
+ char str[65],str2[65];
+ rawtx->I.actualtxid = basilisk_swap_broadcast(rawtx->name,myinfo,swap,rawtx->coin,rawtx->txbytes,rawtx->I.datalen);
+ if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 )
+ {
+ printf("%s rawtxsend %s vs %s\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid));
+ rawtx->I.actualtxid = rawtx->I.signedtxid;
+ }
+ if ( bits256_nonz(rawtx->I.actualtxid) != 0 && msgbits != 0 )
+ {
+ sendlen = 0;
+ sendbuf[sendlen++] = rawtx->I.datalen & 0xff;
+ sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff;
+ sendbuf[sendlen++] = rawtx->I.redeemlen;
+ memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen;
+ if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 )
+ {
+ memcpy(&sendbuf[sendlen],rawtx->redeemscript,rawtx->I.redeemlen);
+ sendlen += rawtx->I.redeemlen;
+ }
+ basilisk_dontforget_update(myinfo,swap,rawtx);
+ //printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen);
+ if ( suppress_swapsend == 0 )
+ return(basilisk_swapsend(myinfo,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs));
+ else
+ {
+ printf("suppress swapsend %x\n",msgbits);
+ return(0);
+ }
+ }
+ }
+ return(nextbits);
+ } else if ( swap->I.iambob == 0 )
+ printf("error from basilisk_swapdata_rawtx.%s %p len.%d\n",rawtx->name,rawtx->txbytes,rawtx->I.datalen);
return(0);
}
@@ -979,78 +2052,84 @@ void basilisk_sendpubkeys(struct supernet_info *myinfo,struct basilisk_swap *swa
int32_t datalen;
datalen = basilisk_swapdata_deck(myinfo,swap,data,maxlen);
printf("send deck.%d\n",datalen);
- swap->statebits |= basilisk_swapsend(myinfo,swap,0x02,data,datalen,0x01);
+ swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x02,data,datalen,0x01,swap->I.crcs_mypub);
}
-void basilisk_checkdeck(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
+int32_t basilisk_checkdeck(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
- if ( (swap->statebits & 0x02) == 0 )
+ if ( (swap->I.statebits & 0x02) == 0 )
{
- printf("check for other deck\n");
+ //printf("check for other deck\n");
if ( basilisk_swapget(myinfo,swap,0x02,data,maxlen,basilisk_verify_otherdeck) == 0 )
- swap->statebits |= 0x02;
+ swap->I.statebits |= 0x02;
+ else return(-1);
}
+ return(0);
}
void basilisk_sendstate(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
- int32_t datalen;
- datalen = iguana_rwnum(1,data,sizeof(swap->statebits),&swap->statebits);
- basilisk_swapsend(myinfo,swap,0x80000000,data,datalen,0);
+ int32_t datalen=0;
+ datalen = iguana_rwnum(1,data,sizeof(swap->I.statebits),&swap->I.statebits);
+ basilisk_swapsend(myinfo,swap,0x80000000,data,datalen,0,0);
}
void basilisk_sendchoosei(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
int32_t i,datalen; char str[65];
- datalen = iguana_rwnum(1,data,sizeof(swap->choosei),&swap->choosei);
- if ( swap->iambob != 0 )
+ datalen = iguana_rwnum(1,data,sizeof(swap->I.choosei),&swap->I.choosei);
+ if ( swap->I.iambob != 0 )
{
for (i=0; i<32; i++)
- data[datalen++] = swap->pubB0.bytes[i];
+ data[datalen++] = swap->I.pubB0.bytes[i];
for (i=0; i<32; i++)
- data[datalen++] = swap->pubB1.bytes[i];
- printf("SEND pubB0/1 %s\n",bits256_str(str,swap->pubB0));
+ data[datalen++] = swap->I.pubB1.bytes[i];
+ printf("SEND pubB0/1 %s\n",bits256_str(str,swap->I.pubB0));
}
else
{
for (i=0; i<32; i++)
- data[datalen++] = swap->pubA0.bytes[i];
+ data[datalen++] = swap->I.pubA0.bytes[i];
for (i=0; i<32; i++)
- data[datalen++] = swap->pubA1.bytes[i];
- printf("SEND pubA0/1 %s\n",bits256_str(str,swap->pubA0));
+ data[datalen++] = swap->I.pubA1.bytes[i];
+ printf("SEND pubA0/1 %s\n",bits256_str(str,swap->I.pubA0));
}
- swap->statebits |= basilisk_swapsend(myinfo,swap,0x08,data,datalen,0x04);
+ swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x08,data,datalen,0x04,swap->I.crcs_mychoosei);
}
void basilisk_waitchoosei(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
- uint8_t pubkey33[33]; char str[65];
- printf("check otherchoosei\n");
+ uint8_t pubkey33[33]; char str[65],str2[65];
+ //printf("check otherchoosei\n");
if ( basilisk_swapget(myinfo,swap,0x08,data,maxlen,basilisk_verify_choosei) == 0 )
{
- if ( swap->iambob != 0 )
+ if ( swap->I.iambob != 0 )
{
- if ( bits256_nonz(swap->privBn) == 0 )
+ if ( bits256_nonz(swap->I.privBn) == 0 )
{
- swap->privBn = swap->privkeys[swap->otherchoosei];
- memset(&swap->privkeys[swap->otherchoosei],0,sizeof(swap->privkeys[swap->otherchoosei]));
- calc_rmd160_sha256(swap->secretBn,swap->privBn.bytes,sizeof(swap->privBn));
- swap->pubBn = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->privBn);
- printf("set privBn.%s\n",bits256_str(str,swap->privBn));
- }
+ swap->I.privBn = swap->privkeys[swap->I.otherchoosei];
+ memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei]));
+ revcalc_rmd160_sha256(swap->I.secretBn,swap->I.privBn);//.bytes,sizeof(swap->privBn));
+ vcalc_sha256(0,swap->I.secretBn256,swap->I.privBn.bytes,sizeof(swap->I.privBn));
+ swap->I.pubBn = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->I.privBn);
+ printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256));
+ basilisk_bobscripts_set(myinfo,swap,1,1);
+ }
}
else
{
- if ( bits256_nonz(swap->privAm) == 0 )
+ if ( bits256_nonz(swap->I.privAm) == 0 )
{
- swap->privAm = swap->privkeys[swap->otherchoosei];
- memset(&swap->privkeys[swap->otherchoosei],0,sizeof(swap->privkeys[swap->otherchoosei]));
- calc_rmd160_sha256(swap->secretAm,swap->privAm.bytes,sizeof(swap->privAm));
- swap->pubAm = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->privAm);
- printf("set privAm.%s\n",bits256_str(str,swap->privAm));
+ swap->I.privAm = swap->privkeys[swap->I.otherchoosei];
+ memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei]));
+ revcalc_rmd160_sha256(swap->I.secretAm,swap->I.privAm);//.bytes,sizeof(swap->privAm));
+ vcalc_sha256(0,swap->I.secretAm256,swap->I.privAm.bytes,sizeof(swap->I.privAm));
+ swap->I.pubAm = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->I.privAm);
+ char str[65],str2[65]; printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256));
+ //basilisk_bobscripts_set(myinfo,swap,0);
}
}
- swap->statebits |= 0x08;
+ swap->I.statebits |= 0x08;
}
}
@@ -1061,379 +2140,1898 @@ void basilisk_sendmostprivs(struct supernet_info *myinfo,struct basilisk_swap *s
for (i=0; iprivkeys)/sizeof(*swap->privkeys); i++)
{
for (j=0; j<32; j++)
- data[datalen++] = (i == swap->otherchoosei) ? 0 : swap->privkeys[i].bytes[j];
+ data[datalen++] = (i == swap->I.otherchoosei) ? 0 : swap->privkeys[i].bytes[j];
}
- if ( swap->iambob != 0 )
+ if ( swap->I.iambob != 0 )
{
for (i=0; i<32; i++)
- data[datalen++] = swap->pubBn.bytes[i];
+ data[datalen++] = swap->I.pubBn.bytes[i];
for (i=0; i<20; i++)
- data[datalen++] = swap->secretBn[i];
+ data[datalen++] = swap->I.secretBn[i];
+ for (i=0; i<32; i++)
+ data[datalen++] = swap->I.secretBn256[i];
}
else
{
for (i=0; i<32; i++)
- data[datalen++] = swap->pubAm.bytes[i];
+ data[datalen++] = swap->I.pubAm.bytes[i];
for (i=0; i<20; i++)
- data[datalen++] = swap->secretAm[i];
+ data[datalen++] = swap->I.secretAm[i];
+ for (i=0; i<32; i++)
+ data[datalen++] = swap->I.secretAm256[i];
}
- printf("send privkeys.%d\n",datalen);
- swap->statebits |= basilisk_swapsend(myinfo,swap,0x20,data,datalen,0x10);
-}
-
-void basilisk_alicepayment(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn)
-{
- alicepayment->spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->redeemlen,alicepayment->spendscript,0,alicepayment->destaddr,coin->chain->p2shtype,pubAm,pubBn);
- basilisk_rawtx_gen("alicepayment",myinfo,0,1,alicepayment,alicepayment->locktime,alicepayment->spendscript,alicepayment->spendlen,coin->chain->txfee,1);
+ //printf("send privkeys.%d\n",datalen);
+ swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x20,data,datalen,0x10,swap->I.crcs_myprivs);
}
-// detect insufficient funds/inputs
-// mode to autocreate required outputs
-
-void basilisk_swaploop(void *_swap)
+int32_t basilisk_swapiteration(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
- uint8_t *data; uint32_t expiration; int32_t retval=0,i,j,maxlen,datalen; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap;
- myinfo = swap->myinfo;
- fprintf(stderr,"start swap\n");
- maxlen = 1024*1024 + sizeof(*swap);
- data = malloc(maxlen);
- expiration = (uint32_t)time(NULL) + 300;
- while ( time(NULL) < expiration )
- {
- printf("A r%u/q%u swapstate.%x\n",swap->req.requestid,swap->req.quoteid,swap->statebits);
- basilisk_sendpubkeys(myinfo,swap,data,maxlen); // send pubkeys
- basilisk_checkdeck(myinfo,swap,data,maxlen); // check for other deck 0x02
- //if ( (swap->statebits & 0x02) != 0 )
- basilisk_sendchoosei(myinfo,swap,data,maxlen);
- basilisk_waitchoosei(myinfo,swap,data,maxlen); // wait for choosei 0x08
- if ( (swap->statebits & (0x08|0x02)) == (0x08|0x02) )
- break;
- sleep(3);
- }
- while ( time(NULL) < expiration )
- {
- printf("B r%u/q%u swapstate.%x\n",swap->req.requestid,swap->req.quoteid,swap->statebits);
- basilisk_sendmostprivs(myinfo,swap,data,maxlen);
- if ( basilisk_swapget(myinfo,swap,0x20,data,maxlen,basilisk_verify_privkeys) == 0 )
- {
- swap->statebits |= 0x20;
- break;
- }
- sleep(3 + (swap->iambob == 0)*10);
- }
- if ( time(NULL) >= expiration )
- retval = -1;
- printf("C r%u/q%u swapstate.%x\n",swap->req.requestid,swap->req.quoteid,swap->statebits);
- if ( retval == 0 && (swap->statebits & 0x40) == 0 ) // send fee
- {
- basilisk_sendstate(myinfo,swap,data,maxlen);
- basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
- if ( swap->myfee.txbytes == 0 )
- {
- for (i=0; i<20; i++)
- printf("%02x",swap->secretAm[i]);
- printf(" <- secretAm\n");
- for (i=0; i<32; i++)
- printf("%02x",swap->pubAm.bytes[i]);
- printf(" <- pubAm\n");
- for (i=0; i<20; i++)
- printf("%02x",swap->secretBn[i]);
- printf(" <- secretBn\n");
- for (i=0; i<32; i++)
- printf("%02x",swap->pubBn.bytes[i]);
- printf(" <- pubBn\n");
- for (i=0; i<32; i++)
- printf("%02x",swap->pubA0.bytes[i]);
- printf(" <- pubA0\n");
- for (i=0; i<32; i++)
- printf("%02x",swap->pubA1.bytes[i]);
- printf(" <- pubA1\n");
- for (i=0; i<32; i++)
- printf("%02x",swap->pubB0.bytes[i]);
- printf(" <- pubB0\n");
- for (i=0; i<32; i++)
- printf("%02x",swap->pubB1.bytes[i]);
- printf(" <- pubB1\n");
- swap->bobpayment.spendlen = basilisk_bobscript(swap->bobpayment.rmd160,swap->bobpayment.redeemscript,&swap->bobpayment.redeemlen,swap->bobpayment.spendscript,0,&swap->bobpayment.locktime,&swap->bobpayment.secretstart,swap,0);
- swap->bobdeposit.spendlen = basilisk_bobscript(swap->bobdeposit.rmd160,swap->bobdeposit.redeemscript,&swap->bobdeposit.redeemlen,swap->bobdeposit.spendscript,0,&swap->bobdeposit.locktime,&swap->bobdeposit.secretstart,swap,1);
- for (i=0; ibobpayment.redeemlen; i++)
- printf("%02x",swap->bobpayment.redeemscript[i]);
- printf(" <- bobpayment.%d\n",i);
- for (i=0; ibobdeposit.redeemlen; i++)
- printf("%02x",swap->bobdeposit.redeemscript[i]);
- printf(" <- bobdeposit.%d\n",i);
- if ( swap->iambob != 0 )
- {
- basilisk_rawtx_gen("deposit",myinfo,1,1,&swap->bobdeposit,swap->bobdeposit.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.spendlen,swap->bobdeposit.coin->chain->txfee,1);
- basilisk_rawtx_gen("payment",myinfo,1,1,&swap->bobpayment,swap->bobpayment.locktime,swap->bobpayment.spendscript,swap->bobpayment.spendlen,swap->bobpayment.coin->chain->txfee,1);
- if ( swap->bobdeposit.txbytes == 0 || swap->bobdeposit.spendlen == 0 || swap->bobpayment.txbytes == 0 || swap->bobpayment.spendlen == 0 )
- {
- printf("error bob generating deposit.%d or payment.%d\n",swap->bobdeposit.spendlen,swap->bobpayment.spendlen);
- retval = -2;
- }
- /*if ( basilisk_bobpayment_reclaim(myinfo,swap) < 0 || basilisk_bobdeposit_refund(myinfo,swap) < 0 )
- {
- printf("error bob reclaiming\n");
- retval = -3;
- }*/
- }
- else
- {
- basilisk_alicepayment(myinfo,swap->alicepayment.coin,&swap->alicepayment,swap->pubAm,swap->pubBn);
- if ( swap->alicepayment.txbytes == 0 || swap->alicepayment.spendlen == 0 )
- {
- printf("error alice generating payment.%d\n",swap->alicepayment.spendlen);
- retval = -4;
- }
- }
- if ( basilisk_rawtx_gen("myfee",myinfo,swap->iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.spendlen,swap->myfee.coin->chain->txfee,1) == 0 )
- swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40);
- else
- {
- printf("error creating myfee\n");
- retval = -6;
- }
- }
- }
- while ( retval == 0 && time(NULL) < swap->expiration )
+ int32_t j,datalen,retval = 0; uint32_t savestatebits=0,saveotherbits=0;
+ if ( swap->I.iambob != 0 )
+ swap->I.statebits |= 0x80;
+ while ( swap->aborted == 0 && ((swap->I.otherstatebits & 0x80) == 0 || (swap->I.statebits & 0x80) == 0) && retval == 0 && time(NULL) < swap->I.expiration )
{
- printf("D r%u/q%u swapstate.%x otherstate.%x\n",swap->req.requestid,swap->req.quoteid,swap->statebits,swap->otherstatebits);
- if ( (swap->statebits & 0x80) == 0 ) // wait for fee
+ if ( swap->connected == 0 )
+ basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
+ printf("D r%u/q%u swapstate.%x otherstate.%x remaining %d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,swap->I.otherstatebits,(int32_t)(swap->I.expiration-time(NULL)));
+ if ( swap->I.iambob != 0 && (swap->I.statebits & 0x80) == 0 ) // wait for fee
{
if ( basilisk_swapget(myinfo,swap,0x80,data,maxlen,basilisk_verify_otherfee) == 0 )
{
// verify and submit otherfee
- swap->statebits |= 0x80;
+ swap->I.statebits |= 0x80;
basilisk_sendstate(myinfo,swap,data,maxlen);
}
}
+ else if ( swap->I.iambob == 0 )
+ swap->I.statebits |= 0x80;
basilisk_sendstate(myinfo,swap,data,maxlen);
basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
- if ( (swap->otherstatebits & 0x80) != 0 && (swap->statebits & 0x80) != 0 )
+ if ( (swap->I.otherstatebits & 0x80) != 0 && (swap->I.statebits & 0x80) != 0 )
break;
- sleep(3 + (swap->iambob == 0)*10);
+ if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
+ sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
+ savestatebits = swap->I.statebits;
+ saveotherbits = swap->I.otherstatebits;
basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
basilisk_sendstate(myinfo,swap,data,maxlen);
- if ( (swap->otherstatebits & 0x80) == 0 )
- basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40);
+ if ( (swap->I.otherstatebits & 0x80) == 0 )
+ basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40,0);
}
- while ( retval == 0 && time(NULL) < swap->expiration ) // both sides have setup required data and paid txfee
+ basilisk_swap_saveupdate(myinfo,swap);
+ while ( swap->aborted == 0 && retval == 0 && time(NULL) < swap->I.expiration ) // both sides have setup required data and paid txfee
{
- printf("E r%u/q%u swapstate.%x otherstate.%x\n",swap->req.requestid,swap->req.quoteid,swap->statebits,swap->otherstatebits);
- if ( swap->iambob != 0 )
+ basilisk_swap_saveupdate(myinfo,swap);
+ if ( swap->connected == 0 )
+ basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
+ //if ( (rand() % 30) == 0 )
+ printf("E r%u/q%u swapstate.%x otherstate.%x remaining %d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,swap->I.otherstatebits,(int32_t)(swap->I.expiration-time(NULL)));
+ if ( swap->I.iambob != 0 )
{
- printf("BOB\n");
- if ( (swap->statebits & 0x100) == 0 )
+ //printf("BOB\n");
+ if ( (swap->I.statebits & 0x100) == 0 )
{
printf("send bobdeposit\n");
- swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x200,data,maxlen,&swap->bobdeposit,0x100);
+ swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0);
}
// [BLOCKING: altfound] make sure altpayment is confirmed and send payment
- else if ( (swap->statebits & 0x1000) == 0 )
+ else if ( (swap->I.statebits & 0x1000) == 0 )
{
printf("check alicepayment\n");
if ( basilisk_swapget(myinfo,swap,0x1000,data,maxlen,basilisk_verify_alicepaid) == 0 )
{
- swap->statebits |= 0x1000;
- printf("got alicepayment\n");
+ swap->I.statebits |= 0x1000;
+ printf("got alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms);
}
}
- else if ( (swap->statebits & 0x2000) == 0 )
+ else if ( (swap->I.statebits & 0x2000) == 0 )
{
- if ( basilisk_numconfirms(myinfo,&swap->alicepayment) >= swap->aliceconfirms )
+ if ( (swap->I.aliceconfirms == 0 && swap->aliceunconf != 0) || basilisk_numconfirms(myinfo,swap,&swap->alicepayment) >= swap->I.aliceconfirms )
{
- swap->statebits |= 0x2000;
+ swap->I.statebits |= 0x2000;
printf("alicepayment confirmed\n");
}
}
- else if ( (swap->statebits & 0x4000) == 0 )
+ else if ( (swap->I.statebits & 0x4000) == 0 )
{
+ basilisk_bobscripts_set(myinfo,swap,0,1);
printf("send bobpayment\n");
- swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000);
+ swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0);
}
// [BLOCKING: privM] Bob waits for privAm either from Alice or alice blockchain
- else if ( (swap->statebits & 0x40000) == 0 )
+ else if ( (swap->I.statebits & 0xc0000) != 0xc0000 )
{
if ( basilisk_swapget(myinfo,swap,0x40000,data,maxlen,basilisk_verify_privi) == 0 || basilisk_privAm_extract(myinfo,swap) == 0 ) // divulges privAm
{
- printf("got privi spend alicepayment\n");
- swap->statebits |= 0x40000;
+ //printf("got privi spend alicepayment, dont divulge privBn until bobspend propagated\n");
basilisk_alicepayment_spend(myinfo,swap,&swap->bobspend);
- if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobspend,0x40000) == 0 )
+ if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobspend,0x40000,1) == 0 )
printf("Bob error spending alice payment\n");
else
{
- basilisk_swap_balancingtrade(myinfo,swap,1);
- printf("Bob spends alicepayment\n");
+ tradebot_swap_balancingtrade(myinfo,swap,1);
+ printf("Bob spends alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms);
+ swap->I.statebits |= 0x40000;
+ if ( basilisk_numconfirms(myinfo,swap,&swap->bobspend) >= swap->I.aliceconfirms )
+ {
+ printf("bobspend confirmed\n");
+ swap->I.statebits |= 0x80000;
+ printf("Bob confirming spend of Alice's payment\n");
+ sleep(DEX_SLEEP);
+ }
+ retval = 1;
}
- break;
- }
- else if ( swap->bobpayment.locktime != 0 && time(NULL) > swap->bobpayment.locktime )
- {
- // submit reclaim of payment
- printf("bob reclaims bobpayment\n");
- swap->statebits |= (0x40000 | 0x80000);
- if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobreclaim,0) == 0 )
- printf("Bob error reclaiming own payment after alice timed out\n");
- else printf("Bob reclaimed own payment\n");
- break;
- }
- }
- else if ( (swap->statebits & 0x80000) == 0 )
- {
- if ( basilisk_numconfirms(myinfo,&swap->bobspend) >= swap->aliceconfirms )
- {
- printf("bobspend confirmed\n");
- swap->statebits |= 0x80000 | 0x100000;
- printf("Bob confirms spend of Alice's payment\n");
- break;
}
}
- else if ( (swap->statebits & 0x100000) == 0 )
+ if ( swap->bobpayment.I.locktime != 0 && time(NULL) > swap->bobpayment.I.locktime )
{
- if ( basilisk_numconfirms(myinfo,&swap->bobreclaim) >= 1 )
+ // submit reclaim of payment
+ printf("bob reclaims bobpayment\n");
+ swap->I.statebits |= (0x40000 | 0x80000);
+ if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobreclaim,0,0) == 0 )
+ printf("Bob error reclaiming own payment after alice timed out\n");
+ else
{
- printf("bobreclaim confirmed\n");
- swap->statebits |= 0x100000;
- printf("Bob confirms reclain of payment\n");
- break;
+ printf("Bob reclaimed own payment\n");
+ while ( 0 && (swap->I.statebits & 0x100000) == 0 ) // why wait for own tx?
+ {
+ if ( basilisk_numconfirms(myinfo,swap,&swap->bobreclaim) >= 1 )
+ {
+ printf("bobreclaim confirmed\n");
+ swap->I.statebits |= 0x100000;
+ printf("Bob confirms reclain of payment\n");
+ break;
+ }
+ }
+ retval = 1;
}
}
}
else
{
- printf("ALICE\n");
+ //printf("ALICE\n");
// [BLOCKING: depfound] Alice waits for deposit to confirm and sends altpayment
- if ( (swap->statebits & 0x200) == 0 )
+ if ( (swap->I.statebits & 0x200) == 0 )
{
printf("checkfor deposit\n");
if ( basilisk_swapget(myinfo,swap,0x200,data,maxlen,basilisk_verify_bobdeposit) == 0 )
{
// verify deposit and submit, set confirmed height
printf("got bobdeposit\n");
- swap->statebits |= 0x200;
+ swap->I.statebits |= 0x200;
} else printf("no valid deposit\n");
}
- else if ( (swap->statebits & 0x400) == 0 )
+ else if ( (swap->I.statebits & 0x400) == 0 )
{
- if ( basilisk_numconfirms(myinfo,&swap->bobdeposit) >= swap->bobconfirms )
+ if ( basilisk_istrustedbob(myinfo,swap) != 0 || (swap->I.bobconfirms == 0 && swap->depositunconf != 0) || basilisk_numconfirms(myinfo,swap,&swap->bobdeposit) >= swap->I.bobconfirms )
{
printf("bobdeposit confirmed\n");
- swap->statebits |= 0x400;
+ swap->I.statebits |= 0x400;
}
}
- else if ( (swap->statebits & 0x800) == 0 )
+ else if ( (swap->I.statebits & 0x800) == 0 )
{
printf("send alicepayment\n");
- swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x1000,data,maxlen,&swap->alicepayment,0x800);
+ swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0);
}
// [BLOCKING: payfound] make sure payment is confrmed and send in spend or see bob's reclaim and claim
- else if ( (swap->statebits & 0x8000) == 0 )
+ else if ( (swap->I.statebits & 0x8000) == 0 )
{
if ( basilisk_swapget(myinfo,swap,0x8000,data,maxlen,basilisk_verify_bobpaid) == 0 )
{
printf("got bobpayment\n");
+ tradebot_swap_balancingtrade(myinfo,swap,0);
// verify payment and submit, set confirmed height
- swap->statebits |= 0x8000;
+ swap->I.statebits |= 0x8000;
}
}
- else if ( (swap->statebits & 0x10000) == 0 )
+ else if ( (swap->I.statebits & 0x10000) == 0 )
{
- if ( basilisk_numconfirms(myinfo,&swap->bobpayment) >= swap->bobconfirms )
+ if ( basilisk_istrustedbob(myinfo,swap) != 0 || (swap->I.bobconfirms == 0 && swap->paymentunconf != 0) || basilisk_numconfirms(myinfo,swap,&swap->bobpayment) >= swap->I.bobconfirms )
{
printf("bobpayment confirmed\n");
- swap->statebits |= 0x10000;
+ swap->I.statebits |= 0x10000;
}
}
- else if ( (swap->statebits & 0x20000) == 0 )
+ else if ( (swap->I.statebits & 0x20000) == 0 )
{
printf("alicespend bobpayment\n");
- if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicespend,0x20000) != 0 )
+ if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicespend,0x20000,0) != 0 )//&& (swap->aliceunconf != 0 || basilisk_numconfirms(myinfo,swap,&swap->alicespend) > 0) )
{
- // maybe wait for alicespend to be confirmed
- for (j=datalen=0; j<32; j++)
- data[datalen++] = swap->privAm.bytes[j];
- printf("send privAm\n");
- swap->statebits |= basilisk_swapsend(myinfo,swap,0x40000,data,datalen,0x20000);
- basilisk_swap_balancingtrade(myinfo,swap,0);
+ swap->I.statebits |= 0x20000;
}
}
- else if ( (swap->statebits & 0x40000) == 0 )
+ else if ( (swap->I.statebits & 0x40000) == 0 )
{
- if ( basilisk_numconfirms(myinfo,&swap->alicespend) >= swap->bobconfirms )
+ int32_t numconfs;
+ if ( (numconfs= basilisk_numconfirms(myinfo,swap,&swap->alicespend)) >= swap->I.bobconfirms )
{
- swap->statebits |= 0x40000;
+ for (j=datalen=0; j<32; j++)
+ data[datalen++] = swap->I.privAm.bytes[j];
+ printf("send privAm %x\n",swap->I.statebits);
+ swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x40000,data,datalen,0x20000,swap->I.crcs_mypriv);
printf("Alice confirms spend of Bob's payment\n");
- break;
- }
+ retval = 1;
+ } else printf("alicespend numconfs.%d < %d\n",numconfs,swap->I.bobconfirms);
}
- if ( swap->bobdeposit.locktime != 0 && time(NULL) > swap->bobdeposit.locktime )
+ if ( swap->bobdeposit.I.locktime != 0 && time(NULL) > swap->bobdeposit.I.locktime )
{
printf("Alice claims deposit\n");
- if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->aliceclaim,0) == 0 )
+ if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->aliceclaim,0,0) == 0 )
printf("Alice couldnt claim deposit\n");
- else printf("Alice claimed deposit\n");
- break;
+ else
+ {
+ printf("Alice claimed deposit\n");
+ retval = 1;
+ }
}
- else if ( basilisk_privBn_extract(myinfo,swap,data,maxlen) == 0 )
+ else if ( swap->aborted != 0 || basilisk_privBn_extract(myinfo,swap,data,maxlen) == 0 )
{
printf("Alice reclaims her payment\n");
- swap->statebits |= 0x40000000;
- if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicereclaim,0x40000000) == 0 )
+ swap->I.statebits |= 0x40000000;
+ if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicereclaim,0x40000000,0) == 0 )
printf("Alice error sending alicereclaim\n");
- else printf("Alice reclaimed her payment\n");
- break;
+ else
+ {
+ printf("Alice reclaimed her payment\n");
+ retval = 1;
+ }
}
}
- printf("finished swapstate.%x other.%x\n",swap->statebits,swap->otherstatebits);
- sleep(3 + (swap->iambob == 0)*10);
+ if ( (rand() % 30) == 0 )
+ printf("finished swapstate.%x other.%x\n",swap->I.statebits,swap->I.otherstatebits);
+ if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
+ sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
+ savestatebits = swap->I.statebits;
+ saveotherbits = swap->I.otherstatebits;
basilisk_sendstate(myinfo,swap,data,maxlen);
basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
}
- printf("end of atomic swap\n");
- if ( swap->iambob != 0 )//&& bits256_nonz(swap->bobdeposit.txid) != 0 )
+ return(retval);
+}
+
+int32_t swapcompleted(struct supernet_info *myinfo,struct basilisk_swap *swap)
+{
+ if ( swap->I.iambob != 0 )
+ return(swap->I.bobspent);
+ else return(swap->I.alicespent);
+}
+
+cJSON *swapjson(struct supernet_info *myinfo,struct basilisk_swap *swap)
+{
+ cJSON *retjson = cJSON_CreateObject();
+ return(retjson);
+}
+
+void basilisk_psockinit(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t amlp)
+{
+ char keystr[64],databuf[1024],pubkeystr[128],*retstr,*retstr2,*datastr,*pushaddr=0,*subaddr=0; cJSON *retjson,*addrjson; uint8_t data[512]; int32_t datalen,timeout,pushsock = -1,subsock = -1;
+ if ( swap->connected == 1 )
+ return;
+ if ( swap->pushsock < 0 && swap->subsock < 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 )
{
- printf("BOB reclaims refund\n");
- basilisk_bobdeposit_refund(myinfo,swap);
- if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobrefund,0x40000000) == 0 ) // use secretBn
+ timeout = 1000;
+ nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
+ timeout = 1;
+ nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
+ nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0);
+ swap->pushsock = pushsock;
+ swap->subsock = subsock;
+ }
+ if ( (subsock= swap->subsock) < 0 || (pushsock= swap->pushsock) < 0 )
+ {
+ printf("error getting nn_sockets\n");
+ return;
+ }
+ sprintf(keystr,"%08x-%08x",swap->I.req.requestid,swap->I.req.quoteid);
+ if ( swap->connected == 0 && (retstr= _dex_kvsearch(myinfo,"KV",keystr)) != 0 )
+ {
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
- printf("Bob submit error getting refund of deposit\n");
+ if ( (datastr= jstr(retjson,"value")) != 0 )
+ {
+ datalen = (int32_t)strlen(datastr) >> 1;
+ decode_hex((uint8_t *)databuf,datalen,datastr);
+ if ( (addrjson= cJSON_Parse(databuf)) != 0 )
+ {
+ pushaddr = jstr(addrjson,"push");
+ subaddr = jstr(addrjson,"sub");
+ if ( pushaddr != 0 && subaddr != 0 )
+ {
+ printf("KV decoded (%s and %s) %d %d\n",pushaddr,subaddr,swap->pushsock,swap->subsock);
+ if ( nn_connect(swap->pushsock,pushaddr) >= 0 && nn_connect(swap->subsock,subaddr) >= 0 )
+ swap->connected = 1;
+ }
+ free_json(addrjson);
+ }
+ }
+ free_json(retjson);
}
- // maybe wait for bobrefund to be confirmed
- for (j=datalen=0; j<32; j++)
- data[datalen++] = swap->privBn.bytes[j];
- basilisk_swapsend(myinfo,swap,0x40000000,data,datalen,0x40000000);
+ printf("KVsearch.(%s) -> (%s) connected.%d socks.(%d %d) amlp.%d\n",keystr,retstr,swap->connected,swap->pushsock,swap->subsock,amlp);
+ free(retstr);
+ }
+ printf("connected.%d amlp.%d subsock.%d pushsock.%d\n",swap->connected,amlp,subsock,pushsock);
+ if ( swap->connected <= 0 && amlp != 0 && subsock >= 0 && pushsock >= 0 )
+ {
+ if ( (retstr= _dex_psock(myinfo,"{}")) != 0 )
+ {
+ printf("psock returns.(%s)\n",retstr);
+ // {"result":"success","pushaddr":"tcp://5.9.102.210:30002","subaddr":"tcp://5.9.102.210:30003","randipbits":3606291758,"coin":"KMD","tag":"6952562460568228137"}
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
+ {
+ pushaddr = jstr(retjson,"pushaddr");
+ subaddr = jstr(retjson,"subaddr");
+ if ( pushaddr != 0 && subaddr != 0 )
+ {
+ if ( nn_connect(pushsock,pushaddr) >= 0 )
+ {
+ printf("connected to %d pushaddr.(%s)\n",pushsock,pushaddr);
+ if ( nn_connect(subsock,subaddr) >= 0 )
+ {
+ swap->connected = 1;
+ init_hexbytes_noT(pubkeystr,myinfo->persistent_pubkey33,33);
+ sprintf((char *)data,"{\"push\":\"%s\",\"sub\":\"%s\",\"trade\":[\"%s\", %.8f, \"%s\", %.8f],\"pub\":\"%s\"}",pushaddr,subaddr,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),pubkeystr);
+ datalen = (int32_t)strlen((char *)data) + 1;
+ printf("datalen.%d (%s)\n",datalen,(char *)data);
+ init_hexbytes_noT(databuf,data,datalen);
+ printf("%s -> %s\n",keystr,databuf);
+ if ( (retstr2= _dex_kvupdate(myinfo,"KV",keystr,databuf,1)) != 0 )
+ {
+ printf("KVupdate.(%s)\n",retstr2);
+ free(retstr2);
+ }
+ } else printf("nn_connect error to %d subaddr.(%s)\n",subsock,subaddr);
+ } else printf("nn_connect error to %d pushaddr.(%s)\n",pushsock,pushaddr);
+ }
+ else printf("missing addr (%p) (%p) (%s)\n",pushaddr,subaddr,jprint(retjson,0));
+ free_json(retjson);
+ } else printf("Error parsing psock.(%s)\n",retstr);
+ free(retstr);
+ } else printf("error issuing _dex_psock\n");
}
- printf("%s swap finished statebits %x\n",swap->iambob!=0?"BOB":"ALICE",swap->statebits);
- basilisk_swap_purge(myinfo,swap);
}
-struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,struct basilisk_request *rp)
+int32_t basilisk_alicetxs(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
- int32_t i; struct basilisk_swap *swap = 0;
- portable_mutex_lock(&myinfo->DEX_swapmutex);
- for (i=0; inumswaps; i++)
- if ( myinfo->swaps[i]->req.requestid == rp->requestid )
+ int32_t i,retval = -1;
+ printf("alicetxs\n");
+ for (i=0; i<3; i++)
+ {
+ if ( swap->alicepayment.I.datalen == 0 )
+ basilisk_alicepayment(myinfo,swap,swap->alicepayment.coin,&swap->alicepayment,swap->I.pubAm,swap->I.pubBn);
+ if ( swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.spendlen == 0 )
{
- printf("basilisk_thread_start error trying to start requestid.%u which is already started\n",rp->requestid);
+ printf("error alice generating payment.%d\n",swap->alicepayment.I.spendlen);
+ sleep(20);
+ }
+ else
+ {
+ retval = 0;
+ for (i=0; ialicepayment.I.datalen; i++)
+ printf("%02x",swap->alicepayment.txbytes[i]);
+ printf(" ALICE PAYMENT created\n");
+ iguana_unspents_mark(myinfo,swap->alicecoin,swap->alicepayment.vins);
+ basilisk_txlog(myinfo,swap,&swap->alicepayment,-1);
break;
}
- if ( i == myinfo->numswaps && i < sizeof(myinfo->swaps)/sizeof(*myinfo->swaps) )
+ }
+ if ( swap->myfee.I.datalen == 0 )
{
- swap = calloc(1,sizeof(*swap));
- swap->req = *rp;
- swap->myinfo = myinfo;
- printf("START swap requestid.%u\n",rp->requestid);
- if ( bitcoin_swapinit(myinfo,swap) != 0 )
+ printf("generate fee\n");
+ if ( basilisk_rawtx_gen("myfee",myinfo,swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,swap->myfee.coin->chain->txfee,1,0) == 0 )
+ {
+ swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40,0);
+ iguana_unspents_mark(myinfo,swap->I.iambob!=0?swap->bobcoin:swap->alicecoin,swap->myfee.vins);
+ basilisk_txlog(myinfo,swap,&swap->myfee,-1);
+ for (i=0; imyfee.I.spendlen; i++)
+ printf("%02x",swap->myfee.txbytes[i]);
+ printf(" fee %p %x\n",swap->myfee.txbytes,swap->I.statebits);
+ swap->I.statebits |= 0x40;
+ }
+ else
+ {
+ printf("error creating myfee\n");
+ return(-2);
+ }
+ }
+ if ( swap->alicepayment.I.datalen != 0 && swap->alicepayment.I.spendlen > 0 && swap->myfee.I.datalen != 0 && swap->myfee.I.spendlen > 0 )
+ return(0);
+ return(-1);
+}
+
+void basilisk_swaploop(void *_swap)
+{
+ uint8_t *data; uint32_t expiration,savestatebits=0,saveotherbits=0; uint32_t channel; int32_t iters,retval=0,j,datalen,maxlen; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap;
+ myinfo = swap->myinfoptr;
+ fprintf(stderr,"start swap\n");
+ maxlen = 1024*1024 + sizeof(*swap);
+ data = malloc(maxlen);
+ expiration = (uint32_t)time(NULL) + 300;
+ myinfo->DEXactive = expiration;
+ channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16);
+ while ( swap->aborted == 0 && (swap->I.statebits & (0x08|0x02)) != (0x08|0x02) && time(NULL) < expiration )
+ {
+ dex_channelsend(myinfo,swap->I.req.srchash,swap->I.req.desthash,channel,0x4000000,(void *)&swap->I.req.requestid,sizeof(swap->I.req.requestid)); //,60);
+ if ( swap->connected == 0 )
+ basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
+ if ( swap->connected > 0 )
+ {
+ printf("A r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits);
+ basilisk_sendstate(myinfo,swap,data,maxlen);
+ basilisk_sendpubkeys(myinfo,swap,data,maxlen); // send pubkeys
+ if ( basilisk_checkdeck(myinfo,swap,data,maxlen) == 0) // check for other deck 0x02
+ basilisk_sendchoosei(myinfo,swap,data,maxlen);
+ basilisk_waitchoosei(myinfo,swap,data,maxlen); // wait for choosei 0x08
+ if ( (swap->I.statebits & (0x08|0x02)) == (0x08|0x02) )
+ break;
+ }
+ if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
+ sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
+ savestatebits = swap->I.statebits;
+ saveotherbits = swap->I.otherstatebits;
+ }
+ if ( swap->connected == 0 )
+ {
+ printf("couldnt establish connection\n");
+ retval = -1;
+ }
+ while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x20) == 0 )
+ {
+ if ( swap->connected == 0 )
+ basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
+ printf("B r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits);
+ basilisk_sendstate(myinfo,swap,data,maxlen);
+ basilisk_sendchoosei(myinfo,swap,data,maxlen);
+ basilisk_sendmostprivs(myinfo,swap,data,maxlen);
+ if ( basilisk_swapget(myinfo,swap,0x20,data,maxlen,basilisk_verify_privkeys) == 0 )
+ {
+ swap->I.statebits |= 0x20;
+ break;
+ }
+ if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
+ sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
+ savestatebits = swap->I.statebits;
+ saveotherbits = swap->I.otherstatebits;
+ if ( time(NULL) > expiration )
+ break;
+ }
+ myinfo->DEXactive = swap->I.expiration;
+ if ( time(NULL) >= expiration )
+ {
+ retval = -1;
+ myinfo->DEXactive = 0;
+ }
+ if ( swap->aborted != 0 )
+ {
+ printf("swap aborted before tx sent\n");
+ retval = -1;
+ }
+ printf("C r%u/q%u swapstate.%x retval.%d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,retval);
+ iters = 0;
+ while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x40) == 0 && iters++ < 10 ) // send fee
+ {
+ if ( swap->connected == 0 )
+ basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
+ //printf("sendstate.%x\n",swap->I.statebits);
+ basilisk_sendstate(myinfo,swap,data,maxlen);
+ //printf("swapget\n");
+ basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
+ //printf("after swapget\n");
+ if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen == 0 )
+ {
+ printf("bobscripts set\n");
+ if ( basilisk_bobscripts_set(myinfo,swap,1,1) < 0 )
+ {
+ sleep(DEX_SLEEP);
+ printf("bobscripts set error\n");
+ continue;
+ }
+ }
+ if ( swap->I.iambob == 0 )
{
- fprintf(stderr,"launch.%d %d\n",myinfo->numswaps,(int32_t)(sizeof(myinfo->swaps)/sizeof(*myinfo->swaps)));
- if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)basilisk_swaploop,(void *)swap) != 0 )
+ /*for (i=0; i<20; i++)
+ printf("%02x",swap->secretAm[i]);
+ printf(" <- secretAm\n");
+ for (i=0; i<32; i++)
+ printf("%02x",swap->secretAm256[i]);
+ printf(" <- secretAm256\n");
+ for (i=0; i<32; i++)
+ printf("%02x",swap->pubAm.bytes[i]);
+ printf(" <- pubAm\n");
+ for (i=0; i<20; i++)
+ printf("%02x",swap->secretBn[i]);
+ printf(" <- secretBn\n");
+ for (i=0; i<32; i++)
+ printf("%02x",swap->secretBn256[i]);
+ printf(" <- secretBn256\n");
+ for (i=0; i<32; i++)
+ printf("%02x",swap->pubBn.bytes[i]);
+ printf(" <- pubBn\n");
+ for (i=0; i<32; i++)
+ printf("%02x",swap->pubA0.bytes[i]);
+ printf(" <- pubA0\n");
+ for (i=0; i<32; i++)
+ printf("%02x",swap->pubA1.bytes[i]);
+ printf(" <- pubA1\n");
+ for (i=0; i<32; i++)
+ printf("%02x",swap->pubB0.bytes[i]);
+ printf(" <- pubB0\n");
+ for (i=0; i<32; i++)
+ printf("%02x",swap->pubB1.bytes[i]);
+ printf(" <- pubB1\n");*/
+ if ( (retval= basilisk_alicetxs(myinfo,swap,data,maxlen)) != 0 )
{
-
+ printf("basilisk_alicetxs error\n");
+ break;
}
- myinfo->swaps[myinfo->numswaps++] = swap;
}
}
- portable_mutex_unlock(&myinfo->DEX_swapmutex);
- return(swap);
-}
+ if ( swap->I.iambob == 0 && (swap->I.statebits & 0x40) == 0 )
+ {
+ printf("couldnt send fee\n");
+ retval = -8;
+ }
+ if ( retval == 0 )
+ {
+ if ( swap->I.iambob == 0 && (swap->myfee.I.datalen == 0 || swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.datalen == 0) )
+ {
+ printf("ALICE's error %d %d %d\n",swap->myfee.I.datalen,swap->alicepayment.I.datalen,swap->alicepayment.I.datalen);
+ retval = -7;
+ }
+ else if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen == 0 ) //swap->bobpayment.I.datalen == 0
+ {
+ printf("BOB's error %d %d %d\n",swap->myfee.I.datalen,swap->bobpayment.I.datalen,swap->bobdeposit.I.datalen);
+ retval = -7;
+ }
+ }
+ while ( swap->aborted == 0 && retval == 0 && basilisk_swapiteration(myinfo,swap,data,maxlen) == 0 )
+ {
+ if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
+ sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
+ savestatebits = swap->I.statebits;
+ saveotherbits = swap->I.otherstatebits;
+ basilisk_sendstate(myinfo,swap,data,maxlen);
+ basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
+ basilisk_swap_saveupdate(myinfo,swap);
+ if ( time(NULL) > swap->I.expiration )
+ break;
+ }
+ if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen != 0 && bits256_nonz(swap->bobdeposit.I.actualtxid) != 0 )
+ {
+ printf("BOB waiting for confirm state.%x\n",swap->I.statebits);
+ sleep(60); // wait for confirm/propagation of msig
+ printf("BOB reclaims refund\n");
+ basilisk_bobdeposit_refund(myinfo,swap,0);
+ if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobrefund,0x40000000,0) == 0 ) // use secretBn
+ {
+ printf("Bob submit error getting refund of deposit\n");
+ }
+ else
+ {
+ // maybe wait for bobrefund to be confirmed
+ for (j=datalen=0; j<32; j++)
+ data[datalen++] = swap->I.privBn.bytes[j];
+ basilisk_swapsend(myinfo,swap,0x40000000,data,datalen,0x40000000,swap->I.crcs_mypriv);
+ }
+ basilisk_swap_saveupdate(myinfo,swap);
+ }
+ if ( retval != 0 )
+ basilisk_swap_sendabort(myinfo,swap);
+ printf("end of atomic swap\n");
+ if ( swapcompleted(myinfo,swap) > 0 ) // only if swap completed
+ {
+ if ( swap->I.iambob != 0 )
+ tradebot_pendingadd(myinfo,swapjson(myinfo,swap),swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount));
+ else tradebot_pendingadd(myinfo,swapjson(myinfo,swap),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.src,dstr(swap->I.req.srcamount));
+ }
+ printf("%s swap finished statebits %x\n",swap->I.iambob!=0?"BOB":"ALICE",swap->I.statebits);
+ basilisk_swap_purge(myinfo,swap);
+ free(data);
+}
+
+cJSON *basilisk_swapjson(struct supernet_info *myinfo,struct basilisk_swap *swap)
+{
+ cJSON *item = cJSON_CreateObject();
+ jaddnum(item,"requestid",swap->I.req.requestid);
+ jaddnum(item,"quoteid",swap->I.req.quoteid);
+ jaddnum(item,"state",swap->I.statebits);
+ jaddnum(item,"otherstate",swap->I.otherstatebits);
+ jadd(item,"request",basilisk_requestjson(&swap->I.req));
+ return(item);
+}
+
+struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit)
+{
+ int32_t i,m,n,iter; uint8_t pubkey33[33]; bits256 pubkey25519; uint32_t channel,starttime; cJSON *retarray,*item,*msgobj; struct iguana_info *coin; double pending=0.; struct basilisk_swap *swap = 0;
+ // statebits 1 -> client, 0 -> LP
+ if ( myinfo->numswaps > 0 )
+ {
+ if ( (coin= iguana_coinfind(rp->src)) == 0 || coin->FULLNODE >= 0 )
+ {
+ printf("dont have SRC coin.%s or not native and already swap pending\n",rp->src);
+ return(0);
+ }
+ if ( (coin= iguana_coinfind(rp->dest)) == 0 || coin->FULLNODE >= 0 )
+ {
+ printf("dont have DEST coin.%s or not native and already swap pending\n",rp->dest);
+ return(0);
+ }
+ }
+ portable_mutex_lock(&myinfo->DEX_swapmutex);
+ for (i=0; inumswaps; i++)
+ if ( myinfo->swaps[i]->I.req.requestid == rp->requestid )
+ {
+ printf("basilisk_thread_start error trying to start requestid.%u which is already started\n",rp->requestid);
+ break;
+ }
+ if ( i == myinfo->numswaps && i < sizeof(myinfo->swaps)/sizeof(*myinfo->swaps) )
+ {
+ swap = calloc(1,sizeof(*swap));
+ swap->subsock = swap->pushsock = -1;
+ vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp));
+ swap->I.req = *rp;
+ swap->myinfoptr = myinfo;
+ printf("basilisk_thread_start request.%u statebits.%d (%s/%s) reinit.%d\n",rp->requestid,statebits,rp->src,rp->dest,reinit);
+ bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey);
+ pubkey25519 = curve25519(privkey,curve25519_basepoint9());
+ swap->persistent_pubkey = pubkey25519;
+ swap->persistent_privkey = privkey;
+ memcpy(swap->persistent_pubkey33,pubkey33,33);
+ m = n = 0;
+ if ( bitcoin_swapinit(myinfo,privkey,pubkey33,pubkey25519,swap,optionduration,statebits,reinit) != 0 )
+ {
+ for (iter=0; iter<16; iter++)
+ {
+ basilisk_psockinit(myinfo,swap,statebits == 0);
+ sleep(3);
+ if ( swap->connected > 0 )
+ break;
+ sleep(10);
+ /*basilisk_sendstate(myinfo,swap,data,sizeof(data));
+ basilisk_swapget(myinfo,swap,0x80000000,data,sizeof(data),basilisk_verify_statebits);
+ if ( swap->connected > 0 )
+ break;
+ printf("loopback didntwork with %d %d\n",swap->pushsock,swap->subsock);*/
+ }
+ if ( reinit != 0 )
+ {
+ if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)basilisk_swaploop,(void *)swap) != 0 )
+ {
+
+ }
+ myinfo->swaps[myinfo->numswaps++] = swap;
+ }
+ else
+ {
+ starttime = (uint32_t)time(NULL);
+ printf("statebits.%x m.%d n.%d\n",statebits,m,n);
+ while ( statebits == 0 && m <= n/2 && time(NULL) < starttime+7*BASILISK_MSGDURATION )
+ {
+ uint32_t msgid; uint8_t data[1024]; int32_t datalen;
+ m = n = 0;
+ sleep(DEX_SLEEP);
+ printf("waiting for offer to be accepted\n");
+ channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16);
+ datalen = basilisk_rwDEXquote(1,data,rp);
+ msgid = (uint32_t)time(NULL);
+ printf("other req.%d >>>>>>>>>>> send response (%llx -> %llx) last.%u r.%u quoteid.%u\n",i,(long long)rp->desthash.txid,(long long)rp->srchash.txid,myinfo->lastdexrequestid,rp->requestid,rp->quoteid);
+ dex_channelsend(myinfo,rp->desthash,rp->srchash,channel,msgid,data,datalen);
+ if ( (retarray= basilisk_channelget(myinfo,rp->srchash,rp->desthash,channel,0x4000000,30)) != 0 )
+ {
+ if ( is_cJSON_Array(retarray) != 0 && (n= cJSON_GetArraySize(retarray)) > 0 )
+ {
+ for (i=0; i 0 )
+ {
+ item = jitem(msgobj,0);
+ if ( jobj(item,"data") != 0 && jobj(item,"key") != 0 )
+ m++;
+ else printf("(%s)\n",jprint(item,0));
+ } //else printf("msgobj.%p m.%d n.%d\n",msgobj,m,n);
+ }
+ }
+ } else printf("no retarray\n");
+ }
+ printf("LAUNCH check.%d m.%d\n",statebits,m);
+ if ( statebits != 0 || m > 0 )//n/2 )
+ {
+ //for (i=0; iI.req); i++)
+ // fprintf(stderr,"%02x",((uint8_t *)&swap->I.req)[i]);
+ fprintf(stderr," M.%d N.%d launch.%d %d %p reinit.%d\n",m,n,myinfo->numswaps,(int32_t)(sizeof(myinfo->swaps)/sizeof(*myinfo->swaps)),&swap->I.req,reinit);
+ if ( (swap->fp= basilisk_swap_save(myinfo,swap,privkey,rp,statebits,optionduration,reinit)) != 0 )
+ {
+ }
+ if ( reinit == 0 )
+ {
+ if ( myinfo->swapsfp == 0 )
+ {
+ char fname[512];
+ sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
+ if ( (myinfo->swapsfp= fopen(fname,"rb+")) == 0 )
+ myinfo->swapsfp = fopen(fname,"wb+");
+ else fseek(myinfo->swapsfp,0,SEEK_END);
+ printf("LIST fp.%p\n",myinfo->swapsfp);
+ }
+ if ( myinfo->swapsfp != 0 )
+ {
+ fwrite(&rp->requestid,1,sizeof(rp->requestid),myinfo->swapsfp);
+ fwrite(&rp->quoteid,1,sizeof(rp->quoteid),myinfo->swapsfp);
+ fflush(myinfo->swapsfp);
+ }
+ }
+ if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)basilisk_swaploop,(void *)swap) != 0 )
+ {
+
+ }
+ myinfo->swaps[myinfo->numswaps++] = swap;
+ }
+ else
+ {
+ if ( statebits != 0 )
+ {
+ if ( (coin= iguana_coinfind(rp->src)) != 0 )
+ {
+
+ }
+ }
+ printf("%u/%u offer wasnt accepted statebits.%d m.%d n.%d pending %.8f\n",rp->requestid,rp->quoteid,statebits,m,n,pending);
+ }
+ }
+ }
+ }
+ portable_mutex_unlock(&myinfo->DEX_swapmutex);
+ return(swap);
+}
+
+/////////////// remember functions
+
+cJSON *basilisk_nullretjson(cJSON *retjson)
+{
+ char *outstr;
+ if ( retjson != 0 )
+ {
+ outstr = jprint(retjson,0);
+ if ( strcmp(outstr,"{}") == 0 )
+ {
+ free_json(retjson);
+ retjson = 0;
+ }
+ free(outstr);
+ }
+ return(retjson);
+}
+
+cJSON *basilisk_swapgettxout(struct supernet_info *myinfo,char *symbol,bits256 trigger,int32_t vout)
+{
+ char *retstr; cJSON *retjson=0; struct iguana_info *coin;
+ if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 )
+ {
+ if ( (retstr= dex_gettxout(myinfo,0,0,0,trigger,symbol,vout)) != 0 )
+ {
+ //printf("dexgettxout.(%s)\n",retstr);
+ retjson = cJSON_Parse(retstr);
+ free(retstr);
+ }
+ if ( 0 && strcmp("BTC",symbol) == 0 )
+ printf("%s gettxout.(%s)\n",symbol,jprint(retjson,0));
+ }
+ else
+ {
+ retjson = dpow_gettxout(myinfo,coin,trigger,vout);
+ //printf("need to verify passthru has this info\n");
+ //printf("dpowgettxout.(%s)\n",jprint(retjson,0));
+ }
+ return(basilisk_nullretjson(retjson));
+}
+
+cJSON *basilisk_swapgettx(struct supernet_info *myinfo,char *symbol,bits256 txid)
+{
+ char *retstr; cJSON *retjson=0; struct iguana_info *coin;
+ if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 )
+ {
+ if ( (retstr= dex_gettransaction(myinfo,0,0,0,txid,symbol)) != 0 )
+ {
+ retjson = cJSON_Parse(retstr);
+ free(retstr);
+ }
+ //if ( strcmp("BTC",symbol) == 0 )
+ // printf("%s gettx.(%s)\n",symbol,jprint(retjson,0));
+ } else retjson = dpow_gettransaction(myinfo,coin,txid);
+ return(basilisk_nullretjson(retjson));
+}
+
+int32_t basilisk_swap_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj)
+{
+ int32_t n,m,retval = -1; cJSON *vouts,*item,*addresses,*skey; char *addr;
+ if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n )
+ {
+ item = jitem(vouts,vout);
+ if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 )
+ {
+ item = jitem(addresses,0);
+ if ( (addr= jstr(item,0)) != 0 )
+ {
+ safecopy(destaddr,addr,64);
+ retval = 0;
+ }
+ //printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr);
+ }
+ }
+ return(retval);
+}
+
+int32_t basilisk_swap_getcoinaddr(struct supernet_info *myinfo,char *symbol,char *coinaddr,bits256 txid,int32_t vout)
+{
+ cJSON *retjson;
+ coinaddr[0] = 0;
+ if ( (retjson= basilisk_swapgettx(myinfo,symbol,txid)) != 0 )
+ {
+ basilisk_swap_txdestaddr(coinaddr,txid,vout,retjson);
+ free_json(retjson);
+ }
+ return(coinaddr[0] != 0);
+}
+
+int32_t basilisk_swap_getsigscript(struct supernet_info *myinfo,char *symbol,uint8_t *script,int32_t maxlen,bits256 txid,int32_t vini)
+{
+ cJSON *retjson,*vins,*item,*skey; int32_t n,scriptlen = 0; char *hexstr;
+ if ( (retjson= basilisk_swapgettx(myinfo,symbol,txid)) != 0 )
+ {
+ if ( (vins= jarray(&n,retjson,"vin")) != 0 && vini < n )
+ {
+ item = jitem(vins,vini);
+ if ( (skey= jobj(item,"scriptSig")) != 0 && (hexstr= jstr(skey,"hex")) != 0 && (scriptlen= (int32_t)strlen(hexstr)) < maxlen*2 )
+ {
+ scriptlen >>= 1;
+ decode_hex(script,scriptlen,hexstr);
+ //char str[65]; printf("%s/v%d sigscript.(%s)\n",bits256_str(str,txid),vini,hexstr);
+ }
+ }
+ free_json(retjson);
+ }
+ return(scriptlen);
+}
+
+int64_t basilisk_txvalue(struct supernet_info *myinfo,char *symbol,bits256 txid,int32_t vout)
+{
+ cJSON *txobj,*vouts,*item; int32_t n; int64_t value = 0;
+ //char str[65]; printf("%s txvalue.(%s)\n",symbol,bits256_str(str,txid));
+ if ( (txobj= basilisk_swapgettx(myinfo,symbol,txid)) != 0 )
+ {
+ //printf("txobj.(%s)\n",jprint(txobj,0));
+ if ( (vouts= jarray(&n,txobj,"vout")) != 0 )
+ {
+ item = jitem(vouts,vout);
+ if ( (value= jdouble(item,"amount") * SATOSHIDEN) == 0 )
+ value = jdouble(item,"value") * SATOSHIDEN;
+ }
+ free_json(txobj);
+ }
+ return(value);
+}
+
+bits256 dex_swap_spendtxid(struct supernet_info *myinfo,char *symbol,char *destaddr,char *coinaddr,bits256 utxotxid,int32_t vout)
+{
+ char *retstr,*addr; cJSON *array,*item,*array2; int32_t i,n,m; bits256 spendtxid,txid;
+ memset(&spendtxid,0,sizeof(spendtxid));
+ if ( (retstr= dex_listtransactions(myinfo,0,0,0,symbol,coinaddr,100,0)) != 0 )
+ {
+ if ( (array= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( (n= cJSON_GetArraySize(array)) > 0 )
+ {
+ for (i=0; i %s\n",bits256_str(str,spendtxid),destaddr);
+ break;
+ }
+ }
+ }
+ }
+ free_json(array);
+ }
+ free(retstr);
+ }
+ return(spendtxid);
+}
+
+bits256 basilisk_swap_spendtxid(struct supernet_info *myinfo,char *symbol,char *destaddr,bits256 utxotxid,int32_t vout)
+{
+ bits256 spendtxid,txid; char *catstr,*addr; cJSON *array,*item,*item2,*txobj,*vins; int32_t i,n,m; char coinaddr[64],str[65]; struct iguana_info *coin = iguana_coinfind(symbol);
+ // listtransactions or listspents
+ destaddr[0] = 0;
+ coinaddr[0] = 0;
+ memset(&spendtxid,0,sizeof(spendtxid));
+ //char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid));
+ if ( (coin == 0 || coin->FULLNODE >= 0) && iguana_isnotarychain(symbol) >= 0 )
+ {
+ //[{"type":"sent","confirmations":379,"height":275311,"timestamp":1492084664,"txid":"8703c5517bc57db38134058370a14e99b8e662b99ccefa2061dea311bbd02b8b","vout":0,"amount":117.50945263,"spendtxid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","vin":0,"paid":{"type":"paid","txid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","height":275663,"timestamp":1492106024,"vouts":[{"RUDpN6PEBsE7ZFbGjUxk1W3QVsxnjBLYw6":117.50935263}]}}]
+ basilisk_swap_getcoinaddr(myinfo,symbol,coinaddr,utxotxid,vout);
+ if ( coinaddr[0] != 0 )
+ spendtxid = dex_swap_spendtxid(myinfo,symbol,destaddr,coinaddr,utxotxid,vout);
+ }
+ else if ( coin != 0 )
+ {
+ if ( (array= dpow_listtransactions(myinfo,coin,destaddr,1000,0)) != 0 )
+ {
+ if ( (n= cJSON_GetArraySize(array)) > 0 )
+ {
+ for (i=0; i 0 )
+ {
+ for (i=0; i jint(item,"vout") )
+ {
+ item2 = jitem(vins,jint(item,"vout"));
+ if ( bits256_cmp(utxotxid,jbits256(item2,"txid")) == 0 && vout == jint(item2,"vout") )
+ {
+ spendtxid = txid;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if ( i == n )
+ printf("dpowlist: native couldnt find spendtxid for %s\n",bits256_str(str,utxotxid));
+ }
+ free_json(array);
+ }
+ if ( bits256_nonz(spendtxid) != 0 )
+ return(spendtxid);
+ }
+ if ( iguana_isnotarychain(symbol) >= 0 )
+ {
+ basilisk_swap_getcoinaddr(myinfo,symbol,coinaddr,utxotxid,vout);
+ printf("fallback use DEX for native (%s) (%s)\n",coinaddr,bits256_str(str,utxotxid));
+ if ( coinaddr[0] != 0 )
+ {
+ spendtxid = dex_swap_spendtxid(myinfo,symbol,destaddr,coinaddr,utxotxid,vout);
+ printf("spendtxid.(%s)\n",bits256_str(str,spendtxid));
+ }
+ }
+ }
+ return(spendtxid);
+}
+
+bits256 basilisk_swap_sendrawtransaction(struct supernet_info *myinfo,char *txname,char *symbol,char *txbytes)
+{
+ char *retstr; bits256 txid; int32_t i,sentflag = 0;
+ memset(&txid,0,sizeof(txid));
+ for (i=0; i<3; i++)
+ {
+ if ( (retstr= _dex_sendrawtransaction(myinfo,symbol,txbytes)) != 0 )
+ {
+ if ( is_hexstr(retstr,0) == 64 )
+ {
+ decode_hex(txid.bytes,32,retstr);
+ sentflag = 1;
+ }
+ char str[65]; printf("[%s] %s RETSTR.(%s) %s.%s\n",txname,txbytes,retstr,symbol,bits256_str(str,txid));
+ free(retstr);
+ }
+ if ( sentflag != 0 )
+ break;
+ }
+ return(txid);
+}
+
+char *basilisk_swap_bobtxspend(char *name,struct supernet_info *myinfo,char *symbol,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,uint8_t *pubkey33,int32_t finalseqid,uint32_t expiration,int64_t *destamountp)
+{
+ char *rawtxbytes=0,*signedtx=0,str[65],hexstr[999],wifstr[128],destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *utxoobj,*txobj,*vins,*item,*sobj,*privkeys; int32_t height,completed,spendlen,ignore_cltverr=1,suppress_pubkeys=1; struct vin_info *V; uint32_t timestamp,locktime = 0,sequenceid = 0xffffffff * finalseqid; struct iguana_info *coin; bits256 txid,signedtxid; uint64_t destamount;
+ *destamountp = 0;
+ if ( finalseqid == 0 )
+ locktime = expiration;
+ //printf("bobtxspend.%s redeem.[%d]\n",symbol,redeemlen);
+ if ( redeemlen < 0 || (coin= iguana_coinfind(symbol)) == 0 )
+ return(0);
+ if ( (utxoobj= basilisk_swapgettxout(myinfo,symbol,utxotxid,vout)) == 0 )
+ {
+ printf("basilisk_swap_bobtxspend.%s utxo already spent or doesnt exist\n",name);
+ return(0);
+ }
+ if ( (destamount= jdouble(utxoobj,"amount")*SATOSHIDEN) == 0 && (destamount= jdouble(utxoobj,"value")*SATOSHIDEN) == 0 )
+ {
+ printf("%s %s basilisk_swap_bobtxspend.%s strange utxo.(%s)\n",symbol,bits256_str(str,utxotxid),name,jprint(utxoobj,0));
+ free_json(utxoobj);
+ return(0);
+ } else free_json(utxoobj);
+ *destamountp = destamount;
+ if ( destamount > 10000 )
+ destamount -= 10000;
+ if ( strcmp(symbol,"BTC") == 0 )
+ {
+ if ( destamount > 40000 )
+ destamount -= 40000;
+ }
+ height = coin->longestchain;
+ timestamp = (uint32_t)time(NULL);
+ V = calloc(256,sizeof(*V));
+ privkeys = cJSON_CreateArray();
+ if ( privkey2p != 0 )
+ {
+ V[0].signers[1].privkey = *privkey2p;
+ bitcoin_pubkey33(myinfo->ctx,V[0].signers[1].pubkey,*privkey2p);
+ bitcoin_priv2wif(wifstr,*privkey2p,coin->chain->wiftype);
+ jaddistr(privkeys,wifstr);
+ V[0].N = V[0].M = 2;
+ } else V[0].N = V[0].M = 1;
+ V[0].signers[0].privkey = privkey;
+ bitcoin_pubkey33(myinfo->ctx,V[0].signers[0].pubkey,privkey);
+ bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype);
+ jaddistr(privkeys,wifstr);
+ V[0].suppress_pubkeys = suppress_pubkeys;
+ V[0].ignore_cltverr = ignore_cltverr;
+ if ( redeemlen != 0 )
+ memcpy(V[0].p2shscript,redeemscript,redeemlen), V[0].p2shlen = redeemlen;
+ txobj = bitcoin_txcreate(coin->symbol,coin->chain->isPoS,locktime,1,timestamp);
+ vins = cJSON_CreateArray();
+ item = cJSON_CreateObject();
+ if ( userdata != 0 && userdatalen > 0 )
+ {
+ memcpy(V[0].userdata,userdata,userdatalen);
+ V[0].userdatalen = userdatalen;
+ init_hexbytes_noT(hexstr,userdata,userdatalen);
+ jaddstr(item,"userdata",hexstr);
+ }
+ jaddbits256(item,"txid",utxotxid);
+ jaddnum(item,"vout",vout);
+ sobj = cJSON_CreateObject();
+ bitcoin_address(destaddr,coin->chain->pubtype,pubkey33,33);
+ bitcoin_addr2rmd160(&addrtype,rmd160,destaddr);
+ /*int32_t i;
+ for (i=0; i<33; i++)
+ printf("%02x",pubkey33[i]);
+ printf(" pubkey33 ->\n");
+ for (i=0; i<20; i++)
+ printf("%02x",rmd160[i]);
+ printf(" destaddr.(%s)\n",destaddr);
+ calc_rmd160_sha256(rmd160,pubkey33,33);
+ for (i=0; i<20; i++)
+ printf("%02x",rmd160[i]);
+ printf(" <- vs direct calc\n");*/
+ spendlen = bitcoin_standardspend(spendscript,0,rmd160);
+ init_hexbytes_noT(hexstr,spendscript,spendlen);
+ jaddstr(sobj,"hex",hexstr);
+ jadd(item,"scriptPubKey",sobj);
+ jaddnum(item,"suppress",suppress_pubkeys);
+ jaddnum(item,"sequence",sequenceid);
+ if ( redeemlen != 0 )
+ {
+ init_hexbytes_noT(hexstr,redeemscript,redeemlen);
+ jaddstr(item,"redeemScript",hexstr);
+ }
+ jaddi(vins,item);
+ jdelete(txobj,"vin");
+ jadd(txobj,"vin",vins);
+ txobj = bitcoin_txoutput(txobj,spendscript,spendlen,destamount);
+ if ( (rawtxbytes= bitcoin_json2hex(myinfo,coin,&txid,txobj,V)) != 0 )
+ {
+ //printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0));
+ if ( (signedtx= iguana_signrawtx(myinfo,coin,height,&signedtxid,&completed,vins,rawtxbytes,privkeys,V)) == 0 )
+ printf("couldnt sign transaction\n");
+ else if ( completed == 0 )
+ printf("incomplete signing\n");
+ else printf("%s -> %s\n",name,bits256_str(str,signedtxid));
+ free(rawtxbytes);
+ } else printf("error making rawtx\n");
+ free_json(privkeys);
+ free_json(txobj);
+ free(V);
+ return(signedtx);
+}
+
+char *basilisk_swap_Aspend(char *name,struct supernet_info *myinfo,char *symbol,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33],uint32_t expiration,int64_t *destamountp)
+{
+ char msigaddr[64],*signedtx = 0; int32_t spendlen,redeemlen; uint8_t tmp33[33],redeemscript[512],spendscript[128]; bits256 pubAm,pubBn; struct iguana_info *coin = iguana_coinfind(symbol);
+ if ( coin != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
+ {
+ pubAm = bitcoin_pubkey33(myinfo->ctx,tmp33,privAm);
+ pubBn = bitcoin_pubkey33(myinfo->ctx,tmp33,privBn);
+ //char str[65];
+ //printf("pubAm.(%s)\n",bits256_str(str,pubAm));
+ //printf("pubBn.(%s)\n",bits256_str(str,pubBn));
+ spendlen = basilisk_alicescript(redeemscript,&redeemlen,spendscript,0,msigaddr,coin->chain->p2shtype,pubAm,pubBn);
+ //char str[65]; printf("%s utxo.(%s) redeemlen.%d spendlen.%d\n",msigaddr,bits256_str(str,utxotxid),redeemlen,spendlen);
+ /*rev = privAm;
+ for (i=0; i<32; i++)
+ privAm.bytes[i] = rev.bytes[31 - i];
+ rev = privBn;
+ for (i=0; i<32; i++)
+ privBn.bytes[i] = rev.bytes[31 - i];*/
+ signedtx = basilisk_swap_bobtxspend(name,myinfo,symbol,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,pubkey33,1,expiration,destamountp);
+ }
+ return(signedtx);
+}
+
+bits256 basilisk_swap_privbob_extract(struct supernet_info *myinfo,char *symbol,bits256 spendtxid,int32_t vini,int32_t revflag)
+{
+ bits256 privkey; int32_t i,scriptlen,siglen; uint8_t script[1024]; // from Bob refund of Bob deposit
+ memset(&privkey,0,sizeof(privkey));
+ if ( (scriptlen= basilisk_swap_getsigscript(myinfo,symbol,script,(int32_t)sizeof(script),spendtxid,vini)) > 0 )
+ {
+ siglen = script[0];
+ for (i=0; i<32; i++)
+ {
+ if ( revflag != 0 )
+ privkey.bytes[31 - i] = script[siglen+2+i];
+ else privkey.bytes[i] = script[siglen+2+i];
+ }
+ char str[65]; printf("extracted privbob.(%s)\n",bits256_str(str,privkey));
+ }
+ return(privkey);
+}
+
+bits256 basilisk_swap_privBn_extract(struct supernet_info *myinfo,bits256 *bobrefundp,char *bobcoin,bits256 bobdeposit,bits256 privBn)
+{
+ char destaddr[64];
+ if ( bits256_nonz(privBn) == 0 )
+ {
+ if ( bits256_nonz(bobdeposit) != 0 )
+ *bobrefundp = basilisk_swap_spendtxid(myinfo,bobcoin,destaddr,bobdeposit,0);
+ if ( bits256_nonz(*bobrefundp) != 0 )
+ privBn = basilisk_swap_privbob_extract(myinfo,bobcoin,*bobrefundp,0,0);
+ }
+ return(privBn);
+}
+
+bits256 basilisk_swap_spendupdate(struct supernet_info *myinfo,char *symbol,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr)
+{
+ bits256 spendtxid,txid; char destaddr[64];
+ txid = txids[utxoind];
+ memset(&spendtxid,0,sizeof(spendtxid));
+ /*if ( aliceaddr != 0 )
+ printf("aliceaddr.(%s)\n",aliceaddr);
+ if ( bobaddr != 0 )
+ printf("bobaddr.(%s)\n",bobaddr);*/
+ if ( bits256_nonz(txid) != 0 )
+ {
+ //char str[65];
+ spendtxid = basilisk_swap_spendtxid(myinfo,symbol,destaddr,txid,vout);
+ if ( bits256_nonz(spendtxid) != 0 )
+ {
+ sentflags[utxoind] = 1;
+ if ( aliceaddr != 0 && strcmp(destaddr,aliceaddr) == 0 )
+ {
+ //printf("ALICE spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
+ sentflags[alicespent] = 1;
+ txids[alicespent] = spendtxid;
+ }
+ else if ( bobaddr != 0 && strcmp(destaddr,bobaddr) == 0 )
+ {
+ //printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
+ sentflags[bobspent] = 1;
+ txids[bobspent] = spendtxid;
+ }
+ else
+ {
+ //printf("OTHER dest spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
+ if ( aliceaddr != 0 )
+ {
+ sentflags[bobspent] = 1;
+ txids[bobspent] = spendtxid;
+ }
+ else if ( bobaddr != 0 )
+ {
+ sentflags[alicespent] = 1;
+ txids[alicespent] = spendtxid;
+ }
+ }
+ }
+ } else printf("utxoind.%d null txid\n",utxoind);
+ return(spendtxid);
+}
+
+#define BASILISK_ALICESPEND 0
+#define BASILISK_BOBSPEND 1
+#define BASILISK_BOBPAYMENT 2
+#define BASILISK_ALICEPAYMENT 3
+#define BASILISK_BOBDEPOSIT 4
+#define BASILISK_OTHERFEE 5
+#define BASILISK_MYFEE 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
+char *txnames[] = { "alicespend", "bobspend", "bobpayment", "alicepayment", "bobdeposit", "otherfee", "myfee", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" };
+
+int32_t basilisk_isbobcoin(int32_t iambob,int32_t ind)
+{
+ switch ( ind )
+ {
+ case BASILISK_MYFEE: return(iambob); break;
+ case BASILISK_OTHERFEE: return(!iambob); break;
+ case BASILISK_BOBSPEND:
+ case BASILISK_ALICEPAYMENT:
+ case BASILISK_ALICERECLAIM:
+ case BASILISK_ALICECLAIM: return(0);
+ break;
+ case BASILISK_BOBDEPOSIT:
+ case BASILISK_ALICESPEND:
+ case BASILISK_BOBPAYMENT:
+ case BASILISK_BOBREFUND:
+ case BASILISK_BOBRECLAIM: return(1);
+ break;
+ default: return(-1); break;
+ }
+}
+
+// add blocktrail presence requirement for BTC
+int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflags,bits256 paymentspent,bits256 Apaymentspent,bits256 depositspent)
+{
+ int32_t i,n = 0;
+ for (i=0; i (%s)\n",fname,fstr);
+ if ( (txobj= cJSON_Parse(fstr)) != 0 )
+ {
+ paymentspent = jbits256(txobj,"paymentspent");
+ Apaymentspent = jbits256(txobj,"Apaymentspent");
+ depositspent = jbits256(txobj,"depositspent");
+ if ( (array= jarray(&n,txobj,"values")) != 0 )
+ for (i=0; i (%s)\n",fname,fstr);
+ if ( (txobj= cJSON_Parse(fstr)) != 0 )
+ {
+ //printf("TXOBJ.(%s)\n",jprint(txobj,0));
+ iambob = jint(txobj,"iambob");
+ txid = jbits256(txobj,"txid");
+ if ( bits256_nonz(txid) == 0 )
+ continue;
+ txids[i] = txid;
+ if ( jobj(txobj,"tx") != 0 )
+ {
+ txbytes[i] = clonestr(jstr(txobj,"tx"));
+ //printf("[%s] TX.(%s)\n",txnames[i],txbytes[i]);
+ }
+ if ( (value= jdouble(txobj,"amount") * SATOSHIDEN) == 0 )
+ value = jdouble(txobj,"value") * SATOSHIDEN;
+ values[i] = value;
+ if ( (symbol= jstr(txobj,"coin")) != 0 )
+ {
+ if ( i == BASILISK_ALICESPEND || i == BASILISK_BOBPAYMENT || i == BASILISK_BOBDEPOSIT || i == BASILISK_BOBREFUND || i == BASILISK_BOBRECLAIM || i == BASILISK_ALICECLAIM )
+ safecopy(bobcoin,symbol,sizeof(bobcoin));
+ else if ( i == BASILISK_BOBSPEND || i == BASILISK_ALICEPAYMENT || i == BASILISK_ALICERECLAIM )
+ safecopy(alicecoin,symbol,sizeof(alicecoin));
+ if ( finishedflag == 0 )
+ {
+ if ( (sentobj= basilisk_swapgettx(myinfo,symbol,txid)) == 0 )
+ {
+ //printf("%s %s ready to broadcast\n",symbol,bits256_str(str2,txid));
+ }
+ else
+ {
+ checktxid = jbits256(sentobj,"txid");
+ if ( bits256_nonz(checktxid) == 0 )
+ checktxid = jbits256(sentobj,"hash");
+ if ( bits256_cmp(checktxid,txid) == 0 )
+ {
+ //printf(">>>>>> %s txid %s\n",jprint(sentobj,0),bits256_str(str,txid));
+ sentflags[i] = 1;
+ }
+ free_json(sentobj);
+ }
+ printf("%s %s %.8f\n",txnames[i],bits256_str(str,txid),dstr(value));
+ }
+ }
+ } //else printf("no symbol\n");
+ free(fstr);
+ } else if ( finishedflag == 0 )
+ printf("%s not finished\n",fname);
+ }
+ //printf("iambob.%d src.%s dest.%s bob.%s alice.%s pubA0.(%s)\n",iambob,src,dest,bobcoin,alicecoin,bits256_str(str,pubA0));
+ Adestaddr[0] = destaddr[0] = 0;
+ Adest = Bdest = AAdest = ABdest = 0;
+ if ( bobcoin[0] == 0 || alicecoin[0] == 0 )
+ return(0);
+ //printf("privAm.(%s) %p/%p\n",bits256_str(str,privAm),Adest,AAdest);
+ //printf("privBn.(%s) %p/%p\n",bits256_str(str,privBn),Bdest,ABdest);
+ if ( finishedflag == 0 && bobcoin[0] != 0 && alicecoin[0] != 0 )
+ {
+ if ( iambob == 0 )
+ {
+ if ( (coin= iguana_coinfind(alicecoin)) != 0 )
+ {
+ bitcoin_address(Adestaddr,coin->chain->pubtype,pubkey33,33);
+ AAdest = Adestaddr;
+ }
+ if ( (coin= iguana_coinfind(bobcoin)) != 0 )
+ {
+ bitcoin_address(destaddr,coin->chain->pubtype,pubkey33,33);
+ Adest = destaddr;
+ }
+ }
+ else
+ {
+ if ( (coin= iguana_coinfind(bobcoin)) != 0 )
+ {
+ bitcoin_address(destaddr,coin->chain->pubtype,pubkey33,33);
+ Bdest = destaddr;
+ }
+ if ( (coin= iguana_coinfind(alicecoin)) != 0 )
+ {
+ bitcoin_address(Adestaddr,coin->chain->pubtype,pubkey33,33);
+ ABdest = Adestaddr;
+ }
+ }
+ if ( sentflags[BASILISK_ALICEPAYMENT] == 0 && bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 )
+ {
+ printf("txbytes.%p Apayment.%s\n",txbytes[BASILISK_ALICEPAYMENT],bits256_str(str,txids[BASILISK_ALICEPAYMENT]));
+ if ( txbytes[BASILISK_ALICEPAYMENT] != 0 )
+ sentflags[BASILISK_ALICEPAYMENT] = 1;
+ else if ( (sentobj= basilisk_swapgettx(myinfo,alicecoin,txids[BASILISK_ALICEPAYMENT])) != 0 )
+ {
+ sentflags[BASILISK_ALICEPAYMENT] = 1;
+ free_json(sentobj);
+ }
+ }
+ paymentspent = basilisk_swap_spendupdate(myinfo,bobcoin,sentflags,txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,Adest,Bdest);
+ Apaymentspent = basilisk_swap_spendupdate(myinfo,alicecoin,sentflags,txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,AAdest,ABdest);
+ depositspent = basilisk_swap_spendupdate(myinfo,bobcoin,sentflags,txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,Adest,Bdest);
+ finishedflag = basilisk_swap_isfinished(iambob,txids,sentflags,paymentspent,Apaymentspent,depositspent);
+ if ( iambob == 0 )
+ {
+ if ( sentflags[BASILISK_ALICESPEND] == 0 )
+ {
+ if ( sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(paymentspent) == 0 )
+ {
+ //if ( txbytes[BASILISK_ALICESPEND] == 0 )
+ {
+ if ( bits256_nonz(txids[BASILISK_BOBPAYMENT]) != 0 )
+ {
+ // alicespend
+ for (j=0; j<32; j++)
+ rev.bytes[j] = privAm.bytes[31 - j];
+ revcalc_rmd160_sha256(secretAm,rev);//privAm);
+ vcalc_sha256(0,secretAm256,rev.bytes,sizeof(rev));
+ redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,rev,privBn,secretAm,secretAm256,secretBn,secretBn256);
+ len = basilisk_swapuserdata(userdata,rev,0,myprivs[0],redeemscript,redeemlen);
+ printf("alicespend len.%d redeemlen.%d\n",len,redeemlen);
+ if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend("alicespend",myinfo,bobcoin,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,1,expiration,&values[BASILISK_ALICESPEND])) != 0 )
+ printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]);
+ }
+ }
+ if ( txbytes[BASILISK_ALICESPEND] != 0 )
+ {
+ txids[BASILISK_ALICESPEND] = basilisk_swap_sendrawtransaction(myinfo,"alicespend",bobcoin,txbytes[BASILISK_ALICESPEND]);
+ if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) // tested
+ {
+ sentflags[BASILISK_ALICESPEND] = 1;
+ paymentspent = txids[BASILISK_ALICESPEND];
+ }
+ }
+ }
+ }
+ if ( sentflags[BASILISK_ALICECLAIM] == 0 && sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(depositspent) == 0 )
+ {
+ if ( time(NULL) > expiration )
+ {
+ //if ( txbytes[BASILISK_ALICECLAIM] == 0 )
+ {
+ redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,zero,secretAm,secretAm256,secretBn,secretBn256);
+ if ( redeemlen > 0 )
+ {
+ len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen);
+ if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend("aliceclaim",myinfo,bobcoin,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,0,expiration,&values[BASILISK_ALICECLAIM])) != 0 )
+ printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]);
+ }
+ }
+ if ( txbytes[BASILISK_ALICECLAIM] != 0 )
+ {
+ txids[BASILISK_ALICECLAIM] = basilisk_swap_sendrawtransaction(myinfo,"aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM]);
+ if ( bits256_nonz(txids[BASILISK_ALICECLAIM]) != 0 ) // tested
+ {
+ sentflags[BASILISK_ALICECLAIM] = 1;
+ depositspent = txids[BASILISK_ALICECLAIM];
+ }
+ }
+ } else printf("now %u before expiration %u\n",(uint32_t)time(NULL),expiration);
+ }
+ if ( sentflags[BASILISK_ALICEPAYMENT] != 0 && bits256_nonz(Apaymentspent) == 0 && sentflags[BASILISK_ALICECLAIM] == 0 )
+ {
+ //if ( txbytes[BASILISK_ALICERECLAIM] == 0 )
+ {
+ privBn = basilisk_swap_privBn_extract(myinfo,&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn);
+ if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
+ {
+ if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",myinfo,alicecoin,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_ALICERECLAIM])) != 0 )
+ printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]);
+ }
+ }
+ if ( txbytes[BASILISK_ALICERECLAIM] != 0 )
+ {
+ txids[BASILISK_ALICERECLAIM] = basilisk_swap_sendrawtransaction(myinfo,"alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM]);
+ if ( bits256_nonz(txids[BASILISK_ALICERECLAIM]) != 0 ) // tested
+ {
+ sentflags[BASILISK_ALICERECLAIM] = 1;
+ Apaymentspent = txids[BASILISK_ALICERECLAIM];
+ }
+ }
+ }
+ }
+ else if ( iambob == 1 )
+ {
+ if ( sentflags[BASILISK_BOBSPEND] == 0 && bits256_nonz(Apaymentspent) == 0 )
+ {
+ printf("try to bobspend aspend.%s have privAm.%d\n",bits256_str(str,txids[BASILISK_ALICESPEND]),bits256_nonz(privAm));
+ if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 || bits256_nonz(privAm) != 0 )
+ {
+ //if ( txbytes[BASILISK_BOBSPEND] == 0 )
+ {
+ if ( bits256_nonz(privAm) == 0 )
+ {
+ privAm = basilisk_swap_privbob_extract(myinfo,bobcoin,txids[BASILISK_ALICESPEND],0,1);
+ }
+ if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
+ {
+ if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",myinfo,alicecoin,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33,expiration,&values[BASILISK_BOBSPEND])) != 0 )
+ printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]);
+ }
+ }
+ if ( txbytes[BASILISK_BOBSPEND] != 0 )
+ {
+ txids[BASILISK_BOBSPEND] = basilisk_swap_sendrawtransaction(myinfo,"bobspend",alicecoin,txbytes[BASILISK_BOBSPEND]);
+ if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) // tested
+ {
+ sentflags[BASILISK_BOBSPEND] = 1;
+ Apaymentspent = txids[BASILISK_BOBSPEND];
+ }
+ }
+ }
+ }
+ if ( sentflags[BASILISK_BOBRECLAIM] == 0 && sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(txids[BASILISK_BOBPAYMENT]) != 0 && time(NULL) > expiration && bits256_nonz(paymentspent) == 0 )
+ {
+ //if ( txbytes[BASILISK_BOBRECLAIM] == 0 )
+ {
+ // bobreclaim
+ redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,zero,privBn,secretAm,secretAm256,secretBn,secretBn256);
+ if ( redeemlen > 0 )
+ {
+ len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen);
+ if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend("bobrefund",myinfo,bobcoin,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,0,expiration,&values[BASILISK_BOBRECLAIM])) != 0 )
+ {
+ int32_t z;
+ for (z=0; z<20; z++)
+ printf("%02x",secretAm[z]);
+ printf(" secretAm, myprivs[1].(%s) bobreclaim.(%s)\n",bits256_str(str,myprivs[1]),txbytes[BASILISK_BOBRECLAIM]);
+ }
+ }
+ }
+ if ( txbytes[BASILISK_BOBRECLAIM] != 0 )
+ {
+ txids[BASILISK_BOBRECLAIM] = basilisk_swap_sendrawtransaction(myinfo,"bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM]);
+ if ( bits256_nonz(txids[BASILISK_BOBRECLAIM]) != 0 ) // tested
+ {
+ sentflags[BASILISK_BOBRECLAIM] = 1;
+ paymentspent = txids[BASILISK_BOBRECLAIM];
+ }
+ }
+ }
+ if ( sentflags[BASILISK_BOBREFUND] == 0 && sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(depositspent) == 0 )
+ {
+ if ( bits256_nonz(paymentspent) != 0 || time(NULL) > expiration )
+ {
+ printf("do the refund!\n");
+ //if ( txbytes[BASILISK_BOBREFUND] == 0 )
+ {
+ revcalc_rmd160_sha256(secretBn,privBn);
+ vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn));
+ redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256);
+ len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen);
+ if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend("bobrefund",myinfo,bobcoin,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,1,expiration,&values[BASILISK_BOBREFUND])) != 0 )
+ printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]);
+ }
+ if ( txbytes[BASILISK_BOBREFUND] != 0 )
+ {
+ txids[BASILISK_BOBREFUND] = basilisk_swap_sendrawtransaction(myinfo,"bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND]);
+ if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested
+ {
+ sentflags[BASILISK_BOBREFUND] = 1;
+ depositspent = txids[BASILISK_BOBREFUND];
+ }
+ }
+ } else printf("time %u vs expiration %u\n",(uint32_t)time(NULL),expiration);
+ }
+ }
+ }
+ //printf("finish.%d iambob.%d REFUND %d %d %d %d\n",finishedflag,iambob,sentflags[BASILISK_BOBREFUND] == 0,sentflags[BASILISK_BOBDEPOSIT] != 0,bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0,bits256_nonz(depositspent) == 0);
+ if ( sentflags[BASILISK_ALICESPEND] != 0 || sentflags[BASILISK_BOBRECLAIM] != 0 )
+ sentflags[BASILISK_BOBPAYMENT] = 1;
+ if ( sentflags[BASILISK_ALICERECLAIM] != 0 || sentflags[BASILISK_BOBSPEND] != 0 )
+ sentflags[BASILISK_ALICEPAYMENT] = 1;
+ if ( sentflags[BASILISK_ALICECLAIM] != 0 || sentflags[BASILISK_BOBREFUND] != 0 )
+ sentflags[BASILISK_BOBDEPOSIT] = 1;
+ for (i=0; inumswaps; i++)
+ if ( (swap= myinfo->swaps[i]) != 0 && swap->I.req.requestid == requestid && swap->I.req.quoteid == quoteid )
+ {
+ jaddi(array,basilisk_swapjson(myinfo,swap));
+ flag = 1;
+ break;
+ }
+ if ( flag == 0 )
+ {
+ if ( (item= basilisk_remember(myinfo,KMDtotals,BTCtotals,requestid,quoteid)) != 0 )
+ {
+ jaddi(array,item);
+ if ( 1 && (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 )
+ break;
+ }
+ }
+ }
+ fclose(fp);
+ }
+ jaddstr(retjson,"result","success");
+ jadd(retjson,"swaps",array);
+ if ( cJSON_GetArraySize(array) > 0 )
+ {
+ totalsobj = cJSON_CreateObject();
+ for (Btotal=i=0; i 0 && Btotal < 0 )
+ jaddnum(retjson,"avebuy",(double)-Btotal/Ktotal);
+ else if ( Ktotal < 0 && Btotal > 0 )
+ jaddnum(retjson,"avesell",(double)-Btotal/Ktotal);
+ }
+ array = cJSON_CreateArray();
+ for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++)
+ {
+ if ( myinfo->linfos[i].base[0] != 0 && myinfo->linfos[i].rel[0] != 0 )
+ jaddi(array,linfo_json(&myinfo->linfos[i]));
+ }
+ jadd(retjson,"quotes",array);
+ return(jprint(retjson,1));
+}
+
+
diff --git a/basilisk/basilisk_tradebot.c b/basilisk/basilisk_tradebot.c
index f7d5dca16..2635cde97 100755
--- a/basilisk/basilisk_tradebot.c
+++ b/basilisk/basilisk_tradebot.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * Copyright © 2014-2016 The SuperNET Developers. *
+ * Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@@ -15,13 +15,191 @@
// included from basilisk.c
+cJSON *basilisk_rawtxobj(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx)
+{
+ char hexstr[sizeof(rawtx->I)*2+1+4096]; cJSON *obj = cJSON_CreateObject();
+ jaddstr(obj,"name",rawtx->name);
+ init_hexbytes_noT(hexstr,(void *)&rawtx->I,sizeof(rawtx->I));
+ jaddstr(obj,"info",hexstr);
+ if ( rawtx->I.datalen < sizeof(hexstr)/2 )
+ {
+ init_hexbytes_noT(hexstr,(void *)rawtx->txbytes,rawtx->I.datalen);
+ jaddstr(obj,"txbytes",hexstr);
+ }
+ return(obj);
+}
+
+struct basilisk_rawtx *basilisk_nameconv(struct supernet_info *myinfo,struct basilisk_swap *swap,char *name)
+{
+ if ( strcmp("myfee",name) == 0 )
+ return(&swap->myfee);
+ else if ( strcmp("otherfee",name) == 0 )
+ return(&swap->otherfee);
+ else if ( strcmp("bobdeposit",name) == 0 )
+ return(&swap->bobdeposit);
+ else if ( strcmp("bobrefund",name) == 0 )
+ return(&swap->bobrefund);
+ else if ( strcmp("aliceclaim",name) == 0 )
+ return(&swap->aliceclaim);
+ else if ( strcmp("bobpayment",name) == 0 )
+ return(&swap->bobpayment);
+ else if ( strcmp("alicespend",name) == 0 )
+ return(&swap->alicespend);
+ else if ( strcmp("bobreclaim",name) == 0 )
+ return(&swap->bobreclaim);
+ else if ( strcmp("alicepayment",name) == 0 )
+ return(&swap->alicepayment);
+ else if ( strcmp("bobspend",name) == 0 )
+ return(&swap->bobspend);
+ else if ( strcmp("alicereclaim",name) == 0 )
+ return(&swap->alicereclaim);
+ else return(0);
+}
+
+int32_t basilisk_txitem(struct supernet_info *myinfo,struct basilisk_swap *swap,cJSON *obj)
+{
+ char *hexstr,*name; struct basilisk_rawtx *rawtx = 0;
+ if ( (name= jstr(obj,"name")) == 0 || (rawtx= basilisk_nameconv(myinfo,swap,name)) == 0 )
+ {
+ printf("basilisk_txitem illegal name.(%s)\n",name);
+ return(-1);
+ }
+ if ( rawtx != 0 && (hexstr= jstr(obj,"info")) != 0 && strlen(hexstr) == sizeof(rawtx->I)*2 )
+ {
+ decode_hex((void *)&rawtx->I,sizeof(rawtx->I),hexstr);
+ if ( (hexstr= jstr(obj,"txbytes")) != 0 && strlen(hexstr) == rawtx->I.datalen*2 )
+ {
+ /*if ( rawtx->txbytes == 0 )
+ {
+ printf("free (%s) txbytes\n",name);
+ free(rawtx->txbytes);
+ }
+ rawtx->txbytes = calloc(1,rawtx->I.datalen);*/
+ decode_hex((void *)rawtx->txbytes,rawtx->I.datalen,hexstr);
+ }
+ printf("PROCESS.(%s)\n",jprint(obj,0));
+ return(0);
+ }
+ return(-1);
+}
+
+cJSON *basilisk_swapobj(struct supernet_info *myinfo,struct basilisk_swap *swap)
+{
+ char hexstr[sizeof(swap->I)*2+1]; cJSON *obj = cJSON_CreateObject();
+ init_hexbytes_noT(hexstr,(void *)&swap->I,sizeof(swap->I));
+ jaddstr(obj,"name","swap");
+ jaddnum(obj,"requestid",swap->I.req.requestid);
+ jaddnum(obj,"quoteid",swap->I.req.quoteid);
+ jadd(obj,"req",basilisk_requestjson(&swap->I.req));
+ jaddstr(obj,"info",hexstr);
+ //printf("strlen(hexstr) swap->I %d vs %d\n",(int32_t)strlen(hexstr),(int32_t)sizeof(swap->I)*2);
+ return(obj);
+}
+
+int32_t basilisk_swapconv(struct supernet_info *myinfo,struct basilisk_swap *swap,cJSON *obj)
+{
+ char *hexstr;
+ if ( (hexstr= jstr(obj,"info")) != 0 && strlen(hexstr) == sizeof(swap->I)*2 )
+ {
+ decode_hex((void *)&swap->I,sizeof(swap->I),hexstr);
+ if ( juint(obj,"requestid") == swap->I.req.requestid && juint(obj,"quoteid") == swap->I.req.quoteid )
+ return(0);
+ printf("swapconv mismatched req/quote %d %d, %d %d\n",juint(obj,"requestid"),swap->I.req.requestid,juint(obj,"quoteid"),swap->I.req.quoteid);
+ } //else printf("no info field in swap obj.(%s) len.%d vs %d\n",jprint(obj,0),(int32_t)strlen(hexstr),(int32_t)sizeof(swap->I)*2);
+ return(-1);
+}
+
+struct basilisk_swap *basilisk_swapstore(struct supernet_info *myinfo,struct basilisk_swap *swap)
+{
+ // save based on requestid/quoteid
+ return(swap);
+}
+
+struct basilisk_swap *basilisk_swapload(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t requestid,uint32_t quoteid)
+{
+ // set swap fields and return it if found
+ return(0);
+}
+
+void basilisk_swapstart(struct supernet_info *myinfo) // scan saved tmpswap, purge if complete, else Q
+{
+ // for resuming pending swaps
+}
+
+void basilisk_txlog(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,int32_t delay)
+{
+ char fname[1024],*jsonstr; long filesize; cJSON *item,*dexobj = 0; int32_t i,n,pending; struct basilisk_swap tmpswap,*swapptr;
+ sprintf(fname,"%s/DEX.log",GLOBAL_DBDIR), OS_compatible_path(fname);
+ if ( myinfo->dexfp == 0 )
+ {
+ if ( (jsonstr= OS_filestr(&filesize,fname)) != 0 )
+ {
+ jsonstr[strlen(jsonstr)-1] = ']';
+ if ( jsonstr[strlen(jsonstr)-2] == ',' )
+ jsonstr[strlen(jsonstr)-2] = ' ';
+ if ( jsonstr[strlen(jsonstr)-3] == ',' )
+ jsonstr[strlen(jsonstr)-3] = ' ';
+ if ( (dexobj= cJSON_Parse(jsonstr)) != 0 )
+ {
+ if ( is_cJSON_Array(dexobj) != 0 && (n= cJSON_GetArraySize(dexobj)) > 0 )
+ {
+ pending = 0;
+ memset(&tmpswap,0,sizeof(tmpswap));
+ swapptr = 0;
+ for (i=0; iI.req.requestid == juint(item,"requestid") && swapptr->I.req.quoteid == juint(item,"quoteid") )
+ basilisk_txitem(myinfo,swapptr,item);
+ }
+ else if ( (swapptr= basilisk_swapload(myinfo,&tmpswap,juint(item,"requestid"),juint(item,"quoteid"))) != 0 )
+ basilisk_txitem(myinfo,swapptr,item);
+ }
+ basilisk_swapstart(myinfo);
+ }
+ free_json(dexobj);
+ dexobj = 0;
+ } else printf("basilisk_txlog error parsing.(%s)\n",jsonstr);
+ free(jsonstr);
+ }
+ if ( (myinfo->dexfp= fopen(fname,"rb+")) != 0 )
+ fseek(myinfo->dexfp,0,SEEK_END);
+ else if ( (myinfo->dexfp= fopen(fname,"wb")) != 0 )
+ fprintf(myinfo->dexfp,"[\n");
+ }
+ if ( rawtx != 0 )
+ {
+ // delay -1 -> dont issue, else submit after block timestamp is delay after swap->started
+ dexobj = basilisk_rawtxobj(myinfo,swap,rawtx);
+ }
+ else if ( swap != 0 )
+ dexobj = basilisk_swapobj(myinfo,swap);
+ if ( dexobj != 0 && (jsonstr= jprint(dexobj,1)) != 0 )
+ {
+ //printf("%s\n",jsonstr);
+ if ( myinfo->dexfp != 0 )
+ {
+ fprintf(myinfo->dexfp,"%s,\n",jsonstr);
+ fflush(myinfo->dexfp);
+ }
+ free(jsonstr);
+ }
+}
+
uint32_t basilisk_requestid(struct basilisk_request *rp)
{
struct basilisk_request R;
R = *rp;
R.requestid = R.quoteid = R.quotetime = 0;
- R.destamount = 0;
- R.relaybits = 0;
+ R.destamount = R.profitmargin = 0;
+ //R.relaybits = 0;
memset(R.desthash.bytes,0,sizeof(R.desthash.bytes));
if ( 0 )
{
@@ -29,7 +207,7 @@ uint32_t basilisk_requestid(struct basilisk_request *rp)
for (i=0; i %s %.8f %s crc.%u\n",R.timestamp,R.requestid,R.quoteid,R.src,dstr(R.srcamount),bits256_str(str,R.hash),R.dest,dstr(R.destamount),bits256_str(str2,R.desthash),calc_crc32(0,(void *)&R,sizeof(R)));
+ char str[65],str2[65]; printf("B REQUESTID: t.%u r.%u q.%u %s %.8f %s -> %s %.8f %s crc.%u\n",R.timestamp,R.requestid,R.quoteid,R.src,dstr(R.srcamount),bits256_str(str,R.srchash),R.dest,dstr(R.destamount),bits256_str(str2,R.desthash),calc_crc32(0,(void *)&R,sizeof(R)));
}
return(calc_crc32(0,(void *)&R,sizeof(R)));
}
@@ -38,7 +216,7 @@ uint32_t basilisk_quoteid(struct basilisk_request *rp)
{
struct basilisk_request R;
R = *rp;
- R.requestid = R.quoteid = R.relaybits = 0;
+ R.requestid = R.quoteid = R.profitmargin = 0; //R.relaybits =
return(calc_crc32(0,(void *)&R,sizeof(R)));
}
@@ -46,15 +224,17 @@ struct basilisk_request *basilisk_parsejson(struct basilisk_request *rp,cJSON *r
{
uint32_t requestid,quoteid;
memset(rp,0,sizeof(*rp));
- rp->hash = jbits256(reqjson,"hash");
+ rp->srchash = jbits256(reqjson,"srchash");
rp->desthash = jbits256(reqjson,"desthash");
rp->srcamount = j64bits(reqjson,"srcamount");
rp->minamount = j64bits(reqjson,"minamount");
- rp->destamount = j64bits(reqjson,"destamount");
+ //rp->destamount = j64bits(reqjson,"destamount");
+ rp->destamount = j64bits(reqjson,"destsatoshis");
+ //printf("parse DESTSATOSHIS.%llu (%s)\n",(long long)rp->destamount,jprint(reqjson,0));
requestid = juint(reqjson,"requestid");
quoteid = juint(reqjson,"quoteid");
- if ( jstr(reqjson,"relay") != 0 )
- rp->relaybits = (uint32_t)calc_ipbits(jstr(reqjson,"relay"));
+ //if ( jstr(reqjson,"relay") != 0 )
+ // rp->relaybits = (uint32_t)calc_ipbits(jstr(reqjson,"relay"));
rp->timestamp = juint(reqjson,"timestamp");
rp->quotetime = juint(reqjson,"quotetime");
safecopy(rp->src,jstr(reqjson,"src"),sizeof(rp->src));
@@ -67,30 +247,20 @@ struct basilisk_request *basilisk_parsejson(struct basilisk_request *rp,cJSON *r
}
rp->requestid = basilisk_requestid(rp);
if ( requestid != rp->requestid )
- printf("basilisk_parsejson requestid.%u != %u error\n",requestid,rp->requestid);
- return(rp);
-}
-
-void basilisk_swap_balancingtrade(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t iambob)
-{
- // update balance, compare to target balance, issue balancing trade via central exchanges, if needed
- if ( iambob != 0 )
- {
-
- }
- else
{
-
+ int32_t i; for (i=0; irequestid);
}
+ return(rp);
}
-
struct basilisk_swap *basilisk_request_started(struct supernet_info *myinfo,uint32_t requestid)
{
int32_t i; struct basilisk_swap *active = 0;
portable_mutex_lock(&myinfo->DEX_swapmutex);
for (i=0; inumswaps; i++)
- if ( myinfo->swaps[i]->req.requestid == requestid )
+ if ( myinfo->swaps[i]->I.req.requestid == requestid )
{
//printf("REQUEST STARTED.[%d] <- req.%u\n",i,requestid);
active = myinfo->swaps[i];
@@ -102,67 +272,26 @@ struct basilisk_swap *basilisk_request_started(struct supernet_info *myinfo,uint
int32_t basilisk_request_cmpref(struct basilisk_request *ref,struct basilisk_request *rp)
{
- if ( bits256_cmp(rp->hash,ref->hash) != 0 || memcmp(rp->src,ref->src,sizeof(ref->src)) != 0 || memcmp(rp->dest,ref->dest,sizeof(ref->dest)) != 0 || rp->srcamount != ref->srcamount || rp->timestamp != ref->timestamp )
+ if ( bits256_cmp(rp->srchash,ref->srchash) != 0 || memcmp(rp->src,ref->src,sizeof(ref->src)) != 0 || memcmp(rp->dest,ref->dest,sizeof(ref->dest)) != 0 || rp->srcamount != ref->srcamount || rp->timestamp != ref->timestamp )
{
printf("basilisk_request_listprocess mismatched hash\n");
return(-1);
} else return(0);
}
-void tradebot_liquidity_command(struct supernet_info *myinfo,char *base,bits256 hash,cJSON *vals)
-{
- struct liquidity_info li,refli; int32_t i;
- memset(&li,0,sizeof(li));
- strcpy(li.base,base), strcpy(li.rel,"BTC");
- li.profit = jdouble(vals,"profit");
- li.refprice = jdouble(vals,"refprice");
- for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++)
- {
- refli = myinfo->linfos[i];
- if ( strcmp(li.rel,refli.base) == 0 && strcmp(li.base,refli.rel) == 0 )
- {
- strcpy(li.base,refli.base);
- strcpy(li.rel,refli.rel);
- li.refprice = (1. / li.refprice);
- printf("Set rev linfo[%d] (%s/%s) %.6f %.8f\n",i,li.base,li.rel,li.profit,li.refprice);
- myinfo->linfos[i] = li;
- return;
- }
- else if ( refli.base[0] == 0 || (strcmp(li.base,refli.base) == 0 && strcmp(li.rel,refli.rel) == 0) )
- {
- myinfo->linfos[i] = li;
- printf("Set linfo[%d] (%s/%s) %.6f %.8f\n",i,li.base,li.rel,li.profit,li.refprice);
- return;
- }
- }
- printf("ERROR: too many linfos %d\n",i);
-}
-
-double tradebot_liquidity_active(struct supernet_info *myinfo,double *refpricep,char *base,char *rel)
-{
- int32_t i; struct liquidity_info refli;
- *refpricep = 0.;
- for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++)
- {
- refli = myinfo->linfos[i];
- if ( (strcmp(base,refli.base) == 0 && strcmp(rel,refli.rel) == 0) || (strcmp(rel,refli.base) == 0 && strcmp(base,refli.rel) == 0 ))
- {
- *refpricep = refli.refprice;
- return(refli.profit);
- }
- }
- return(0.);
-}
-
double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk_request *issueR,struct basilisk_request *list,int32_t n)
{
- int32_t i,noquoteflag=0,havequoteflag=0,myrequest=0,maxi=-1; uint64_t destamount,minamount = 0,maxamount = 0; uint32_t pendingid=0; struct basilisk_swap *active; double metric = 0.;
+ int32_t i,noquoteflag=0,havequoteflag=0,myrequest=0,maxi=-1; int64_t balance=0,destamount,minamount = 0,maxamount = 0; bits256 privkey; uint32_t pendingid=0; struct basilisk_swap *active; double metric = 0.,bidasks[2]; char typestr[64];
memset(issueR,0,sizeof(*issueR));
minamount = list[0].minamount;
- printf("need to verify null quoteid is list[0] requestid.%u quoteid.%u\n",list[0].requestid,list[0].quoteid);
+ //printf("need to verify null quoteid is list[0] requestid.%u quoteid.%u\n",list[0].requestid,list[0].quoteid);
if ( (active= basilisk_request_started(myinfo,list[0].requestid)) != 0 )
- pendingid = active->req.quoteid;
- if ( bits256_cmp(myinfo->myaddr.persistent,list[0].hash) == 0 ) // my request
+ {
+ if ( active->I.req.quoteid != 0 )
+ return(0.);
+ pendingid = active->I.req.quoteid;
+ }
+ if ( smartaddress_pubkey(myinfo,typestr,bidasks,&privkey,list[0].src,list[0].srchash) >= 0 )
myrequest = 1;
for (i=0; imyaddr.persistent,list[i].desthash) == 0 ) // my quoteid
+ if ( smartaddress_pubkey(myinfo,typestr,bidasks,&privkey,list[i].dest,list[i].desthash) >= 0 )
myrequest |= 2;
havequoteflag++;
if ( pendingid == 0 )
@@ -178,6 +307,7 @@ double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk
if ( list[i].destamount > maxamount )
{
maxamount = list[i].destamount;
+ //printf("set maxamount %llu\n",(long long)maxamount);
maxi = i;
}
}
@@ -186,38 +316,65 @@ double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk
}
} else noquoteflag++;
}
- printf("myrequest.%d pendingid.%u noquoteflag.%d havequoteflag.%d maxi.%d %.8f\n",myrequest,pendingid,noquoteflag,havequoteflag,maxi,dstr(maxamount));
- double retvals[4],refprice,profitmargin,aveprice,balance=0.; cJSON *retjson; char *retstr;
- if ( myinfo->IAMLP != 0 && myrequest == 0 && pendingid == 0 && noquoteflag != 0 && (profitmargin= tradebot_liquidity_active(myinfo,&refprice,list[0].src,list[0].dest)) > 0. )
+ struct iguana_info *coin; char coinaddr[64]; double retvals[4],refprice=0.,profitmargin,aveprice,destvolume;
+ destvolume = dstr(maxamount);
+ //printf("destvolume <- %.8f\n",dstr(destvolume));
+ if ( fabs(destvolume) < SMALLVAL )
+ {
+ if ( (destvolume= dstr(minamount)) == 0 )
+ {
+ aveprice = instantdex_avehbla(myinfo,retvals,list[0].src,list[0].dest,1.3 * dstr(list[0].srcamount));
+ destvolume = aveprice * dstr(list[0].srcamount);
+ printf("set destvolume %.8f\n",destvolume);
+ } // else printf("destvolume %.8f <- minamount\n",destvolume);
+ }
+ printf("<<<<<<< %s -> %s myrequest.%d pendingid.%u noquoteflag.%d havequoteflag.%d maxi.%d %.8f destvol %.8f\n",list[0].src,list[0].dest,myrequest,pendingid,noquoteflag,havequoteflag,maxi,dstr(maxamount),destvolume);
+ if ( myinfo->IAMLP != 0 && myrequest == 0 && pendingid == 0 && noquoteflag != 0 && ((profitmargin= tradebot_liquidity_active(myinfo,&refprice,"DEX",list[0].src,list[0].dest,destvolume)) > 0. || refprice != 0.) )
{
- if ( (aveprice= instantdex_avehbla(myinfo,retvals,list[0].src,list[0].dest,1.3 * dstr(list[0].srcamount))) == 0. || refprice > aveprice )
+ if ( profitmargin == 0. || (aveprice= instantdex_avehbla(myinfo,retvals,list[0].src,list[0].dest,.1 * dstr(list[0].srcamount))) == 0. || refprice > aveprice )
aveprice = refprice;
+ if ( fabs(aveprice) < SMALLVAL )
+ return(0);
+ if ( strcmp("BTC",list[0].src) == 0 )
+ aveprice = (1. / aveprice);
+ //retvals[0] = avebid, retvals[1] = bidvol, retvals[2] = aveask, retvals[3] = askvol;
destamount = (1.0 - profitmargin) * aveprice * list[0].srcamount;
- if ( (retstr= InstantDEX_available(myinfo,iguana_coinfind(list[0].dest),0,0,list[0].dest)) != 0 )
+ if ( destamount > minamount )
+ destamount = minamount + ((destamount - minamount) * (1 + (rand() % 100))) / 100.;
+ printf("%s/%s pm %f aveprice %f src %.8f dest %.8f avebid %f bidvol %f, aveask %f askvol %f\n",list[0].src,list[0].dest,profitmargin,aveprice,dstr(list[0].srcamount),dstr(destamount),retvals[0],retvals[1],retvals[2],retvals[3]);
+ if ( (coin= iguana_coinfind(list[0].dest)) != 0 )
+ {
+ bitcoin_address(coinaddr,coin->chain->pubtype,myinfo->persistent_pubkey33,33);
+ balance = jumblr_balance(myinfo,coin,coinaddr);
+ printf("%s %s balance %.8f destamount %.8f aveprice %.8f maxamount %.8f minamount %.8f\n",list[0].dest,coinaddr,dstr(balance),dstr(destamount),aveprice,dstr(maxamount),dstr(minamount));
+ }
+ /*if ( (retstr= InstantDEX_available(myinfo,iguana_coinfind(list[0].dest),0,0,list[0].dest)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
- balance = jdouble(retjson,"result");
+ balance = jdouble(retjson,"result") * SATOSHIDEN;
free_json(retjson);
}
free(retstr);
- }
- printf("balance %.8f destamount %.8f aveprice %.8f minamount %.8f\n",balance,dstr(destamount),aveprice,dstr(minamount));
- if ( balance > destamount && destamount > 0 && destamount >= maxamount && destamount >= minamount )
+ }*/
+ if ( balance > destamount && (int64_t)destamount > 0 && destamount >= minamount ) // max?
{
metric = 1.;
*issueR = list[0];
issueR->desthash = myinfo->myaddr.persistent;
issueR->destamount = destamount;
issueR->quotetime = (uint32_t)time(NULL);
+ issueR->profitmargin = (uint32_t)(profitmargin * 1000000);
}
}
else if ( myrequest != 0 && pendingid == 0 && maxi >= 0 ) // automatch best quote
{
- if ( minamount != 0 && maxamount > minamount && time(NULL) > BASILISK_DEXDURATION/2 )
+ if ( minamount != 0 && maxamount >= minamount )//&& time(NULL) > list[0].timestamp+BASILISK_AUCTION_DURATION )
{
- printf("automatch quoteid.%u triggered %.8f > %.8f\n",list[maxi].quoteid,dstr(maxamount),dstr(minamount));
*issueR = list[maxi];
+ for (i=0; i= %.8f\n",maxi,list[maxi].requestid,list[maxi].quoteid,dstr(maxamount),dstr(minamount));
if ( minamount > 0 )
metric = (dstr(maxamount) / dstr(minamount)) - 1.;
else metric = 1.;
@@ -228,31 +385,61 @@ double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk
double basilisk_process_results(struct supernet_info *myinfo,struct basilisk_request *issueR,cJSON *retjson,double hwm)
{
- cJSON *array,*item; int32_t i,n,m; struct basilisk_request tmpR,R,refR,list[BASILISK_MAXRELAYS]; double metric=0.;
- //printf("process_results.(%s)\n",jprint(retjson,0));
- if ( (array= jarray(&n,retjson,"result")) != 0 )
+ cJSON *array,*item; uint8_t *hexdata,*allocptr,hexspace[32768]; char *hexstr; int32_t i,hexlen,n,m,nonz; struct basilisk_request tmpR,R,refR,list[BASILISK_MAXRELAYS]; double metric=0.;
+ memset(&refR,0,sizeof(refR));
+ memset(&R,0,sizeof(R));
+//printf("process.(%s)\n",jprint(retjson,0));
+ if ( (array= jarray(&n,retjson,"messages")) != 0 )
{
- for (i=m=0; i hwm )
- *issueR = tmpR, hwm = metric;
- m = 0;
+ if ( refR.requestid == R.requestid )
+ list[m++] = R;
+ else
+ {
+ if ( (metric= basilisk_request_listprocess(myinfo,&tmpR,list,m)) > hwm )
+ {
+ *issueR = tmpR;
+ hwm = metric;
+ refR = tmpR;
+ printf("SET HWM\n");
+ }
+ m = 0;
+ }
+ }
+ nonz++;
+ if ( m < sizeof(list)/sizeof(*list) )
+ {
+ //basilisk_parsejson(&list[m++],item);
+ list[m++] = R;
}
}
- if ( m < sizeof(list)/sizeof(*list) )
- basilisk_parsejson(&list[m++],item);
}
+ //printf("process_results n.%d m.%d nonz.%d\n",n,m,nonz);
if ( m > 0 && m < sizeof(list)/sizeof(*list) )
if ( (metric= basilisk_request_listprocess(myinfo,&tmpR,list,m)) > hwm )
+ {
*issueR = tmpR, hwm = metric;
+ //printf("set hwm\n");
+ //for (i=0; ichain->pubtype,pubkey,33);
+ // get stake of address
+ return(stake);
+}
+
+int32_t basilisk_voter_process(struct supernet_info *myinfo,uint8_t *rmd160,struct iguana_info *coin,struct election_info *ep,struct vote_info *vp)
+{
+ int32_t i;
+ if ( vp->stake == 0 )
+ vp->stake = 1;
+ if ( bits256_nonz(vp->vote) != 0 )
+ {
+ for (i=1; i<8; i++)
+ if ( vp->vote.uints[i] != 0 )
+ break;
+ if ( i == 8 )
+ return(vp->vote.uints[0]);
+ else
+ {
+ for (i=0; i<20; i++)
+ rmd160[i] = vp->vote.bytes[i + 4];
+ return(ep->numcandidates);
+ }
+ }
+ return(-1);
+}
+
+int32_t basilisk_election_process(struct supernet_info *myinfo,int64_t *tally,struct iguana_info *coin,struct election_info *ep)
+{
+ int32_t i,j,pending = 0; struct vote_info *vp; uint8_t rmd160[20];
+ for (i=0; inumvotes; i++)
+ ep->votes[i].repstake = 0;
+ for (i=0; inumvotes; i++)
+ {
+ vp = &ep->votes[i];
+ if ( basilisk_voter_process(myinfo,rmd160,coin,ep,vp) == ep->numcandidates && vp->repid < 0 )
+ {
+ for (j=0; jnumvotes; j++)
+ {
+ if ( i != j && memcmp(rmd160,ep->votes[j].rmd160,20) == 0 )
+ {
+ vp->repid = j;
+ ep->votes[j].repstake += vp->stake;
+ break;
+ }
+ }
+ }
+ }
+ if ( tally != 0 )
+ {
+ memset(tally,0,ep->numcandidates*sizeof(*tally));
+ for (i=0; inumvotes; i++)
+ {
+ vp = &ep->votes[i];
+ if ( vp->repid < 0 && vp->vote.uints[0] > 0 && vp->vote.uints[0] <= ep->numcandidates )
+ tally[vp->vote.uints[0]] += (vp->stake + vp->repstake);
+ else if ( vp->repid < 0 )
+ pending++;
+ }
+ }
+ return(pending);
+}
+
+cJSON *basilisk_voterjson(struct supernet_info *myinfo,struct iguana_info *coin,struct election_info *ep,struct vote_info *vp)
+{
+ char coinaddr[64],sigstr[74*2+1]; int32_t i; uint8_t rmd160[20]; cJSON *item;
+ item = cJSON_CreateObject();
+ basilisk_voter_process(myinfo,rmd160,coin,ep,vp);
+ bitcoin_address(coinaddr,5,vp->pubkey,sizeof(vp->pubkey));
+ jaddstr(item,"coinaddr",coinaddr);
+ jaddnum(item,"stake",dstr(vp->stake));
+ if ( vp->repstake != 0 )
+ jaddnum(item,"repstake",dstr(vp->repstake));
+ if ( bits256_nonz(vp->vote) != 0 )
+ {
+ for (i=1; i<8; i++)
+ if ( vp->vote.uints[i] != 0 )
+ break;
+ if ( i == 8 )
+ {
+ if ( vp->vote.uints[0] <= ep->numcandidates )
+ jaddnum(item,"vote",vp->vote.uints[0]);
+ else jaddstr(item,"error","illegal vote");
+ }
+ else
+ {
+ for (i=0; i<20; i++)
+ rmd160[i] = vp->vote.bytes[i + 4];
+ bitcoin_address(coinaddr,5,rmd160,20);
+ jaddstr(item,"delegated",coinaddr);
+ }
+ }
+ else if ( bits256_nonz(vp->commit) != 0 )
+ jaddbits256(item,"commit",vp->commit);
+ init_hexbytes_noT(sigstr,vp->sig,vp->siglen);
+ jaddstr(item,"sig",sigstr);
+ return(item);
+}
+
+cJSON *basilisk_electionjson(struct supernet_info *myinfo,struct iguana_info *coin,struct election_info *ep)
+{
+ int32_t i; cJSON *array,*obj = cJSON_CreateObject();
+ jaddstr(obj,"name",ep->name);
+ jaddbits256(obj,"hash",ep->hash);
+ jaddnum(obj,"expiration",ep->expiration);
+ jaddnum(obj,"numcandidates",ep->numcandidates);
+ jaddnum(obj,"numvotes",ep->numvotes);
+ jadd(obj,"ballot",jduplicate(ep->ballot));
+ array = cJSON_CreateArray();
+ for (i=0; inumvotes; i++)
+ jaddi(array,basilisk_voterjson(myinfo,coin,ep,&ep->votes[i]));
+ jadd(obj,"votes",array);
+ return(obj);
+}
+
+int32_t basilisk_electionsave(struct election_info *ep)
+{
+ char fname[512],str[65],*ballotstr; int32_t n; FILE *fp;
+ OS_ensure_directory("elections");
+ sprintf(fname,"elections/%s",bits256_str(str,ep->hash));
+ OS_compatible_path(fname);
+ if ( (fp= fopen(fname,"wb")) != 0 )
+ {
+ if ( fwrite(ep,1,sizeof(*ep),fp) != sizeof(*ep) )
+ printf("error saving election.(%s) to %s\n",ep->name,fname);
+ else
+ {
+ if ( fwrite(&ep->numvotes,1,sizeof(ep->numvotes),fp) != sizeof(ep->numvotes) )
+ printf("error saving numvotes.%d to %s\n",ep->numvotes,fname);
+ else if ( ep->numvotes > 0 )
+ {
+ if ( fwrite(ep->votes,sizeof(*ep->votes),ep->numvotes,fp) != ep->numvotes )
+ printf("error saving votes.%d for %s to %s\n",ep->numvotes,ep->name,fname);
+ else
+ {
+ if ( (ballotstr= jprint(ep->ballot,0)) != 0 )
+ {
+ n = (int32_t)strlen(ballotstr) + 1;
+ if ( fwrite(&n,1,sizeof(n),fp) != sizeof(n) )
+ printf("error saving n.%d for (%s) to %s\n",n,ballotstr,fname);
+ else if ( fwrite(ballotstr,1,n,fp) != n )
+ printf("error saving election.(%s) to %s\n",ballotstr,fname);
+ free(ballotstr);
+ }
+ }
+ }
+ }
+ fclose(fp);
+ return(0);
+ }
+ return(-1);
+}
+
+struct vote_info *basilisk_vote_find(struct election_info *ep,struct vote_info *vote)
+{
+ int32_t i;
+ for (i=0; inumvotes; i++)
+ {
+ if ( memcmp(ep->votes[i].pubkey,vote->pubkey,33) == 0 )
+ return(&ep->votes[i]);
+ }
+ return(0);
+}
+
+struct election_info *basilisk_election_find(int32_t createflag,bits256 hash)
+{
+ int32_t i; uint32_t now = (uint32_t)time(NULL);
+ for (i=0; i Elections[i].expiration )
+ {
+ basilisk_electionsave(&Elections[i]);
+ memset(&Elections[i],0,sizeof(Elections[i]));
+ }
+ if ( bits256_nonz(hash) != 0 )
+ {
+ if ( bits256_nonz(Elections[i].hash) == 0 )
+ return(&Elections[i]);
+ else if ( bits256_cmp(Elections[i].hash,hash) == 0 )
+ return(0);
+ }
+ }
+ return(0);
+}
+
+int32_t basilisk_vote_extract(struct supernet_info *myinfo,char *coinaddr,struct vote_info *vote,cJSON *item)
+{
+ char str[65],str2[65],str3[65]; uint8_t *sig,*pubkey; int32_t action,siglen,plen; bits256 data,hash;
+ memset(vote,0,sizeof(*vote));
+ if ( get_dataptr(0,&sig,&siglen,vote->sig,sizeof(vote->sig),jstr(item,"sig")) != 0 )
+ {
+ vote->siglen = siglen;
+ action = juint(item,"action");
+ if ( get_dataptr(0,&pubkey,&plen,vote->pubkey,sizeof(vote->pubkey),jstr(item,"pubkey")) != 0 )
+ {
+ bitcoin_address(coinaddr,5,pubkey,33);
+ data = jbits256(item,"data");
+ if ( bitcoin_verify(myinfo->ctx,vote->sig,vote->siglen,data,vote->pubkey,33) == 0 )
+ {
+ if ( (action & 0xff) == 'c' )
+ {
+ vote->commit = data;
+ printf("%s commits to %s\n",coinaddr,bits256_str(str,data));
+ return(action);
+ }
+ else if ( (action & 0xff) == 'r' )
+ {
+ if ( bits256_nonz(vote->commit) != 0 )
+ {
+ vcalc_sha256(0,hash.bytes,data.bytes,sizeof(data));
+ if ( bits256_cmp(hash,vote->commit) == 0 )
+ {
+ printf("%s vote %s -> %s matches commit %s\n",coinaddr,bits256_str(str,data),bits256_str(str2,hash),bits256_str(str3,vote->commit));
+ vote->vote = data;
+ // error check vote
+ return(action);
+ }
+ else
+ {
+ printf("%s vote %s -> %s doesnt match commit %s\n",coinaddr,bits256_str(str,data),bits256_str(str2,hash),bits256_str(str3,vote->commit));
+ return(-2);
+ }
+ }
+ }
+ } else return(-1);
+ }
+ }
+ return(-1);
+}
+
+char *basilisk_respond_VOT(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk)
+{
+ int32_t i,duration,winner,pending,action,numcandidates; char coinaddr[64],*symbol,*votemethod,*ballotstr; cJSON *item,*array,*electionobj,*ballot,*retjson; struct election_info *ep; struct vote_info vote,*vp; struct iguana_info *coin; int64_t *tally,max;
+ retjson = cJSON_CreateObject();
+ if ( (symbol= jstr(valsobj,"coin")) == 0 )
+ symbol = "BTCD";
+ coin = iguana_coinfind(symbol);
+ if ( (votemethod= jstr(valsobj,"votemethod")) != 0 )
+ {
+ if ( strcmp(votemethod,"create") == 0 )
+ {
+ if ( (ballot= jarray(&numcandidates,valsobj,"ballot")) != 0 && numcandidates > 0 )
+ {
+ if ( (duration= juint(valsobj,"duration")) == 0 )
+ duration = 3600;
+ ballotstr = jprint(ballot,0);
+ vcalc_sha256(0,hash.bytes,(uint8_t *)ballotstr,(int32_t)strlen(ballotstr));
+ free(ballotstr);
+ if ( (ep= basilisk_election_find(1,hash)) != 0 )
+ {
+ ep->hash = hash;
+ ep->duration = duration;
+ ep->expiration = (uint32_t)time(NULL) + duration;
+ ep->ballot = jduplicate(ballot);
+ ep->numcandidates = numcandidates;
+ safecopy(ep->name,jstr(valsobj,"name"),sizeof(ep->name));
+ if ( (electionobj= basilisk_electionjson(myinfo,coin,ep)) != 0 )
+ {
+ jaddstr(retjson,"result","success");
+ jadd(retjson,"election",electionobj);
+ } else jaddstr(retjson,"error","couldnt create election object");
+ } else jaddstr(retjson,"error","couldnt allocate election slot");
+ }
+ }
+ else if ( strcmp(votemethod,"list") == 0 )
+ {
+ array = cJSON_CreateArray();
+ for (i=0; inumcandidates+1,sizeof(*tally));
+ pending = basilisk_election_process(myinfo,tally,coin,ep);
+ if ( pending != 0 )
+ jaddnum(retjson,"pending",pending);
+ jadd(retjson,"election",basilisk_electionjson(myinfo,coin,ep));
+ array = cJSON_CreateArray();
+ max = 0;
+ winner = -1;
+ for (i=1; i<=ep->numcandidates; i++)
+ {
+ if ( tally[i] > max )
+ {
+ max = tally[i];
+ winner = i;
+ }
+ jaddinum(array,dstr(tally[i]));
+ }
+ jadd(retjson,"tally",array);
+ if ( winner > 0 )
+ {
+ item = jitem(ep->ballot,winner-1);
+ jadd(retjson,"winner",item);
+ }
+ free(tally);
+ }
+ else if ( strcmp(votemethod,"ratify") == 0 )
+ {
+ // record ratification of tally
+ }
+ else if ( (action= basilisk_vote_extract(myinfo,coinaddr,&vote,valsobj)) > 0 )
+ {
+ vp = basilisk_vote_find(ep,&vote);
+ if ( strcmp(votemethod,"vote") == 0 )
+ {
+ if ( vp == 0 )
+ {
+ ep->votes = realloc(ep->votes,sizeof(*ep->votes) + (ep->numvotes + 1));
+ vote.repid = -1;
+ vote.stake = basilisk_voter_stake(myinfo,vote.rmd160,coin,vote.pubkey);
+ ep->votes[ep->numvotes++] = vote;
+ jaddstr(retjson,"result","success");
+ }
+ else if ( action == 'c' )
+ {
+ *vp = vote;
+ jaddstr(retjson,"result","success");
+ }
+ else if ( action == 'r' )
+ {
+ *vp = vote;
+ jaddstr(retjson,"result","success");
+ } else jaddstr(retjson,"error","illegal vote action");
+ }
+ else if ( strcmp(votemethod,"verify") == 0 )
+ {
+ if ( vp == 0 )
+ jaddstr(retjson,"error","cant find voter");
+ else if ( action == 'c' )
+ {
+ if ( bits256_cmp(vote.commit,vp->commit) == 0 )
+ jaddstr(retjson,"result","success");
+ else jaddstr(retjson,"error","mismatched commit");
+ jaddbits256(retjson,"oldcommit",vp->commit);
+ jaddbits256(retjson,"newcommit",vote.commit);
+ }
+ else if ( action == 'r' )
+ {
+ if ( bits256_cmp(vote.vote,vp->vote) == 0 )
+ jaddstr(retjson,"result","success");
+ else jaddstr(retjson,"error","mismatched vote");
+ jaddbits256(retjson,"oldvote",vp->vote);
+ jaddbits256(retjson,"newvote",vote.vote);
+ } else jaddstr(retjson,"error","illegal vote action");
+ } else jaddstr(retjson,"error","illegal vote method");
+ } else jaddstr(retjson,"error","couldnt extract vote info");
+ }
+ }
+ return(jprint(retjson,1));
+}
+
+
diff --git a/basilisk/jumblr.c b/basilisk/jumblr.c
new file mode 100755
index 000000000..9618a9421
--- /dev/null
+++ b/basilisk/jumblr.c
@@ -0,0 +1,772 @@
+/******************************************************************************
+ * Copyright © 2014-2017 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. *
+ * *
+ ******************************************************************************/
+
+// included from basilisk.c
+// connect DEX to jumblr-core
+
+/*
+ z_exportkey "zaddr"
+ z_exportwallet "filename"
+ z_getoperationstatus (["operationid", ... ])
+ z_gettotalbalance ( minconf )
+ z_importkey "zkey" ( rescan )
+ z_importwallet "filename"
+ z_listaddresses
+ z_sendmany "fromaddress" [{"address":... ,"amount":..., "memo":""},...] ( minconf ) ( fee )
+ */
+
+#define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t"
+#define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6"
+
+int32_t jumblr_addresstype(struct supernet_info *myinfo,struct iguana_info *coin,char *addr)
+{
+ if ( strcmp(coin->symbol,"KMD") == 0 )
+ {
+ if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 )
+ return('z');
+ else if ( strlen(addr) < 40 )
+ return('t');
+ else return(-1);
+ } else return('t');
+}
+
+struct jumblr_item *jumblr_opidfind(struct supernet_info *myinfo,char *opid)
+{
+ struct jumblr_item *ptr;
+ HASH_FIND(hh,myinfo->jumblrs,opid,(int32_t)strlen(opid),ptr);
+ return(ptr);
+}
+
+struct jumblr_item *jumblr_opidadd(struct supernet_info *myinfo,struct iguana_info *coin,char *opid)
+{
+ struct jumblr_item *ptr;
+ if ( (ptr= jumblr_opidfind(myinfo,opid)) == 0 )
+ {
+ ptr = calloc(1,sizeof(*ptr));
+ safecopy(ptr->opid,opid,sizeof(ptr->opid));
+ HASH_ADD_KEYPTR(hh,myinfo->jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr);
+ if ( ptr != jumblr_opidfind(myinfo,opid) )
+ printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid);
+ }
+ return(ptr);
+}
+
+char *jumblr_validateaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *addr)
+{
+ char params[1024];
+ if ( coin->FULLNODE < 0 )
+ {
+ sprintf(params,"[\"%s\"]",addr);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"validateaddress",params));
+ } else return(_dex_validateaddress(myinfo,coin->symbol,addr));
+}
+
+int32_t jumblr_ismine(struct supernet_info *myinfo,struct iguana_info *coin,char *addr)
+{
+ char params[1024],*retstr; cJSON *retjson,*obj; int32_t retval = -1;
+ sprintf(params,"[\"%s\"]",addr);
+ if ( (retstr= jumblr_validateaddress(myinfo,coin,addr)) != 0 )
+ {
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( (obj= jobj(retjson,"ismine")) != 0 && is_cJSON_True(obj) != 0 )
+ retval = 1;
+ else retval = 0;
+ free_json(retjson);
+ }
+ free(retstr);
+ }
+ return(retval);
+}
+
+char *jumblr_zgetnewaddress(struct supernet_info *myinfo,struct iguana_info *coin)
+{
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getnewaddress",""));
+}
+
+char *jumblr_zlistoperationids(struct supernet_info *myinfo,struct iguana_info *coin)
+{
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_listoperationids",""));
+}
+
+char *jumblr_zgetoperationresult(struct supernet_info *myinfo,struct iguana_info *coin,char *opid)
+{
+ char params[1024];
+ sprintf(params,"[[\"%s\"]]",opid);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getoperationresult",params));
+}
+
+char *jumblr_zgetoperationstatus(struct supernet_info *myinfo,struct iguana_info *coin,char *opid)
+{
+ char params[1024];
+ sprintf(params,"[[\"%s\"]]",opid);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getoperationstatus",params));
+}
+
+char *jumblr_sendt_to_z(struct supernet_info *myinfo,struct iguana_info *coin,char *taddr,char *zaddr,double amount)
+{
+ char params[1024]; double fee = (amount-3*JUMBLR_TXFEE) * JUMBLR_FEE;
+ if ( jumblr_addresstype(myinfo,coin,zaddr) != 'z' || jumblr_addresstype(myinfo,coin,taddr) != 't' )
+ return(clonestr("{\"error\":\"illegal address in t to z\"}"));
+ sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_sendmany",params));
+}
+
+char *jumblr_sendz_to_z(struct supernet_info *myinfo,struct iguana_info *coin,char *zaddrS,char *zaddrD,double amount)
+{
+ char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE;
+ if ( jumblr_addresstype(myinfo,coin,zaddrS) != 'z' || jumblr_addresstype(myinfo,coin,zaddrD) != 'z' )
+ return(clonestr("{\"error\":\"illegal address in z to z\"}"));
+ sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_sendmany",params));
+}
+
+char *jumblr_sendz_to_t(struct supernet_info *myinfo,struct iguana_info *coin,char *zaddr,char *taddr,double amount)
+{
+ char params[1024]; double fee = (amount-JUMBLR_TXFEE) * JUMBLR_FEE;
+ if ( jumblr_addresstype(myinfo,coin,zaddr) != 'z' || jumblr_addresstype(myinfo,coin,taddr) != 't' )
+ return(clonestr("{\"error\":\"illegal address in z to t\"}"));
+ sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_sendmany",params));
+}
+
+char *jumblr_zlistreceivedbyaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *addr)
+{
+ char params[1024];
+ sprintf(params,"[\"%s\", 1]",addr);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_listreceivedbyaddress",params));
+}
+
+char *jumblr_getreceivedbyaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *addr)
+{
+ char params[1024];
+ sprintf(params,"[\"%s\", 1]",addr);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getreceivedbyaddress",params));
+}
+
+char *jumblr_importprivkey(struct supernet_info *myinfo,struct iguana_info *coin,char *wifstr)
+{
+ char params[1024];
+ sprintf(params,"[\"%s\", \"\", false]",wifstr);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"importprivkey",params));
+}
+
+char *jumblr_zgetbalance(struct supernet_info *myinfo,struct iguana_info *coin,char *addr)
+{
+ char params[1024];
+ sprintf(params,"[\"%s\", 1]",addr);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getbalance",params));
+}
+
+char *jumblr_listunspent(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr)
+{
+ char params[1024];
+ if ( coin->FULLNODE == 0 )
+ return(dex_listunspent(myinfo,coin,0,0,coin->symbol,coinaddr));
+ sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr);
+ return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",params));
+}
+
+int64_t jumblr_receivedby(struct supernet_info *myinfo,struct iguana_info *coin,char *addr)
+{
+ char *retstr; int64_t total = 0;
+ if ( (retstr= jumblr_getreceivedbyaddress(myinfo,coin,addr)) != 0 )
+ {
+ total = atof(retstr) * SATOSHIDEN;
+ free(retstr);
+ }
+ return(total);
+}
+
+int64_t jumblr_balance(struct supernet_info *myinfo,struct iguana_info *coin,char *addr)
+{
+ char *retstr; double val; cJSON *retjson; int32_t i,n; int64_t balance = 0;
+ if ( jumblr_addresstype(myinfo,coin,addr) == 't' )
+ {
+ if ( coin->FULLNODE < 0 && iguana_isnotarychain(coin->symbol) < 0 )
+ {
+ if ( (retstr= jumblr_listunspent(myinfo,coin,addr)) != 0 )
+ {
+ printf("jumblr.[%s].(%s)\n",coin->symbol,retstr);
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( (n= cJSON_GetArraySize(retjson)) > 0 )
+ for (i=0; isymbol,addr)) != 0 )
+ {
+ //printf("DEX retstr.(%s)\n",retstr);
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
+ {
+ balance = jdouble(retjson,"balance") * SATOSHIDEN;
+ //printf("GOT BALANCE %s %.8f\n",coin->symbol,dstr(balance));
+ free_json(retjson);
+ }
+ free(retstr);
+ }
+ }
+ else if ( (retstr= jumblr_zgetbalance(myinfo,coin,addr)) != 0 )
+ {
+ if ( (val= atof(retstr)) > SMALLVAL )
+ balance = val * SATOSHIDEN;
+ free(retstr);
+ }
+ return(balance);
+}
+
+int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status)
+{
+ cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount;
+ /*"params" : {
+ "fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5",
+ "amounts" : [
+ {
+ "address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft",
+ "amount" : 3.00000000
+ }
+ ],
+ "minconf" : 1,
+ "fee" : 0.00010000
+ }*/
+ if ( (params= jobj(item,"params")) != 0 )
+ {
+ //printf("params.(%s)\n",jprint(params,0));
+ if ( (from= jstr(params,"fromaddress")) != 0 )
+ {
+ safecopy(ptr->src,from,sizeof(ptr->src));
+ }
+ if ( (amounts= jarray(&n,params,"amounts")) != 0 )
+ {
+ for (i=0; i 0 )
+ {
+ if ( strcmp(addr,JUMBLR_ADDR) == 0 )
+ ptr->fee = amount;
+ else
+ {
+ ptr->amount = amount;
+ safecopy(ptr->dest,addr,sizeof(ptr->dest));
+ }
+ }
+ }
+ }
+ ptr->txfee = jdouble(params,"fee") * SATOSHIDEN;
+ }
+ return(1);
+}
+
+void jumblr_opidupdate(struct supernet_info *myinfo,struct iguana_info *coin,struct jumblr_item *ptr)
+{
+ char *retstr,*status,KMDjumblr[64],KMDdeposit[64],BTCaddr[64]; cJSON *retjson,*item;
+ if ( ptr->status == 0 )
+ {
+ if ( (retstr= jumblr_zgetoperationstatus(myinfo,coin,ptr->opid)) != 0 )
+ {
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( cJSON_GetArraySize(retjson) == 1 )
+ {
+ item = jitem(retjson,0);
+ //printf("%s\n",jprint(item,0));
+ if ( (status= jstr(item,"status")) != 0 )
+ {
+ if ( strcmp(status,"success") == 0 )
+ {
+ ptr->status = jumblr_itemset(ptr,item,status);
+ jumblr_privkey(myinfo,BTCaddr,0,KMDdeposit,JUMBLR_DEPOSITPREFIX);
+ jumblr_privkey(myinfo,BTCaddr,0,KMDjumblr,"");
+ if ( (jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && strcmp(ptr->src,KMDdeposit) != 0) || (jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->src) == 't' && strcmp(ptr->dest,KMDjumblr) != 0) )
+ {
+ printf("a non-jumblr t->z pruned\n");
+ free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid));
+ ptr->status = -1;
+ }
+
+ }
+ else if ( strcmp(status,"failed") == 0 )
+ {
+ printf("%s failed\n",ptr->opid);
+ free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid));
+ ptr->status = -1;
+ }
+ }
+ }
+ free_json(retjson);
+ }
+ free(retstr);
+ }
+ }
+}
+
+void jumblr_prune(struct supernet_info *myinfo,struct iguana_info *coin,struct jumblr_item *ptr)
+{
+ struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1;
+ printf("PRUNE %s\n",ptr->opid);
+ strcpy(oldsrc,ptr->src);
+ free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid));
+ while ( flag != 0 )
+ {
+ flag = 0;
+ HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
+ {
+ if ( strcmp(oldsrc,ptr->dest) == 0 )
+ {
+ printf("prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest);
+ free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid));
+ strcpy(oldsrc,ptr->src);
+ flag = 1;
+ break;
+ }
+ }
+ }
+}
+
+void jumblr_opidsupdate(struct supernet_info *myinfo,struct iguana_info *coin)
+{
+ char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr;
+ if ( (retstr= jumblr_zlistoperationids(myinfo,coin)) != 0 )
+ {
+ if ( (array= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( (n= cJSON_GetArraySize(array)) > 0 )
+ {
+ for (i=0; istatus == 0 )
+ jumblr_opidupdate(myinfo,coin,ptr);
+ //printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount));
+ if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 't' )
+ jumblr_prune(myinfo,coin,ptr);
+ }
+ }
+ }
+ free_json(array);
+ }
+ free(retstr);
+ }
+}
+
+int64_t jumblr_DEXsplit(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *splittxidp,char *coinaddr,bits256 txid,int32_t vout,int64_t remaining,double bigprice,double middleprice,double smallprice,double fees[4],cJSON *privkeys,double esttxfee)
+{
+ int64_t values[4],outputs[64],value,total,estfee; int32_t i,n,success=0,completed,sendflag,numoutputs = 0; char *retstr; cJSON *retjson,*utxo,*item;
+ total = 0;
+ estfee = SATOSHIDEN * esttxfee;
+ memset(values,0,sizeof(values));
+ memset(outputs,0,sizeof(outputs));
+ if ( bigprice > SMALLVAL )
+ values[0] = SATOSHIDEN * bigprice;
+ if ( middleprice > SMALLVAL )
+ values[1] = SATOSHIDEN * middleprice;
+ if ( smallprice > SMALLVAL )
+ values[2] = SATOSHIDEN * smallprice;
+ for (i=0; i<4; i++)
+ {
+ if ( fees[i] > SMALLVAL )
+ values[3+i] = SATOSHIDEN * fees[i];
+ }
+ for (i=0; i<7; i++)
+ {
+ if ( (value= values[i]) != 0 )
+ {
+ n = 0;
+ while ( n < 10 && remaining > value && numoutputs < sizeof(outputs)/sizeof(*outputs) )
+ {
+ outputs[numoutputs++] = value;
+ remaining -= value;
+ total += value;
+ printf("%.8f ",dstr(value));
+ n++;
+ }
+ }
+ }
+ char str[65]; printf("numoutputs.%d total %.8f %s/v%d\n",numoutputs,dstr(total),bits256_str(str,txid),vout);
+ if ( numoutputs > 1 ) // no point to make just one
+ {
+ if ( (retstr= _dex_gettxout(myinfo,coin->symbol,txid,vout)) != 0 )
+ {
+ item = cJSON_Parse(retstr);
+ jaddbits256(item,"txid",txid);
+ jaddnum(item,"vout",vout);
+ free(retstr);
+ if ( item != 0 )
+ {
+ utxo = cJSON_CreateArray();
+ jaddi(utxo,item);
+ sendflag = 0;
+ ///printf("jitem.(%s)\n",jprint(utxo,0));
+ if ( (retstr= iguana_utxorawtx(myinfo,coin,0,coinaddr,coinaddr,outputs,numoutputs,0,&completed,sendflag,utxo,privkeys)) != 0 )
+ {
+ if ( completed != 0 )
+ {
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( jobj(retjson,"error") == 0 && jobj(retjson,"sent") != 0 )
+ {
+ *splittxidp = jbits256(retjson,"sent");
+ success = 1;
+ printf("DEXsplit success %.8f\n",dstr(total));
+ }
+ free_json(retjson);
+ }
+ }
+ free(retstr);
+ }
+ free_json(utxo);
+ }
+ }
+ }
+ return(success * total);
+}
+
+double jumblr_DEXutxosize(double *targetvolBp,double *targetvolMp,double *targetvolSp,int32_t isbob,double kmdprice)
+{
+ double fee,depositfactor = (isbob == 0) ? 1. : 1.2;
+ fee = JUMBLR_INCR * JUMBLR_FEE;
+ *targetvolBp = depositfactor * kmdprice * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE);
+ *targetvolMp = depositfactor * kmdprice * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE);
+ *targetvolSp = depositfactor * kmdprice * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);
+ return(depositfactor);
+}
+
+int32_t jumblr_DEXutxoind(int32_t *shouldsplitp,double targetvolB,double targetvolM,double targetvolS,double amount,double margin,double dexfeeratio,double esttxfee)
+{
+ *shouldsplitp = 0;
+ if ( amount >= targetvolB )
+ {
+ if ( amount > margin * (targetvolB + targetvolS) )
+ *shouldsplitp = 1;
+ return(0);
+ }
+ else
+ {
+ if ( amount >= targetvolM )
+ {
+ if ( amount > margin * (targetvolM + targetvolS) )
+ *shouldsplitp = 1;
+ return(1);
+ }
+ else
+ {
+ if ( amount >= targetvolS )
+ {
+ if ( amount > margin * targetvolS )
+ *shouldsplitp = 1;
+ return(2);
+ }
+ else if ( amount >= targetvolB/dexfeeratio )
+ {
+ if ( amount > margin * targetvolB/dexfeeratio )
+ *shouldsplitp = 1;
+ return(3);
+ }
+ else if ( amount >= targetvolM/dexfeeratio )
+ {
+ if ( amount > margin * targetvolM/dexfeeratio )
+ *shouldsplitp = 1;
+ return(4);
+ }
+ else if ( amount >= targetvolS/dexfeeratio )
+ {
+ if ( amount > margin * targetvolS/dexfeeratio )
+ *shouldsplitp = 1;
+ return(5);
+ }
+ else if ( amount >= esttxfee )
+ {
+ if ( amount > esttxfee*4 )
+ *shouldsplitp = 1;
+ return(6);
+ }
+ else return(-1);
+ }
+ }
+}
+
+int32_t jumblr_DEXutxoupdate(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *shouldsplitp,bits256 *splittxidp,char *coinaddr,bits256 privkey,bits256 txid,int32_t vout,uint64_t value,int32_t isbob,double kmdprice,double estfee)
+{
+ double fees[4],targetvolB,amount,targetvolM,targetvolS,depositfactor,dexfeeratio,margin; int32_t ind = -1,i; cJSON *privkeys; char wifstr[128];
+ *shouldsplitp = 0;
+ margin = 1.1;
+ depositfactor = (isbob == 0) ? 1. : 1.2;
+ dexfeeratio = 500.;
+ amount = dstr(value);
+ memset(splittxidp,0,sizeof(*splittxidp));
+ depositfactor = jumblr_DEXutxosize(&targetvolB,&targetvolM,&targetvolS,isbob,kmdprice);
+ printf("depositfactor %.8f targetvols %.8f %.8f %.8f\n",depositfactor,targetvolB,targetvolM,targetvolS);
+ fees[0] = (margin * targetvolB) / dexfeeratio;
+ fees[1] = (margin * targetvolM) / dexfeeratio;
+ fees[2] = (margin * targetvolS) / dexfeeratio;
+ fees[3] = (strcmp("BTC",coin->symbol) == 0) ? 50000 : 10000;
+ for (i=0; i<4; i++)
+ if ( fees[i] < 10000 )
+ fees[i] = 10000;
+ if ( (ind= jumblr_DEXutxoind(shouldsplitp,targetvolB,targetvolM,targetvolS,amount,margin,dexfeeratio,fees[3])) >= 0 )
+ {
+ printf("shouldsplit.%d ind.%d\n",*shouldsplitp,ind);
+ if ( *shouldsplitp != 0 )
+ {
+ privkeys = cJSON_CreateArray();
+ bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype);
+ jaddistr(privkeys,wifstr);
+ if ( jumblr_DEXsplit(myinfo,coin,splittxidp,coinaddr,txid,vout,value,margin * targetvolB,margin * targetvolM,margin * targetvolS,fees,privkeys,estfee) > 0 )
+ ind = -1;
+ else *shouldsplitp = 0;
+ free_json(privkeys);
+ }
+ } // else printf("negative ind\n");
+ return(ind);
+}
+
+/*struct DEXcoin_info
+ {
+ bits256 deposit_privkey,jumblr_privkey;
+ struct iguana_info *coin;
+ cJSON *utxos,*spentutxos,*bigutxos,*normalutxos,*smallutxos,*feeutxos,*otherutxos;
+ double btcprice,USD_average,DEXpending,maxbid,minask,avail,KMDavail;
+ uint32_t lasttime;
+ char CMCname[32],symbol[16],depositaddr[64],KMDdepositaddr[64],KMDjumblraddr[64],jumblraddr[64];
+ };*/
+
+int32_t jumblr_utxotxidpending(struct supernet_info *myinfo,bits256 *splittxidp,int32_t *indp,struct iguana_info *coin,bits256 txid,int32_t vout)
+{
+ int32_t i;
+ memset(splittxidp,0,sizeof(*splittxidp));
+ for (i=0; iDEXinfo.numpending; i++)
+ {
+ if ( coin->DEXinfo.pending[i].vout == vout && bits256_cmp(coin->DEXinfo.pending[i].txid,txid) == 0 )
+ {
+ *indp = coin->DEXinfo.pending[i].ind;
+ *splittxidp = coin->DEXinfo.pending[i].splittxid;
+ // printf("jumblr_utxotxidpending found txid in slot.%d\n",i);
+ return(i);
+ }
+ }
+ // printf("jumblr_utxotxidpending cant find txid\n");
+ return(-1);
+}
+
+void jumblr_utxotxidpendingadd(struct supernet_info *myinfo,char *dest,struct iguana_info *coin,bits256 txid,int32_t vout,uint64_t value,bits256 splittxid,int32_t ind,double price,double estfee,int32_t shouldsplit)
+{
+ struct jumblr_pending pend; cJSON *vals,*retjson; bits256 hash; char *retstr;
+ memset(&pend,0,sizeof(pend));
+ pend.splittxid = splittxid;
+ pend.txid = txid;
+ pend.vout = vout;
+ pend.ind = ind;
+ if ( 0 && myinfo->IAMLP == 0 && shouldsplit == 0 && ind < 3 )
+ {
+ static uint32_t num;
+ if ( num == 0 && price > SMALLVAL )
+ {
+ num++;
+ vals = cJSON_CreateObject();
+ jaddstr(vals,"source",coin->symbol);
+ jaddstr(vals,"dest",dest);
+ jaddnum(vals,"amount",price * 100);//dstr(value) - estfee);
+ jaddnum(vals,"minprice",price);
+ jaddnum(vals,"usejumblr",1);
+ memset(hash.bytes,0,sizeof(hash));
+ if ( (retstr= InstantDEX_request(myinfo,coin,0,0,hash,vals,"")) != 0 )
+ {
+ if ( (retjson= cJSON_Parse(retstr)) != 0 )
+ {
+ printf("request.(%s) -> (%s)\n",jprint(vals,0),retstr);
+ free_json(retjson);
+ }
+ free(retstr);
+ }
+ free_json(vals);
+ }
+ }
+ coin->DEXinfo.pending = realloc(coin->DEXinfo.pending,sizeof(*coin->DEXinfo.pending) * (1 + coin->DEXinfo.numpending));
+ coin->DEXinfo.pending[coin->DEXinfo.numpending++] = pend;
+}
+
+void jumblr_utxoupdate(struct supernet_info *myinfo,char *dest,struct iguana_info *coin,double price,char *coinaddr,bits256 privkey,double estfee)
+{
+ char *retstr; cJSON *array,*item; int32_t shouldsplit,i,n,vout,ind; bits256 txid,splittxid; uint64_t value;
+ if ( (retstr= jumblr_listunspent(myinfo,coin,coinaddr)) != 0 )
+ {
+ //printf("%s.(%s)\n",coin->symbol,retstr);
+ if ( (array= cJSON_Parse(retstr)) != 0 )
+ {
+ if ( (n= cJSON_GetArraySize(array)) > 0 )
+ {
+ for (i=0; iIAMLP,price,estfee);
+ jumblr_utxotxidpendingadd(myinfo,dest,coin,txid,vout,value,splittxid,ind,price,estfee,shouldsplit);
+ }
+ else
+ {
+ // update status of utxo
+ }
+ }
+ }
+ free_json(array);
+ }
+ free(retstr);
+ }
+}
+
+void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int32_t selector,int32_t modval)
+{
+ //static uint32_t lasttime;
+ char BTCaddr[64],KMDaddr[64],*zaddr,*retstr; int32_t iter,counter,chosen_one,n; bits256 privkey; uint64_t amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint8_t r,s;
+ if ( myinfo->IAMNOTARY != 0 )
+ return;
+ fee = JUMBLR_INCR * JUMBLR_FEE;
+ OS_randombytes(&r,sizeof(r));
+//r = 0;
+ // randomize size chosen and order of chunks
+ if ( strcmp(coin->symbol,"KMD") == 0 && coin->FULLNODE < 0 )
+ {
+ s = (selector + (r>>1)) % 3;
+ //printf("JUMBLR selector.%d modval.%d r.%d\n",selector,modval,r&7);
+ switch ( s )
+ {
+ case 0: // public -> z, need to importprivkey
+ jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,JUMBLR_DEPOSITPREFIX);
+ if ( (total= jumblr_balance(myinfo,coin,KMDaddr)) >= (JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))*SATOSHIDEN )
+ {
+ if ( (r & 1) == 0 )
+ {
+ if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 )
+ {
+ amount = 0;
+ if ( total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) )
+ amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE);
+ if ( (r & 2) != 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) )
+ amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE);
+ if ( (r & 4) != 0 )
+ amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);
+ if ( amount > 0 && (retstr= jumblr_sendt_to_z(myinfo,coin,KMDaddr,zaddr,dstr(amount))) != 0 )
+ {
+ printf("sendt_to_z.(%s)\n",retstr);
+ free(retstr);
+ }
+ free(zaddr);
+ } else printf("no zaddr from jumblr_zgetnewaddress\n");
+ }
+ } else printf("%s total %.8f vs %.8f\n",KMDaddr,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE)));
+ break;
+ case 1: // z -> z
+ jumblr_opidsupdate(myinfo,coin);
+ chosen_one = -1;
+ for (iter=counter=0; iter<2; iter++)
+ {
+ counter = n = 0;
+ HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
+ {
+ if ( jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' )
+ {
+ if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
+ {
+ if ( iter == 1 && counter == chosen_one )
+ {
+ if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 )
+ {
+ if ( (retstr= jumblr_sendz_to_z(myinfo,coin,ptr->dest,zaddr,dstr(total))) != 0 )
+ {
+ printf("n.%d counter.%d chosen_one.%d sendz_to_z.(%s)\n",n,counter,chosen_one,retstr);
+ free(retstr);
+ }
+ ptr->spent = (uint32_t)time(NULL);
+ free(zaddr);
+ break;
+ }
+ }
+ counter++;
+ }
+ }
+ n++;
+ }
+ if ( counter == 0 )
+ break;
+ if ( iter == 0 )
+ {
+ OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one));
+ if ( chosen_one < 0 )
+ chosen_one = -chosen_one;
+ chosen_one %= counter;
+ printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n);
+ }
+ }
+ break;
+ case 2: // z -> public
+ if ( myinfo->runsilent == 0 )
+ {
+ jumblr_opidsupdate(myinfo,coin);
+ chosen_one = -1;
+ for (iter=0; iter<2; iter++)
+ {
+ counter = n = 0;
+ HASH_ITER(hh,myinfo->jumblrs,ptr,tmp)
+ {
+ if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' )
+ {
+ if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
+ {
+ if ( iter == 1 && n == chosen_one )
+ {
+ privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,"");
+ if ( (retstr= jumblr_sendz_to_t(myinfo,coin,ptr->dest,KMDaddr,dstr(total))) != 0 )
+ {
+ printf("sendz_to_t.(%s)\n",retstr);
+ free(retstr);
+ }
+ ptr->spent = (uint32_t)time(NULL);
+ break;
+ }
+ counter++;
+ }
+ }
+ n++;
+ }
+ if ( counter == 0 )
+ break;
+ if ( iter == 0 )
+ {
+ OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one));
+ if ( chosen_one < 0 )
+ chosen_one = -chosen_one;
+ chosen_one %= counter;
+ printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n);
+ }
+ }
+ }
+ break;
+ }
+ }
+}
+
diff --git a/basilisk/smartaddress.c b/basilisk/smartaddress.c
new file mode 100755
index 000000000..727a54709
--- /dev/null
+++ b/basilisk/smartaddress.c
@@ -0,0 +1,685 @@
+/******************************************************************************
+ * Copyright © 2014-2017 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. *
+ * *
+ ******************************************************************************/
+
+// included from basilisk.c
+
+// deposit address -> corresponding KMD address, if KMD deposit starts JUMBLR
+// jumblr address is the destination of JUMBLR and JUMBLR BTC (would need tracking to map back to non-BTC)
+// address is DEX'ed for
+
+// return value convention: -1 error, 0 partial match, >= 1 exact match
+
+int32_t smartaddress_type(char *typestr)
+{
+ char upper[64];
+ if ( strcmp(typestr,"deposit") != 0 && strcmp(typestr,"jumblr") != 0 && strcmp(typestr,"dividend") != 0 && strcmp(typestr,"pangea") != 0 )
+ {
+ upper[sizeof(upper)-1] = 0;
+ strncpy(upper,typestr,sizeof(upper)-1);
+ touppercase(upper);
+ if ( iguana_coinfind(upper) != 0 )
+ return(0);
+ else return(-1);
+ }
+ return(1);
+}
+
+bits256 jumblr_privkey(struct supernet_info *myinfo,char *coinaddr,uint8_t pubtype,char *KMDaddr,char *prefix)
+{
+ bits256 privkey,pubkey; uint8_t pubkey33[33]; char passphrase[sizeof(myinfo->jumblr_passphrase) + 64];
+ sprintf(passphrase,"%s%s",prefix,myinfo->jumblr_passphrase);
+ if ( myinfo->jumblr_passphrase[0] == 0 )
+ strcpy(myinfo->jumblr_passphrase,"password");
+ conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
+ bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey);
+ bitcoin_address(coinaddr,pubtype,pubkey33,33);
+ bitcoin_address(KMDaddr,60,pubkey33,33);
+ //printf("(%s) -> (%s %s)\n",passphrase,coinaddr,KMDaddr);
+ return(privkey);
+}
+
+cJSON *smartaddress_extrajson(struct smartaddress *ap)
+{
+ cJSON *retjson = cJSON_CreateObject();
+ if ( strcmp(ap->typestr,"dividend") == 0 )
+ {
+
+ }
+ return(retjson);
+}
+
+cJSON *smartaddress_json(struct smartaddress *ap)
+{
+ char coinaddr[64],symbol[64]; uint8_t desttype,tmp,rmd160[20]; int32_t j,n; struct iguana_info *coin,*dest; cJSON *array,*item,*retjson; double amount;
+ retjson = cJSON_CreateObject();
+ jaddstr(retjson,"type",ap->typestr);
+ strcpy(symbol,ap->typestr), touppercase(symbol);
+ if ( (dest= iguana_coinfind(symbol)) != 0 )
+ desttype = dest->chain->pubtype;
+ else desttype = 60;
+ if ( (n= ap->numsymbols) > 0 )
+ {
+ array = cJSON_CreateArray();
+ for (j=0; jsymbols[j].symbol)) != 0 )
+ {
+ bitcoin_address(coinaddr,coin->chain->pubtype,ap->pubkey33,33);
+ item = cJSON_CreateObject();
+ jaddstr(item,"coin",coin->symbol);
+ jaddstr(item,"address",coinaddr);
+ if ( (amount= ap->symbols[j].srcavail) != 0 )
+ jaddnum(item,"sourceamount",amount);
+ if ( dest != 0 )
+ {
+ bitcoin_addr2rmd160(&tmp,rmd160,coinaddr);
+ bitcoin_address(coinaddr,desttype,rmd160,20);
+ jaddstr(item,"dest",coinaddr);
+ if ( (amount= ap->symbols[j].destamount) != 0 )
+ jaddnum(item,"destamount",amount);
+ if ( coin->DEXinfo.depositaddr[0] != 0 )
+ {
+ jaddstr(item,"jumblr_deposit",coin->DEXinfo.depositaddr);
+ jaddnum(item,"deposit_avail",coin->DEXinfo.avail);
+ }
+ if ( coin->DEXinfo.jumblraddr[0] != 0 )
+ {
+ jaddstr(item,"jumblr",coin->DEXinfo.jumblraddr);
+ jaddnum(item,"jumblr_avail",coin->DEXinfo.jumblravail);
+ }
+ if ( ap->symbols[j].maxbid != 0. )
+ jaddnum(item,"maxbid",ap->symbols[j].maxbid);
+ if ( ap->symbols[j].minask != 0. )
+ jaddnum(item,"minask",ap->symbols[j].minask);
+ }
+ jadd(item,"extra",smartaddress_extrajson(ap));
+ jaddi(array,item);
+ }
+ }
+ jadd(retjson,"coins",array);
+ }
+ return(retjson);
+}
+
+void smartaddress_symboladd(struct smartaddress *ap,char *symbol,double maxbid,double minask)
+{
+ char tmp[64]; struct smartaddress_symbol *sp;
+ strcpy(tmp,ap->typestr), touppercase(tmp);
+ if ( strcmp(tmp,symbol) != 0 )
+ {
+ ap->symbols = realloc(ap->symbols,(ap->numsymbols+1) * sizeof(*ap->symbols));
+ sp = &ap->symbols[ap->numsymbols++];
+ memset(sp,0,sizeof(*sp));
+ safecopy(sp->symbol,symbol,sizeof(sp->symbol));
+ sp->maxbid = maxbid;
+ sp->minask = minask;
+ printf("symboladd.%d (%s) <- (%s %f %f)\n",ap->numsymbols,ap->typestr,symbol,maxbid,minask);
+ }
+}
+
+struct smartaddress *smartaddressptr(struct smartaddress_symbol **ptrp,struct supernet_info *myinfo,char *_type,char *_symbol)
+{
+ char type[64],symbol[64]; int32_t i,j,n; struct smartaddress *ap;
+ if ( ptrp != 0 )
+ *ptrp = 0;
+ strcpy(type,_type), tolowercase(type);
+ strcpy(symbol,_symbol), touppercase(symbol);
+ for (i=0; inumsmartaddrs; i++)
+ {
+ ap = &myinfo->smartaddrs[i];
+ if ( strcmp(type,ap->typestr) == 0 )
+ {
+ n = ap->numsymbols;
+ for (j=0; jsymbols[j].symbol,symbol) == 0 )
+ {
+ if ( ptrp != 0 )
+ *ptrp = &ap->symbols[j];
+ return(ap);
+ }
+ }
+ }
+ }
+ return(0);
+}
+
+void smartaddress_minmaxupdate(struct supernet_info *myinfo,char *_type,char *_symbol,double maxbid,double minask)
+{
+ struct smartaddress *ap; struct smartaddress_symbol *sp;
+ if ( (ap= smartaddressptr(&sp,myinfo,_type,_symbol)) != 0 && sp != 0 )
+ {
+ dxblend(&sp->maxbid,maxbid,0.5);
+ dxblend(&sp->minask,minask,0.5);
+ }
+}
+
+void smartaddress_availupdate(struct supernet_info *myinfo,char *_type,char *_symbol,double srcavail,double destamount)
+{
+ struct smartaddress *ap; struct smartaddress_symbol *sp;
+ if ( (ap= smartaddressptr(&sp,myinfo,_type,_symbol)) != 0 && sp != 0 )
+ {
+ if ( srcavail > SMALLVAL )
+ sp->srcavail = srcavail;
+ if ( destamount > SMALLVAL )
+ sp->destamount = destamount;
+ }
+}
+
+int32_t _smartaddress_add(struct supernet_info *myinfo,bits256 privkey,char *type,char *symbol,double maxbid,double minask)
+{
+ char coinaddr[64]; uint8_t addrtype,rmd160[20]; struct smartaddress *ap; int32_t i,j,n;
+ if ( myinfo->numsmartaddrs < sizeof(myinfo->smartaddrs)/sizeof(*myinfo->smartaddrs) )
+ {
+ for (i=0; inumsmartaddrs; i++)
+ {
+ ap = &myinfo->smartaddrs[i];
+ if ( strcmp(type,ap->typestr) == 0 && bits256_cmp(ap->privkey,privkey) == 0 )
+ {
+ n = ap->numsymbols;
+ for (j=0; jsymbols[j].symbol,symbol) == 0 )
+ {
+ ap->symbols[j].maxbid = maxbid;
+ ap->symbols[j].minask = minask;
+ if ( maxbid > SMALLVAL && minask > SMALLVAL && smartaddress_type(type) == 0 )
+ smartaddress_minmaxupdate(myinfo,symbol,type,1./minask,1./maxbid);
+ return(0);
+ }
+ }
+ smartaddress_symboladd(ap,symbol,maxbid,minask);
+ return(i+1);
+ }
+ }
+ ap = &myinfo->smartaddrs[myinfo->numsmartaddrs];
+ if ( smartaddress_type(symbol) < 0 )
+ return(-1);
+ strcpy(ap->typestr,type);
+ smartaddress_symboladd(ap,"KMD",0.,0.);
+ smartaddress_symboladd(ap,"BTC",0.,0.);
+ ap->privkey = privkey;
+ bitcoin_pubkey33(myinfo->ctx,ap->pubkey33,privkey);
+ calc_rmd160_sha256(ap->rmd160,ap->pubkey33,33);
+ ap->pubkey = curve25519(privkey,curve25519_basepoint9());
+ char str[65]; printf("pubkey.(%s) ",bits256_str(str,ap->pubkey));
+ bitcoin_address(coinaddr,0,ap->pubkey33,33);
+ for (i=0; i<20; i++)
+ printf("%02x",ap->rmd160[i]);
+ bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr);
+ printf(", ");
+ for (i=0; i<20; i++)
+ printf("%02x",rmd160[i]);
+ printf (" <- rmd160 for %d %s\n",myinfo->numsmartaddrs,coinaddr);
+ return(++myinfo->numsmartaddrs + 1);
+ }
+ printf("too many smartaddresses %d vs %d\n",myinfo->numsmartaddrs,(int32_t)(sizeof(myinfo->smartaddrs)/sizeof(*myinfo->smartaddrs)));
+ return(-1);
+}
+
+int32_t smartaddress_add(struct supernet_info *myinfo,bits256 privkey,char *type,char *symbol,double maxbid,double minask)
+{
+ int32_t retval;
+ portable_mutex_lock(&myinfo->smart_mutex);
+ retval = _smartaddress_add(myinfo,privkey,type,symbol,maxbid,minask);
+ portable_mutex_unlock(&myinfo->smart_mutex);
+ return(retval);
+}
+
+int32_t smartaddress_symbolmatch(char *typestr,double *bidaskp,struct smartaddress *ap,char *symbol)
+{
+ int32_t j,n;
+ strcpy(typestr,ap->typestr);
+ if ( (n= ap->numsymbols) > 0 )
+ {
+ for (j=0; jsymbols[j].symbol,symbol) == 0 )
+ {
+ bidaskp[0] = ap->symbols[j].maxbid;
+ bidaskp[1] = ap->symbols[j].minask;
+ return(j);
+ }
+ }
+ }
+ return(-1);
+}
+
+int32_t smartaddress(struct supernet_info *myinfo,char *typestr,double *bidaskp,bits256 *privkeyp,char *symbol,char *coinaddr)
+{
+ int32_t i,j,retval = -1; uint8_t addrtype,rmd160[20]; struct smartaddress *ap;
+ memset(privkeyp,0,sizeof(*privkeyp));
+ memset(bidaskp,0,sizeof(*bidaskp) * 2);
+ bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr);
+ portable_mutex_lock(&myinfo->smart_mutex);
+ for (i=0; inumsmartaddrs; i++)
+ if ( memcmp(myinfo->smartaddrs[i].rmd160,rmd160,20) == 0 )
+ {
+ ap = &myinfo->smartaddrs[i];
+ *privkeyp = ap->privkey;
+ if ( (j= smartaddress_symbolmatch(typestr,bidaskp,ap,symbol)) >= 0 )
+ retval = 0;
+ else retval = (i+1);
+ break;
+ }
+ portable_mutex_unlock(&myinfo->smart_mutex);
+ for (i=0; i<20; i++)
+ printf("%02x",rmd160[i]);
+ printf(" <- rmd160 smartaddress cant find (%s) of %d\n",coinaddr,myinfo->numsmartaddrs);
+ return(retval);
+}
+
+int32_t smartaddress_pubkey(struct supernet_info *myinfo,char *typestr,double *bidaskp,bits256 *privkeyp,char *symbol,bits256 pubkey)
+{
+ int32_t i,j,retval = -1; struct smartaddress *ap;
+ memset(privkeyp,0,sizeof(*privkeyp));
+ memset(bidaskp,0,sizeof(*bidaskp) * 2);
+ if ( bits256_cmp(myinfo->myaddr.persistent,pubkey) == 0 )
+ {
+ *privkeyp = myinfo->persistent_priv;
+ return(myinfo->numsmartaddrs);
+ }
+ portable_mutex_lock(&myinfo->smart_mutex);
+ for (i=0; inumsmartaddrs; i++)
+ if ( bits256_cmp(myinfo->smartaddrs[i].pubkey,pubkey) == 0 )
+ {
+ ap = &myinfo->smartaddrs[i];
+ *privkeyp = ap->privkey;
+ if ( (j= smartaddress_symbolmatch(typestr,bidaskp,ap,symbol)) >= 0 )
+ retval = 0;
+ else retval = (i+1);
+ break;
+ }
+ portable_mutex_unlock(&myinfo->smart_mutex);
+ //char str[65]; if ( retval < 0 )
+ // printf("smartaddress_pubkey no match for %s\n",bits256_str(str,pubkey));
+ return(retval);
+}
+
+int32_t smartaddress_pubkey33(struct supernet_info *myinfo,char *typestr,double *bidaskp,bits256 *privkeyp,char *symbol,uint8_t *pubkey33)
+{
+ int32_t i,j,retval = -1; struct smartaddress *ap;
+ memset(privkeyp,0,sizeof(*privkeyp));
+ memset(bidaskp,0,sizeof(*bidaskp) * 2);
+ portable_mutex_lock(&myinfo->smart_mutex);
+ for (i=0; inumsmartaddrs; i++)
+ if ( memcmp(myinfo->smartaddrs[i].pubkey33,pubkey33,33) == 0 )
+ {
+ ap = &myinfo->smartaddrs[i];
+ *privkeyp = ap->privkey;
+ if ( (j= smartaddress_symbolmatch(typestr,bidaskp,ap,symbol)) >= 0 )
+ retval = 0;
+ else retval = (i+1);
+ break;
+ }
+ portable_mutex_unlock(&myinfo->smart_mutex);
+ return(retval);
+}
+
+void smartaddress_CMCname(char *CMCname,char *symbol)
+{
+ if ( strcmp(symbol,"KMD") == 0 )
+ strcpy(CMCname,"komodo");
+ else if ( strcmp(symbol,"BTC") == 0 )
+ strcpy(CMCname,"bitcoin");
+}
+
+void smartaddress_coinupdate(struct supernet_info *myinfo,char *symbol,double BTC2KMD,double KMDavail,double KMD2USD)
+{
+ int32_t r; double avebid,aveask,highbid,lowask,CMC_average,changes[3]; struct iguana_info *coin; struct DEXcoin_info *ptr;
+ if ( (coin= iguana_coinfind(symbol)) != 0 )
+ {
+ ptr = &coin->DEXinfo;
+ ptr->coin = coin;
+ if ( coin->CMCname[0] == 0 )
+ smartaddress_CMCname(coin->CMCname,symbol);
+ r = (((symbol[0]^symbol[1]^symbol[2])&0x7f) % 15) - 7; // 53 to 67 seconds
+ if ( time(NULL) > (ptr->lasttime + 60 + r) )
+ {
+ if ( strcmp(symbol,ptr->symbol) != 0 )
+ {
+ safecopy(ptr->symbol,symbol,sizeof(ptr->symbol));
+ safecopy(ptr->CMCname,coin->CMCname,sizeof(ptr->CMCname));
+ }
+ ptr->deposit_privkey = jumblr_privkey(myinfo,ptr->depositaddr,coin->chain->pubtype,ptr->KMDdepositaddr,JUMBLR_DEPOSITPREFIX);
+ ptr->jumblr_privkey = jumblr_privkey(myinfo,ptr->jumblraddr,coin->chain->pubtype,ptr->KMDjumblraddr,"");
+ ptr->avail = dstr(jumblr_balance(myinfo,coin,ptr->depositaddr));
+ ptr->jumblravail = dstr(jumblr_balance(myinfo,ptr->coin,ptr->jumblraddr));
+ if ( strcmp(symbol,"USD") == 0 )
+ {
+ if ( KMD2USD > SMALLVAL )
+ {
+ ptr->kmdprice = 1./ KMD2USD;
+ if ( (ptr->BTC2KMD= BTC2KMD) > SMALLVAL )
+ ptr->btcprice = ptr->kmdprice * BTC2KMD;
+ }
+ printf("USD btcprice %.8f kmdprice %.8f\n",ptr->btcprice,ptr->kmdprice);
+ }
+ else
+ {
+ if ( strcmp(symbol,"BTC") == 0 )
+ ptr->btcprice = 1.;
+ else if ( coin->CMCname[0] != 0 && (ptr->btcprice == 0. || (ptr->counter++ % 10) == 0) )
+ ptr->btcprice = get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,coin->CMCname,symbol,"BTC",&ptr->USD_average);
+ if ( strcmp("KMD",symbol) == 0 )
+ ptr->kmdprice = 1.;
+ else if ( (ptr->BTC2KMD= BTC2KMD) > SMALLVAL )
+ ptr->kmdprice = ptr->btcprice / BTC2KMD;
+ }
+ ptr->lasttime = (uint32_t)time(NULL);
+ printf("%s avail %.8f KMDavail %.8f btcprice %.8f deposit.(%s %s) -> jumblr.(%s %s)\n",symbol,ptr->avail,KMDavail,ptr->btcprice,ptr->depositaddr,ptr->KMDdepositaddr,ptr->jumblraddr,ptr->KMDjumblraddr);
+ }
+ } // else printf("skip\n");
+}
+
+void smartaddress_dex(struct supernet_info *myinfo,char *type,int32_t selector,struct iguana_info *basecoin,char *coinaddr,double maxavail,struct iguana_info *relcoin,double maxbid,double minask,cJSON *extraobj,double maxvol)
+{
+ double minamount,minbtc,price,avail,vol,btc2kmd,basebtc,relbtc,baseusd,relusd; char *retstr; cJSON *vals; bits256 hash; struct smartaddress *ap;
+ basebtc = basecoin->DEXinfo.btcprice;
+ relbtc = relcoin->DEXinfo.btcprice;
+ baseusd = basecoin->DEXinfo.USD_average;
+ relusd = relcoin->DEXinfo.USD_average;
+ if ( (btc2kmd= basecoin->DEXinfo.BTC2KMD) < SMALLVAL && (btc2kmd= relcoin->DEXinfo.BTC2KMD) < SMALLVAL )
+ return;
+ minamount = price = 0.;
+ if ( basebtc < SMALLVAL && relbtc < SMALLVAL )
+ return;
+ if ( myinfo->DEXratio < .95 || myinfo->DEXratio > 1.01 )
+ myinfo->DEXratio = 0.995;
+ if ( basebtc < SMALLVAL || relbtc < SMALLVAL )
+ {
+ if ( (price= maxbid) > SMALLVAL )
+ {
+ if ( basebtc < SMALLVAL )
+ basebtc = price * relbtc, printf("calculated basebtc %.8f from (%.8f * %.8f)\n",basebtc,price,relbtc);
+ else if ( relbtc < SMALLVAL )
+ relbtc = basebtc / price, printf("calculated relbtc %.8f from (%.8f / %.8f)\n",relbtc,basebtc,price); // price * relbtc == basebtc
+ }
+ } else price = myinfo->DEXratio * (basebtc / relbtc);
+ minbtc = btc2kmd * (JUMBLR_INCR + 3*(JUMBLR_INCR * JUMBLR_FEE + JUMBLR_TXFEE));
+ if ( minamount == 0. && basebtc > SMALLVAL )
+ minamount = (minbtc / basebtc);
+ printf("DEX %s/%s maxavail %.8f minbtc %.8f btcprice %.8f -> minamount %.8f price %.8f vs maxbid %.8f DEXratio %.5f DEXpending %.8f\n",basecoin->symbol,relcoin->symbol,maxavail,minbtc,basecoin->DEXinfo.btcprice,minamount,price,maxbid,myinfo->DEXratio,basecoin->DEXinfo.DEXpending);
+ if ( minamount > SMALLVAL && maxavail > minamount + basecoin->DEXinfo.DEXpending && (maxbid == 0. || price <= maxbid) )
+ {
+ avail = (maxavail - basecoin->DEXinfo.DEXpending);
+ /*if ( avail >= (100. * minamount) )
+ vol = (100. * minamount);
+ else if ( avail >= (10. * minamount) )
+ vol = (10. * minamount);
+ else*/ if ( avail >= minamount )
+ vol = minamount;
+ else vol = 0.;
+ if ( vol > 0. )
+ {
+ vals = cJSON_CreateObject();
+ jaddstr(vals,"source",basecoin->symbol);
+ jaddstr(vals,"dest",relcoin->symbol);
+ jaddnum(vals,"amount",vol);
+ jaddnum(vals,"minprice",price);
+ if ( (ap= smartaddressptr(0,myinfo,type,basecoin->symbol)) != 0 )
+ jaddbits256(vals,"srchash",ap->pubkey);
+ if ( selector != 0 )
+ {
+ jaddnum(vals,"usejumblr",selector);
+ jaddnum(vals,"DEXselector",selector);
+ }
+ memset(hash.bytes,0,sizeof(hash));
+ basecoin->DEXinfo.DEXpending += vol;
+ if ( (retstr= InstantDEX_request(myinfo,basecoin,0,0,hash,vals,"")) != 0 )
+ {
+ printf("request.(%s) -> (%s)\n",jprint(vals,0),retstr);
+ free(retstr);
+ }
+ free_json(vals);
+ } else printf("avail %.8f < minamount %.8f\n",avail,minamount);
+ } //else printf("failed if check %d %d %d %d\n",minamount > SMALLVAL,maxavail > minamount + basecoin->DEXinfo.DEXpending,maxbid == 0,price <= maxbid);
+ /*
+ minbtc = (basecoin->DEXinfo.btcprice * 1.2) * (JUMBLR_INCR + 3*(JUMBLR_INCR * JUMBLR_FEE + JUMBLR_TXFEE));
+ btcavail = dstr(jumblr_balance(myinfo,coinbtc,kmdcoin->DEXinfo.depositaddr));
+ avail = (btcavail - coinbtc->DEXinfo.DEXpending);
+ printf("BTC.%d deposits %.8f, min %.8f avail %.8f pending %.8f\n",toKMD,btcavail,minbtc,avail,coinbtc->DEXinfo.DEXpending);
+ if ( toKMD == 0 && coinbtc != 0 && btcavail > (minbtc + coinbtc->DEXinfo.DEXpending) )
+ {
+ if ( vol > 0. )
+ {
+ vals = cJSON_CreateObject();
+ jaddstr(vals,"source","BTC");
+ jaddstr(vals,"dest","KMD");
+ jaddnum(vals,"amount",vol);
+ jaddnum(vals,"minprice",0.985/kmdcoin->DEXinfo.btcprice);
+ jaddnum(vals,"usejumblr",1);
+ jaddnum(vals,"DEXselector",1);
+ memset(hash.bytes,0,sizeof(hash));
+ coinbtc->DEXinfo.DEXpending += vol;
+ if ( (retstr= InstantDEX_request(myinfo,coinbtc,0,0,hash,vals,"")) != 0 )
+ {
+ printf("request.(%s) -> (%s)\n",jprint(vals,0),retstr);
+ free(retstr);
+ }
+ free_json(vals);
+ // curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"InstantDEX\",\"method\":\"request\",\"vals\":{\"source\":\"KMD\",\"amount\":20,\"dest\":\"USD\",\"minprice\":0.08}}"
+ }
+ } //else printf("btcavail %.8f pending %.8f\n",btcavail,pending);
+ minkmd = 100.;
+ avail = (kmdcoin->DEXinfo.KMDavail - kmdcoin->DEXinfo.DEXpending);
+ printf("KMD.%d deposits %.8f, min %.8f, avail %.8f pending %.8f\n",toKMD,kmdcoin->DEXinfo.KMDavail,minkmd,avail,kmdcoin->DEXinfo.DEXpending);
+ if ( toKMD != 0 && coinbtc != 0 && kmdcoin->DEXinfo.KMDavail > (minkmd + kmdcoin->DEXinfo.DEXpending) )
+ {
+ if ( avail > 100.*JUMBLR_INCR )
+ vol = 100.*JUMBLR_INCR;
+ else if ( avail > 10.*JUMBLR_INCR )
+ vol = 10.*JUMBLR_INCR;
+ else if ( avail >= JUMBLR_INCR )
+ vol = JUMBLR_INCR;
+ else vol = 0.;
+ if ( vol > 0. )
+ {
+ vals = cJSON_CreateObject();
+ jaddstr(vals,"source","KMD");
+ jaddstr(vals,"dest","BTC");
+ jaddnum(vals,"amount",vol);
+ //jaddnum(vals,"destamount",JUMBLR_INCR*kmdcoin->DEXinfo.btcprice);
+ jaddnum(vals,"minprice",0.985 * kmdcoin->DEXinfo.btcprice);
+ jaddnum(vals,"usejumblr",2);
+ memset(hash.bytes,0,sizeof(hash));
+ kmdcoin->DEXinfo.DEXpending += vol;
+ jaddnum(vals,"DEXselector",2);
+ if ( (retstr= InstantDEX_request(myinfo,coinbtc,0,0,hash,vals,"")) != 0 )
+ {
+ printf("request.(%s) -> (%s)\n",jprint(vals,0),retstr);
+ free(retstr);
+ }
+ free_json(vals);
+ }
+ } else printf("kmdavail %.8f pending %.8f\n",kmdcoin->DEXinfo.avail,kmdcoin->DEXinfo.DEXpending);*/
+}
+
+void smartaddress_depositjumblr(struct supernet_info *myinfo,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj)
+{
+ struct iguana_info *basecoin,*relcoin;
+ if ( (basecoin= iguana_coinfind(symbol)) != 0 && (relcoin= iguana_coinfind("KMD")) != 0 )
+ {
+ if ( strcmp(coinaddr,basecoin->DEXinfo.depositaddr) == 0 )
+ smartaddress_dex(myinfo,"deposit",1,basecoin,coinaddr,basecoin->DEXinfo.avail,relcoin,maxbid,minask,extraobj,0.);
+ else printf("smartaddress_jumblr.%s: mismatch deposit address (%s) vs (%s)\n",symbol,coinaddr,basecoin->DEXinfo.depositaddr);
+ }
+}
+
+double smartaddress_jumblrcredit(struct supernet_info *myinfo,char *symbol)
+{
+ return(0.); // default to BTC conversion for now
+}
+
+void smartaddress_jumblr(struct supernet_info *myinfo,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj)
+{
+ struct iguana_info *basecoin,*relcoin; double credits = 0.;
+ if ( strcmp("BTC",symbol) != 0 )
+ {
+ if ( (credits= smartaddress_jumblrcredit(myinfo,symbol)) <= 0. )
+ return;
+ }
+ if ( (basecoin= iguana_coinfind("KMD")) != 0 && (relcoin= iguana_coinfind(symbol)) != 0 )
+ {
+ if ( strcmp(coinaddr,basecoin->DEXinfo.jumblraddr) == 0 )
+ smartaddress_dex(myinfo,"jumblr",2,basecoin,coinaddr,basecoin->DEXinfo.jumblravail,relcoin,maxbid,minask,extraobj,credits);
+ else printf("smartaddress_jumblr.%s: mismatch jumblr address (%s) vs (%s)\n",symbol,coinaddr,basecoin->DEXinfo.jumblraddr);
+ }
+}
+
+void smartaddress_dividend(struct supernet_info *myinfo,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj)
+{
+ // support list of weighted addresses, including snapshots
+}
+
+void smartaddress_pangea(struct supernet_info *myinfo,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj)
+{
+ // table deposit
+}
+
+void smartaddress_action(struct supernet_info *myinfo,int32_t selector,char *typestr,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj)
+{
+ char rel[64]; struct iguana_info *basecoin,*relcoin; double avail;
+ if ( strcmp(typestr,"deposit") == 0 && selector == 0 )
+ smartaddress_depositjumblr(myinfo,symbol,coinaddr,maxbid,minask,extraobj);
+ else if ( strcmp(typestr,"jumblr") == 0 && selector == 0 )
+ smartaddress_jumblr(myinfo,symbol,coinaddr,maxbid,minask,extraobj);
+ else if ( strcmp(typestr,"dividend") == 0 && selector == 0 )
+ smartaddress_dividend(myinfo,symbol,coinaddr,maxbid,minask,extraobj);
+ else if ( strcmp(typestr,"pangea") == 0 && selector == 0 )
+ smartaddress_pangea(myinfo,symbol,coinaddr,maxbid,minask,extraobj);
+ else
+ {
+ safecopy(rel,typestr,sizeof(rel));
+ touppercase(rel);
+ if ( (relcoin= iguana_coinfind(rel)) != 0 && (basecoin= iguana_coinfind(symbol)) != 0 )
+ {
+ if ( myinfo->numswaps == 0 )//|| (basecoin->FULLNODE < 0 && relcoin->FULLNODE < 0) )
+ {
+ if ( (avail= dstr(jumblr_balance(myinfo,basecoin,coinaddr))) > SMALLVAL )
+ {
+ smartaddress_availupdate(myinfo,typestr,symbol,avail,SMALLVAL*0.99);
+ smartaddress_dex(myinfo,typestr,0,basecoin,coinaddr,avail,relcoin,maxbid,minask,extraobj,0.);
+ }
+ }
+ }
+ }
+}
+
+void smartaddress_update(struct supernet_info *myinfo,int32_t selector)
+{
+ double maxbid,minask; uint8_t addrtype,rmd160[20]; char *smartstr,*typestr,*symbol,*address,coinaddr[64]; cJSON *smartarray,*extraobj,*item,*array,*coinitem; int32_t iter,i,n,j,m; struct iguana_info *kmdcoin,*coinbtc = 0;
+ //printf("smartaddress_update numswaps.%d notary.%d IAMLP.%d %p %p %f\n",myinfo->numswaps,myinfo->IAMNOTARY,myinfo->IAMLP,kmdcoin,coinbtc,kmdcoin->DEXinfo.btcprice);
+ if ( myinfo->IAMNOTARY != 0 || myinfo->IAMLP != 0 || myinfo->secret[0] == 0 )
+ return;
+ kmdcoin = iguana_coinfind("KMD");
+ coinbtc = iguana_coinfind("BTC");
+ if ( kmdcoin == 0 || coinbtc == 0 )
+ return;
+ smartaddress_coinupdate(myinfo,"KMD",0.,0.,0.); // must be first
+ if ( kmdcoin->DEXinfo.btcprice > SMALLVAL )
+ {
+ if ( (smartstr= InstantDEX_smartaddresses(myinfo,0,0,0)) != 0 )
+ {
+ if ( (smartarray= cJSON_Parse(smartstr)) != 0 )
+ {
+ if ( (n= cJSON_GetArraySize(smartarray)) > 0 )
+ {
+ for (iter=0; iter<2; iter++)
+ {
+ for (i=0; iDEXinfo.btcprice,kmdcoin->DEXinfo.avail,kmdcoin->DEXinfo.USD_average);
+ else
+ {
+ printf("Action.%s (%s)\n",typestr,jprint(coinitem,0));
+ if ( (address= jstr(coinitem,"address")) != 0 )
+ {
+ if ( strcmp(typestr,"jumblr") == 0 )
+ {
+ bitcoin_addr2rmd160(&addrtype,rmd160,address);
+ bitcoin_address(coinaddr,kmdcoin->chain->pubtype,rmd160,20);
+ } else strcpy(coinaddr,address);
+ maxbid = jdouble(coinitem,"maxbid");
+ minask = jdouble(coinitem,"minask");
+ extraobj = jobj(coinitem,"extra");
+ smartaddress_action(myinfo,selector,typestr,symbol,coinaddr,maxbid,minask,extraobj);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ free_json(smartarray);
+ }
+ free(smartstr);
+ }
+ }
+}
+
+#include "../includes/iguana_apidefs.h"
+#include "../includes/iguana_apideclares.h"
+#include "../includes/iguana_apideclares2.h"
+
+ZERO_ARGS(InstantDEX,smartaddresses)
+{
+ int32_t i; cJSON *retjson = cJSON_CreateArray();
+ portable_mutex_lock(&myinfo->smart_mutex);
+ for (i=0; inumsmartaddrs; i++)
+ jaddi(retjson,smartaddress_json(&myinfo->smartaddrs[i]));
+ portable_mutex_unlock(&myinfo->smart_mutex);
+ return(jprint(retjson,1));
+}
+
+TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,smartaddress,type,symbol,maxbid,minask)
+{
+ char prefix[64],coinaddr[64],KMDaddr[64],typestr[64]; double bidask[2]; uint8_t pubkey33[33]; bits256 privkey;
+ if ( smartaddress_type(type) < 0 )
+ return(clonestr("{\"error\":\"non-supported smartaddress type\"}"));
+ if ( iguana_coinfind(symbol) == 0 )
+ return(clonestr("{\"error\":\"non-supported smartaddress symbol\"}"));
+ if ( strcmp(type,"deposit") == 0 || strcmp(type,"jumblr") == 0 )
+ {
+ if ( smartaddress_pubkey(myinfo,typestr,bidask,&privkey,symbol,strcmp(type,"deposit") == 0 ? myinfo->jumblr_depositkey : myinfo->jumblr_pubkey) < 0 )
+ return(clonestr("{\"error\":\"unexpected missing smartaddress deposit/jumblr\"}"));
+ }
+ else
+ {
+ strcpy(prefix,type);
+ tolowercase(prefix);
+ if ( strcmp(prefix,"btc") == 0 || strcmp(prefix,"kmd") == 0 )
+ return(clonestr("{\"success\":\"no need add BTC or KMD to smartaddress\"}"));
+ strcat(prefix," ");
+ privkey = jumblr_privkey(myinfo,coinaddr,0,KMDaddr,prefix);
+ }
+ if ( (coin= iguana_coinfind(symbol)) == 0 )
+ return(clonestr("{\"error\":\"non-supported smartaddress symbol\"}"));
+ bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey);
+ bitcoin_address(coinaddr,coin->chain->pubtype,pubkey33,33);
+ smartaddress_add(myinfo,privkey,type,symbol,maxbid,minask);
+ return(InstantDEX_smartaddresses(myinfo,0,0,0));
+}
+
+#include "../includes/iguana_apiundefs.h"
diff --git a/basilisk/tradebots_SVM.h b/basilisk/tradebots_SVM.h
new file mode 100755
index 000000000..a7a0b7d3b
--- /dev/null
+++ b/basilisk/tradebots_SVM.h
@@ -0,0 +1,1072 @@
+/******************************************************************************
+ * Copyright © 2014-2017 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. *
+ * *
+ ******************************************************************************/
+
+/*
+ requires *vals and *vars to be initialized
+ external calls: OS_milliseconds(), get_jfp_features(), get_yval(), set_ocas_model(), update_ocas_preds(), ocasCL_glue()
+ */
+//#include
+
+typedef float svmtype;
+
+// fadedreamz@gmail.com - added for successful compilation, however, for MSVC probably require a particular OpenCL SDK
+// to work with it (e,g nvidia or amd SDK)
+typedef struct fake_opencl_double { //use a struct for double2 typedefinition on all OS - ca333@protonmail.ch
+ double x;
+ double y;
+}double2;
+
+#define MAX_VECTORS (1440 * 365 * 5)
+#define MAIN_MAXCORES 16
+#define c_to_refc(c) (c)
+#define refc_to_c(refc) (refc)
+
+#define CONDITION(feature) (feature)
+#define FEATURE_THRESHOLD 10.
+#define HWMPERC_THRESHOLD 101
+#define HWMPERC_THRESHOLD0 HWMPERC_THRESHOLD
+
+#ifdef INSIDE_OPENCL
+#pragma OPENCL EXTENSION cl_khr_fp64: enable
+#define local_barrier() barrier(CLK_LOCAL_MEM_FENCE)
+#define global_barrier() barrier(CLK_GLOBAL_MEM_FENCE)
+#else
+//double get_features(register struct ocas_ptrs *PTRS,register int c,register int weekind,register int numfeatures,register double *features,register double *model,register double *addptr,register struct baserel_info *BR,register double wt);
+svmtype *get_jfp_features(register int selector,register int numfeatures,register int c,register int weekind);
+
+#endif
+
+#define OCAS_INFINITY (-log(0.0))
+#define OCAS_NEGINFINITY (log(0.0))
+#define OCAS_DECAY .1
+#define OCAS_BIAS 1.
+#define OCAS_INDEX(ROW,COL,NUM_ROWS) ((COL)*(NUM_ROWS)+(ROW))
+#define QPSOLVER_MAXITER 1000000
+#define QPSOLVER_MINITER (QPSOLVER_MAXITER * .1)
+//#define NUM_CUDA_GROUPS 14
+//#define NUM_BUNDLE_ANSWERS 64
+//#define NUM_TOPCOEFFIS 558
+//#define SMALLVAL .00000000000001
+//#define NUM_PRIMARY_FEATURES 4096
+#ifdef __APPLE__
+#define MAX_OCAS_LHS 512
+#else
+#define MAX_OCAS_LHS 2000
+#endif
+#define MAX_OCAS_FEATURES (1024 * 1024)
+
+struct ptrhdr { long allocsize; void *ptr; int devid; char str[64]; };
+
+struct ocas_lhsbuffers
+{
+ double H[MAX_OCAS_LHS * MAX_OCAS_LHS];
+ double alpha[MAX_OCAS_LHS],b[MAX_OCAS_LHS],diag_H[MAX_OCAS_LHS],A0[MAX_OCAS_LHS],d[MAX_OCAS_LHS];
+ double full_A[];
+};
+
+struct ocas_CLtmpspace
+{
+ double2 hpfb[MAX_VECTORS];
+ int poslist[MAX_VECTORS],neglist[MAX_VECTORS];
+};
+
+struct ocas_CLbuffers
+{
+ double output_pred[MAX_VECTORS],old_output[MAX_VECTORS];
+ double W[MAX_OCAS_FEATURES+4],oldW[MAX_OCAS_FEATURES+4],new_a[MAX_OCAS_FEATURES+4];
+};
+
+struct ocas_vars
+{
+ struct ptrhdr pH[256];
+ double Q_P[TRADEBOTS_NUMANSWERS],Q_D[TRADEBOTS_NUMANSWERS];
+ double netcuts[TRADEBOTS_NUMANSWERS],perc[TRADEBOTS_NUMANSWERS],hwmperc[TRADEBOTS_NUMANSWERS],lastmetrics[TRADEBOTS_NUMANSWERS][2];
+ double learningrates[TRADEBOTS_NUMANSWERS][2],maxiters[TRADEBOTS_NUMANSWERS],dot_prod_WoldW[TRADEBOTS_NUMANSWERS],cutsum[TRADEBOTS_NUMANSWERS];
+ double sq_norm_oldW[TRADEBOTS_NUMANSWERS],oldW0[TRADEBOTS_NUMANSWERS],W0[TRADEBOTS_NUMANSWERS],sq_norm_W[TRADEBOTS_NUMANSWERS];
+ double predabs[TRADEBOTS_NUMANSWERS],predsum[TRADEBOTS_NUMANSWERS],dist[TRADEBOTS_NUMANSWERS];
+ double xi[TRADEBOTS_NUMANSWERS],pratio[TRADEBOTS_NUMANSWERS],errperc[TRADEBOTS_NUMANSWERS],hwmdist[TRADEBOTS_NUMANSWERS];
+ double answerabsaves[TRADEBOTS_NUMANSWERS],answeraves[TRADEBOTS_NUMANSWERS];
+ int answercounts,firstweekinds[TRADEBOTS_NUMANSWERS];
+ int posA[TRADEBOTS_NUMANSWERS],negA[TRADEBOTS_NUMANSWERS];
+ int numIt[TRADEBOTS_NUMANSWERS],numlhs[TRADEBOTS_NUMANSWERS],nNZAlpha[TRADEBOTS_NUMANSWERS],trn_err[TRADEBOTS_NUMANSWERS];
+ int qp_exitflag[TRADEBOTS_NUMANSWERS],exitflag[TRADEBOTS_NUMANSWERS],len[TRADEBOTS_NUMANSWERS];
+ int have_pendingmodel[TRADEBOTS_NUMANSWERS],cutlen[TRADEBOTS_NUMANSWERS],good[TRADEBOTS_NUMANSWERS],bad[TRADEBOTS_NUMANSWERS];
+ int nohwm[TRADEBOTS_NUMANSWERS],numposcuts[TRADEBOTS_NUMANSWERS],numnegcuts[TRADEBOTS_NUMANSWERS];
+ struct ocas_CLbuffers *CLspaces[TRADEBOTS_NUMANSWERS];
+ struct ocas_lhsbuffers *lhs[TRADEBOTS_NUMANSWERS];
+ int *weekinds[TRADEBOTS_NUMANSWERS];
+ float *answers,**features;
+ //unsigned long CLallocsize,tmpallocsize,tmpCLallocsize;
+ double C,TolRel,TolAbs,MaxTime,QPBound,QPSolverTolAbs,QPSolverTolRel;
+ double output_time,sort_time,add_time,w_time,qp_solver_time,ocas_time; // total time spent in svm_ocas_solver
+ int selector,numthreads,starti,modelind,c,refc,maxlen,numfeatures,firstweekind,startweekind,endweekind,numptrs,maxlhs;
+};
+
+/////////////////////////// Most of runtime is in the add/dot functions
+#ifdef INSIDE_OPENCL
+typedef double svmtype;
+
+// numCLthreads: NUM_CUDA_CORES, numgroups: (numdocs + NUM_CUDA_CORES-1)/NUM_CUDA_CORES
+__kernel void dot_featuresCL(__local void *lp,__global double *preds,int numfeatures,__global double *W,double W0,__global svmtype *matrix,int numdocs)
+{
+ register int i,j,docid;
+ register double sum;
+ register __global svmtype *features;
+ if ( (docid = (int)get_global_id(0)) < numdocs )
+ {
+ sum = 0.;
+ features = &matrix[docid * numfeatures];
+ for (i=0; i>= 1;
+ if ( docid < numdocs )
+ {
+ features = &matrix[docid * numfeatures];
+ if ( dir == 0 )
+ sum += CONDITION(features[j]);
+ else sum -= CONDITION(features[j]);
+ }
+ }
+ new_a[j] = sum;
+ }
+}
+
+#else
+
+void ocas_purge(struct ocas_vars *vars)
+{
+ int32_t i;
+ free(vars->answers);
+ for (i=0; imaxlen; i++)
+ if ( vars->features[i] != 0 )
+ free(vars->features[i]);
+ free(vars->features);
+ for (i=0; iCLspaces[i] != 0 )
+ myaligned_free(vars->CLspaces[i],sizeof(*vars->CLspaces[i]));
+ if ( vars->lhs[i] != 0 )
+ myaligned_free(vars->lhs[i],sizeof(*vars->lhs[i]) + vars->numfeatures*vars->maxlhs*sizeof(double));
+ if ( vars->weekinds[i] != 0 )
+ free(vars->weekinds[i]);
+ }
+ free(vars);
+}
+
+/*static inline double dot_expanded_features(register double *W,register int c,register int selector,register int numfeatures)
+ {
+ fatal("dot_expanded_features not implemented");
+ return(0);
+ }
+
+ static inline void add_expanded_features(register double *W,register double y,register int c,register int selector,register int numfeatures)
+ {
+ fatal("add_expanded_features not implemented");
+ }*/
+
+static inline double calc_ocas_output(register struct ocas_vars *vars,register int selector,register int c,register int weekind,register int answerind,register double *W,register double W0,register int numfeatures)
+{
+ register svmtype *features;
+ register double feature,y,sum = 0.;
+ register int coeffi;
+ if ( (y= vars->answers[(weekind-vars->starti)*TRADEBOTS_NUMANSWERS + answerind]) != 0.f )
+ {
+ if ( (features= vars->features[weekind-vars->starti]) != 0 )//get_jfp_features(vars->selector,numfeatures,c,weekind)) != 0 )
+ {
+#ifdef OCAS_USE_TOPCOEFFIS
+ for (int i=0; iselector,numfeatures);
+ sum = y * (W0 + sum);
+ }
+ // printf("%f ",sum);
+ return(sum);
+}
+
+static inline void add_ocas_output(register double y,register struct ocas_vars *vars,register int selector,register int c,register int weekind,register int answerind,register double *W,register double *new_a,register int numfeatures)
+{
+ register int coeffi;
+ register svmtype *features,feature;
+ if ( y != 0 )
+ {
+ if ( (features= vars->features[weekind-vars->starti]) != 0 )//get_jfp_features(vars->selector,numfeatures,c,weekind)) != 0 )
+ {
+ //features = get_jfp_features(vars->selector,numfeatures,c,weekind);
+#ifdef OCAS_USE_TOPCOEFFIS
+ int32_t i;
+ for (i=0; iselector,numfeatures);
+ }
+}
+
+static inline void STocas_calc_outputs(register struct ocas_vars *vars,register int c,register int answerind,register double *output,register double *old_output,register double *W,register double W0,register int numfeatures,register int *weekinds,register int numdocs)
+{
+ register int i,j;
+ //vars->good[answerind] = vars->bad[answerind] = 0;
+ //printf("start STocas_calc_outputs.(%p %s.A%d %p) %p %p %p\n",vars,CONTRACTS[c],answerind,weekinds,output,old_output,W);
+ for (i=0; iselector,c,weekinds[i],answerind,W,W0,numfeatures);
+ if ( 1 && isnan(output[i]) != 0 )
+ {
+ svmtype *features = vars->features[weekinds[i]-vars->starti];//get_jfp_features(vars->selector,numfeatures,c,weekinds[i]);
+ if ( features != 0 )
+ {
+ for (j=0; janswers[(i-vars->starti)*TRADEBOTS_NUMANSWERS + answerind]*output[i] <= 0 )
+ {
+ if ( vars->answers[(i-vars->starti)*TRADEBOTS_NUMANSWERS + answerind] != 0.f )
+ printf("(%f %f) ",vars->answers[(i-vars->starti)*TRADEBOTS_NUMANSWERS + answerind],output[i]);
+ }
+ //printf("[%f %f] ",vars->answers[(i-vars->starti)*TRADEBOTS_NUMANSWERS + answerind],output[i]);
+ }
+ }
+ //printf("finish STocas_calc_outputs\n");
+}
+
+static inline void STocas_add_newcuts(register struct ocas_vars *vars,register int answerind,register int numfeatures,register int *weekinds,register int *new_cut,register int numcuts,register double *W,register double *new_a)
+{
+ register int weekind,dir,i,c = vars->c;
+ memset(new_a,0,sizeof(*new_a) * numfeatures);
+ //printf("STocas_add_newcuts numcuts.%d numfeatures.%d\n",numcuts,numfeatures);
+ for (i=0; i>= 1;
+ add_ocas_output(dir==0?1:-1,vars,vars->selector,c,weekind,answerind,W,new_a,numfeatures);
+ }
+}
+//////////////////////////// end of add/dot functions
+static inline double _dbufave(register double *buf,register int len)
+{
+ register int i,n;
+ register double sum;
+ sum = 0.;
+ n = 0;
+ for (i=0; i 0.0000000001 )
+ {
+ n++;
+ sum += buf[i];
+ }
+ }
+ if ( n != 0 )
+ sum /= n;
+ if ( fabs(sum) <= 0.0000000001 )
+ sum = 0.;
+ return(sum);
+}
+
+static inline void add_newcut_entry(register struct ocas_vars *vars,register int answerind,register int *new_cut,register int i,register int weekind,register double y)
+{
+ weekind <<= 1;
+ if ( y > 0 ) vars->numposcuts[answerind]++;
+ else if ( y < 0 ) vars->numnegcuts[answerind]++, weekind |= 1;
+ new_cut[vars->cutlen[answerind]++] = weekind;
+}
+
+static inline double validate_ocas_model(register struct ocas_vars *vars,register int answerind,register double *output_pred,register double *old_output,register int *weekinds,register int numdocs,register double *W,register double W0,register int numfeatures,register int paranoid)
+{
+ register svmtype *features;
+ register double y,pred,perc,answer=0.,feature;
+ register int i,j,pos,neg,good,bad,oldcuts,training_errors,weekind,nonz=0,posA,negA;
+ for (i=pos=neg=good=bad=oldcuts=training_errors=posA=negA=0; ianswers[(weekind-vars->starti)*TRADEBOTS_NUMANSWERS + answerind]) != 0. )
+ {
+ if ( y > 0 ) posA++;
+ else if ( y < 0 ) negA++;
+ if ( paranoid != 0 )
+ {
+ pred = 0.;
+ if ( (features= vars->features[weekind-vars->starti]) != 0 )//get_jfp_features(vars->selector,numfeatures,vars->c,weekind)) != 0 )
+ {
+ for (j=nonz=0; j SMALLVAL )
+ pred += W0;
+ }
+ else pred = 0;//dot_expanded_features(W,c,selector,numfeatures);
+ if ( output_pred[i] != 0 && fabs(pred - output_pred[i]) > .000001 )
+ // if ( (rand() % 10000) == 0 )
+ printf("i.%d A %9.6f pred %9.6f != output_pred %9.6f [%14.10f]\n",i,answer,pred,output_pred[i],pred-output_pred[i]);
+ }
+ else pred = output_pred[i], nonz = numfeatures;
+ if ( nonz != 0 )
+ {
+ if ( pred > 0 ) pos++;
+ else if ( pred < 0 ) neg++;
+ if ( pred*y > 0 ) good++;
+ else if ( pred*y < 0 ) bad++;
+ }
+ if ( old_output[i] <= 1. )
+ {
+ oldcuts++;
+ if ( old_output[i] <= 0. )
+ training_errors++;
+ }
+ }
+ }
+ nonz = 0;
+ for (i=0; i>>>>> %d.A%02d.(+%-6d -%-6d oc.%-6d | good.%-6d bad.%-6d >>>>> %6.2f%% <<<<<).%-6d | W0 %9.6f W[%d] %9.6f | A +%-6d -%-6d | paranoid.%d numdocs.%d\n",c_to_refc(vars->c),answerind,pos,neg,oldcuts,good,bad,perc,training_errors,W0,nonz,_dbufave(W,numfeatures),posA,negA,paranoid,numdocs);
+ return(perc);
+}
+
+static int _increasing_double(const void *a,const void *b)
+{
+#define double_a (*(double *)a)
+#define double_b (*(double *)b)
+ if ( double_b > double_a )
+ return(-1);
+ else if ( double_b < double_a )
+ return(1);
+ return(0);
+#undef double_a
+#undef double_b
+}
+
+static inline void calc_ocas_strategy(register struct ocas_vars *vars,register int answerind,register double C,register int numfeatures,register int len,register int *weekinds,register int *new_cut,register double *W,register double *oldW,register double *output,register double *old_output,register double2 *hpfb)
+{
+ double answermag;
+ register int i,j,num_hp,good,bad,zero;
+ register double Bval,Cval,newoutput,W0,oldW0,sq_norm_W,A0val,B0,dist,GradVal,t,t1,t2,t_new,val,GradVal_new,y,starttime,*preds = output;
+ num_hp = 0;
+ W0 = vars->W0[answerind]; oldW0 = vars->oldW0[answerind];
+ A0val = vars->sq_norm_W[answerind] - (2. * vars->dot_prod_WoldW[answerind]) + vars->sq_norm_oldW[answerind];
+ B0 = (vars->dot_prod_WoldW[answerind] - vars->sq_norm_oldW[answerind]);
+ GradVal = B0;
+ for (i=0; ianswers[(weekinds[i]-vars->starti)*TRADEBOTS_NUMANSWERS + answerind]) != 0.f )
+ {
+ svmtype *features = vars->features[weekinds[i]-vars->starti];//get_jfp_features(vars->selector,numfeatures,vars->c,weekinds[i]);
+ //printf("i.%d weekind.%d starti.%d y %f %p\n",i,weekinds[i],vars->starti,y,features);
+ if ( 0 && features != 0 )
+ {
+ double oldsum=oldW0,sum=W0;
+ for (j=0; j .000001 )
+ {
+ printf("A%d numIt.%d docid.%-6d sum %11.7f * y%2.0f %11.7f != %11.7f output [%11.7f] W0 %11.7f oldW0 %11.7f\n",answerind,vars->numIt[answerind],i,sum,y,sum*y,output[i],output[i]-sum*y,W0,oldW0);
+ //output[i] = sum*y;
+ }
+ if ( fabs(oldsum*y - old_output[i]) > .000001 )
+ {
+ if ( old_output[i] != 0 && oldW0 != 0 && (rand() % 1000) == 0 )
+ printf("A%d numIt.%d docid.%-6d oldsum %11.7f * y%2.0f %11.7f != %11.7f oldoutput [%11.7f] W0 %11.7f oldW0 %11.7f\n",answerind,vars->numIt[answerind],i,oldsum,y,oldsum*y,old_output[i],old_output[i]-oldsum*y,W0,oldW0);
+ old_output[i] = oldsum*y;
+ }
+ }
+ Cval = C * (1. - old_output[i]);
+ Bval = C * (old_output[i] - output[i]);
+ if ( Bval != 0 )
+ val = -(Cval / Bval);
+ else val = OCAS_NEG_INF;
+ if ( val > 0 )
+ {
+ hpfb[num_hp].y = Bval;
+ hpfb[num_hp].x = val;
+ num_hp++;
+ }
+ if ( (Bval < 0 && val > 0) || (Bval > 0 && val <= 0) )
+ GradVal += Bval;
+ }
+ }
+ //printf("num_hp.%d\n",num_hp);
+ t = 0;
+ if ( GradVal < 0 )
+ {
+ starttime = OS_milliseconds();
+ qsort(hpfb,num_hp,sizeof(double2),_increasing_double);
+ //ocas_sort(hpfb,num_hp);
+ i = 0;
+ while ( GradVal < 0 && i < num_hp )
+ {
+ t_new = hpfb[i].x;
+ GradVal_new = GradVal + fabs(hpfb[i].y) + A0val*(t_new - t);
+ if ( GradVal_new >= 0 )
+ t = t + GradVal * (t - t_new) / (GradVal_new - GradVal);
+ else t = t_new, i++;
+ GradVal = GradVal_new;
+ }
+ vars->sort_time += OS_milliseconds() - starttime;
+ }
+ t = MAX(t,0.); // just sanity check; t < 0 should not occur
+ t1 = t; // new (best so far) W
+ t2 = t + OCAS_DECAY*(1. - t); // new cutting plane
+ W0 = oldW0 * (1. - t) + (t * W0);
+ sq_norm_W = W0 * W0;
+ for (j=0; jW0[answerind] = W0; vars->sq_norm_W[answerind] = sq_norm_W;
+ vars->trn_err[answerind] = 0; dist = 0.;
+ for (i=good=bad=zero=0; ianswers[(weekinds[i]-vars->starti)*TRADEBOTS_NUMANSWERS + answerind]) != 0.f )
+ {
+ answermag = fabs(y); // 1.;
+ if ( (old_output[i] * (1. - t2) + t2*output[i]) <= answermag ) //1.
+ add_newcut_entry(vars,answerind,new_cut,i,weekinds[i],y);
+ newoutput = (old_output[i] * (1. - t1)) + (t1 * output[i]);
+ if ( 0 ) // won't match unless old_output corresponds with features*oldW
+ {
+ double sum=W0;
+ svmtype *features = vars->features[weekinds[i]-vars->starti];//get_jfp_features(vars->selector,numfeatures,vars->c,weekinds[i]);
+ if ( features != 0 )
+ {
+ for (j=0; j .0000001 )
+ printf("numIt.%d docid.%-6d w%-6d sum %11.7f * y%2.0f %11.7f != %11.7f newoutput [%11.7f] W0 %11.7f oldW0 %11.7f\n",vars->numIt[answerind],i,weekinds[i],sum,y,sum*y,newoutput,newoutput-sum*y,W0,oldW0);
+ newoutput = sum*y;
+ }
+ }
+ if ( newoutput <= answermag )
+ {
+ vars->xi[answerind] += (answermag - newoutput);
+ if ( newoutput <= 0. )
+ vars->trn_err[answerind]++;
+ }
+ preds[i] = y * newoutput;
+ dist += fabs(preds[i] - y);
+ old_output[i] = newoutput;
+ if ( newoutput > 0. ) good++;
+ else if ( newoutput < 0. )
+ {
+ bad++;
+ //printf("(%f %f) ",y,newoutput);
+ }
+ } else zero++;//,printf("i.%d -> w%d | zeroes.%d good.%d bad.%d of len.%d\n",i,weekinds[i],zero,good,bad,len);
+ }
+ //printf("finished strategy\n");
+ vars->good[answerind] = good; vars->bad[answerind] = bad; vars->dist[answerind] = dist / MAX(1,good+bad);
+ vars->perc[answerind] = (100. * (double)vars->good[answerind]) / MAX(1,good+bad);
+ if ( vars->perc[answerind] > vars->hwmperc[answerind] || (vars->perc[answerind] == vars->hwmperc[answerind] && (vars->hwmdist[answerind] == 0 || vars->dist[answerind] < vars->hwmdist[answerind])) )
+ {
+ double set_ocas_model(int refc,int answerind,double *W,double W0,int numfeatures,int firstweekind,int len,int bad,double dist,double predabs,int posA,int negA,double answerabs,double aveanswer);
+ vars->W0[answerind] = set_ocas_model(vars->refc,answerind,vars->CLspaces[answerind]->W,vars->W0[answerind],vars->numfeatures,vars->firstweekind,vars->len[answerind],vars->trn_err[answerind],vars->dist[answerind],vars->predabs[answerind],vars->posA[answerind],vars->negA[answerind],vars->answerabsaves[answerind],0.);
+ vars->nohwm[answerind] = 0;
+ vars->hwmperc[answerind] = vars->perc[answerind]; vars->hwmdist[answerind] = vars->dist[answerind];
+ }
+ else vars->nohwm[answerind]++;
+ //printf("good.%d bad.%d zero.%d errors.%d | selector.%d\n",good,bad,zero,vars->trn_err[answerind],vars->selector);
+}
+
+static inline double ocas_splx_solver(register int *nonzalphap,register int maxlhs,register double *d,register double *activeH,register double *diag_H,register double *f,register double C,register double *alpha,register int n,register int MaxIter,register double TolAbs,register double TolRel,register double QP_TH)
+{
+ register double *col_u=0,*col_v=0;
+ register double QP,QD,lastQD,tmp,diff,distA,distB,etaA,etaB,improv,tmp_num,delta,x_neq0,xval,dval,diagval=0.,tmp_den,tau=0.;
+ register int u=0,v=0,i,j,iter,nonzalpha=0,unlikely = 0;
+ QP = distA = distB = OCAS_PLUS_INF; lastQD = QD = OCAS_NEG_INF;
+ x_neq0 = C;
+ etaA = etaB = 0.;
+ for (i=0; i 0. )
+ {
+ col_u = &activeH[maxlhs * i];
+ for (j=0; j 10*(MaxIter-iter) && etaB > 10*(MaxIter-iter) )
+ unlikely++;
+ else unlikely = 0;
+ } else unlikely = 0;
+ diff = (QP - QD);
+ if ( 0 && (diff <= fabs(QP)*TolRel || diff <= TolAbs || QP <= QP_TH || unlikely > 100) )
+ {
+ if ( 0 )
+ {
+ if ( diff <= fabs(QP)*TolRel )
+ printf("caseA %f | ",diff - fabs(QP)*TolRel);
+ else if ( diff <= TolAbs )
+ printf("caseB %f | ",diff - TolAbs);
+ else if ( etaA > 2*(MaxIter-iter) && etaB > 2*(MaxIter-iter) )
+ printf("caseC etas %f %f | ",etaA,etaB);
+ printf("%d: QP %f QD %f diff %f n.%d d0 %9.6f dA %9.6f %9.6f dB %9.6f %9.6f\n",iter,QP,QD,QP-QD,n,d[0],distA,etaA,distB,etaB);
+ }
+ break;
+ }
+ distA = (diff - fabs(QP)*TolRel);
+ distB = (diff - TolAbs);
+ lastQD = QD;
+ if ( d[u] > 0 )
+ u = -1;
+ else delta -= C * d[u];
+ // if satisfied then k-th block of variables needs update
+ if ( delta > TolAbs && delta > (TolRel * fabs(QP)) )
+ {
+ // for fixed u select v = argmax_{i in I_k} Improvement(i)
+ improv = OCAS_NEG_INF;
+ for (i=0; i<=n; i++)
+ {
+ if ( i == u || (xval = ((i 0 )
+ {
+ tmp_num = xval * dval;
+ if ( tmp_num < tmp_den )
+ tmp = tmp_num*tmp_num / tmp_den;
+ else tmp = tmp_num - .5 * tmp_den;
+ if ( 0 && i < n ) // jimbo tweak
+ {
+ tmp = alpha[i] * MIN(1.,tmp_num/tmp_den);
+ alpha[i] -= tmp;
+ if ( u == -1 )
+ x_neq0 += tmp;
+ else alpha[u] += tmp;
+ }
+ if ( tmp > improv )
+ {
+ improv = tmp;
+ tau = MIN(1.,tmp_num/tmp_den);
+ v = i;
+ }
+ }
+ }
+ // update d = H*x + f
+ if ( v < n )
+ {
+ tau *= alpha[v];
+ alpha[v] -= tau;
+ if ( u != -1 )
+ {
+ alpha[u] += tau;
+ col_v = &activeH[maxlhs * v];
+ for (i=0; isq_norm_oldW[answerind] = vars->sq_norm_W[answerind];
+ oldW0 = vars->oldW0[answerind] = vars->W0[answerind];
+ W0 = 0.;
+ for (i=0; ialpha[i]) > 0 )
+ {
+ //printf("%9.6f ",alpha);
+ for (j=0; jfull_A[OCAS_INDEX(j,i,numfeatures)];
+ W0 += lhs->A0[i] * alpha;
+ }
+ }
+ vars->W0[answerind] = W0;
+ sq_norm_W = W0 * W0;
+ dot_prod_WoldW = W0 * oldW0;
+ for (j=0; jalpha,numlhs),W0,sq_norm_W,answerind);
+ vars->dot_prod_WoldW[answerind] = dot_prod_WoldW;
+ vars->sq_norm_W[answerind] = sq_norm_W;
+}
+
+static inline void ocas_update_Lspace(register struct ocas_vars *vars,register int answerind,register double netcuts,register double cut_length,register int numfeatures,register double C,register double QPSolverTolAbs,register double QPSolverTolRel)
+{
+ register struct ocas_CLbuffers *ptr = vars->CLspaces[answerind];
+ register struct ocas_lhsbuffers *lhs = vars->lhs[answerind];
+ register double *new_col_H;
+ register double sq_norm_a,maxiters,metric,tmp;
+ register int i,j,iters,numlhs,maxlhs = vars->maxlhs;
+ numlhs = vars->numlhs[answerind];
+ new_col_H = &lhs->H[OCAS_INDEX(0,numlhs,maxlhs)];
+ lhs->A0[numlhs] = netcuts;
+ lhs->b[numlhs] = -cut_length;
+ sq_norm_a = lhs->A0[numlhs] * lhs->A0[numlhs];
+ for (j=0; jfull_A[OCAS_INDEX(j,numlhs,numfeatures)] = ptr->new_a[j];
+ if ( fabs(ptr->new_a[j]) > 1000 )
+ {
+ //printf("(%d %9.6f %f) ",j,ptr->new_a[j],sq_norm_a);
+ ptr->new_a[j] = 0.;
+ }
+ else
+ sq_norm_a += ptr->new_a[j] * ptr->new_a[j];
+ ptr->oldW[j] = ptr->W[j]; ptr->W[j] = 0.;
+ }
+ new_col_H[numlhs] = sq_norm_a;
+ //printf("QPsolver.A%02d: ABS %f Rel %.11f numlhs.%d cutlen.%f netcuts.%f sq_norm_a %f netcuts.%f\n",answerind,QPSolverTolAbs,QPSolverTolRel,vars->numlhs[answerind],cut_length,lhs->A0[numlhs],sq_norm_a,netcuts);
+ for (i=0; iA0[numlhs] * lhs->A0[i];
+ for (j=0; jnew_a[j] * lhs->full_A[OCAS_INDEX(j,i,numfeatures)];
+ new_col_H[i] = tmp;
+ }
+ lhs->d[numlhs] = lhs->alpha[numlhs] = 0.;
+ lhs->diag_H[numlhs] = lhs->H[OCAS_INDEX(numlhs,numlhs,maxlhs)];
+ for (i=0; i H[OCAS_INDEX(numlhs,i,maxlhs)] = lhs->H[OCAS_INDEX(i,numlhs,maxlhs)];
+ numlhs = ++vars->numlhs[answerind];
+ iters = vars->numIt[answerind];
+ if ( vars->nohwm[answerind] > 3 )
+ vars->maxiters[answerind] *= 1 + sqrt(vars->nohwm[answerind])/100;
+ else if ( vars->nohwm[answerind] == 0 )
+ vars->maxiters[answerind] *= .5;
+ if ( vars->maxiters[answerind] > QPSOLVER_MAXITER )
+ vars->maxiters[answerind] = QPSOLVER_MAXITER;
+ if ( vars->maxiters[answerind] < QPSOLVER_MINITER )
+ vars->maxiters[answerind] = QPSOLVER_MINITER;
+ maxiters = MAX(QPSOLVER_MINITER,vars->maxiters[answerind]);
+ vars->Q_D[answerind] = ocas_splx_solver(&vars->nNZAlpha[answerind],maxlhs,lhs->d,lhs->H,lhs->diag_H,lhs->b,C,lhs->alpha,vars->numlhs[answerind],MIN(maxiters,QPSOLVER_MAXITER),QPSolverTolAbs,QPSolverTolRel,OCAS_NEG_INF);
+ metric = ((double)vars->len[answerind] / MAX(1,vars->trn_err[answerind])) / 1.;
+ vars->lastmetrics[answerind][iters & 1] = metric;
+ update_ocas_model(ptr->W,ptr->oldW,vars,numfeatures,answerind,lhs,numlhs);
+}
+
+static inline void start_ocas_iter(register struct ocas_vars *vars,register int c,register int answerind)
+{
+ if ( vars->pratio[answerind] == 0. )
+ vars->pratio[answerind] = vars->answerabsaves[answerind];
+ vars->good[answerind] = -1;
+ vars->bad[answerind] = vars->trn_err[answerind] = vars->cutlen[answerind] = vars->numposcuts[answerind] = vars->numnegcuts[answerind] = 0;
+ vars->xi[answerind] = vars->predsum[answerind] = vars->dist[answerind] = vars->cutsum[answerind] = vars->netcuts[answerind] = 0.;
+}
+
+static void ocas_print(struct ocas_vars *vars,int answerind,int ishwm,double C)
+{
+ int i;
+ double dispvals[4];
+ //printf("ocas_print.A%d\n",answerind);
+ //printf("%s.A%02d %4d %8.2f | QP %9.3f QD %9.3f [%9.4f %7.3f] SV.%d %4d | M%9.6f (%9.6f max %8.1f %9.6f) %s.A%02d %9.6f%%\n",
+ dispvals[0] = vars->Q_P[answerind]/1000000000.; dispvals[1] = (C * vars->Q_D[answerind])/1000000000.;
+ dispvals[2] = (vars->Q_P[answerind]-C * vars->Q_D[answerind]) / 1000000000;
+ dispvals[3] = (vars->Q_P[answerind]-C * vars->Q_D[answerind]) / MAX(1,fabs(vars->Q_P[answerind]));
+ printf("%3d %d.A%02d +%d -%d",vars->nohwm[answerind],vars->refc,answerind,vars->good[answerind],vars->bad[answerind]);
+ printf(" %4d %8.2f |QP %9.3f QD %10.2f [%11.2f %9.1f] SV.%3d %3d |M%9.3f errs.%-6d %-8.0f %5.2f%% errs %6.5f A%9.6f W0%9.6f D%11.9f\n",//[%7.4f%%]\n",
+ vars->numIt[answerind],vars->ocas_time/1000,dispvals[0],dispvals[1],dispvals[2],dispvals[3],
+ vars->nNZAlpha[answerind], vars->numlhs[answerind],
+ // PTRS->lastmetrics[answerind],PTRS->learningrates[answerind][0],PTRS->maxiters[answerind],PTRS->learningrates[answerind][1],
+ vars->lastmetrics[answerind][0],vars->trn_err[answerind],vars->maxiters[answerind],vars->perc[answerind],
+ vars->errperc[answerind]/100,_dbufave(vars->CLspaces[answerind]->new_a,vars->numfeatures),vars->W0[answerind],
+ vars->dist[answerind]/vars->answerabsaves[answerind]);//_dbufave(vars->hwmperc,81));//,vars->errperc+vars->perc);
+ for (i=0; i<4; i++)
+ if ( isnan(dispvals[i]) != 0 )
+ break;
+ if ( vars->lastmetrics[answerind][0] > 10 )
+ usleep(vars->lastmetrics[answerind][0] * vars->lastmetrics[answerind][0]);
+ /*if ( 0 && i < 4 )//|| (vars->answerind >= 32 && fabs(vars->W0) > .9) )
+ {
+ int save_model(int refc,int answerind,double *W,int numfeatures,double W0,double perc,int posA,int negA);
+ memset(&vars->CLspaces[answerind],0,sizeof(vars->CLspaces[answerind]));
+ vars->W0[answerind] = vars->oldW0[answerind] = 0.;
+ vars->numIt[answerind] = 0;
+ vars->perc[answerind] = vars->hwmperc[answerind] = 0.;
+ printf("reset model %s.A%02d\n",CONTRACTS[vars->selector!=3?vars->refc:NUM_COMBINED],answerind);
+ save_model(vars->refc,answerind,vars->CLspaces[answerind]->W,vars->numfeatures,vars->W0[answerind],vars->perc[answerind]);
+ }*/
+}
+
+static inline void finish_ocasiter(register int answerind,register struct ocas_vars *vars,register double C)
+{
+ register double den;
+ vars->have_pendingmodel[answerind] = 0;
+ if ( vars->good[answerind] == 0 && vars->bad[answerind] == 0 )
+ {
+ vars->bad[answerind] = vars->trn_err[answerind];
+ vars->good[answerind] = (vars->len[answerind] - vars->trn_err[answerind]);
+ }
+ den = MAX(1.,vars->good[answerind]+vars->bad[answerind]);
+ if ( (vars->predabs[answerind] = (vars->predsum[answerind] / den)) != 0. )
+ vars->pratio[answerind] = (vars->answerabsaves[answerind] / vars->predabs[answerind]);
+ else vars->pratio[answerind] = 0.;
+ vars->dist[answerind] = sqrt(vars->dist[answerind] / den);
+ //printf("W0 %9.6f pred sum %f %f | pratio %f distsum %f (%f vs hwm %f)\n",vars->W0[answerind],vars->predsum[answerind],vars->predabs[answerind],vars->pratio[answerind],vars->dist[answerind],vars->perc[answerind],vars->hwmperc[answerind]);
+ vars->errperc[answerind] = (100 * (double)vars->trn_err[answerind])/(double)MAX(1,vars->len[answerind]);
+ vars->Q_P[answerind] = 0.5*vars->sq_norm_W[answerind] + (C * vars->xi[answerind]);
+ vars->ocas_time = (vars->output_time + vars->w_time + vars->add_time + vars->sort_time + vars->qp_solver_time);
+ ocas_print(vars,answerind,0,C);
+}
+
+static inline int ocas_iter(struct ocas_vars *vars,int max_nohwm)
+{
+ int Method = 1;
+ int min_nohwm = 1;
+ int skipflags[84];
+ static int new_cut[MAX_VECTORS];
+ static double2 hpfb[MAX_VECTORS];
+ int inactives[81];
+ register struct ocas_CLbuffers *ptr;
+ register double netcuts,startmilli,y,psum,pcount,nosum;
+ register int i,numfeatures,cutlen,lastanswerind,lwm=(1<<20),numactive,numthreads,answerind,*weekinds;
+ numactive = 0;
+ if ( (numfeatures= vars->numfeatures) > MAX_OCAS_FEATURES )
+ {
+ printf("numfeatures > MAX_OCAS_FEATURES\n");
+ exit(-1);
+ }
+ psum = pcount = nosum = 0;
+ {
+ //printf("c.%d mask %lx %p\n",c,contractmask,PTRS->ocas[c]);
+ memset(inactives,0,sizeof(inactives));
+ lastanswerind = TRADEBOTS_NUMANSWERS;
+ numfeatures = vars->numfeatures;
+ answerind = 0;
+ //printf("numIt.%d ocas iter.%s A.mask%lx len.%d CLspace.%p lhs.%p | vars.%p\n",vars->numIt[answerind],CONTRACTS[c_to_refc(c)],answerindmask,vars->len[answerind],vars->CLspaces[answerind],vars->lhs[answerind],vars);
+ memset(skipflags,0,sizeof(skipflags));
+ for (answerind=0; answerindCLspaces[answerind],vars->weekinds[answerind],vars->nohwm[answerind],max_nohwm);
+ if ( vars->hwmperc[answerind] != 0 )
+ {
+ nosum += vars->nohwm[answerind];
+ pcount++, psum += vars->hwmperc[answerind];
+ }
+ //printf("answerind.%d\n",answerind);
+ if ( vars->len[answerind] == 0 || vars->CLspaces[answerind] == 0 || (vars->nohwm[answerind] > min_nohwm && vars->hwmperc[answerind] > ((answerind==0) ? HWMPERC_THRESHOLD0 : HWMPERC_THRESHOLD)) )
+ {
+ inactives[answerind] = 1;
+ continue;
+ }
+ if ( vars->nohwm[answerind] < max_nohwm )
+ {
+ numactive++;
+ if ( vars->numIt[answerind]++ == 0 )
+ {
+ for (i=0; iCLspaces[answerind]->W[i] != 0 )
+ break;
+ if ( i == numfeatures )
+ skipflags[answerind] = 1;
+ }
+ ptr = vars->CLspaces[answerind];
+ weekinds = vars->weekinds[answerind];
+ //printf("start iter %p %p\n",ptr,weekinds);
+ start_ocas_iter(vars,vars->c,answerind);
+ numthreads = vars->numthreads;
+ if ( skipflags[answerind] != 0 )
+ {
+ for (i=0; ilen[answerind]; i++)
+ {
+ if ( (y= vars->answers[(weekinds[i]-vars->starti)*TRADEBOTS_NUMANSWERS + answerind]) != 0.f )
+ {
+ ptr->output_pred[i] = 0;
+ add_newcut_entry(vars,answerind,new_cut,i,weekinds[i],y);
+ }
+ }
+ fprintf(stderr,"skip %d.A%02d cuts +%d -%d, ",c_to_refc(vars->c),answerind,vars->numposcuts[answerind],vars->numnegcuts[answerind]);
+ }
+ else
+ {
+ startmilli = OS_milliseconds();
+ //printf("%s ocas_calc_outputs.A%d len.%d | numthreads.%d\n",CONTRACTS[c_to_refc(c)],answerind,vars->len[answerind],numthreads);
+ STocas_calc_outputs(vars,vars->c,answerind,ptr->output_pred,ptr->old_output,ptr->W,vars->W0[answerind],numfeatures,weekinds,vars->len[answerind]);
+ //ocas_calc_outputs(PTRS,numthreads,vars,c,answerind,ptr->output_pred,ptr->old_output,ptr->W,vars->W0[answerind],numfeatures,weekinds,vars->len[answerind]);
+ vars->output_time += (OS_milliseconds() - startmilli);
+ if ( Method != 0 )
+ {
+ startmilli = OS_milliseconds();
+ //printf("%d calc_ocas_strategy.A%d len.%d | numthreads.%d\n",c_to_refc(vars->c),answerind,vars->len[answerind],numthreads);
+ calc_ocas_strategy(vars,answerind,vars->C,numfeatures,vars->maxlen,weekinds,new_cut,ptr->W,ptr->oldW,ptr->output_pred,ptr->old_output,hpfb);
+ vars->w_time += (OS_milliseconds() - startmilli);
+ }
+ finish_ocasiter(answerind,vars,vars->C);
+ }
+ //printf("%s calc ocas_add_newcuts.A%d poscuts.%d negcuts.%d | numthreads.%d\n",CONTRACTS[c_to_refc(c)],answerind,vars->numposcuts[answerind],vars->numnegcuts[answerind],vars->numthreads);
+ startmilli = OS_milliseconds();
+ //if ( vars->nohwm[answerind] > 13 )
+ // numthreads = vars->numthreads;///MAIN_MAXCORES;
+ memset(ptr->new_a,0,sizeof(ptr->new_a));
+ //ocas_add_newcuts(PTRS,numthreads,vars,answerind,numfeatures,weekinds,new_cut,vars->numposcuts[answerind]+vars->numnegcuts[answerind],ptr->W,ptr->new_a);
+ STocas_add_newcuts(vars,answerind,numfeatures,weekinds,new_cut,vars->numposcuts[answerind]+vars->numnegcuts[answerind],ptr->W,ptr->new_a);
+ vars->add_time += (OS_milliseconds() - startmilli);
+//printf("done %d calc ocas_add_newcuts.A%d poscuts.%d negcuts.%d | good.%d bad.%d\n",c_to_refc(vars->c),answerind,vars->numposcuts[answerind],vars->numnegcuts[answerind],vars->good[answerind],vars->bad[answerind]);
+ } else inactives[answerind] = 1;//, printf("maxnohwm.%d\n",max_nohwm);
+ }
+ startmilli = OS_milliseconds();
+ for (answerind=0; answerindnumposcuts[answerind] - vars->numnegcuts[answerind]);
+ cutlen = (vars->numposcuts[answerind] + vars->numnegcuts[answerind]);
+ if ( vars->nohwm[answerind] < lwm )
+ lwm = vars->nohwm[answerind];
+ ocas_update_Lspace(vars,answerind,netcuts,cutlen,numfeatures,vars->C,0.,vars->QPSolverTolRel);
+ }
+ vars->qp_solver_time += (OS_milliseconds() - startmilli);
+ }
+ if ( pcount != 0 )
+ printf("numactive.%d %.0f | ave perf %f%% | ave nohwm %.1f\n",numactive,pcount,psum/pcount,nosum/pcount);
+ return(numactive);
+}
+
+static inline int init_ocas_vars(int numthreads,int selector,long answerindmask,struct ocas_vars *vars,int c,double C,int numfeatures,int maxlhs,int maxlen,int len,double *answerabsave,int *posA,int *negA)
+{
+ int answerind,lastanswerind,retval = 0;
+ lastanswerind = TRADEBOTS_NUMANSWERS;
+ vars->maxlen = maxlen;
+ vars->numthreads = numthreads;
+ vars->selector = selector;
+ //printf("init_ocas_vars lastanswerind.%d\n",lastanswerind);
+ for (answerind=0; answerindlen[answerind]);
+ if ( vars->len[answerind] > 0 )//&& (answerindmask == -1L || ((1L<refc = c_to_refc(c); vars->c = c; vars->C = C;
+ vars->numfeatures = numfeatures; vars->maxlhs = maxlhs;
+ if ( vars->CLspaces[answerind] == 0 )
+ vars->CLspaces[answerind] = myaligned_alloc(sizeof(*vars->CLspaces[answerind]));
+ vars->answerabsaves[answerind] = answerabsave[answerind];
+ vars->posA[answerind] = posA[answerind]; vars->negA[answerind] = negA[answerind];
+ if ( vars->lhs[answerind] == 0 )
+ vars->lhs[answerind] = myaligned_alloc(sizeof(*vars->lhs[answerind]) + numfeatures*maxlhs*sizeof(double));
+ vars->maxiters[answerind] = QPSOLVER_MINITER; vars->trn_err[answerind] = vars->len[answerind]; vars->Q_P[answerind] = 0.5*vars->sq_norm_W[answerind] + C*vars->len[answerind];
+ vars->perc[answerind] = vars->hwmperc[answerind] = vars->dist[answerind] = vars->hwmdist[answerind] = 0.; vars->numIt[answerind] = 0;
+ //printf("init.A%d %d | %p %p weekinds.%p\n",answerind,vars->len[answerind],vars->CLspaces[answerind],vars->lhs[answerind],vars->weekinds[answerind]);
+ }
+ }
+ //printf("mask.%lx init_ocas_vars selector.%d weekinds[0].%p\n",answerindmask,selector,vars->weekinds[0]);
+ return(retval);
+}
+
+void ocas_init(struct ocas_vars *vars,int32_t c,int32_t numfeatures,int32_t starti,int32_t endi)
+{
+ struct ocas_CLbuffers *ptr; struct ocas_lhsbuffers *lhs;
+ int32_t nonz,weekind,answerind; double answer,y;
+ if ( numfeatures < 0 )
+ return;
+ vars->maxlhs = MAX_OCAS_LHS;
+ vars->numfeatures = numfeatures;
+ vars->maxlen = (endi - starti + 1);
+ vars->C = 1.;
+ vars->c = c;
+ vars->TolRel = 0.01;
+ vars->TolAbs = 0.0;
+ vars->QPSolverTolRel = vars->TolRel*0.5;
+ vars->QPSolverTolAbs = vars->TolAbs*0.5;
+ vars->MaxTime = OCAS_INFINITY;
+ vars->QPBound = 0.0;
+ memset(vars->posA,0,sizeof(vars->posA));
+ memset(vars->negA,0,sizeof(vars->negA));
+ memset(vars->answeraves,0,sizeof(vars->answeraves));
+ memset(vars->answerabsaves,0,sizeof(vars->answerabsaves));
+ memset(vars->firstweekinds,0,sizeof(vars->firstweekinds));
+ vars->starti = starti;
+ vars->answers = calloc(TRADEBOTS_NUMANSWERS,sizeof(vars->answers)*vars->maxlen);
+ vars->features = calloc(vars->maxlen,sizeof(*vars->features));
+ for (answerind=0; answerindweekinds[answerind] = calloc(vars->maxlen,sizeof(*vars->weekinds[answerind]));
+ for (weekind=starti; weekind<=endi; weekind++)
+ {
+ if ( (vars->features[weekind - starti]= get_features(numfeatures,c,weekind)) == 0 )
+ continue;
+ for (answerind=0; answerindposA[answerind]+vars->negA[answerind]) >= vars->maxlen )
+ continue;
+ if ( (y= get_yval(&answer,0,weekind,c,answerind)) != 0.f )
+ {
+ vars->answers[(weekind-starti)*TRADEBOTS_NUMANSWERS + answerind] = y;
+ vars->weekinds[answerind][vars->len[answerind]++] = weekind;
+ if ( vars->posA[answerind]+vars->negA[answerind] == 0 )
+ vars->firstweekinds[answerind] = weekind;
+ vars->answeraves[answerind] += answer;
+ if ( answer > 0 )
+ {
+ vars->posA[answerind]++;
+ vars->answerabsaves[answerind] += answer;
+ }
+ else if ( answer < 0 )
+ {
+ vars->negA[answerind]++;
+ vars->answerabsaves[answerind] -= answer;
+ }
+ }
+ }
+ }
+ for (answerind=0; answerindposA[answerind]+vars->negA[answerind])) != 0 )
+ {
+ vars->answerabsaves[answerind] /= nonz;
+ vars->answeraves[answerind] /= nonz;
+ printf("A%02d.(%9.6f %d %d) ",answerind,vars->answerabsaves[answerind],vars->posA[answerind],vars->negA[answerind]);
+ }
+ init_ocas_vars(1,0,-1,vars,c,vars->C,numfeatures,MAX_OCAS_LHS,vars->maxlen,vars->maxlen,vars->answerabsaves,vars->posA,vars->negA);
+ for (answerind=0; answerindlen[answerind]);
+ lhs = vars->lhs[answerind];
+ ptr = vars->CLspaces[answerind];
+ //printf("%d.A%d call init ocas vars weekinds[0] %p numfeatures.%d (%p %p)\n",c_to_refc(vars->c),answerind,vars->weekinds[0],numfeatures,lhs,ptr);
+ if ( lhs == 0 || ptr == 0 )
+ continue;
+ vars->numlhs[answerind] = 0;//init_full_A(lhs->full_A,vars->numfeatures,c,answerind,models);
+ memset(ptr->W,0,sizeof(*ptr->W) * numfeatures);
+ memset(ptr->oldW,0,sizeof(*ptr->oldW) * numfeatures);
+ vars->W0[answerind] = vars->oldW0[answerind] = 0;
+#ifndef DISABLE_EXISTINGMODEL
+ double init_model(double *percp,double *W,double *oldW,int c,int answerind,int numfeatures);
+ vars->W0[answerind] = init_model(&vars->hwmperc[answerind],ptr->W,ptr->oldW,c,answerind,vars->numfeatures);
+ if ( _dbufave(ptr->W,numfeatures) != 0 )
+ validate_ocas_model(vars,answerind,ptr->output_pred,ptr->old_output,vars->weekinds[answerind],vars->len[answerind],ptr->W,vars->W0[answerind],numfeatures,1);
+#endif
+ //printf("%s.A%d call init ocas vars weekinds[0] %p\n",CONTRACTS[c_to_refc(c)],answerind,vars->weekinds[0]);
+ }
+ vars->output_time = vars->sort_time = vars->w_time = vars->qp_solver_time = vars->ocas_time = vars->add_time = 0;
+ vars->startweekind = starti; vars->endweekind = endi;
+}
+
+int32_t ocas_gen(int32_t c,int32_t numfeatures,int32_t starti,int32_t endi)
+{
+ int32_t i; struct ocas_vars *vars = calloc(1,sizeof(*vars));
+ ocas_init(vars,c,numfeatures,starti,endi);
+ for (i=0; i<10; i++)
+ ocas_iter(vars,3);
+ ocas_purge(vars);
+ return(0);
+}
+#endif
diff --git a/basilisk/tradebots_liquidity.c b/basilisk/tradebots_liquidity.c
new file mode 100755
index 000000000..b044accd4
--- /dev/null
+++ b/basilisk/tradebots_liquidity.c
@@ -0,0 +1,1237 @@
+/******************************************************************************
+ * Copyright © 2014-2017 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. *
+ * *
+ ******************************************************************************/
+
+// included from basilisk.c
+/*
+ In order to provide liquidity from central exchanges, we need to issue balancing trades, however to do this properly, we need to know what the desired balance is. If unspecified, then a neutral balance is assumed.
+ The liquidity_info interface is quite flexible, there is a single function liquidity_active() which returns non-zero if the LP node should respond. The model is that the liquidity_command() is used to configure the liquidity_active()'s response.
+ In order for dynamic adaptiveness to work, the liquidity_command/liquidity_active needs to interact with the balancing.
+ A simplistic default trio of functions are provided, but any level of complexity is possible with the liquidity interface.
+ */
+
+#define TRADEBOTS_NUMANSWERS 8
+#define TRADEBOTS_NUMDECAYS 8
+#define TRADEBOTS_RAWFEATURESINCR 7
+#define TRADEBOTS_MAXPAIRS 1024
+
+#define _OCAS_PLUS_INF (-log(0.0))
+double OCAS_PLUS_INF,OCAS_NEG_INF;
+
+double Tradebots_decays[TRADEBOTS_NUMDECAYS] = { 0.5, 0.666, 0.8, 0.9, 0.95, 0.99, 0.995, 0.999 };
+int32_t Tradebots_answergaps[TRADEBOTS_NUMANSWERS] = { 60, 60, 120, 120, 240, 240, 720, 720 };
+
+struct tradebot_arbentry
+{
+ char exchange[16];
+ double price,volume,profitmargin;
+ uint32_t timestamp;
+};
+
+struct tradebot_arbexchange
+{
+ char name[16];
+ struct tradebot_arbentry trades[2];
+};
+
+struct tradebot_arbpair
+{
+ char base[32],rel[32];
+ uint32_t lasttime,lastanswertime; FILE *fp;
+ int32_t numexchanges,counter,btccounter,usdcounter,cnycounter,refc;
+ double highbid,lowask,hblavolume,btcbid,btcask,btcvol,usdbid,usdask,usdvol,cnybid,cnyask,cnyvol;
+ double bidaves[TRADEBOTS_NUMDECAYS],askaves[TRADEBOTS_NUMDECAYS];
+ double bidslopes[TRADEBOTS_NUMDECAYS],askslopes[TRADEBOTS_NUMDECAYS];
+ struct tradebot_arbexchange exchanges[16];
+ uint8_t dirmasks[2],slopedirs[2];
+ char *svmpairs[TRADEBOTS_MAXPAIRS][2];
+ int32_t RTgood[TRADEBOTS_NUMANSWERS],RTbad[TRADEBOTS_NUMANSWERS],numrawfeatures,numsvmfeatures,numpairs;
+ float rawfeatures[TRADEBOTS_NUMANSWERS+64],prevrawfeatures[60 * TRADEBOTS_NUMANSWERS+64],*svms; // svms is coeffs vector[TRADEBOTS_NUMANSWERS]
+ float RTpreds[TRADEBOTS_NUMANSWERS],svmpreds[TRADEBOTS_NUMANSWERS],answers[TRADEBOTS_NUMANSWERS];
+};
+struct tradebot_arbpair Arbpairs[TRADEBOTS_MAXPAIRS],*Pair_NXTBTC,*Pair_BTCUSD,*Pair_BTCCNY;
+int32_t Tradebot_numarbpairs;
+
+struct tradebot_arbpair *tradebots_arbpair_find(char *base,char *rel)
+{
+ int32_t i;
+ for (i=0; i0; i--)
+ memcpy(&pair->prevrawfeatures[i*72],&pair->prevrawfeatures[(i-1)*72],sizeof(pair->rawfeatures));
+ memcpy(pair->prevrawfeatures,pair->rawfeatures,sizeof(pair->rawfeatures));
+ memset(pair->rawfeatures,0,sizeof(pair->rawfeatures));
+ if ( fabs(pair->highbid) < SMALLVAL || fabs(pair->lowask) < SMALLVAL )
+ return(-1);
+ ave = _pairaved(pair->highbid,pair->lowask);
+ timestamp = (uint32_t)time(NULL);
+ n = TRADEBOTS_NUMANSWERS;
+ memcpy(&pair->rawfeatures[TRADEBOTS_NUMANSWERS],×tamp,sizeof(*pair->rawfeatures)), n++;
+ pair->rawfeatures[n++] = pair->highbid;
+ pair->rawfeatures[n++] = pair->lowask;
+ pair->rawfeatures[n++] = pair->hblavolume / ave;
+ n = TRADEBOTS_RAWFEATURESINCR + TRADEBOTS_NUMANSWERS;
+ for (i=0; ibidaves[i]) < SMALLVAL || fabs(pair->askaves[i]) < SMALLVAL )
+ return(-1);
+ starti = n;
+ pair->rawfeatures[n++] = (pair->bidaves[i] / ave) - 1.;
+ pair->rawfeatures[n++] = (pair->askaves[i] / ave) - 1.;
+ pair->rawfeatures[n++] = 10000. * (pair->bidslopes[i] / ave);
+ pair->rawfeatures[n++] = 10000. * (pair->askslopes[i] / ave);
+ if ( n < starti+TRADEBOTS_RAWFEATURESINCR )
+ n = starti+TRADEBOTS_RAWFEATURESINCR;
+ }
+ if ( pair->fp != 0 )
+ {
+ if ( fwrite(pair->rawfeatures,1,sizeof(pair->rawfeatures),pair->fp) != sizeof(pair->rawfeatures) )
+ printf("fwrite error for %s/%s rawfeatures[%d]\n",pair->base,pair->rel,n);
+ else fflush(pair->fp);
+ }
+ if ( n > sizeof(pair->rawfeatures)/sizeof(*pair->rawfeatures) )
+ {
+ printf("n.%d too many for rawfeatures %d\n",n,(int32_t)(sizeof(pair->rawfeatures)/sizeof(*pair->rawfeatures)));
+ exit(-1);
+ }
+ return(n);
+}
+
+uint32_t tradebots_featureset(double *highbidp,double *lowaskp,double *avep,double *volp,double *bidaves,double *askaves,double *bidslopes,double *askslopes,float *rawfeatures)
+{
+ uint32_t timestamp; int32_t i,n,starti;
+ memcpy(×tamp,&rawfeatures[TRADEBOTS_NUMANSWERS],sizeof(timestamp));
+ n = TRADEBOTS_NUMANSWERS + 1;
+ *highbidp = rawfeatures[n++];
+ *lowaskp = rawfeatures[n++];
+ *avep = _pairaved(*highbidp,*lowaskp);
+ *volp = rawfeatures[n++];
+ //printf("[%9.6f %9.6f] vol %f t.%u\n",*highbidp,*lowaskp,*volp,timestamp);
+ n = TRADEBOTS_RAWFEATURESINCR + TRADEBOTS_NUMANSWERS;
+ for (i=0; i