Browse Source

many changes

blockexplorer tab: needs to allow to input height, blockhash or txid.
also please display images/BTC_blocks.jpg below the text as a w800 x
h400 bitmap, which is active using the mouse api

for coin management, below the active coins have a form that arbitrary
json can be input with an add button to the right that will call
"addcoin" API. this way I can test adding new coins dynamically. dont
worry if it doesnt work, just as long as it submits the json to the C
code. I am pretty sure I need to do some debugging of this

peers management is not working for me at all. maybe it is due to bad
internet. On initialization you need to read in the
confs/BTCD_peers.txt from the native filesystem and save it into the
chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is
only to be done if there isnt already such a file inside chrome. if
there is, only do it upon a button invoked by the user. the reason is
that the pexe is updating this file with the latest. Maybe it is nice
to have an "extract" button that will copy out from the chrome storage
into the native filesystem. There is also the manifest issue about
localstorage vs chrome.localstorage. not sure what is needed to be
done, but certainly a priority to get it so everything works as a
chrome app. I know before it was making ramchain files inside the
chrome filesystem, so it is probably things the GUI is doing. maybe in
the settings tab, which has obsolete stuff that can be removed.

anyway, the issue about files existing in the native filesystem ->
chrome and optionally extracting them is an issue for the confs files
and .html template files used to autogenerate the port7778, maybe other
files are affected. i think we need a way to have a list of hardcoded
files that are just copied into chrome on startup if they dont exist
already (or if possible copy over if the native version is bigger?) and
buttons to extract them

for debug tab:
THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything);
TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile);
at the top of page a way to put in passphrase and optional
permanentfile along with arbitrary json. The standard form template has
no easy way to describe to pass in everything as it is oriented to
specific fields. but the encryptjson API saves all the fields, so the
arbitrary json from the form needs to be combined at the same level as
the "agent", "method", etc. I know, not the best, but internally it
makes it easier. so
{"agent":"SuperNET","method":"encryptjson","passphrase":"<passphrase>","
permanentfile":"<filename>","fromform":"valuefromform","fromform2":"valu
efromform2",...rest of form at top level}

then this will save it into a file with crazy number (it is a hash like
txid) but given the same passphrase and filename, it will regenerate
this hash so you dont actually have to store it, but it helps during
debugging.
for the filename, we must warn quite strongly to the user that if the
file is ever lost or even changed in any way that the data will not be
recoverable. also best to not allow the user to specify a file that
does not exist. I think at this point chrome app version gets a bit
tricky. we could simply push the native file into the chrome storage,
but then an attacker who gets access to the computer could just get a
list of these files and it really wont be much protection. So that
means if a filename is specified, it needs to be copied into the chrome
space, then immediately deleted... ok, this seems like not a good
approach. let us make it so that the permanentfile option is not
available from the chrome app, but only if the native version is
running. that way we sidestep the issue of the pexe not having access
to the specified file.

Speaking of native vs pexe, on the startup page we should have a radio
button that allows the user to select which the GUI will talk to. It
should default based on a self test to the more likely value, but it is
possible that the user wants to use the native  version, even if the
pexe is running.

another thing to have on the startup page is a simple login:
THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle);
ZERO_ARGS(SuperNET,logout);
ZERO_ARGS(SuperNET,activehandle);
the handle is a human readable name that is associated with the
passphrase/permanentfile. There can only be one active account (though
it will be possible to associate different accounts with tradebots).
use the activehandle API to find out who is logged in and the
associated addresses and pubkeys

The above is not yet tested so if it doesnt work, dont fret, just let
me know. Once set the handle can be displayed in various places to let
the user know which account is logged in. The standard 12 dictionary
word passphrases should be used, but any string can be sent in as the
password

for Pangea:
INT_AND_ARRAY(pangea,host,minplayers,params);
ZERO_ARGS(pangea,lobby);
HASH_AND_STRING(pangea,join,tablehash,handle);
HASH_AND_INT(pangea,buyin,tablehash,numchips);
HASH_ARG(pangea,start,tablehash); // by host only

HASH_ARG(pangea,status,tablehash);

HASH_ARG(pangea,call,tablehash);
HASH_ARG(pangea,check,tablehash);
HASH_AND_INT(pangea,raise,tablehash,numchips);
HASH_AND_INT(pangea,bet,tablehash,numchips);
HASH_ARG(pangea,fold,tablehash);

HASH_AND_STRING(pangea,mode,tablehash,modestr);
HASH_ARG(pangea,history,tablehash);
HASH_AND_INT(pangea,handhistory,tablehash,hand);

The first thing that is done is a "host" by any node. the "params"
should be an arbitrary json (like encryptjson) as it needs to be at the
top level and it has quite a few different parameters still subject to
change. The lobby API will just display all the hosted tables.
once a table exists, players can join and then buyin. the buyin is
denominated in chips, each chip's value is determined by the host's
initial parameters.

once there are enough players joined with adequate buyin's verified,
the host will be able to do a start. if done before it will
(eventually) give an error. for now it will just proceed.
The host and players that have joined a tablehash, need to do regular
status calls to see if the game has started. Probably just once per 5
or even 10 seconds is fine before the start. Once the game starts (the
status will have this info) then once per second polling is needed.

Then when it is your turn (as indicated by status) you need to do one
of the 5 actions (fold, call, check, raise, bet). do not worry if you
dont understand what all these do, just allow the user to do any of
these. I guess it is possible to submit it ahead of time. I will
support internally remembering the most recent action done prior to it
being your turn. once it is your turn and an action is sent to the
table, it is too late to change.

The last API calls are for getting handhistory where hand is 0 to N-1,
being the numbering of the hands played at that table. if just history,
all the history for all hands at the table is coming back, so it could
be quite big. probably  I will make it a summary, but for the GUI just
display the returned values.
the mode is to change some poker specific modes, so just allow there to
be a string entered.
do not worry about understanding the pokerness of the API, just the
overall flow:

host -> creates, join/buyin -> fills up player slots, start -> starts
the game
status -> to determine when the game starts (or if it is cancelled) and
once started
actions -> game specific but basically just (button + arg) that is the
user input
results are via status for current game and history for past ones

please try to do the above logic in a generic way so it can be reused
for other games. The basic flow should be the same for almost all
multiplayer turn based games and even for multiplayer realtime games

For InstantDEX:
on the apikeypair/userid there needs to be two modes. one for when
there is no stored apikey and the current form is fine, just need to
make it wider as most apikeys are quite long. Now once there is an
apikey saved all that is needed is the passphrase to unlock it. So here
is where the encrptjson/decryptjson is used. When saving the apikey for
the first time, it can be:
a) not saved -> nothing extra to do
b) saved without password -> you can just save to a file and use it to
load it back in. use confs dir confs/instantdex.exchange.api or
something like that
c) saved with password (optional filename for native) -> probably best
to save in the confs dir to indicate that there is an encrypted file
for this, so just that and not the actual passphrase in the file

with the above, when the exchange is selected, you can see if the confs
file exists and if it has the plaintext, just populate the field, if
not, then indicate that a passphrase is needed. if the user provides
the passphrase, then decryptjson and populate the fields and autosubmit.

A special case is to encrypt the apikeys with the passphrase used when
logging in. This is only available if the checkbox to "remember
passphrase during session" is set on the main iguana login screen. (i
forgot to mention that checkbox!) So the login passphrase is stored in
memory, then the GUI simply uses that + encryptjson for
storing/decrypting. I would imagine that storing in the confs file that
it is encrypted using "handle"'s account login might be a good way to
differentiate between this mode of password usage.

OK, so we now have the insecure plaintext, the decent using handle's
passphrase and paranoid different passphrase for each exchange (with
additional permanentfile for native versions)

"SUPPORT" -> "SUPPORTS" just a typo
and "allpairs" API is missing from the selection

Might as well add a "tradebots" tab:
THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission);
STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission);
THREE_STRINGS(tradebot,unmonitor,exchange,base,rel);
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr
ice,volume,duration);
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price,
volume,duration);
STRING_ARG(tradebot,activebots,exchange);
TWO_STRINGS(tradebot,status,exchange,botid);
TWO_STRINGS(tradebot,pause,exchange,botid);
TWO_STRINGS(tradebot,stop,exchange,botid);
TWO_STRINGS(tradebot,resume,exchange,botid);

the above are API for exchange specific bots, most should be
self-explanatory. bots are created via "accumulate" or "divest" API
call. it returns botid. once created, you can do status, pause, stop,
resume to a botid. and an activebots API call lists all the active bots
for an exchange.

duration is in seconds

the "monitor" API starts background monitoring of a specific base/rel,
"unmonitor" stops this. "monitorall" just does a  monitor to the entire
list of "allpairs" for that exchange. Keep in mind that doing a
monitorall will not add load to an exchange as the request to each
exchange is governed by pollgap, but if you have 3 things monitored, it
will take 3*pollgap + time each one takes to execute. and if N are
monitored it is N*pollgap + time of each, with the "time of each"
possibly taking a very long time.

And one final request for today: Bitmap tab.
It should be an active bitmap using mouse api. either a dropdown to
select the bitmap or a form entry. then the rest of the page (resize
the bitmap to the page size) being the active bitmap. So on  a small
screen the bitmap is smaller x/y dimensions and larger on larger
screens. plz make sure the proper dimensions are communicated to the
pexe via API if it ever is changed.

@vineet.bhargav86: I changed the "passphrase" fieldname to "password"
for the encryptjson/decryptjson related API. The reason is that the
password is like a wallet password and is only local, so it doesnt need
to be as high entropy as passphrase. I also added a field to the login
API as I realized that the 12 word "passphrase" is the payload and
usually wont be sent in:
FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase);
using "abiglongpassword" for the passphrase ->
{"pubkey":"6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906
209","RS":"NXT-KGV9-DXX8-TM86-DXR96","NXT":"12834974574569896807","btcpu
bkey":"024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c
8","rmd160":"33453c24914db7b77069b7ea24df44f6be145938","BTC":"15g6QK2dSd
iW9ZTQEnnJxKrSph6uP7uU23","BTCD":"RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC","r
esult":"success","handle":"test","tag":"14805226009240621255"}
and if you use that to log into NXT, it gives the same address. The BTC
and BTCD addresses are all derived from the same privkey so they are
all interchangeable with the NXT address. The user can therefore select
which coin's addressing they are most comfortable with

I also added an "allin" action API for pangea. all the action API will
autocalculate the number of chips if passed in 0 for numchips

***************** security issue ********
please dont use the GET URL method when dealing with passphrase!!!
Those URL's tend to get logged and available in browser histories. so
anything dealing with the actual passphrase needs to use the postCall
form or POST
release/v0.1
jl777 9 years ago
parent
commit
6d4dbcbaa9
  1. 16
      crypto777/OS_portable.h
  2. 4
      crypto777/OS_time.c
  3. 9
      crypto777/iguana_OS.c
  4. 93
      crypto777/iguana_utils.c
  5. 185
      iguana/SuperNET.c
  6. 6
      iguana/SuperNET.h
  7. 68
      iguana/SuperNET_keys.c
  8. 110
      iguana/exchanges/PAX.c
  9. 50
      iguana/exchanges/bitcoin.c
  10. 52
      iguana/exchanges/jumblr.c
  11. 123
      iguana/exchanges/nxtae.c
  12. 16
      iguana/exchanges/truefx.c
  13. 94
      iguana/exchanges/unconf.c
  14. 8
      iguana/exchanges777.h
  15. 2
      iguana/iguana.sources
  16. 10
      iguana/iguana777.c
  17. 101
      iguana/iguana_exchanges.c
  18. 9
      iguana/iguana_instantdex.c
  19. 8
      iguana/iguana_json.c
  20. 34
      iguana/iguana_rpc.c
  21. 38
      iguana/iguana_tradebots.c
  22. 2
      iguana/main.c
  23. 7
      iguana/pangea777.h
  24. 193
      iguana/pangea_api.c
  25. 42
      iguana/pangea_bets.c
  26. 4
      iguana/pangea_hand.c
  27. 30
      iguana/pangea_json.c
  28. 689
      iguana/peggy.c
  29. 375
      iguana/peggy.h
  30. 325
      iguana/peggy_accts.c
  31. 829
      iguana/peggy_consensus.c
  32. 837
      iguana/peggy_price.c
  33. 243
      iguana/peggy_ramkv.c
  34. 812
      iguana/peggy_serdes.c
  35. 769
      iguana/peggy_tx.c
  36. 474
      iguana/peggy_txind.c
  37. 767
      iguana/peggy_update.c
  38. BIN
      iguana/pnacl/Release/iguana.pexe
  39. 27
      includes/iguana_apideclares.h
  40. 4
      includes/iguana_apidefs.h
  41. 2
      includes/iguana_apiundefs.h
  42. 90
      prices/prices777.c

16
crypto777/OS_portable.h

@ -43,6 +43,9 @@
#include <sys/socket.h>
#define closesocket close
#endif
#ifndef MIN
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
#endif
#include "../includes/libgfshare.h"
#include "../includes/utlist.h"
@ -74,6 +77,10 @@ int32_t ramcoder_decompress(uint8_t *data,int32_t maxlen,uint8_t *bits,uint32_t
int32_t ramcoder_compress(uint8_t *bits,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 seed);
uint64_t hconv_bitlen(uint64_t bitlen);
void _init_HUFF(HUFF *hp,int32_t allocsize,void *buf);
int32_t hgetbit(HUFF *hp);
int32_t hputbit(HUFF *hp,int32_t bit);
uint64_t hconv_bitlen(uint64_t bitlen);
int32_t hseek(HUFF *hp,int32_t offset,int32_t mode);
#define SCRIPT_OPRETURN 0x6a
#define GENESIS_ACCT "1739068987193023818" // NXT-MRCC-2YLS-8M54-3CMAJ
@ -179,7 +186,7 @@ int32_t expand_datenum(char *date,int32_t datenum);
int32_t calc_datenum(int32_t year,int32_t month,int32_t day);
int32_t ecb_decrdate(int32_t *yearp,int32_t *monthp,int32_t *dayp,char *date,int32_t datenum);
int32_t conv_date(int32_t *secondsp,char *buf);
uint64_t OS_conv_datenum(int32_t datenum,int32_t hour,int32_t minute,int32_t second);
uint32_t OS_conv_datenum(int32_t datenum,int32_t hour,int32_t minute,int32_t second);
int32_t OS_conv_unixtime(struct tai *t,int32_t *secondsp,time_t timestamp);
double OS_milliseconds();
@ -253,6 +260,9 @@ int32_t strsearch(char *strs[],int32_t num,char *name);
int32_t OS_getline(int32_t waitflag,char *line,int32_t max,char *dispstr);
int32_t sort64s(uint64_t *buf,uint32_t num,int32_t size);
int32_t revsort64s(uint64_t *buf,uint32_t num,int32_t size);
int decode_base32(uint8_t *token,uint8_t *tokenstr,int32_t len);
int init_base32(char *tokenstr,uint8_t *token,int32_t len);
char *OS_mvstr();
long _stripwhite(char *buf,int accept);
int32_t is_DST(int32_t datenum);
@ -261,9 +271,10 @@ int32_t expand_datenum(char *date,int32_t datenum);
int32_t calc_datenum(int32_t year,int32_t month,int32_t day);
int32_t ecb_decrdate(int32_t *yearp,int32_t *monthp,int32_t *dayp,char *date,int32_t datenum);
int32_t conv_date(int32_t *secondsp,char *buf);
uint64_t OS_conv_datenum(int32_t datenum,int32_t hour,int32_t minute,int32_t second);
uint32_t OS_conv_datenum(int32_t datenum,int32_t hour,int32_t minute,int32_t second);
int32_t OS_conv_unixtime(struct tai *t,int32_t *secondsp,time_t timestamp);
int32_t btc_coinaddr(char *coinaddr,uint8_t addrtype,char *pubkeystr);
int32_t btc_convaddr(char *hexaddr,char *addr58);
uint64_t RS_decode(char *rs);
int32_t RS_encode(char *rsaddr,uint64_t id);
@ -348,6 +359,7 @@ int32_t btc_priv2pub(uint8_t pubkey[33],uint8_t privkey[32]);
extern char *Iguana_validcommands[];
extern bits256 GENESIS_PUBKEY,GENESIS_PRIVKEY;
extern char NXTAPIURL[];
extern int32_t smallprimes[168],Debuglevel;
#endif

4
crypto777/OS_time.c

@ -520,7 +520,7 @@ int32_t extract_datenum(int32_t *yearp,int32_t *monthp,int32_t *dayp,int32_t dat
else return(-1);
}
uint64_t OS_conv_datenum(int32_t datenum,int32_t hour,int32_t minute,int32_t second) // datenum+H:M:S -> unix time
uint32_t OS_conv_datenum(int32_t datenum,int32_t hour,int32_t minute,int32_t second) // datenum+H:M:S -> unix time
{
int32_t year,month,day; struct tai t; struct taitime ct;
if ( 1 )
@ -530,7 +530,7 @@ uint64_t OS_conv_datenum(int32_t datenum,int32_t hour,int32_t minute,int32_t sec
ct = taitime_set(taidate_set(year,month,day),hour,minute,second);
t = taitime2tai(ct);
//char str[65]; printf("conv.(y%d m%d d%d %d:%d:%d) %s\n",year,month,day,hour,minute,second,tai_str(str,t));
return(tai2utc(t));//tai2utime(t)+788250398LL - 4294967296LL);
return((uint32_t)tai2utc(t));//tai2utime(t)+788250398LL - 4294967296LL);
}
return(0);
}

9
crypto777/iguana_OS.c

@ -24,6 +24,15 @@
#define MAP_FILE 0
#endif
char *OS_mvstr()
{
#ifdef __WIN32
return("rename");
#else
return("mv");
#endif
}
void OS_randombytes(unsigned char *x,long xlen)
{
OS_portable_randombytes(x,xlen);

93
crypto777/iguana_utils.c

@ -15,6 +15,27 @@
#include "../iguana/iguana777.h"
int32_t smallprimes[168] =
{
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
947, 953, 967, 971, 977, 983, 991, 997
};
bits256 bits256_doublesha256(char *hashstr,uint8_t *data,int32_t datalen)
{
bits256 hash,hash2; int32_t i;
@ -880,6 +901,78 @@ int32_t RS_encode(char *rsaddr,uint64_t id)
return(0);
}
uint64_t conv_acctstr(char *acctstr)
{
uint64_t nxt64bits = 0;
int32_t len;
if ( acctstr != 0 )
{
if ( (len= is_decimalstr(acctstr)) > 0 && len < 24 )
nxt64bits = calc_nxt64bits(acctstr);
else if ( strncmp("NXT-",acctstr,4) == 0 )
{
nxt64bits = RS_decode(acctstr);
//nxt64bits = conv_rsacctstr(acctstr,0);
}
}
return(nxt64bits);
}
int32_t base32byte(int32_t val)
{
if ( val < 26 )
return('A' + val);
else if ( val < 32 )
return('2' + val - 26);
else return(-1);
}
int32_t unbase32(char c)
{
if ( c >= 'A' && c <= 'Z' )
return(c - 'A');
else if ( c >= '2' && c <= '7' )
return(c - '2' + 26);
else return(-1);
}
int init_base32(char *tokenstr,uint8_t *token,int32_t len)
{
int32_t i,j,n,val5,offset = 0;
for (i=n=0; i<len; i++)
{
for (j=val5=0; j<5; j++,offset++)
if ( GETBIT(token,offset) != 0 )
SETBIT(&val5,offset);
tokenstr[n++] = base32byte(val5);
}
tokenstr[n] = 0;
return(n);
}
int decode_base32(uint8_t *token,uint8_t *tokenstr,int32_t len)
{
int32_t i,j,n,val5,offset = 0;
for (i=n=0; i<len; i++)
{
if ( (val5= unbase32(tokenstr[i])) >= 0 )
{
for (j=val5=0; j<5; j++,offset++)
{
if ( GETBIT(&val5,j) != 0 )
SETBIT(token,offset);
else CLEARBIT(token,offset);
}
} else return(-1);
}
while ( (offset & 7) != 0 )
{
CLEARBIT(token,offset);
offset++;
}
return(offset);
}
void calc_hexstr(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len)
{
init_hexbytes_noT(hexstr,(void *)msg,len+1);

185
iguana/SuperNET.c

@ -878,11 +878,53 @@ void SuperNET_parsepeers(struct supernet_info *myinfo,cJSON *array,int32_t n,int
}
}
cJSON *SuperNET_rosettajson(bits256 privkey,int32_t showprivs)
{
uint8_t rmd160[20],pub[33],flag = 0; uint64_t nxt64bits; bits256 pubkey;
char str2[41],wifbuf[64],addr[64],str[128]; cJSON *retjson;
pubkey = acct777_pubkey(privkey);
nxt64bits = acct777_nxt64bits(pubkey);
retjson = cJSON_CreateObject();
jaddbits256(retjson,"pubkey",pubkey);
RS_encode(str,nxt64bits);
jaddstr(retjson,"RS",str);
jadd64bits(retjson,"NXT",nxt64bits);
btc_priv2pub(pub,privkey.bytes);
init_hexbytes_noT(str,pub,33);
jaddstr(retjson,"btcpubkey",str);
calc_OP_HASH160(str2,rmd160,str);
jaddstr(retjson,"rmd160",str2);
if ( btc_coinaddr(addr,0,str) == 0 )
{
jaddstr(retjson,"BTC",addr);
if ( flag != 0 )
{
btc_priv2wif(wifbuf,privkey.bytes,0x80);
jaddstr(retjson,"BTCwif",wifbuf);
}
}
if ( btc_coinaddr(addr,60,str) == 0 )
{
jaddstr(retjson,"BTCD",addr);
if ( flag != 0 )
{
btc_priv2wif(wifbuf,privkey.bytes,0xbc);
jaddstr(retjson,"BTCDwif",wifbuf);
}
}
if ( flag != 0 )
jaddbits256(retjson,"privkey",privkey);
return(retjson);
}
#include "../includes/iguana_apidefs.h"
HASH_ARG(SuperNET,priv2pub,privkey)
{
cJSON *retjson = cJSON_CreateObject(); bits256 pubkey;
cJSON *retjson; bits256 pubkey;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
retjson = cJSON_CreateObject();
crypto_box_priv2pub(pubkey.bytes,privkey.bytes);
jaddbits256(retjson,"result",pubkey);
return(jprint(retjson,1));
@ -890,7 +932,10 @@ HASH_ARG(SuperNET,priv2pub,privkey)
ZERO_ARGS(SuperNET,keypair)
{
cJSON *retjson = cJSON_CreateObject(); bits256 pubkey,privkey;
cJSON *retjson; bits256 pubkey,privkey;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
retjson = cJSON_CreateObject();
crypto_box_keypair(pubkey.bytes,privkey.bytes);
jaddstr(retjson,"result","generated keypair");
jaddbits256(retjson,"privkey",privkey);
@ -901,6 +946,8 @@ ZERO_ARGS(SuperNET,keypair)
TWOHASHES_AND_STRING(SuperNET,decipher,privkey,srcpubkey,cipherstr)
{
int32_t cipherlen=0,msglen; char *retstr; cJSON *retjson; void *ptr = 0; uint8_t *cipher,*message,space[8192];
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( cipherstr != 0 )
cipherlen = (int32_t)strlen(cipherstr) >> 1;
if ( cipherlen < crypto_box_NONCEBYTES )
@ -924,6 +971,8 @@ TWOHASHES_AND_STRING(SuperNET,cipher,privkey,destpubkey,message)
{
cJSON *retjson; char *retstr,*hexstr,space[8129]; uint8_t space2[8129];
uint8_t *cipher; int32_t cipherlen,onetimeflag; bits256 origprivkey; void *ptr = 0;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (cipher= SuperNET_ciphercalc(&ptr,&cipherlen,&privkey,&destpubkey,(uint8_t *)message,(int32_t)strlen(message)+1,space2,sizeof(space2))) != 0 )
{
if ( cipherlen > sizeof(space)/2 )
@ -973,8 +1022,10 @@ bits256 SuperNET_pindecipher(IGUANA_ARGS,char *pin,char *privcipher)
THREE_STRINGS(SuperNET,rosetta,passphrase,pin,showprivkey)
{
uint8_t rmd160[20],pub[33],flag = 0; uint64_t nxt64bits; bits256 check,privkey,pubkey,pinpriv,pinpub;
char str2[41],wifbuf[64],addr[64],str[128],privcipher[512],*privcipherstr,*cstr; cJSON *retjson;
uint8_t flag = 0; uint64_t nxt64bits; bits256 check,privkey,pubkey,pinpriv,pinpub;
char str[128],privcipher[512],*privcipherstr,*cstr; cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
nxt64bits = conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
if ( showprivkey != 0 && strcmp(showprivkey,"yes") == 0 )
flag = 1;
@ -990,40 +1041,8 @@ THREE_STRINGS(SuperNET,rosetta,passphrase,pin,showprivkey)
} else printf("error parsing cipher retstr.(%s)\n",cstr);
free(cstr);
} else printf("error SuperNET_cipher null return\n");
retjson = cJSON_CreateObject();
retjson = SuperNET_rosettajson(privkey,flag);
jaddstr(retjson,"privcipher",privcipher);
jaddbits256(retjson,"pubkey",pubkey);
RS_encode(str,nxt64bits);
jaddstr(retjson,"RS",str);
jadd64bits(retjson,"NXT",nxt64bits);
btc_priv2pub(pub,privkey.bytes);
init_hexbytes_noT(str,pub,33);
jaddstr(retjson,"btcpubkey",str);
calc_OP_HASH160(str2,rmd160,str);
jaddstr(retjson,"rmd160",str2);
if ( btc_coinaddr(addr,0,str) == 0 )
{
jaddstr(retjson,"BTC",addr);
btc_priv2wif(wifbuf,privkey.bytes,0x80);
if ( flag != 0 )
jaddstr(retjson,"BTCwif",wifbuf);
}
if ( btc_coinaddr(addr,60,str) == 0 )
{
jaddstr(retjson,"BTCD",addr);
btc_priv2wif(wifbuf,privkey.bytes,0xbc);
if ( flag != 0 )
jaddstr(retjson,"BTCDwif",wifbuf);
}
if ( btc_coinaddr(addr,5,str) == 0 )
{
jaddstr(retjson,"VPN",addr);
btc_priv2wif(wifbuf,privkey.bytes,0xbc);
if ( flag != 0 )
jaddstr(retjson,"VPNwif",wifbuf);
}
if ( flag != 0 )
jaddbits256(retjson,"privkey",privkey);
check = SuperNET_pindecipher(IGUANA_CALLARGS,pin,privcipher);
if ( memcmp(check.bytes,privkey.bytes,sizeof(check)) != 0 )
{
@ -1040,6 +1059,8 @@ THREE_STRINGS(SuperNET,rosetta,passphrase,pin,showprivkey)
STRING_ARG(SuperNET,broadcastcipher,message)
{
bits256 zero;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
memset(zero.bytes,0,sizeof(zero));
return(SuperNET_cipher(IGUANA_CALLARGS,zero,zero,message));
}
@ -1047,6 +1068,8 @@ STRING_ARG(SuperNET,broadcastcipher,message)
STRING_ARG(SuperNET,broadcastdecipher,message)
{
bits256 zero;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
memset(zero.bytes,0,sizeof(zero));
return(SuperNET_decipher(IGUANA_CALLARGS,zero,zero,message));
}
@ -1054,6 +1077,8 @@ STRING_ARG(SuperNET,broadcastdecipher,message)
HASH_AND_STRING(SuperNET,multicastcipher,pubkey,message)
{
bits256 zero;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
memset(zero.bytes,0,sizeof(zero));
return(SuperNET_cipher(IGUANA_CALLARGS,zero,pubkey,message));
}
@ -1061,6 +1086,8 @@ HASH_AND_STRING(SuperNET,multicastcipher,pubkey,message)
HASH_AND_STRING(SuperNET,multicastdecipher,privkey,cipherstr)
{
bits256 zero;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
memset(zero.bytes,0,sizeof(zero));
return(SuperNET_decipher(IGUANA_CALLARGS,privkey,zero,cipherstr));
}
@ -1122,17 +1149,23 @@ TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(SuperNET,DHT,hexmsg,destip,categoryhash,sub
HASH_AND_STRING(SuperNET,saveconf,wallethash,confjsonstr)
{
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
return(clonestr("{\"result\":\"saveconf here\"}"));
}
HASH_ARRAY_STRING(SuperNET,layer,mypriv,otherpubs,str)
{
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
return(clonestr("{\"result\":\"layer encrypt here\"}"));
}
TWO_STRINGS(SuperNET,categoryhashes,category,subcategory)
{
bits256 categoryhash,subhash; cJSON *retjson = cJSON_CreateObject();
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
categoryhash = calc_categoryhashes(&subhash,category,subcategory);
jaddstr(retjson,"result","category hashes calculated");
jaddbits256(retjson,"categoryhash",categoryhash);
@ -1143,6 +1176,8 @@ TWO_STRINGS(SuperNET,categoryhashes,category,subcategory)
TWO_STRINGS(SuperNET,subscribe,category,subcategory)
{
bits256 categoryhash,subhash;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
categoryhash = calc_categoryhashes(&subhash,category,subcategory);
if ( category_subscribe(myinfo,categoryhash,subhash) != 0 )
return(clonestr("{\"result\":\"subscribed\"}"));
@ -1152,6 +1187,8 @@ TWO_STRINGS(SuperNET,subscribe,category,subcategory)
TWO_STRINGS(SuperNET,gethexmsg,category,subcategory)
{
bits256 categoryhash,subhash; struct category_msg *m; char *hexstr; cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
categoryhash = calc_categoryhashes(&subhash,category,subcategory);
if ( (m= category_gethexmsg(myinfo,categoryhash,subhash)) != 0 )
{
@ -1167,6 +1204,8 @@ TWO_STRINGS(SuperNET,gethexmsg,category,subcategory)
THREE_STRINGS(SuperNET,posthexmsg,category,subcategory,hexmsg)
{
bits256 categoryhash,subhash;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
categoryhash = calc_categoryhashes(&subhash,category,subcategory);
category_posthexmsg(myinfo,categoryhash,subhash,hexmsg,tai_now(),remoteaddr);
return(clonestr("{\"result\":\"posted message\"}"));
@ -1175,6 +1214,8 @@ THREE_STRINGS(SuperNET,posthexmsg,category,subcategory,hexmsg)
THREE_STRINGS(SuperNET,announce,category,subcategory,message)
{
bits256 categoryhash,subhash;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
categoryhash = calc_categoryhashes(&subhash,category,subcategory);
return(SuperNET_categorymulticast(myinfo,0,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext")));
}
@ -1182,6 +1223,8 @@ THREE_STRINGS(SuperNET,announce,category,subcategory,message)
THREE_STRINGS(SuperNET,survey,category,subcategory,message)
{
bits256 categoryhash,subhash;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
categoryhash = calc_categoryhashes(&subhash,category,subcategory);
return(SuperNET_categorymulticast(myinfo,1,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext")));
}
@ -1214,4 +1257,72 @@ INT_ARG(SuperNET,utc2utime,utc)
return(jprint(retjson,1));
}
ZERO_ARGS(SuperNET,logout)
{
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
memset(myinfo->persistent_priv.bytes,0,sizeof(myinfo->persistent_priv));
memset(myinfo->myaddr.persistent.bytes,0,sizeof(myinfo->myaddr.persistent));
memset(myinfo->handle,0,sizeof(myinfo->handle));
memset(myinfo->myaddr.NXTADDR,0,sizeof(myinfo->myaddr.NXTADDR));
myinfo->myaddr.nxt64bits = 0;
return(clonestr("{\"result\":\"logged out\"}"));
}
ZERO_ARGS(SuperNET,activehandle)
{
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
retjson = SuperNET_rosettajson(myinfo->persistent_priv,0);
jaddstr(retjson,"result","success");
jaddstr(retjson,"handle",myinfo->handle);
return(jprint(retjson,1));
}
FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase)
{
char *str,*decryptstr = 0; cJSON *argjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( bits256_nonz(myinfo->persistent_priv) != 0 && (str= SuperNET_logout(IGUANA_CALLARGS)) != 0 )
free(str);
if ( handle != 0 )
safecopy(myinfo->handle,handle,sizeof(myinfo->handle));
if ( (passphrase == 0 || passphrase[0] == 0) && (decryptstr= SuperNET_decryptjson(IGUANA_CALLARGS,password,permanentfile)) != 0 )
{
if ( (argjson= cJSON_Parse(decryptstr)) != 0 )
{
printf("decrypted.(%s)\n",decryptstr);
free(decryptstr);
if ( (passphrase= jstr(argjson,"passphrase")) != 0 )
{
SuperNET_setkeys(myinfo,passphrase,(int32_t)strlen(passphrase),1);
free_json(argjson);
return(SuperNET_activehandle(IGUANA_CALLARGS));
}
else
{
free_json(argjson);
return(clonestr("{\"error\":\"cant find passphrase in decrypted json\"}"));
}
}
else
{
free(decryptstr);
return(clonestr("{\"error\":\"cant parse decrypted json\"}"));
}
}
if ( passphrase != 0 && passphrase[0] != 0 )
{
SuperNET_setkeys(myinfo,passphrase,(int32_t)strlen(passphrase),1);
if ( (str= SuperNET_encryptjson(IGUANA_CALLARGS,password,permanentfile,passphrase)) != 0 )
free(str);
return(SuperNET_activehandle(IGUANA_CALLARGS));
}
else return(clonestr("{\"error\":\"need passphrase\"}"));
printf("logged into (%s) %s %s\n",myinfo->myaddr.NXTADDR,myinfo->myaddr.BTC,myinfo->myaddr.BTCD);
return(SuperNET_activehandle(IGUANA_CALLARGS));
}
#include "../includes/iguana_apiundefs.h"

6
iguana/SuperNET.h

@ -70,7 +70,7 @@ struct supernet_address
{
bits256 pubkey,iphash,persistent;
uint32_t selfipbits,myipbits; int32_t confirmed,totalconfirmed; uint64_t nxt64bits;
char NXTADDR[32];
char NXTADDR[32],BTC[64],BTCD[64];
};
struct supernet_info
@ -86,6 +86,7 @@ struct supernet_info
struct nn_pollfd pfd[SUPERNET_MAXAGENTS]; //struct relay_info active;
struct supernet_agent agents[SUPERNET_MAXAGENTS]; queue_t acceptQ; int32_t numagents,numexchanges;
struct exchange_info *tradingexchanges[SUPERNET_MAXEXCHANGES];
char handle[1024];
};
/*struct supernet_endpoint
@ -118,7 +119,7 @@ struct category_info
extern struct category_info *Categories;
struct category_msg { struct queueitem DL; struct tai t; uint64_t remoteipbits; int32_t len; uint8_t msg[]; };
struct exchange_quote { uint64_t satoshis,orderid,offerNXT; double price,volume; uint32_t timestamp,val; };
struct exchange_quote { uint64_t satoshis,orderid,offerNXT,exchangebits; double price,volume; uint32_t timestamp,val; };
void expand_epbits(char *endpoint,struct endpoint epbits);
struct endpoint calc_epbits(char *transport,uint32_t ipbits,uint16_t port,int32_t type);
@ -162,6 +163,7 @@ struct category_chain *category_chain_functions(struct supernet_info *myinfo,bit
void category_init(struct supernet_info *myinfo);
char *SuperNET_keysinit(struct supernet_info *myinfo,char *jsonstr);
double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *sortbuf,int32_t max,double *totalvolp,char *base,char *rel,double volume,cJSON *argjson);
void SuperNET_setkeys(struct supernet_info *myinfo,void *pass,int32_t passlen,int32_t dosha256);
#endif

68
iguana/SuperNET_keys.c

@ -28,7 +28,7 @@ bits256 SuperNET_wallet2priv(char *wallet2fname,bits256 wallethash)
{
char *wallet2str; uint32_t r,i,crc; long allocsize; bits256 wallet2priv;
wallet2priv = GENESIS_PRIVKEY;
if ( (wallet2str= OS_filestr(&allocsize,wallet2fname)) != 0 )
if ( wallet2fname[0] != 0 && (wallet2str= OS_filestr(&allocsize,wallet2fname)) != 0 )
{
r = crc = calc_crc32(0,wallet2str,(int32_t)allocsize);
r %= 32;
@ -37,7 +37,8 @@ bits256 SuperNET_wallet2priv(char *wallet2fname,bits256 wallethash)
vcalc_sha256(0,wallet2priv.bytes,(void *)wallet2str,(int32_t)allocsize);
free(wallet2str);
//char str[65]; printf("wallet2priv.(%s) from.(%s) crc.%u and passphrase r.%d len.%ld\n",bits256_str(str,wallet2priv),wallet2fname,crc,r,allocsize);
} else printf("SuperNET_wallet2priv cant open (%s)\n",wallet2fname);
} else if ( wallet2fname[0] != 0 )
printf("SuperNET_wallet2priv cant open (%s)\n",wallet2fname);
return(wallet2priv);
}
@ -58,7 +59,7 @@ char *SuperNET_parsemainargs(struct supernet_info *myinfo,bits256 *wallethashp,b
printf("ARGSTR.(%s)\n",argjsonstr);
if ( jobj(json,"numhelpers") != 0 )
IGUANA_NUMHELPERS = juint(json,"numhelpers");
if ( (secret= jstr(json,"wallet")) != 0 )
if ( (secret= jstr(json,"passphrase")) != 0 )
{
len = (int32_t)strlen(secret);
if ( is_hexstr(secret,0) != 0 && len == 128 )
@ -68,7 +69,7 @@ char *SuperNET_parsemainargs(struct supernet_info *myinfo,bits256 *wallethashp,b
} else vcalc_sha256(0,secretbuf,(void *)secret,len), len = sizeof(bits256);
memcpy(wallethash.bytes,secretbuf,sizeof(wallethash));
//printf("wallethash.(%s)\n",bits256_str(str,wallethash));
if ( (wallet2fname= jstr(json,"2fafile")) != 0 )
if ( (wallet2fname= jstr(json,"permanentfile")) != 0 )
wallet2priv = SuperNET_wallet2priv(wallet2fname,wallethash);
}
exchanges = jarray(&n,json,"exchanges");
@ -77,7 +78,8 @@ char *SuperNET_parsemainargs(struct supernet_info *myinfo,bits256 *wallethashp,b
free_json(json);
}
}
exchanges777_init(myinfo,exchanges,0);
if ( exchanges != 0 )
exchanges777_init(myinfo,exchanges,0);
*wallethashp = wallethash, *wallet2privp = wallet2priv;
return(coinargs);
}
@ -122,7 +124,7 @@ int32_t SuperNET_savejsonfile(char *fname,bits256 privkey,bits256 destpubkey,cJS
//sprintf(fname,"confs/iguana.%llu",(long long)wallet2shared.txid);
if ( (ciphered= SuperNET_cipher(0,0,json,0,privkey,destpubkey,confstr)) != 0 )
{
//printf("save (%s) <- (%s)\n",fname,ciphered);
printf("save (%s) <- (%s)\n",fname,confstr);
if ( (fp= fopen(fname,"wb")) != 0 )
{
fwrite(ciphered,1,strlen(ciphered)+1,fp);
@ -188,7 +190,7 @@ cJSON *SuperNET_decryptedjson(char *passphrase,int32_t passsize,bits256 walletha
wallet2shared = SuperNET_wallet2shared(wallethash,wallet2priv);
wallet2pub = curve25519(wallet2shared,curve25519_basepoint9());
sprintf(fname,"confs/%s",bits256_str(str,wallet2pub));
//printf("fname.(%s) wallet2shared.%s\n",fname,bits256_str(str,wallet2pub));
printf("fname.(%s) wallet2shared.%s\n",fname,bits256_str(str,wallet2pub));
if ( (confstr= OS_filestr(&allocsize,fname)) != 0 )
{
if ( (filejson= cJSON_Parse(confstr)) != 0 )
@ -224,7 +226,7 @@ cJSON *SuperNET_decryptedjson(char *passphrase,int32_t passsize,bits256 walletha
return(msgjson);
}
int32_t SuperNET_encryptjson(char *destfname,char *passphrase,int32_t passsize,char *fname2fa,int32_t fnamesize,cJSON *argjson)
int32_t _SuperNET_encryptjson(char *destfname,char *passphrase,int32_t passsize,char *fname2fa,int32_t fnamesize,cJSON *argjson)
{
bits256 wallethash,wallet2priv,wallet2shared,wallet2pub; char str[65];
wallethash = wallet2priv = GENESIS_PRIVKEY;
@ -233,7 +235,7 @@ int32_t SuperNET_encryptjson(char *destfname,char *passphrase,int32_t passsize,c
wallethash = SuperNET_linehash(passphrase);
SuperNET_linehash(fname2fa); // maps special chars
wallet2priv = SuperNET_wallet2priv(fname2fa,wallethash);
//char str2[65]; printf("ENCRYPT.[%s %s] (%s) 2.%s\n",passphrase,fname2fa,bits256_str(str,wallethash),bits256_str(str2,wallet2priv));
char str2[65]; printf("ENCRYPT.[%s %s] (%s) 2.%s\n",passphrase,fname2fa,bits256_str(str,wallethash),bits256_str(str2,wallet2priv));
wallet2shared = SuperNET_wallet2shared(wallethash,wallet2priv);
wallet2pub = curve25519(wallet2shared,curve25519_basepoint9());
sprintf(destfname,"confs/%s",bits256_str(str,wallet2pub));
@ -242,20 +244,37 @@ int32_t SuperNET_encryptjson(char *destfname,char *passphrase,int32_t passsize,c
return(0);
}
void SuperNET_setkeys(struct supernet_info *myinfo,void *pass,int32_t passlen,int32_t dosha256)
{
char pubkeystr[128]; uint8_t pubkey33[33]; bits256 hash;
if ( dosha256 != 0 )
myinfo->myaddr.nxt64bits = conv_NXTpassword(myinfo->persistent_priv.bytes,myinfo->myaddr.persistent.bytes,pass,passlen);
else
{
myinfo->myaddr.persistent = curve25519(myinfo->persistent_priv,curve25519_basepoint9());
vcalc_sha256(0,hash.bytes,myinfo->myaddr.persistent.bytes,32);
myinfo->myaddr.nxt64bits = hash.txid;
}
RS_encode(myinfo->myaddr.NXTADDR,myinfo->myaddr.nxt64bits);
btc_priv2pub(pubkey33,myinfo->persistent_priv.bytes);
init_hexbytes_noT(pubkeystr,pubkey33,33);
btc_coinaddr(myinfo->myaddr.BTC,0,pubkeystr);
btc_coinaddr(myinfo->myaddr.BTCD,60,pubkeystr);
}
void SuperNET_parsemyinfo(struct supernet_info *myinfo,cJSON *msgjson)
{
char *ipaddr,*secret,str[65]; bits256 checkhash,acct;
char *ipaddr,*secret,str[65]; bits256 checkhash;
if ( msgjson != 0 )
{
if ( (ipaddr= jstr(msgjson,"ipaddr")) != 0 && is_ipaddr(ipaddr) != 0 )
strcpy(myinfo->ipaddr,ipaddr);
if ( (secret= jstr(msgjson,"secret")) != 0 )
{
myinfo->myaddr.nxt64bits = conv_NXTpassword(myinfo->persistent_priv.bytes,myinfo->myaddr.persistent.bytes,(uint8_t *)secret,(int32_t)strlen(secret));
}
if ( (secret= jstr(msgjson,"passphrase")) != 0 )
SuperNET_setkeys(myinfo,secret,(int32_t)strlen(secret),1);
else
{
myinfo->persistent_priv = jbits256(msgjson,"persistent_priv");
SuperNET_setkeys(myinfo,myinfo->persistent_priv.bytes,sizeof(myinfo->persistent_priv),0);
if ( bits256_nonz(myinfo->persistent_priv) == 0 )
{
printf("null persistent_priv? generate new one\n");
@ -271,13 +290,8 @@ void SuperNET_parsemyinfo(struct supernet_info *myinfo,cJSON *msgjson)
} else printf("persistent VALIDATED persistentpub.(%s)\n",bits256_str(str,checkhash));
}
if ( bits256_nonz(myinfo->persistent_priv) == 0 )
{
OS_randombytes(myinfo->persistent_priv.bytes,sizeof(myinfo->persistent_priv));
myinfo->myaddr.persistent = curve25519(myinfo->persistent_priv,curve25519_basepoint9());
}
vcalc_sha256(0,acct.bytes,(void *)myinfo->myaddr.persistent.bytes,sizeof(bits256));
myinfo->myaddr.nxt64bits = acct.txid;
RS_encode(myinfo->myaddr.NXTADDR,myinfo->myaddr.nxt64bits);
SuperNET_setkeys(myinfo,myinfo->persistent_priv.bytes,sizeof(myinfo->persistent_priv),0);
}
char *SuperNET_keysinit(struct supernet_info *myinfo,char *argjsonstr)
@ -307,7 +321,7 @@ char *SuperNET_keysinit(struct supernet_info *myinfo,char *argjsonstr)
OS_randombytes((void *)&r,sizeof(r));
jadd64bits(json,"rand",r);
//printf("call SuperNET_encryptjson\n");
SuperNET_encryptjson(destfname,passphrase,sizeof(passphrase),fname2fa,sizeof(fname2fa),json);
_SuperNET_encryptjson(destfname,passphrase,sizeof(passphrase),fname2fa,sizeof(fname2fa),json);
//printf("save.(%s)\n",jprint(json,0));
free_json(json);
}
@ -342,20 +356,20 @@ char *SuperNET_keysinit(struct supernet_info *myinfo,char *argjsonstr)
#include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h"
THREE_STRINGS(InstantDEX,encryptjson,passphrase,permanentfile,anything)
THREE_STRINGS(SuperNET,encryptjson,password,permanentfile,anything)
{
char destfname[4096],pass[8192],fname2[1023]; cJSON *argjson,*retjson = cJSON_CreateObject();
safecopy(pass,passphrase,sizeof(pass));
safecopy(pass,password,sizeof(pass));
safecopy(fname2,permanentfile,sizeof(fname2));
argjson = jduplicate(json);
//printf("argjson.(%s)\n",jprint(argjson,0));
jdelete(argjson,"agent");
jdelete(argjson,"method");
jdelete(argjson,"passphrase");
jdelete(argjson,"password");
jdelete(argjson,"permanentfile");
jdelete(argjson,"timestamp");
jdelete(argjson,"tag");
if ( SuperNET_encryptjson(destfname,pass,sizeof(pass),fname2,sizeof(fname2),argjson) == 0 )
if ( _SuperNET_encryptjson(destfname,pass,sizeof(pass),fname2,sizeof(fname2),argjson) == 0 )
{
jaddstr(retjson,"result","success");
jaddstr(retjson,"filename",destfname);
@ -364,10 +378,10 @@ THREE_STRINGS(InstantDEX,encryptjson,passphrase,permanentfile,anything)
return(jprint(retjson,1));
}
TWO_STRINGS(InstantDEX,decryptjson,passphrase,permanentfile)
TWO_STRINGS(SuperNET,decryptjson,password,permanentfile)
{
char pass[8192],fname2[1023]; cJSON *retjson,*obj; bits256 wallethash,wallet2priv;
safecopy(pass,passphrase,sizeof(pass));
safecopy(pass,password,sizeof(pass));
safecopy(fname2,permanentfile,sizeof(fname2));
wallethash = wallet2priv = GENESIS_PRIVKEY;
if ( strlen(pass) == sizeof(wallethash)*2 && is_hexstr(pass,(int32_t)sizeof(bits256)*2) > 0 )

110
iguana/exchanges/PAX.c

@ -0,0 +1,110 @@
/******************************************************************************
* 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. *
* *
******************************************************************************/
#define EXCHANGE_NAME "PAX"
#define UPDATE PAX ## _price
#define SUPPORTS PAX ## _supports
#define SIGNPOST PAX ## _signpost
#define TRADE PAX ## _trade
#define ORDERSTATUS PAX ## _orderstatus
#define CANCELORDER PAX ## _cancelorder
#define OPENORDERS PAX ## _openorders
#define TRADEHISTORY PAX ## _tradehistory
#define BALANCES PAX ## _balances
#define PARSEBALANCE PAX ## _parsebalance
#define WITHDRAW PAX ## _withdraw
#define CHECKBALANCE PAX ## _checkbalance
#define ALLPAIRS PAX ## _allpairs
#define FUNCS PAX ## _funcs
#define BASERELS PAX ## _baserels
#include "../peggy.h"
char *peggy_bases[64] =
{
"BTCD", "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK",
"BTCUSD", "NXTBTC", "SuperNET", "ETHBTC", "LTCBTC", "XMRBTC", "BTSBTC", "XCPBTC", // BTC priced
"XAUUSD", "XAGUSD", "XPTUSD", "XPDUSD", "COPPER", "NGAS", "UKOIL", "USOIL", // USD priced
"BUND", "NAS100", "SPX500", "US30", "EUSTX50", "UK100", "JPN225", "GER30", "SUI30", "AUS200", "HKG33", "XAUUSD", "BTCRUB", "BTCCNY", "BTCUSD" // abstract
};
char *ALLPAIRS(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"PAX is not yet\"}"));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
return(0);
}
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert)
{
return(0);
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *path)
{
if ( retstrp != 0 )
*retstrp = clonestr("{\"error\":\"PAX signing is not yet\"}");
return(cJSON_Parse("{}"));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
return(clonestr("{\"error\":\"PAX parsebalance is not yet\"}"));
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(cJSON_Parse("{\"error\":\"PAX balances is not yet\"}"));
}
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
return(0);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
return(clonestr("{\"error\":\"PAX orderstatus is not yet\"}"));
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
return(clonestr("{\"error\":\"PAX cancel order is not yet\"}"));
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"PAX open orders is not yet\"}"));
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"PAX tradehistory is not yet\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
return(clonestr("{\"error\":\"PAX redeem is not yet\"}"));
}
struct exchange_funcs PAX_funcs = EXCHANGE_FUNCS(PAX,EXCHANGE_NAME);
#include "exchange_undefs.h"

50
iguana/exchanges/ecb.c → iguana/exchanges/bitcoin.c

@ -13,22 +13,22 @@
* *
******************************************************************************/
#define EXCHANGE_NAME "ecb"
#define UPDATE ecb ## _price
#define SUPPORTS ecb ## _supports
#define SIGNPOST ecb ## _signpost
#define TRADE ecb ## _trade
#define ORDERSTATUS ecb ## _orderstatus
#define CANCELORDER ecb ## _cancelorder
#define OPENORDERS ecb ## _openorders
#define TRADEHISTORY ecb ## _tradehistory
#define BALANCES ecb ## _balances
#define PARSEBALANCE ecb ## _parsebalance
#define WITHDRAW ecb ## _withdraw
#define CHECKBALANCE ecb ## _checkbalance
#define ALLPAIRS ecb ## _allpairs
#define FUNCS ecb ## _funcs
#define BASERELS ecb ## _baserels
#define EXCHANGE_NAME "bitcoin"
#define UPDATE bitcoin ## _price
#define SUPPORTS bitcoin ## _supports
#define SIGNPOST bitcoin ## _signpost
#define TRADE bitcoin ## _trade
#define ORDERSTATUS bitcoin ## _orderstatus
#define CANCELORDER bitcoin ## _cancelorder
#define OPENORDERS bitcoin ## _openorders
#define TRADEHISTORY bitcoin ## _tradehistory
#define BALANCES bitcoin ## _balances
#define PARSEBALANCE bitcoin ## _parsebalance
#define WITHDRAW bitcoin ## _withdraw
#define CHECKBALANCE bitcoin ## _checkbalance
#define ALLPAIRS bitcoin ## _allpairs
#define FUNCS bitcoin ## _funcs
#define BASERELS bitcoin ## _baserels
static char *BASERELS[][2] = { {"btc","nxt"}, {"btc","btcd"}, {"btc","ltc"}, {"btc","vrc"}, {"btc","doge"} };
#include "exchange_supports.h"
@ -45,18 +45,18 @@ double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchang
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *path)
{
if ( retstrp != 0 )
*retstrp = clonestr("{\"error\":\"ecb is readonly data source\"}");
*retstrp = clonestr("{\"error\":\"bitcoin is not yet\"}");
return(cJSON_Parse("{}"));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
return(clonestr("{\"error\":\"ecb is readonly data source\"}"));
return(clonestr("{\"error\":\"bitcoin is not yet\"}"));
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(cJSON_Parse("{\"error\":\"ecb is readonly data source\"}"));
return(cJSON_Parse("{\"error\":\"bitcoin is not yet\"}"));
}
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
@ -66,29 +66,29 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
return(clonestr("{\"error\":\"ecb is readonly data source\"}"));
return(clonestr("{\"error\":\"bitcoin is not yet\"}"));
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
return(clonestr("{\"error\":\"ecb is readonly data source\"}"));
return(clonestr("{\"error\":\"bitcoin is not yet\"}"));
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"ecb is readonly data source\"}"));
return(clonestr("{\"error\":\"bitcoin is not yet\"}"));
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"ecb is readonly data source\"}"));
return(clonestr("{\"error\":\"bitcoin is not yet\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
return(clonestr("{\"error\":\"ecb is readonly data source\"}"));
return(clonestr("{\"error\":\"bitcoin is not yet\"}"));
}
struct exchange_funcs ecb_funcs = EXCHANGE_FUNCS(ecb,EXCHANGE_NAME);
struct exchange_funcs bitcoin_funcs = EXCHANGE_FUNCS(bitcoin,EXCHANGE_NAME);
#include "exchange_undefs.h"

52
iguana/exchanges/yahoo.c → iguana/exchanges/jumblr.c

@ -13,24 +13,24 @@
* *
******************************************************************************/
#define EXCHANGE_NAME "yahoo"
#define UPDATE yahoo ## _price
#define SUPPORTS yahoo ## _supports
#define SIGNPOST yahoo ## _signpost
#define TRADE yahoo ## _trade
#define ORDERSTATUS yahoo ## _orderstatus
#define CANCELORDER yahoo ## _cancelorder
#define OPENORDERS yahoo ## _openorders
#define TRADEHISTORY yahoo ## _tradehistory
#define BALANCES yahoo ## _balances
#define PARSEBALANCE yahoo ## _parsebalance
#define WITHDRAW yahoo ## _withdraw
#define CHECKBALANCE yahoo ## _checkbalance
#define ALLPAIRS yahoo ## _allpairs
#define FUNCS yahoo ## _funcs
#define BASERELS yahoo ## _baserels
#define EXCHANGE_NAME "jumblr"
#define UPDATE jumblr ## _price
#define SUPPORTS jumblr ## _supports
#define SIGNPOST jumblr ## _signpost
#define TRADE jumblr ## _trade
#define ORDERSTATUS jumblr ## _orderstatus
#define CANCELORDER jumblr ## _cancelorder
#define OPENORDERS jumblr ## _openorders
#define TRADEHISTORY jumblr ## _tradehistory
#define BALANCES jumblr ## _balances
#define PARSEBALANCE jumblr ## _parsebalance
#define WITHDRAW jumblr ## _withdraw
#define CHECKBALANCE jumblr ## _checkbalance
#define ALLPAIRS jumblr ## _allpairs
#define FUNCS jumblr ## _funcs
#define BASERELS jumblr ## _baserels
static char *BASERELS[][2] = { {"EUR","USD"},{"USD","JPY"},{"GBP","USD"},{"EUR","GBP"},{"USD","CHF"},{"AUD","NZD"},{"CAD","CHF"},{"CHF","JPY"},{"EUR","AUD"},{"EUR","CAD"},{"EUR","JPY"},{"EUR","CHF"},{"USD","CAD"},{"AUD","USD"},{"GBP","JPY"},{"AUD","CAD"},{"AUD","CHF"},{"AUD","JPY"},{"EUR","NOK"},{"EUR","NZD"},{"GBP","CAD"},{"GBP","CHF"},{"NZD","JPY"},{"NZD","USD"},{"USD","NOK"},{"USD","SEK"} };
static char *BASERELS[][2] = { {"btc","nxt"}, {"btc","btcd"}, {"btc","ltc"}, {"btc","vrc"}, {"btc","doge"} };
#include "exchange_supports.h"
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert)
@ -45,18 +45,18 @@ double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchang
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *path)
{
if ( retstrp != 0 )
*retstrp = clonestr("{\"error\":\"yahoo is readonly data source\"}");
*retstrp = clonestr("{\"error\":\"jumblr is not yet\"}");
return(cJSON_Parse("{}"));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
return(clonestr("{\"error\":\"yahoo is readonly data source\"}"));
return(clonestr("{\"error\":\"jumblr is not yet\"}"));
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(cJSON_Parse("{\"error\":\"yahoo is readonly data source\"}"));
return(cJSON_Parse("{\"error\":\"jumblr is not yet\"}"));
}
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
@ -66,29 +66,29 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
return(clonestr("{\"error\":\"yahoo is readonly data source\"}"));
return(clonestr("{\"error\":\"jumblr is not yet\"}"));
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
return(clonestr("{\"error\":\"yahoo is readonly data source\"}"));
return(clonestr("{\"error\":\"jumblr is not yet\"}"));
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"yahoo is readonly data source\"}"));
return(clonestr("{\"error\":\"jumblr is not yet\"}"));
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"yahoo is readonly data source\"}"));
return(clonestr("{\"error\":\"jumblr is not yet\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
return(clonestr("{\"error\":\"yahoo is readonly data source\"}"));
return(clonestr("{\"error\":\"jumblr is not yet\"}"));
}
struct exchange_funcs yahoo_funcs = EXCHANGE_FUNCS(yahoo,EXCHANGE_NAME);
struct exchange_funcs jumblr_funcs = EXCHANGE_FUNCS(jumblr,EXCHANGE_NAME);
#include "exchange_undefs.h"

123
iguana/exchanges/nxtae.c

@ -33,141 +33,70 @@
static char *BASERELS[][2] = { {"btc","nxt"}, {"btc","btcd"}, {"btc","ltc"}, {"btc","vrc"}, {"btc","doge"} };
#include "exchange_supports.h"
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert)
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert)
{
char url[1024],lrel[16],lbase[16];
strcpy(lrel,rel), strcpy(lbase,base);
tolowercase(lrel), tolowercase(lbase);
sprintf(url,"http://api.quadrigacx.com/v2/order_book?book=%s_%s",lbase,lrel);
return(exchanges777_standardprices(exchange,commission,base,rel,url,quotes,0,0,maxdepth,0,invert));
double bid,ask,bids[64],asks[64],highs[64],lows[64]; int32_t numbids,numasks,c; char name[32];
if ( fxcm_ensure() == 0 )
{
strcpy(name,base), strcat(name,rel), touppercase(name);
if ( (c= strsearch(FXCM_contracts,num_FXCM,name)) >= 0 )
{
prices777_fxcm(bids,asks,highs,lows);
numbids = numasks = 0;
bid = exchange_setquote(bidasks,&numbids,&numasks,0,invert,bids[c],1,commission,0,(uint32_t)time(NULL),0);
ask = exchange_setquote(bidasks,&numbids,&numasks,1,invert,asks[c],1,commission,0,(uint32_t)time(NULL),0);
if ( bid > SMALLVAL && ask > SMALLVAL )
return((bid + ask) * .5);
}
}
return(0);
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *path)
{
char url[1024],req[1024],md5secret[128],tmp[1024],dest[1025],hdr1[512],hdr2[512],hdr3[512],hdr4[512],*sig,*data = 0;
cJSON *json; uint64_t nonce;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
nonce = exchange_nonce(exchange) * 1000 + ((uint64_t)OS_milliseconds() % 1000);
sprintf(tmp,"%llu%s%s",(long long)nonce,exchange->userid,exchange->apikey);
calc_md5(md5secret,exchange->apisecret,(int32_t)strlen(exchange->apisecret));
if ( (sig= hmac_sha256_str(dest,md5secret,(int32_t)strlen(md5secret),tmp)) != 0 )
{
sprintf(req,"{\"key\":\"%s\",%s\"nonce\":%llu,\"signature\":\"%s\"}",exchange->apikey,payload,(long long)nonce,sig);
sprintf(hdr1,"Content-Type:application/json");
sprintf(hdr2,"charset=utf-8");
sprintf(hdr3,"Content-Length:%ld",(long)strlen(req));
sprintf(url,"https://api.quadrigacx.com/v2/%s",path);
if ( dotrade == 0 )
data = exchange_would_submit(req,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,req,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
}
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
*retstrp = clonestr("{\"error\":\"nxtae is readonly data source\"}");
return(cJSON_Parse("{}"));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
//[{"btc_available":"0.00000000","btc_reserved":"0.00000000","btc_balance":"0.00000000","cad_available":"0.00","cad_reserved":"0.00","cad_balance":"0.00","usd_available":"0.00","usd_reserved":"0.00","usd_balance":"0.00","xau_available":"0.000000","xau_reserved":"0.000000","xau_balance":"0.000000","fee":"0.5000"}]
char field[128],*str,*itemstr = 0; cJSON *obj; double reserv,total;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
strcat(field,"_available");
if ( argjson != 0 && (str= jstr(argjson,field)) != 0 )
{
*balancep = jdouble(argjson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_reserved");
reserv = jdouble(argjson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_balance");
total = jdouble(argjson,field);
obj = cJSON_CreateObject();
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked_balance",reserv);
jaddnum(obj,"total",total);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
return(clonestr("{\"error\":\"nxtae is readonly data source\"}"));
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(SIGNPOST(&exchange->cHandle,1,0,exchange,"","balance"));
return(cJSON_Parse("{\"error\":\"nxtae is readonly data source\"}"));
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],pairstr[64],*extra,*path; cJSON *json; uint64_t txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel,argjson)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
path = (dir > 0) ? "buy" : "sell";
//key - API key
//signature - signature
//nonce - nonce
//amount - amount of major currency
//price - price to buy at
//book - optional, if not specified, will default to btc_cad
sprintf(payload,"\"amount\":%.6f,\"price\":%.3f,\"book\":\"%s_%s\",",volume,price,base,rel);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,payload,path)) != 0 )
{
// parse json and set txid
free_json(json);
}
return(txid);
return(0);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char buf[64];
sprintf(buf,"\"id\":%llu,",(long long)quoteid);
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,buf,"lookup_order"),1));
return(clonestr("{\"error\":\"nxtae is readonly data source\"}"));
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char buf[64];
sprintf(buf,"\"id\":%llu,",(long long)quoteid);
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,buf,"cancel_order"),1));
return(clonestr("{\"error\":\"nxtae is readonly data source\"}"));
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,"","open_orders"),1));
return(clonestr("{\"error\":\"nxtae is readonly data source\"}"));
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,"","user_transactions"),1));
return(clonestr("{\"error\":\"nxtae is readonly data source\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
uint64_t txid,assetid,assetoshis; cJSON *retjson = cJSON_CreateObject();
if ( is_validNXT(destaddr) < 0 )
jaddstr(retjson,"error","invalid NXT address");
else if ( (assetid= is_MGW_asset(base)) == 0 )
jaddstr(retjson,"error","invalid MGW asset");
else if ( is_validNXT_amount(base) < 0 )
jaddstr(retjson,"error","invalid NXT asset");
else if ( (txid= MGW_redeem(passphrase,assetid,assetoshis,destaddr)) != 0 )
{
jaddstr(retjson,"result","success");
jadd64bits(retjson,"redeemtxid",txid);
} else jaddstr(retjson,"error","couldnt submit MGW redeem");
return(jprint(retjson,1));
return(clonestr("{\"error\":\"nxtae is readonly data source\"}"));
}
struct exchange_funcs nxtae_funcs = EXCHANGE_FUNCS(nxtae,EXCHANGE_NAME);

16
iguana/exchanges/truefx.c

@ -77,7 +77,19 @@ uint64_t prices777_truefx(char *reqbase,char *reqrel,uint64_t *millistampp,doubl
}
if ( str != 0 )
{
//printf("(%s) -> (%s)\n",url,str);
printf("(%s) -> (%s)\n",url,str);
/*EUR/USD,1454354222037,1.08,997,1.09,000,1.08142,1.09130,1.08333
USD/JPY,1454354221120,121.,049,121.,053,120.676,121.496,121.289
GBP/USD,1454354221048,1.44,242,1.44,254,1.42280,1.44305,1.42483
EUR/GBP,1454354220966,0.75,561,0.75,567,0.75517,0.76238,0.76031
USD/CHF,1454354221288,1.01,866,1.01,876,1.01553,1.02514,1.02209
EUR/JPY,1454354221693,131.,937,131.,944,131.224,132.003,131.381
EUR/CHF,1454354221028,1.11,027,1.11,032,1.10542,1.11173,1.10705
USD/CAD,1454354221764,1.39,473,1.39,479,1.39437,1.40627,1.39729
AUD/USD,1454354221515,0.70,955,0.70,961,0.70421,0.70970,0.70817
GBP/JPY,1454354221581,174.,602,174.,621,172.408,174.730,172.805
*/
while ( str[n + 0] != 0 && str[n] != '\n' && str[n] != '\r' )
{
for (i=jpyflag=0; str[n + i]!=' '&&str[n + i]!='\n'&&str[n + i]!='\r'&&str[n + i]!=0; i++)
@ -94,7 +106,7 @@ uint64_t prices777_truefx(char *reqbase,char *reqrel,uint64_t *millistampp,doubl
memcpy(base,str+n,3), base[3] = 0;
memcpy(rel,str+n+4,3), rel[3] = 0;
str[n + i] = 0;
//printf("str.(%s) (%s/%s) %d n.%d i.%d\n",str+n,base,rel,str[n],n,i);
printf("str.(%s) (%s/%s) %d n.%d i.%d\n",str+n,base,rel,str[n],n,i);
sprintf(buf,"[%s]",str+n+7+1);
n += i + 1;
if ( (array= cJSON_Parse(buf)) != 0 )

94
iguana/exchanges/unconf.c

@ -0,0 +1,94 @@
/******************************************************************************
* 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. *
* *
******************************************************************************/
#define EXCHANGE_NAME "unconf"
#define UPDATE unconf ## _price
#define SUPPORTS unconf ## _supports
#define SIGNPOST unconf ## _signpost
#define TRADE unconf ## _trade
#define ORDERSTATUS unconf ## _orderstatus
#define CANCELORDER unconf ## _cancelorder
#define OPENORDERS unconf ## _openorders
#define TRADEHISTORY unconf ## _tradehistory
#define BALANCES unconf ## _balances
#define PARSEBALANCE unconf ## _parsebalance
#define WITHDRAW unconf ## _withdraw
#define CHECKBALANCE unconf ## _checkbalance
#define ALLPAIRS unconf ## _allpairs
#define FUNCS unconf ## _funcs
#define BASERELS unconf ## _baserels
static char *BASERELS[][2] = { {"btc","nxt"}, {"btc","btcd"}, {"btc","ltc"}, {"btc","vrc"}, {"btc","doge"} };
#include "exchange_supports.h"
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert)
{
char url[1024],lrel[16],lbase[16];
strcpy(lrel,rel), strcpy(lbase,base);
tolowercase(lrel), tolowercase(lbase);
sprintf(url,"http://api.quadrigacx.com/v2/order_book?book=%s_%s",lbase,lrel);
return(exchanges777_standardprices(exchange,commission,base,rel,url,quotes,0,0,maxdepth,0,invert));
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *path)
{
if ( retstrp != 0 )
*retstrp = clonestr("{\"error\":\"unconf is read only\"}");
return(cJSON_Parse("{}"));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
return(clonestr("{\"error\":\"unconf is read only\"}"));
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(cJSON_Parse("{\"error\":\"unconf is read only\"}"));
}
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
return(0);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
return(clonestr("{\"error\":\"unconf is read only\"}"));
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
return(clonestr("{\"error\":\"unconf is read only\"}"));
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"unconf is read only\"}"));
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"unconf is read only\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
return(clonestr("{\"error\":\"unconf is read only\"}"));
}
struct exchange_funcs unconf_funcs = EXCHANGE_FUNCS(unconf,EXCHANGE_NAME);
#include "exchange_undefs.h"

8
iguana/exchanges777.h

@ -48,7 +48,8 @@ struct exchange_info
struct exchange_funcs issue;
char name[16],apikey[MAX_JSON_FIELD],apisecret[MAX_JSON_FIELD],tradepassword[MAX_JSON_FIELD],userid[MAX_JSON_FIELD];
uint32_t exchangeid,pollgap,lastpoll;
uint64_t lastnonce; double commission;
uint64_t lastnonce,exchangebits; double commission;
void *privatedata;
CURL *cHandle; queue_t requestQ,pricesQ,pendingQ[2],tradebotsQ;
};
@ -79,7 +80,12 @@ char *exchanges777_unmonitor(struct exchange_info *exchange,char *base,char *rel
void tradebot_timeslice(struct exchange_info *exchange,void *bot);
char *exchanges777_Qtrade(struct exchange_info *exchange,char *base,char *rel,int32_t maxseconds,int32_t dotrade,int32_t dir,double price,double volume,cJSON *argjson);
struct exchange_request *exchanges777_baserelfind(struct exchange_info *exchange,char *base,char *rel,int32_t func);
struct exchange_info *exchanges777_find(char *exchangestr);
void prices777_processprice(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth);
double truefx_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert);
double fxcm_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert);
double instaforex_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert);
#endif

2
iguana/iguana.sources

@ -1,3 +1,3 @@
#iguana_html.c
SOURCES := SuperNET.c SuperNET_keys.c SuperNET_category.c SuperNET_hexmsg.c iguana_exchanges.c iguana_tradebots.c iguana_instantdex.c pangea_api.c pangea_bets.c cards777.c pangea_summary.c pangea_json.c pangea_hand.c poker.c ramchain_api.c iguana_tx.c iguana_wallet.c iguana_pubkeys.c iguana_recv.c iguana_bundles.c iguana_msg.c iguana_rpc.c iguana777.c iguana_chains.c iguana_peers.c iguana_accept.c iguana_bitmap.c iguana_init.c iguana_ramchain.c iguana_blocks.c iguana_json.c main.c
SOURCES := SuperNET.c SuperNET_keys.c SuperNET_category.c SuperNET_hexmsg.c peggy.c peggy_consensus.c peggy_price.c peggy_update.c peggy_accts.c peggy_tx.c peggy_txind.c peggy_ramkv.c peggy_serdes.c iguana_exchanges.c iguana_tradebots.c iguana_instantdex.c pangea_api.c pangea_bets.c cards777.c pangea_summary.c pangea_json.c pangea_hand.c poker.c ramchain_api.c iguana_tx.c iguana_wallet.c iguana_pubkeys.c iguana_recv.c iguana_bundles.c iguana_msg.c iguana_rpc.c iguana777.c iguana_chains.c iguana_peers.c iguana_accept.c iguana_bitmap.c iguana_init.c iguana_ramchain.c iguana_blocks.c iguana_json.c main.c

10
iguana/iguana777.c

@ -559,16 +559,6 @@ void iguana_coins(void *arg)
}
}
int32_t opreturns_init(uint32_t blocknum,uint32_t blocktimestamp,char *path)
{
printf("opreturns_init not yet\n");
return(-1);
}
void peggy()
{
printf("peggy not yet\n");
}
char *busdata_sync(uint32_t *noncep,char *jsonstr,char *broadcastmode,char *destNXTaddr)
{
printf("busdata_sync.(%s)\n",jsonstr);

101
iguana/iguana_exchanges.c

@ -14,14 +14,13 @@
******************************************************************************/
#include "exchanges777.h"
#include "peggy.h"
#define EXCHANGE777_DONE 1
#define EXCHANGE777_ISPENDING 2
#define EXCHANGE777_REQUEUE 3
char *Exchange_names[] = { "poloniex", "bittrex", "btc38", "huobi", "bitstamp", "bitfinex", "btce", "coinbase", "okcoin", "lakebtc", "quadriga", "truefx", "ecb", "instaforex", "fxcm", "yahoo" };
struct exchange_info *Exchanges[sizeof(Exchange_names)/sizeof(*Exchange_names)];
//char *Exchange_names[] = { "poloniex", "bittrex", "btc38", "huobi", "bitstamp", "bitfinex", "btce", "coinbase", "okcoin", "lakebtc", "quadriga", "truefx", "ecb", "instaforex", "fxcm", "yahoo" };
void prices777_processprice(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth)
{
@ -443,10 +442,25 @@ int32_t baserel_polarity(char *pairs[][2],int32_t n,char *_base,char *_rel)
#include "exchanges/bitstamp.c"
#include "exchanges/truefx.c"
#include "exchanges/yahoo.c"
#include "exchanges/PAX.c"
#include "exchanges/fxcm.c"
#include "exchanges/instaforex.c"
#include "exchanges/ecb.c"
#include "exchanges/jumblr.c"
#include "exchanges/bitcoin.c"
#include "exchanges/nxtae.c"
#include "exchanges/unconf.c"
struct exchange_funcs *Exchange_funcs[] =
{
&truefx_funcs, &instaforex_funcs, &fxcm_funcs, // prices only
&PAX_funcs, &nxtae_funcs, &bitcoin_funcs, &jumblr_funcs, // special
&bitfinex_funcs, &huobi_funcs, &lakebtc_funcs, &quadriga_funcs, &okcoin_funcs, // BTC exchanges
&poloniex_funcs, &bittrex_funcs, &btce_funcs, &btc38_funcs, // altcoin exchanges
&coinbase_funcs, &bitstamp_funcs // authentication not working yet
};
struct exchange_info *Exchanges[sizeof(Exchange_funcs)/sizeof(*Exchange_funcs)];
int32_t exchanges777_orient(struct exchange_info *exchange,char *base,char *rel,double *pricep,double *volumep,struct exchange_request *req)
{
@ -560,10 +574,28 @@ char *exchanges777_process(struct exchange_info *exchange,int32_t *retvalp,struc
void exchanges777_loop(void *ptr)
{
struct exchange_info *exchange = ptr;
int32_t flag,retval,i; struct exchange_request *req; char *retstr; void *bot;
struct peggy_info *PEGS; struct exchange_info *exchange = ptr;
int32_t flag,retval,i,peggyflag = 0; struct exchange_request *req; char *retstr; void *bot;
if ( strcmp(exchange->name,"PAX") == 0 )
{
PEGS = calloc(1,sizeof(*PEGS));
PAX_init(PEGS);
exchange->privatedata = PEGS;
peggyflag = 1;
_crypto_update(PEGS,PEGS->cryptovols,&PEGS->data,1,peggyflag);
PEGS->lastupdate = (uint32_t)time(NULL);
}
while ( 1 )
{
if ( peggyflag != 0 )
{
PAX_idle(PEGS,peggyflag,3);
if ( time(NULL) > PEGS->lastupdate+100 )
{
_crypto_update(PEGS,PEGS->cryptovols,&PEGS->data,1,peggyflag);
PEGS->lastupdate = (uint32_t)time(NULL);
}
}
flag = retval = 0;
retstr = 0;
if ( (req= queue_dequeue(&exchange->requestQ,0)) != 0 )
@ -764,16 +796,29 @@ char *exchanges777_Qrequest(struct exchange_info *exchange,int32_t func,char *ba
int32_t exchanges777_id(char *exchangestr)
{
int32_t i;
for (i=0; i<sizeof(Exchange_names)/sizeof(*Exchange_names); i++)
for (i=0; i<sizeof(Exchange_funcs)/sizeof(*Exchange_funcs); i++)
{
//printf("%s ",Exchange_names[i]);
if ( strcmp(exchangestr,Exchange_names[i]) == 0 )
//printf("%s ",Exchange_funcs[i]->name);
if ( strcmp(exchangestr,Exchange_funcs[i]->name) == 0 )
return(i);
}
//printf("cant find (%s)\n",exchangestr);
return(-1);
}
struct exchange_info *exchanges777_findbits(uint64_t exchangebits)
{
int32_t i;
for (i=0; i<sizeof(Exchange_funcs)/sizeof(*Exchange_funcs); i++)
{
//printf("%s ",Exchange_funcs[i]->name);
if ( Exchanges[i] != 0 && exchangebits == Exchanges[i]->exchangebits )
return(Exchanges[i]);
}
//printf("cant find (%s)\n",exchangestr);
return(0);
}
struct exchange_info *exchanges777_find(char *exchangestr)
{
int32_t exchangeid;
@ -784,12 +829,21 @@ struct exchange_info *exchanges777_find(char *exchangestr)
struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson)
{
struct exchange_funcs funcs[] =
static int didinit;
if ( didinit == 0 )
{
truefx_funcs, ecb_funcs, instaforex_funcs, fxcm_funcs, yahoo_funcs,
poloniex_funcs, bittrex_funcs, btce_funcs, bitfinex_funcs, btc38_funcs,
huobi_funcs, lakebtc_funcs, quadriga_funcs, okcoin_funcs, coinbase_funcs, bitstamp_funcs
};
int32_t i,j;
for (i=0; i<sizeof(Exchange_funcs)/sizeof(*Exchange_funcs)-1; i++)
{
for (j=i+1; j<sizeof(Exchange_funcs)/sizeof(*Exchange_funcs); j++)
if ( stringbits((char *)Exchange_funcs[i]->name) == stringbits((char *)Exchange_funcs[j]->name) )
{
printf("FIRST 8 chars of Exchange_func[].name must be unique: %d.(%s) vs %d.(%s)\n",i,Exchange_funcs[i]->name,j,Exchange_funcs[j]->name);
exit(-1);
}
}
didinit = 1;
}
char *key,*secret,*userid,*tradepassword; struct exchange_info *exchange; int32_t i,exchangeid;
if ( exchangestr == 0 || exchangestr[0] == 0 )
return(0);
@ -798,18 +852,18 @@ struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson)
printf("exchange_create: cant find.(%s)\n",exchangestr);
return(0);
}
for (i=0; i<sizeof(funcs)/sizeof(*funcs); i++)
for (i=0; i<sizeof(Exchange_funcs)/sizeof(*Exchange_funcs); i++)
{
if ( strcmp(exchangestr,funcs[i].name) == 0 )
if ( strcmp(exchangestr,Exchange_funcs[i]->name) == 0 )
break;
}
if ( i == sizeof(funcs)/sizeof(*funcs) )
if ( i == sizeof(Exchange_funcs)/sizeof(*Exchange_funcs) )
{
printf("cant find exchange.(%s)\n",exchangestr);
return(0);
}
exchange = calloc(1,sizeof(*exchange));
exchange->issue = funcs[i];
exchange->issue = *Exchange_funcs[i];
iguana_initQ(&exchange->pricesQ,"prices");
iguana_initQ(&exchange->requestQ,"request");
iguana_initQ(&exchange->tradebotsQ,"tradebots");
@ -817,6 +871,7 @@ struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson)
iguana_initQ(&exchange->pendingQ[1],"pending1");
exchange->exchangeid = exchangeid;
safecopy(exchange->name,exchangestr,sizeof(exchange->name));
exchange->exchangebits = stringbits(exchange->name);
if ( (exchange->pollgap= juint(argjson,"pollgap")) < EXCHANGES777_MINPOLLGAP )
exchange->pollgap = EXCHANGES777_MINPOLLGAP;
if ( (key= jstr(argjson,"apikey")) != 0 || (key= jstr(argjson,"key")) != 0 )
@ -869,8 +924,8 @@ void exchanges777_init(struct supernet_info *myinfo,cJSON *exchanges,int32_t sle
if ( 1 )
{
argjson = cJSON_CreateObject();
for (i=0; i<sizeof(Exchange_names)/sizeof(*Exchange_names); i++)
if ( (exchange= exchanges777_info(Exchange_names[i],sleepflag,argjson,0)) != 0 )
for (i=0; i<sizeof(Exchange_funcs)/sizeof(*Exchange_funcs); i++)
if ( (exchange= exchanges777_info(Exchange_funcs[i]->name,sleepflag,argjson,0)) != 0 )
myinfo->tradingexchanges[myinfo->numexchanges++] = exchange;
free_json(argjson);
}
@ -1000,8 +1055,8 @@ ZERO_ARGS(InstantDEX,allexchanges)
{
int32_t i; cJSON *retjson,*array;
retjson = cJSON_CreateObject(); array = cJSON_CreateArray();
for (i=0; i<sizeof(Exchange_names)/sizeof(*Exchange_names); i++)
jaddistr(array,Exchange_names[i]);
for (i=0; i<sizeof(Exchange_funcs)/sizeof(*Exchange_funcs); i++)
jaddistr(array,Exchange_funcs[i]->name);
jadd(retjson,"result",array);
return(jprint(retjson,1));
}

9
iguana/iguana_instantdex.c

@ -78,7 +78,7 @@ char *instantdex_sendcmd(struct supernet_info *myinfo,cJSON *argjson,char *cmdst
}
}
int32_t instantdex_updatesources(struct exchange_quote *sortbuf,int32_t n,int32_t max,int32_t ind,int32_t dir,struct exchange_quote *quotes,int32_t numquotes)
int32_t instantdex_updatesources(struct exchange_info *exchange,struct exchange_quote *sortbuf,int32_t n,int32_t max,int32_t ind,int32_t dir,struct exchange_quote *quotes,int32_t numquotes)
{
int32_t i; struct exchange_quote *quote;
//printf("instantdex_updatesources update dir.%d numquotes.%d\n",dir,numquotes);
@ -90,6 +90,7 @@ int32_t instantdex_updatesources(struct exchange_quote *sortbuf,int32_t n,int32_
{
sortbuf[n] = *quote;
sortbuf[n].val = ind;
sortbuf[n].exchangebits = exchange->exchangebits;
//printf("sortbuf[%d] <-\n",n*2);
if ( ++n >= max )
break;
@ -135,9 +136,9 @@ double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *s
for (i=n=0; i<num; i++)
{
if ( dir < 0 && active[i]->numbids > 0 )
n = instantdex_updatesources(sortbuf,n,max,i,1,active[i]->bidasks,active[i]->numbids);
n = instantdex_updatesources(active[i]->exchange,sortbuf,n,max,i,1,active[i]->bidasks,active[i]->numbids);
else if ( dir > 0 && active[i]->numasks > 0 )
n = instantdex_updatesources(sortbuf,n,max,i,-1,&active[i]->bidasks[1],active[i]->numasks);
n = instantdex_updatesources(active[i]->exchange,sortbuf,n,max,i,-1,&active[i]->bidasks[1],active[i]->numasks);
}
//printf("dir.%d %s/%s numX.%d n.%d\n",dir,base,rel,num,n);
if ( dir < 0 )
@ -156,7 +157,7 @@ double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *s
}
if ( totalvol > 0. )
{
*totalvolp = pricesum;
*totalvolp = totalvol;
return(pricesum / totalvol);
}
}

8
iguana/iguana_json.c

@ -82,6 +82,7 @@ cJSON *SuperNET_helpjson()
#define IGUANA_HELP_S(agent,name,str) array = helpjson(IGUANA_ARGS,#agent,#name,helparray(cJSON_CreateArray(),helpitem(#str,"string")))
#define IGUANA_HELP_SS(agent,name,str,str2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string")))
#define IGUANA_HELP_SSS(agent,name,str,str2,str3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string")))
#define IGUANA_HELP_SSSS(agent,name,str,str2,str3,str4) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#str4,"string")))
#define IGUANA_HELP_SSSD(agent,name,str,str2,str3,amount) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#amount,"float")))
#define IGUANA_HELP_SSSDDD(agent,name,str,str2,str3,amount,val2,val3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#amount,"float"),helpitem(#val2,"float"),helpitem(#val3,"float")))
#define IGUANA_HELP_SSSIII(agent,name,str,str2,str3,val,val2,val3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#val,"int"),helpitem(#val2,"int"),helpitem(#val3,"int")))
@ -91,6 +92,7 @@ cJSON *SuperNET_helpjson()
#define IGUANA_HELP_SSHII(agent,name,str,str2,hash,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray5(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#val,"int"),helpitem(#val2,"int")))
#define IGUANA_HELP_SSHHII(agent,name,str,str2,hash,hash2,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#hash2,"hash"),helpitem(#val,"int"),helpitem(#val2,"int")))
#define IGUANA_HELP_SI(agent,name,str,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#val,"int")))
#define IGUANA_HELP_SD(agent,name,str,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#val,"float")))
#define IGUANA_HELP_SII(agent,name,str,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#val,"int"),helpitem(#val2,"int")))
#define IGUANA_HELP_SSI(agent,name,str,str2,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#val,"int")))
#define IGUANA_HELP_SA(agent,name,str,obj) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#obj,"array")))
@ -129,6 +131,7 @@ cJSON *SuperNET_helpjson()
#define STRING_ARG IGUANA_HELP_S
#define TWO_STRINGS IGUANA_HELP_SS
#define THREE_STRINGS IGUANA_HELP_SSS
#define FOUR_STRINGS IGUANA_HELP_SSSS
#define STRING_AND_INT IGUANA_HELP_SI
#define STRING_AND_TWOINTS IGUANA_HELP_SII
#define HASH_AND_STRING IGUANA_HELP_HS
@ -160,6 +163,7 @@ cJSON *SuperNET_helpjson()
#define THREE_STRINGS_AND_THREE_INTS IGUANA_HELP_SSSIII
#define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_HELP_SSSDDD
#define THREE_STRINGS_AND_DOUBLE IGUANA_HELP_SSSD
#define STRING_AND_DOUBLE IGUANA_HELP_SD
#include "../includes/iguana_apideclares.h"
@ -749,7 +753,9 @@ char *SuperNET_parser(struct supernet_info *myinfo,char *agentstr,char *method,c
#define IGUANA_DISPATCH0(agent,name) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS))
#define IGUANA_DISPATCH_S(agent,name,str) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str)))
#define IGUANA_DISPATCH_SS(agent,name,str,str2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2)))
#define IGUANA_DISPATCH_SD(agent,name,str,val) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jdouble(json,#val)))
#define IGUANA_DISPATCH_SSS(agent,name,str,str2,str3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3)))
#define IGUANA_DISPATCH_SSSS(agent,name,str,str2,str3,str4) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jstr(json,#str4)))
#define IGUANA_DISPATCH_SSSD(agent,name,str,str2,str3,amount) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jdouble(json,#amount)))
#define IGUANA_DISPATCH_SSSDDD(agent,name,str,str2,str3,val,val2,val3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jdouble(json,#val),jdouble(json,#val2),jdouble(json,#val3)))
#define IGUANA_DISPATCH_SSSIII(agent,name,str,str2,str3,val,val2,val3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jint(json,#val),jint(json,#val2),jint(json,#val3)))
@ -798,6 +804,7 @@ char *SuperNET_parser(struct supernet_info *myinfo,char *agentstr,char *method,c
#define STRING_ARG IGUANA_DISPATCH_S
#define TWO_STRINGS IGUANA_DISPATCH_SS
#define THREE_STRINGS IGUANA_DISPATCH_SSS
#define FOUR_STRINGS IGUANA_DISPATCH_SSSS
#define STRING_AND_INT IGUANA_DISPATCH_SI
#define STRING_AND_TWOINTS IGUANA_DISPATCH_SII
#define HASH_AND_INT IGUANA_DISPATCH_HI
@ -829,6 +836,7 @@ char *SuperNET_parser(struct supernet_info *myinfo,char *agentstr,char *method,c
#define THREE_STRINGS_AND_THREE_INTS IGUANA_DISPATCH_SSSIII
#define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_DISPATCH_SSSDDD
#define THREE_STRINGS_AND_DOUBLE IGUANA_DISPATCH_SSSD
#define STRING_AND_DOUBLE IGUANA_DISPATCH_SD
#include "../includes/iguana_apideclares.h"
//#undef IGUANA_ARGS

34
iguana/iguana_rpc.c

@ -959,21 +959,25 @@ void iguana_rpcloop(void *args)
sprintf(hdrs,"Access-Control-Allow-Methods: GET, POST\r\n");
sprintf(hdrs,"Cache-Control: no-cache, no-store, must-revalidate\r\n");
sprintf(hdrs,"Content-type: application/javascript\r\n");
sprintf(hdrs,"Content-Length: %8d\r\n",(int32_t)strlen(retstr));
send(sock,hdrs,strlen(hdrs),MSG_NOSIGNAL);*/
char * response ;
char hdrs[1024];
response = malloc(strlen(retstr)+1024+1);
sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\nContent-Length : %8d\r\n\r\n",(int32_t)strlen(retstr));
response[0] = '\0';
strcat(response,hdrs);
strcat(response,retstr);
remains = (int32_t)strlen(response);
i = 0;
sprintf(hdrs,"Content-Length: %8d\r\n",(int32_t)strlen(retstr));
send(sock,hdrs,strlen(hdrs),MSG_NOSIGNAL);*/
char *response,hdrs[1024];
if ( jsonflag != 0 )
{
response = malloc(strlen(retstr)+1024+1);
sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\nContent-Length : %8d\r\n\r\n",(int32_t)strlen(retstr));
response[0] = '\0';
strcat(response,hdrs);
strcat(response,retstr);
if ( retstr != space )
free(retstr);
retstr = response;
}
remains = (int32_t)strlen(retstr);
i = 0;
while ( remains > 0 )
{
if ( (numsent= (int32_t)send(sock,&response[i],remains,MSG_NOSIGNAL)) < 0 )
if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 )
{
if ( errno != EAGAIN && errno != EWOULDBLOCK )
{
@ -989,10 +993,8 @@ void iguana_rpcloop(void *args)
printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen);
}
}
if ( response != space){
if ( retstr != space)
free(retstr);
free(response);
}
}
//if ( Currentjsonstr[0] != 0 )
// strcpy(Prevjsonstr,Currentjsonstr);

38
iguana/iguana_tradebots.c

@ -211,6 +211,44 @@ THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission)
} else return(clonestr("{\"error\":\"tradebots only local usage!\"}"));
}
STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission)
{
int32_t i,n,allfields = 1,depth = 50; cJSON *arg,*array,*item; char *base,*rel,*str,*str2; struct exchange_info *ptr;
if ( remoteaddr == 0 )
{
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
{
if ( (str= InstantDEX_allpairs(myinfo,0,json,remoteaddr,exchange)) != 0 )
{
if ( (arg= cJSON_Parse(str)) != 0 )
{
if ( (array= jarray(&n,arg,"result")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( is_cJSON_Array(item) != 0 && cJSON_GetArraySize(item) == 2 )
{
base = jstr(jitem(item,0),0);
rel = jstr(jitem(item,1),0);
if ( base != 0 && rel != 0 && (str2= exchanges777_Qprices(ptr,base,rel,30,allfields,depth,json,1,commission * .01)) != 0 )
{
printf("%s/%s ",base,rel);
free(str2);
}
}
}
}
free_json(arg);
}
free(str);
}
return(clonestr("{\"result\":\"monitorall started\"}"));
}
else return(clonestr("{\"error\":\"couldnt find/create exchange info\"}"));
} else return(clonestr("{\"error\":\"tradebots only local usage!\"}"));
}
THREE_STRINGS(tradebot,unmonitor,exchange,base,rel)
{
struct exchange_info *ptr;

2
iguana/main.c

@ -320,7 +320,7 @@ void iguana_main(void *arg)
iguana_initQ(&helperQ,"helperQ");
OS_ensure_directory("confs");
OS_ensure_directory("DB");
OS_ensure_directory("DB"), OS_ensure_directory("DB/ECB");
OS_ensure_directory("tmp");
if ( (tmpstr= SuperNET_JSON(myinfo,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"help\"}"),0)) != 0 )
{

7
iguana/pangea777.h

@ -74,10 +74,10 @@ struct player_info
bits256 playerpub;
struct iguana_peer *addr;
uint64_t ipbits,nxt64bits,havemask;
int64_t balance,buyinamount,bets,won,snapshot;
int64_t balance,buyinamount,bets,won,snapshot,actualbet;
uint32_t handrank;
uint8_t hand[7];
int8_t ind,action,betstatus,turni;
int8_t ind,action,betstatus,turni,actualaction;
char handle[32];
};
@ -171,7 +171,7 @@ int32_t pangea_queueprocess(struct supernet_info *myinfo,struct table_info *tp);
void pangea_update(struct supernet_info *myinfo);
void pangea_checkantes(struct supernet_info *myinfo,struct table_info *tp);
int32_t pangea_bet(struct supernet_info *myinfo,struct table_info *tp,struct player_info *player,int64_t bet,int32_t action);
int32_t pangea_playerbet(struct supernet_info *myinfo,int64_t *actualbetp,struct table_info *tp,struct player_info *player,int64_t bet,int32_t action);
int32_t pangea_sidepots(struct supernet_info *myinfo,struct table_info *tp,int32_t dispflag,int64_t sidepots[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS],int64_t *bets);
int64_t pangea_splitpot(struct supernet_info *myinfo,struct table_info *tp,uint64_t *pangearakep,int64_t sidepot[CARDS777_MAXPLAYERS],int32_t rakemillis);
@ -192,6 +192,7 @@ void pangea_confirm(PANGEA_HANDARGS);
void pangea_action(PANGEA_HANDARGS);
void pangea_showdown(PANGEA_HANDARGS);
void pangea_summary(PANGEA_HANDARGS);
int64_t pangea_chipsvalue(struct supernet_info *myinfo,struct table_info *tp,int32_t numchips);
extern int32_t Debuglevel,PANGEA_MAXTHREADS,Showmode,Autofold;

193
iguana/pangea_api.c

@ -185,7 +185,7 @@ struct table_info *pangea_table(bits256 tablehash,int32_t N)
{
struct table_info *tp; bits256 pangeahash; char str[65];
pangeahash = calc_categoryhashes(0,"pangea",0);
if ( (tp= category_info(pangeahash,tablehash)) == 0 )
if ( (tp= category_info(pangeahash,tablehash)) == 0 && N > 0 )
{
tp = pangea_tablealloc(0,N);
memset(tp,0,sizeof(*tp));
@ -205,6 +205,19 @@ struct table_info *pangea_table(bits256 tablehash,int32_t N)
return(tp);
}
struct player_info *pangea_playerfind(struct supernet_info *myinfo,struct table_info *tp)
{
struct player_info *player;
if ( tp->priv.myind >= 0 && tp->priv.myind < tp->G.numactive )
{
player = tp->active[tp->priv.myind];
if ( memcmp(player->playerpub.bytes,myinfo->myaddr.persistent.bytes,sizeof(player->playerpub)) == 0 )
return(player);
char str[65],str2[65]; printf("unexpected playerpub mismatch %s vs %s\n",bits256_str(str,player->playerpub),bits256_str(str2,myinfo->myaddr.persistent));
}
return(0);
}
char *pangea_jsondatacmd(struct supernet_info *myinfo,bits256 tablehash,struct pangea_msghdr *pm,cJSON *json,char *cmdstr,char *ipaddr)
{
cJSON *argjson; char *reqstr,hexstr[8192]; uint64_t nxt64bits;
@ -212,7 +225,7 @@ char *pangea_jsondatacmd(struct supernet_info *myinfo,bits256 tablehash,struct p
pangeahash = calc_categoryhashes(0,"pangea",0);
category_subscribe(myinfo,pangeahash,GENESIS_PUBKEY);
category_subscribe(myinfo,pangeahash,tablehash);
argjson = cJSON_CreateObject();//SuperNET_argjson(json);
argjson = json != 0 ? jduplicate(json) : cJSON_CreateObject();
jaddstr(argjson,"cmd",cmdstr);
if ( myinfo->ipaddr[0] == 0 || strncmp(myinfo->ipaddr,"127.0.0.1",strlen("127.0.0.1")) == 0 )
return(clonestr("{\"error\":\"need to send your ipaddr for now\"}"));
@ -297,21 +310,6 @@ void pangea_sendcmd(struct supernet_info *myinfo,struct table_info *tp,char *cmd
free(pm);
}
void pangea_ping(PANGEA_HANDARGS)
{
}
void pangea_ready(PANGEA_HANDARGS)
{
}
void pangea_addfunds(PANGEA_HANDARGS)
{
}
void pangea_tablejoin(struct supernet_info *myinfo,struct table_info *tp,uint8_t *data,int32_t datalen,uint64_t signer64bits,uint32_t sigtimestamp,bits256 sigtablehash)
{
char str[65],str2[65],space[4096]; int32_t i; cJSON *json;
@ -334,7 +332,7 @@ void pangea_tablejoin(struct supernet_info *myinfo,struct table_info *tp,uint8_t
printf("add player.%d %p\n",i,tp);
if ( tp->G.creatorbits == myinfo->myaddr.nxt64bits )
{
pangea_jsondatacmd(myinfo,sigtablehash,(struct pangea_msghdr *)space,json,"accept",myinfo->ipaddr);
pangea_jsondatacmd(myinfo,sigtablehash,(struct pangea_msghdr *)space,0,"accept",myinfo->ipaddr);
printf("my table! ");
}
} else printf("duplicate player.%llu\n",(long long)signer64bits);
@ -436,15 +434,32 @@ void pangea_parse(struct supernet_info *myinfo,struct pangea_msghdr *pm,cJSON *a
printf("ACCEPT.(%s)\n",jprint(argjson,0));
//pangea_tableaccept(myinfo,pm,tp,pm->serialized,(int32_t)(pm->sig.allocsize - sizeof(*pm)));
}
else if ( strcmp(method,"addfunds") == 0 )
{
printf("ADDFUNDS.(%s)\n",jprint(argjson,0));
}
else if ( strcmp(method,"buyin") == 0 )
{
printf("BUYIN.(%s)\n",jprint(argjson,0));
}
else if ( strcmp(method,"status") == 0 )
{
printf("STATUS.(%s)\n",jprint(argjson,0));
}
}
}
void pangea_addfunds(PANGEA_HANDARGS)
{
printf("got remote addfunds\n");
}
char *pangea_hexmsg(struct supernet_info *myinfo,void *data,int32_t len,char *remoteaddr)
{
static struct { char *cmdstr; void (*func)(PANGEA_HANDARGS); uint64_t cmdbits; } tablecmds[] =
{
//{ "newtable", pangea_tablecreate }, { "join", pangea_tablejoin }, { "accept", pangea_tableaccept },
{ "addfunds", pangea_addfunds }, { "ping", pangea_ping }, { "ready", pangea_ready },
{ "addfunds", pangea_addfunds }, //{ "ping", pangea_ping }, { "ready", pangea_ready },
{ "newhand", pangea_newhand }, { "gothand", pangea_gothand },
{ "encoded", pangea_encoded }, { "sentencoded", pangea_sentencoded },
{ "final", pangea_final }, { "gotfinal", pangea_gotfinal },
@ -680,9 +695,123 @@ HASH_AND_ARRAY(pangea,history,tablehash,params)
return(_pangea_history(myinfo,tablehash,json));
}*/
char *pangea_submitaction(struct supernet_info *myinfo,struct table_info *tp,int64_t bet,int32_t action,char *name)
{
char retbuf[1024]; struct player_info *player;
if ( (player= pangea_playerfind(myinfo,tp)) != 0 )
{
pangea_action(myinfo,tp->G.numactive,action,action,-1,tp->priv.myind,tp,(uint8_t *)&bet,sizeof(bet));
if ( player->actualaction != action )
sprintf(retbuf,"{\"result\":\"submitted %s, but got mismatched\",\"action\":\"%d\",\"expected\":\"%d\",\"bet\":%.8f}",name,action,player->actualaction,dstr(player->actualbet));
else sprintf(retbuf,"{\"result\":\"success\",\"broadcast\":\"%s\",\"bet\":%.8f}",name,dstr(player->actualbet));
return(clonestr(retbuf));
} else return(clonestr("{\"error\":\"not a player on the table\"}"));
}
HASH_ARG(pangea,call,tablehash)
{
struct table_info *tp;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (tp= pangea_table(tablehash,0)) == 0 )
return(clonestr("{\"result\":\"table doesnt exist\"}"));
else return(pangea_submitaction(myinfo,tp,0,CARDS777_CALL,"call"));
}
HASH_AND_INT(pangea,raise,tablehash,numchips)
{
struct table_info *tp; int64_t value;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (tp= pangea_table(tablehash,0)) == 0 )
return(clonestr("{\"result\":\"table doesnt exist\"}"));
else
{
value = pangea_chipsvalue(myinfo,tp,numchips);
return(pangea_submitaction(myinfo,tp,value,CARDS777_RAISE,"raise"));
}
}
HASH_ARG(pangea,allin,tablehash)
{
struct table_info *tp;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (tp= pangea_table(tablehash,0)) == 0 )
return(clonestr("{\"result\":\"table doesnt exist\"}"));
else return(pangea_submitaction(myinfo,tp,0,CARDS777_ALLIN,"allin"));
}
HASH_AND_INT(pangea,bet,tablehash,numchips)
{
struct table_info *tp; int64_t value;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (tp= pangea_table(tablehash,0)) == 0 )
return(clonestr("{\"result\":\"table doesnt exist\"}"));
else
{
value = pangea_chipsvalue(myinfo,tp,numchips);
return(pangea_submitaction(myinfo,tp,value,CARDS777_BET,"bet"));
}
}
HASH_ARG(pangea,check,tablehash)
{
struct table_info *tp;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (tp= pangea_table(tablehash,0)) == 0 )
return(clonestr("{\"result\":\"table doesnt exist\"}"));
else return(pangea_submitaction(myinfo,tp,0,CARDS777_CHECK,"check"));
}
HASH_ARG(pangea,fold,tablehash)
{
struct table_info *tp;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (tp= pangea_table(tablehash,0)) == 0 )
return(clonestr("{\"result\":\"table doesnt exist\"}"));
else return(pangea_submitaction(myinfo,tp,0,CARDS777_FOLD,"fold"));
}
HASH_ARG(pangea,status,tablehash)
{
struct table_info *tp;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (tp= pangea_table(tablehash,0)) == 0 )
return(clonestr("{\"result\":\"table doesnt exist\"}"));
else return(jprint(pangea_tablestatus(myinfo,tp),1));
}
HASH_AND_STRING(pangea,mode,tablehash,params)
{
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
return(clonestr("{\"result\":\"mode not active yet\"}"));
}
HASH_ARG(pangea,history,tablehash)
{
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
return(clonestr("{\"result\":\"history not active yet\"}"));
}
HASH_AND_INT(pangea,handhistory,tablehash,hand)
{
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
return(clonestr("{\"result\":\"handhistory not active yet\"}"));
}
ZERO_ARGS(pangea,lobby)
{
//cJSON *retjson,*argjson; char *retstr,*result; uint8_t *buf; int32_t flag,len; struct pangea_msghdr *pm;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
bits256 pangeahash = calc_categoryhashes(0,"pangea",0);
category_subscribe(myinfo,pangeahash,GENESIS_PUBKEY);
pangea_update(myinfo);
@ -692,6 +821,8 @@ ZERO_ARGS(pangea,lobby)
INT_AND_ARRAY(pangea,host,minplayers,params)
{
bits256 tablehash; struct table_info *tp; uint8_t space[sizeof(struct pangea_msghdr) + 4096];
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
OS_randombytes(tablehash.bytes,sizeof(tablehash));
tp = pangea_table(tablehash,9);
if ( tp != 0 )
@ -705,12 +836,32 @@ INT_AND_ARRAY(pangea,host,minplayers,params)
HASH_AND_STRING(pangea,join,tablehash,handle)
{
uint8_t space[sizeof(struct pangea_msghdr) + 4096];
return(pangea_jsondatacmd(myinfo,tablehash,(struct pangea_msghdr *)space,json,"join",myinfo->ipaddr));
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
return(pangea_jsondatacmd(myinfo,tablehash,(struct pangea_msghdr *)space,0,"join",myinfo->ipaddr));
}
HASH_AND_INT(pangea,buyin,tablehash,numchips)
{
uint8_t space[sizeof(struct pangea_msghdr) + 4096]; struct table_info *tp; int64_t value; cJSON *fundsjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (tp= pangea_table(tablehash,0)) == 0 )
return(clonestr("{\"result\":\"table doesnt exist\"}"));
else
{
value = pangea_chipsvalue(myinfo,tp,numchips);
fundsjson = cJSON_CreateObject();
jaddnum(fundsjson,"amount",dstr(value));
return(pangea_jsondatacmd(myinfo,tablehash,(struct pangea_msghdr *)space,fundsjson,"addfunds",myinfo->ipaddr));
}
}
HASH_AND_ARRAY(pangea,start,tablehash,params)
HASH_ARG(pangea,start,tablehash)
{
struct table_info *tp; int32_t allocsize;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( (tp= pangea_table(tablehash,9)) != 0 )
{
if ( tp->G.numactive >= tp->G.minplayers && pangea_tableismine(myinfo,tp) >= 0 )

42
iguana/pangea_bets.c

@ -15,7 +15,12 @@
#include "pangea777.h"
void pangea_fold(struct supernet_info *myinfo,struct table_info *tp,struct player_info *player)
int64_t pangea_chipsvalue(struct supernet_info *myinfo,struct table_info *tp,int32_t numchips)
{
return((tp->G.bigblind >> 1) * numchips);
}
void pangea_playerfold(struct supernet_info *myinfo,struct table_info *tp,struct player_info *player)
{
uint8_t tmp;
//printf("player.%d folded\n",player); //getchar();
@ -26,15 +31,28 @@ void pangea_fold(struct supernet_info *myinfo,struct table_info *tp,struct playe
pangea_summaryadd(myinfo,tp,CARDS777_FOLD,&tmp,sizeof(tmp),(void *)&player->bets,sizeof(player->bets));
}
int32_t pangea_bet(struct supernet_info *myinfo,struct table_info *tp,struct player_info *player,int64_t bet,int32_t action)
int32_t pangea_playerbet(struct supernet_info *myinfo,int64_t *actualbetp,struct table_info *tp,struct player_info *player,int64_t bet,int32_t action)
{
uint64_t sum; uint8_t tmp; struct hand_info *hand = &tp->hand;
if ( bet == 0 ) // autobet
{
if ( action == CARDS777_CALL )
bet = hand->betsize;
else if ( action == CARDS777_BET )
bet = hand->betsize + hand->lastraise;
else if ( action == CARDS777_RAISE )
bet = hand->betsize + hand->lastraise * 2;
bet -= player->bets;
}
*actualbetp = 0;
if ( Debuglevel > 2 )
printf("PANGEA_BET[%d] <- %.8f\n",player->ind,dstr(bet));
if ( player->betstatus == CARDS777_ALLIN )
return(CARDS777_ALLIN);
else if ( player->betstatus == CARDS777_FOLD )
return(CARDS777_FOLD);
else if ( action == CARDS777_ALLIN )
bet = player->balance;
if ( bet > 0 && bet >= player->balance )
{
bet = player->balance;
@ -52,7 +70,7 @@ int32_t pangea_bet(struct supernet_info *myinfo,struct table_info *tp,struct pla
sum = player->bets;
if ( sum+bet < hand->betsize && action != CARDS777_ALLIN )
{
pangea_fold(myinfo,tp,player);
pangea_playerfold(myinfo,tp,player);
action = CARDS777_FOLD;
if ( Debuglevel > 2 )
printf("player.%d betsize %.8f < hand.betsize %.8f FOLD\n",player->ind,dstr(bet),dstr(hand->betsize));
@ -84,20 +102,21 @@ int32_t pangea_bet(struct supernet_info *myinfo,struct table_info *tp,struct pla
tmp = player->ind;
pangea_summaryadd(myinfo,tp,action,&tmp,sizeof(tmp),(void *)&bet,sizeof(bet));
player->balance -= bet, player->bets += bet;
if ( Debuglevel > 2 )
//if ( Debuglevel > 2 )
printf("player.%d: player.%d BET %f -> balances %f bets %f\n",tp->priv.myind,player->ind,dstr(bet),dstr(player->balance),dstr(player->bets));
*actualbetp = bet;
return(action);
}
void pangea_antes(struct supernet_info *myinfo,struct table_info *tp)
{
int32_t i,n,N; struct player_info *p; uint64_t threshold; int32_t handid;
int32_t i,n,N; struct player_info *p; uint64_t threshold; int32_t handid; int64_t actualbet;
N = tp->G.numactive;
for (i=0; i<tp->G.N; i++)
{
tp->G.P[i].ind = i;
if ( (tp->snapshot[i]= tp->G.P[i].balance) <= 0 )
pangea_fold(myinfo,tp,&tp->G.P[i]);
pangea_playerfold(myinfo,tp,&tp->G.P[i]);
}
handid = tp->numhands - 1;
pangea_summaryadd(myinfo,tp,CARDS777_SNAPSHOT,(void *)&handid,sizeof(handid),(void *)tp->snapshot,sizeof(uint64_t)*CARDS777_MAXPLAYERS);
@ -108,8 +127,8 @@ void pangea_antes(struct supernet_info *myinfo,struct table_info *tp)
if ( (p= tp->active[i]) != 0 )
{
if ( p->balance < tp->G.ante )
pangea_fold(myinfo,tp,p);
else pangea_bet(myinfo,tp,p,tp->G.ante,CARDS777_ANTE);
pangea_playerfold(myinfo,tp,p);
else pangea_playerbet(myinfo,&actualbet,tp,p,tp->G.ante,CARDS777_ANTE);
} else printf("unexpected null player ptr\n");
}
}
@ -121,16 +140,15 @@ void pangea_antes(struct supernet_info *myinfo,struct table_info *tp)
threshold = tp->G.bigblind - 1;
else threshold = 0;
if ( (p= tp->active[i]) != 0 && p->balance < threshold )
pangea_fold(myinfo,tp,p);
pangea_playerfold(myinfo,tp,p);
else n++;
}
if ( n < 2 )
printf("pangea_antes not enough players n.%d\n",n);
else
{
pangea_bet(myinfo,tp,tp->active[0],(tp->G.bigblind>>1),CARDS777_SMALLBLIND);
pangea_bet(myinfo,tp,tp->active[1],tp->G.bigblind,CARDS777_BIGBLIND);
pangea_playerbet(myinfo,&actualbet,tp,tp->active[0],(tp->G.bigblind>>1),CARDS777_SMALLBLIND);
pangea_playerbet(myinfo,&actualbet,tp,tp->active[1],tp->G.bigblind,CARDS777_BIGBLIND);
}
}

4
iguana/pangea_hand.c

@ -824,7 +824,7 @@ int32_t pangea_lastman(struct supernet_info *myinfo,struct table_info *tp)
void pangea_action(PANGEA_HANDARGS)
{
uint32_t now; struct player_info *p; int64_t x,snapshot[CARDS777_MAXPLAYERS + 1]; int32_t action,i,j;
bits256 audit[CARDS777_MAXPLAYERS]; struct hand_info *hand; uint8_t tmp; uint64_t amount = 0;
bits256 audit[CARDS777_MAXPLAYERS]; struct hand_info *hand; uint8_t tmp; int64_t amount = 0;
hand = &tp->hand;
p = tp->active[senderind];
memcpy(&amount,data,sizeof(amount));
@ -840,8 +840,8 @@ void pangea_action(PANGEA_HANDARGS)
return;
}
tmp = senderind;
pangea_bet(myinfo,tp,tp->active[senderind],amount,CARDS777_CHECK);
p->action = action;
p->actualaction = pangea_playerbet(myinfo,&p->actualbet,tp,tp->active[senderind],amount,CARDS777_CHECK);
hand->undergun = (hand->undergun + 1) % N;
hand->numactions++;
//if ( Debuglevel > 2 )//|| tp->priv.myind == 0 )

30
iguana/pangea_json.c

@ -25,7 +25,7 @@ cJSON *pangea_playerjson(struct supernet_info *myinfo,struct table_info *tp,stru
return(json);
}
cJSON *pangea_tablejson(struct supernet_info *myinfo,struct table_info *tp)
/*cJSON *pangea_tablejson(struct supernet_info *myinfo,struct table_info *tp)
{
char ipaddr[64],str[64]; int32_t i; cJSON *array,*json; struct game_info *gp;
gp = &tp->G;
@ -64,9 +64,8 @@ cJSON *pangea_tablejson(struct supernet_info *myinfo,struct table_info *tp)
jadd(json,"players",array);
}
jaddnum(json,"numactive",tp->G.numactive);
printf("tp.%p\n",tp);
return(json);
}
}*/
void pangea_gamecreate(struct game_info *gp,uint32_t timestamp,bits256 tablehash,cJSON *json)
{
@ -116,7 +115,7 @@ cJSON *pangea_lobbyjson(struct supernet_info *myinfo)
HASH_ITER(hh,cat->sub,sub,tmp)
{
if ( (tp= sub->info) != 0 && pangea_opentable(&tp->G) > 0 )
jaddi(array,pangea_tablejson(myinfo,tp));
jaddi(array,pangea_tablestatus(myinfo,tp));
}
}
jadd(retjson,"tables",array);
@ -203,10 +202,29 @@ cJSON *pangea_tablestatus(struct supernet_info *myinfo,struct table_info *tp)
jaddnum(json,"pangearake",dstr(gp->pangearake));
jaddnum(json,"bigblind",dstr(gp->bigblind));
jaddnum(json,"ante",dstr(gp->ante));
array = cJSON_CreateArray();
if ( gp->opentime != 0 )
{
char utcbuf[65];
jaddstr(json,"opentime",utc_str(utcbuf,gp->opentime));
if ( gp->started != 0 )
{
jaddstr(json,"started",utc_str(utcbuf,gp->started));
if ( gp->finished != 0 )
jaddstr(json,"finished",utc_str(utcbuf,gp->finished));
}
}
if ( tp->G.numactive > 0 )
{
array = cJSON_CreateArray();
for (i=0; i<tp->G.numactive; i++)
jaddi(array,pangea_playerjson(myinfo,tp,&tp->G.P[i]));
jadd(json,"players",array);
}
jaddnum(json,"numactive",tp->G.numactive);
/*array = cJSON_CreateArray();
for (i=0; i<tp->G.numactive; i++)
jaddi64bits(array,tp->active[i]!=0?tp->active[i]->nxt64bits:0);
jadd(json,"addrs",array);
jadd(json,"addrs",array);*/
total = 0;
for (iter=0; iter<6; iter++)
{

689
iguana/peggy.c

@ -0,0 +1,689 @@
/******************************************************************************
* 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 "peggy.h"
#include "exchanges777.h"
int32_t Peggy_inds[539] = {289, 404, 50, 490, 59, 208, 87, 508, 366, 288, 13, 38, 159, 440, 120, 480, 361, 104, 534, 195, 300, 362, 489, 108, 143, 220, 131, 244, 133, 473, 315, 439, 210, 456, 219, 352, 153, 444, 397, 491, 286, 479, 519, 384, 126, 369, 155, 427, 373, 360, 135, 297, 256, 506, 322, 425, 501, 251, 75, 18, 420, 537, 443, 438, 407, 145, 173, 78, 340, 240, 422, 160, 329, 32, 127, 128, 415, 495, 372, 522, 60, 238, 129, 364, 471, 140, 171, 215, 378, 292, 432, 526, 252, 389, 459, 350, 233, 408, 433, 51, 423, 19, 62, 115, 211, 22, 247, 197, 530, 7, 492, 5, 53, 318, 313, 283, 169, 464, 224, 282, 514, 385, 228, 175, 494, 237, 446, 105, 150, 338, 346, 510, 6, 348, 89, 63, 536, 442, 414, 209, 216, 227, 380, 72, 319, 259, 305, 334, 236, 103, 400, 176, 267, 355, 429, 134, 257, 527, 111, 287, 386, 15, 392, 535, 405, 23, 447, 399, 291, 112, 74, 36, 435, 434, 330, 520, 335, 201, 478, 17, 162, 483, 33, 130, 436, 395, 93, 298, 498, 511, 66, 487, 218, 65, 309, 419, 48, 214, 377, 409, 462, 139, 349, 4, 513, 497, 394, 170, 307, 241, 185, 454, 29, 367, 465, 194, 398, 301, 229, 212, 477, 303, 39, 524, 451, 116, 532, 30, 344, 85, 186, 202, 517, 531, 515, 230, 331, 466, 147, 426, 234, 304, 64, 100, 416, 336, 199, 383, 200, 166, 258, 95, 188, 246, 136, 90, 68, 45, 312, 354, 184, 314, 518, 326, 401, 269, 217, 512, 81, 88, 272, 14, 413, 328, 393, 198, 226, 381, 161, 474, 353, 337, 294, 295, 302, 505, 137, 207, 249, 46, 98, 27, 458, 482, 262, 253, 71, 25, 0, 40, 525, 122, 341, 107, 80, 165, 243, 168, 250, 375, 151, 503, 124, 52, 343, 371, 206, 178, 528, 232, 424, 163, 273, 191, 149, 493, 177, 144, 193, 388, 1, 412, 265, 457, 255, 475, 223, 41, 430, 76, 102, 132, 96, 97, 316, 472, 213, 263, 3, 317, 324, 274, 396, 486, 254, 205, 285, 101, 21, 279, 58, 467, 271, 92, 538, 516, 235, 332, 117, 500, 529, 113, 445, 390, 358, 79, 34, 488, 245, 83, 509, 203, 476, 496, 347, 280, 12, 84, 485, 323, 452, 10, 146, 391, 293, 86, 94, 523, 299, 91, 164, 363, 402, 110, 321, 181, 138, 192, 469, 351, 276, 308, 277, 428, 182, 260, 55, 152, 157, 382, 121, 507, 225, 61, 431, 31, 106, 327, 154, 16, 49, 499, 73, 70, 449, 460, 187, 24, 248, 311, 275, 158, 387, 125, 67, 284, 35, 463, 190, 179, 266, 376, 221, 42, 26, 290, 357, 268, 43, 167, 99, 374, 242, 156, 239, 403, 339, 183, 320, 180, 306, 379, 441, 20, 481, 141, 77, 484, 69, 410, 502, 172, 417, 118, 461, 261, 47, 333, 450, 296, 453, 368, 359, 437, 421, 264, 504, 281, 270, 114, 278, 56, 406, 448, 411, 521, 418, 470, 123, 455, 148, 356, 468, 109, 204, 533, 365, 8, 345, 174, 370, 28, 57, 11, 2, 231, 310, 196, 119, 82, 325, 44, 342, 37, 189, 142, 222, 9, 54, };
char *peggy_mapname(char *basebuf,char *relbuf,int32_t i) // sorry it is messy thing
{
char *base,*rel,buf[16];
base = rel = 0;
strcpy(buf,peggy_bases[i]);
base = buf, rel = "BTCD";
if ( strlen(buf) > 3 && strcmp(buf+strlen(buf)-3,"USD") == 0 )
{
if ( strcmp(buf,"BTCUSD") == 0 )
base = "BTC";
buf[strlen(buf)-3] = 0;
}
else if ( strcmp(buf,"COPPER") == 0 || strcmp(buf,"NGAS") == 0 || strcmp(buf,"UKOIL") == 0 || strcmp(buf,"USOIL") == 0 || strcmp(buf,"US30") == 0 || strcmp(buf,"SPX500") == 0 || strcmp(buf,"NAS100") == 0 )
rel = "USD";
else if ( strcmp(buf,"BUND") == 0 )
rel = "yield";
else if ( strcmp(buf,"EUSTX50") == 0 )
rel = "EUR";
else if ( strcmp(buf,"JPN225") == 0 )
rel = "JPY";
else if ( strcmp(buf,"UK100") == 0 )
rel = "GBP";
else if ( strcmp(buf,"GER30") == 0 )
rel = "EUR";
else if ( strcmp(buf,"SUI30") == 0 )
rel = "CHF";
else if ( strcmp(buf,"AUS200") == 0 )
rel = "AUD";
else if ( strcmp(buf,"HKG33") == 0 )
rel = "HKD";
else if ( strlen(buf) > 3 && strcmp(buf+strlen(buf)-3,"BTC") == 0 )
base = buf, buf[strlen(buf)-3] = 0;
if ( i == sizeof(peggy_bases)/sizeof(*peggy_bases)-1 && strcmp(peggy_bases[i],"BTCUSD") == 0 )
base = "BTC", rel = "USD";
else if ( i == sizeof(peggy_bases)/sizeof(*peggy_bases)-2 && strcmp(peggy_bases[i],"BTCCNY") == 0 )
base = "BTC", rel = "CNY";
else if ( i == sizeof(peggy_bases)/sizeof(*peggy_bases)-3 && strcmp(peggy_bases[i],"BTCRUB") == 0 )
base = "BTC", rel = "RUB";
else if ( i == sizeof(peggy_bases)/sizeof(*peggy_bases)-4 && strcmp(peggy_bases[i],"XAUUSD") == 0 )
base = "XAU", rel = "USD";
else if ( i == 0 )
base = "BTCD", rel = "maincurrency peggy, realtime";
basebuf[0] = relbuf[0] = 0;
if ( rel != 0 )
strcpy(relbuf,rel);//, printf("rel.(%s) ",rel);
if ( base != 0 )
strcpy(basebuf,base);//, printf("base.(%s) ",base);
return(basebuf);
}
uint64_t peggy_basebits(char *name)
{
int32_t i; char basebuf[64],relbuf[64];
for (i=0; i<64; i++)
{
if ( strcmp(name,peggy_bases[i]) == 0 )
{
peggy_mapname(basebuf,relbuf,i);
return(stringbits(basebuf));
}
}
return(0);
}
uint64_t peggy_relbits(char *name)
{
int32_t i; char basebuf[64],relbuf[64];
for (i=0; i<64; i++)
{
if ( strcmp(name,peggy_bases[i]) == 0 )
{
peggy_mapname(basebuf,relbuf,i);
return(stringbits(relbuf));
}
}
return(0);
}
static uint64_t peggy_assetbits(char *name) { return((is_decimalstr(name) != 0) ? calc_nxt64bits(name) : stringbits(name)); }
int32_t find_uint64(int32_t *emptyslotp,uint64_t *nums,long max,uint64_t val)
{
int32_t i;
*emptyslotp = -1;
for (i=0; i<max; i++)
{
if ( nums[i] == 0 )
{
*emptyslotp = i;
break;
}
else if ( nums[i] == val )
{
if ( Debuglevel > 2 )
printf("found in slot[%d] %llx\n",i,(long long)val);
return(i);
}
}
if ( Debuglevel > 2 )
printf("emptyslot[%d] for %llx\n",i,(long long)val);
return(-1);
}
int32_t add_uint64(uint64_t *nums,long max,uint64_t val)
{
int32_t i,emptyslot;
if ( (i= find_uint64(&emptyslot,nums,max,val)) >= 0 )
return(i);
else if ( emptyslot >= 0 )
{
nums[emptyslot] = val;
return(emptyslot);
} else return(-1);
}
// init time
void peggy_descriptions(struct peggy_info *PEGS,struct peggy_description *P,char *name,char *base,char *rel)
{
int32_t emptyslot;
strcpy(P->name,name), strcpy(P->base,base);
if ( rel != 0 )
strcpy(P->rel,rel);
P->assetbits = peggy_assetbits(name), P->basebits = stringbits(base), P->relbits = stringbits(P->rel);
P->baseid = add_uint64(PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->basebits);
P->relid = add_uint64(PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->relbits);
if ( find_uint64(&emptyslot,PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->basebits) != P->baseid )
printf("(%s) (%s) (%s) error cant find baseid.%d for %llx\n",name,base,P->rel,P->baseid,(long long)P->basebits);
if ( P->relbits != 0 && find_uint64(&emptyslot,PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->relbits) != P->relid )
printf("(%s) (%s) (%s) error cant find relid.%d for %llx\n",name,base,P->rel,P->relid,(long long)P->relbits);
}
/*int32_t peggy_timeframes(struct peggy_limits *limits,int64_t *scales,uint32_t *timeframes,int32_t numtimeframes,uint64_t maxsupply,uint64_t maxnetbalance)
{
int32_t i;
memset(limits,0,sizeof(*limits));
limits->maxsupply = maxsupply, limits->maxnetbalance = maxnetbalance;
if ( limits->maxsupply < 0 || limits->maxnetbalance < 0 )
{
printf("peggy_check_limits: maxnetbalance %lld > %d\n",(long long)limits->maxnetbalance,(int32_t)PRICE_RESOLUTION);
return(-1);
}
limits->numtimeframes = (numtimeframes <= MAX_TIMEFRAMES) ? numtimeframes : MAX_TIMEFRAMES;
for (i=0; i<limits->numtimeframes; i++)
{
limits->scales[i] = scales[i];
if ( (limits->timeframes[i]= PEGGY_DAYTICKS * timeframes[i]) > MAX_TIMEFRAME || (i > 0 && limits->timeframes[i] <= limits->timeframes[i-1]) )
{
printf("createpeg: illegal timeframe.%d: %d %d vs %d\n",i,timeframes[i],limits->timeframes[i],MAX_TIMEFRAME);
getchar(); return(-1);
}
}
limits->timeframes[0] = 0;
return(0);
}*/
int32_t peggy_lockparms(struct peggy_lock *dest,int32_t peg,struct peggy_lock *lockparms)
{
if ( lockparms->minlockdays > lockparms->maxlockdays )
{
printf("peggy_check_lockparms: minlockdays %d > %d maxlockdays\n",lockparms->minlockdays,lockparms->maxlockdays);
return(-1);
}
if ( lockparms->mixrange == 0 )
lockparms->mixrange = PEGGY_MIXRANGE;
if ( lockparms->extralockdays < PEGGY_MINEXTRADAYS * 2 )
lockparms->extralockdays = PEGGY_MINEXTRADAYS * 2;
*dest = *lockparms, dest->peg = peg;
return(0);
}
int32_t peggy_setvars(struct peggy_info *PEGS,struct peggy *PEG,int16_t baseid,int16_t relid,int32_t peg,uint64_t maxsupply,uint64_t maxnetbalance,struct peggy_lock *lockparms,uint32_t unitincr,int32_t dailyrate,struct price_resolution *initialprices,int32_t numprices,int32_t hasprice)
{
int32_t i;
PEG->name.id = peg, PEG->name.hasprice = hasprice;
//if ( peggy_timeframes(&PEG->limits,limits->scales,limits->timeframes,limits->numtimeframes,limits->maxsupply,limits->maxnetbalance) < 0 )
// return(-1);
if ( peggy_lockparms(&PEG->lockparms,peg,lockparms) < 0 )
return(-1);
PEG->unitincr = unitincr;
PEG->maxdailyrate = dailyrate;
PEG->maxsupply = maxsupply, PEG->maxnetbalance = maxnetbalance;
if ( initialprices != 0 )
{
if ( numprices > 0 )
{
//if ( initialprices[0].Pval >= PRICE_RESOLUTION_MAXPVAL )
// initialprices[0].Pval = PRICE_RESOLUTION_MAXPVAL;
PEG->genesisprice = PEG->dayprice = PEG->price = initialprices[0];
for (i=0; i<numprices; i++)
peggy_setprice(PEG,initialprices[i],i);
}
else if ( peg != 0 )
return(-1);
}
return(0);
}
struct price_resolution peggy_scaleprice(struct price_resolution price,int64_t peggymils)
{
price.Pval = (10000 * price.Pval) / peggymils;
return(price);
}
struct peggy *peggy_createpair(struct peggy_info *PEGS,int64_t quorum,int64_t decisionthreshold,char *name,char *base,char *rel,uint64_t maxsupply,uint64_t maxnetbalance,struct peggy_lock *lockparms,uint32_t unitincr,int32_t maxdailyrate,uint32_t firsttimestamp,struct price_resolution *initialprices,int32_t numprices,struct price_resolution spread,uint16_t maxmargin,struct price_resolution mindenomination,int32_t contractnum,int32_t hasprice,int32_t peggymils)
{
struct peggy *PEG; char *maincurrency; uint64_t assetbits,mainunitsize; int32_t i;
maincurrency = PEGS->maincurrency, mainunitsize = PEGS->mainunitsize;
if ( lockparms == 0 )
lockparms = &PEGS->default_lockparms;
//if ( limits == 0 )
// limits = &PEGS->default_limits;
if ( (PEGS->numpegs == 0 && stringbits(base) != PEGS->mainbits) || maxmargin > PEGGY_MARGINMAX )
{
printf("peggy_create: numpegs.%d mismatched maincurrency.(%s) || illegal maxmargin.%d vs %d\n",PEGS->numpegs,maincurrency,maxmargin,PEGGY_MARGINMAX);
return(0);
}
if ( firsttimestamp + (numprices-1)*PEGGY_DAYTICKS > time(NULL) )
{
printf("peggy_createpair latest price must be in the past: 1st.%u + numprices.%d -> %u vs %u\n",firsttimestamp,numprices,firsttimestamp + (numprices-1)*PEGGY_DAYTICKS,(uint32_t)time(NULL));
return(0);
}
if ( quorum == 0 )
quorum = PEGS->quorum;
if ( decisionthreshold == 0 )
decisionthreshold = PEGS->decisionthreshold;
assetbits = peggy_assetbits(name);
if ( PEGS->numpegs > 0 )
{
for (i=0; i<PEGS->numpegs; i++)
if ( PEGS->contracts[i]->name.assetbits == assetbits )
{
printf("peggy_create: cant create duplicate peggy.(%s) base.(%s) rel.(%s)\n",name,base,rel);
return(0);
}
}
if ( hasprice != 0 )
PEG = &PEGS->pricedpegs[PEGS->numpricedpegs].PEG;
else PEG = &PEGS->pairedpegs[PEGS->numpairedpegs];
memset(PEG,0,sizeof(*PEG));
peggy_descriptions(PEGS,&PEG->name,name,base,rel);
PEG->pool.quorum = (quorum != 0) ? quorum : PEGS->quorum, PEG->pool.decisionthreshold = (decisionthreshold != 0) ? decisionthreshold : PEGS->decisionthreshold;
PEG->pool.mainunitsize = PEGS->mainunitsize, PEG->pool.mainbits = PEGS->mainbits;
PEG->genesistime = firsttimestamp, PEG->name.id = PEGS->numpegs;
PEG->spread = spread, PEG->lockparms.margin = maxmargin, PEG->mindenomination = mindenomination;
if ( hasprice == 0 )
PEG->baseprices = PEGS->pricedpegs[PEG->name.baseid].prices, PEG->relprices = PEGS->pricedpegs[PEG->name.relid].prices;
else PEG->baseprices = PEGS->pricedpegs[PEG->name.id].prices, PEG->relprices = 0;
if ( peggy_setvars(PEGS,PEG,PEG->name.baseid,PEG->name.relid,PEGS->numpegs,maxsupply,maxnetbalance,lockparms,unitincr,maxdailyrate,initialprices,numprices,hasprice) < 0 )
{
printf("peggy_create: error init peggy.(%s) base.(%s) rel.(%s)\n",name,base,rel);
return(0);
}
//printf("PEG.%p num.%d priced.%d paired.%d\n",PEG,PEGS->numpegs,PEGS->numpricedpegs,PEGS->numpairedpegs);
if ( hasprice != 0 )
PEGS->numpricedpegs++;
else PEGS->numpairedpegs++;
PEGS->contracts[PEGS->numpegs++] = PEG;
PEG->peggymils = peggymils;
PEG->name.enabled = 1;
return(PEG);
}
struct peggy_info *peggy_init(char *path,int32_t maxdays,char *maincurrency,uint64_t maincurrencyunitsize,uint64_t quorum,uint64_t decisionthreshold,struct price_resolution spread,uint32_t dailyrate,int32_t interesttenths,int32_t posboost,int32_t negpenalty,int32_t feediv,int32_t feemult,uint32_t firsttimestamp,uint32_t BTCD_price0)
{
//struct peggy_limits limits = { { PERCENTAGE(10), PERCENTAGE(25), PERCENTAGE(33), PERCENTAGE(50) }, SATOSHIDEN * 10000, SATOSHIDEN * 1000, { 0, 30, 90, 180 }, 4 };
struct peggy_lock default_lockparms = { 7, 365, 7, 0, 180, 0, -1 };
struct price_resolution mindenom,price; struct peggy_info *PEGS = calloc(1,sizeof(*PEGS));
//if ( default_limits != 0 )
// limits = *default_limits;
spread.Pval = PERCENTAGE(1);
OS_ensure_directory(path);
strcpy(PEGS->maincurrency,maincurrency);
PEGS->mainbits = stringbits(maincurrency), PEGS->mainunitsize = maincurrencyunitsize, PEGS->quorum = quorum, PEGS->decisionthreshold = decisionthreshold;
PEGS->default_lockparms = default_lockparms, PEGS->default_lockparms.maxlockdays = maxdays;
//PEGS->default_limits = limits,
PEGS->default_spread = spread, PEGS->default_dailyrate = dailyrate;
PEGS->interesttenths = interesttenths, PEGS->posboost = posboost, PEGS->negpenalty = negpenalty, PEGS->feediv = feediv, PEGS->feemult = feemult;
mindenom.Pval = PRICE_RESOLUTION;
PEGS->genesistime = firsttimestamp;
price.Pval = PEGS->BTCD_price0 = BTCD_price0;
printf("set genesistime.%u BTCD0.%u\n",firsttimestamp,BTCD_price0);
peggy_createpair(PEGS,0,0,"BTCD","BTCD",0,SATOSHIDEN*1000000,SATOSHIDEN*100000,0,SATOSHIDEN,PEGGY_RATE_777,firsttimestamp,&price,1,spread,0,mindenom,0,1,peggy_mils(0));
//PEGS->accts = accts777_init(path,0);
return(PEGS);
}
//////////// end of consensus safe
long hdecode_varint(uint64_t *valp,uint8_t *ptr,long offset,long mappedsize)
{
uint16_t s; uint32_t i; int32_t c;
if ( ptr == 0 )
return(-1);
*valp = 0;
if ( offset < 0 || offset >= mappedsize )
return(-1);
c = ptr[offset++];
switch ( c )
{
case 0xfd: if ( offset+sizeof(s) > mappedsize ) return(-1); memcpy(&s,&ptr[offset],sizeof(s)), *valp = s, offset += sizeof(s); break;
case 0xfe: if ( offset+sizeof(i) > mappedsize ) return(-1); memcpy(&i,&ptr[offset],sizeof(i)), *valp = i, offset += sizeof(i); break;
case 0xff: if ( offset+sizeof(*valp) > mappedsize ) return(-1); memcpy(valp,&ptr[offset],sizeof(*valp)), offset += sizeof(*valp); break;
default: *valp = c; break;
}
return(offset);
}
struct peggy_info *peggy_genesis(int32_t lookbacks[OPRETURNS_CONTEXTS],struct peggy_info *PEGS,char *path,uint32_t firsttimestamp,char *opreturnstr)
{
//struct peggy_limits limits = { { PERCENTAGE(10), PERCENTAGE(25), PERCENTAGE(33), PERCENTAGE(50) }, SATOSHIDEN * 10000, SATOSHIDEN * 1000, { 0, 30, 90, 180 }, 4 };
char name[64],base[64],rel[64]; uint8_t opret[1024]; struct peggy_tx Ptx; struct peggy *PEG;
struct price_resolution mindenom,spread,price; uint64_t len; long offset; uint64_t maxsupply=0,maxnetbalance=0;
int32_t i,c,baseid,relid,peggymils=0,signedcount,datalen,n=0,maxmargin=0,numprices,err=-1; uint32_t pval = 0;
numprices = 1;
datalen = (int32_t)strlen(opreturnstr) / 2;
decode_hex(opret,datalen,opreturnstr);
printf("peggy_genesis(%s)\n",opreturnstr);
if ( opret[0] == OP_RETURN_OPCODE )
{
offset = hdecode_varint(&len,opret,1,sizeof(opret));
if ( opret[offset] == 'P' && opret[offset+1] == 'A' && opret[offset+2] == 'X' )
{
printf("deser\n");
if ( (n= serdes777_deserialize(&signedcount,&Ptx,firsttimestamp,opret+offset+3,(int32_t)len-3)) > 0 )
{
err = 0;
for (i=0; i<Ptx.details.price.num; i++)
if ( Ptx.details.price.feed[i] == 0 )
break;
if ( i == Ptx.details.price.num )
{
printf("GENESIS.(%s)\n",opreturnstr);
for (i=0; i<Ptx.details.price.num; i++)
printf("%u ",Ptx.details.price.feed[i]);
printf("prices\n");
lookbacks[0] = 0, lookbacks[1] = 1000;
if ( PEGS == 0 )
{
spread.Pval = PERCENTAGE(1);
PEGS = peggy_init(path,PEGGY_MAXLOCKDAYS,"BTCD",SATOSHIDEN/100,1,1,spread,PEGGY_RATE_777,40,10,2,5,2,Ptx.timestamp,Ptx.details.price.feed[0]);
//EGS->accts = accts777_init(path,0);
PEGS->genesis = opreturnstr, opreturnstr = 0;
}
} else printf("i.%d vs %d\n",i,Ptx.details.price.num);
} else printf("deser got n.%d\n",n);
} else printf("illegal opret.(%c%c%c)\n",opret[offset],opret[offset+1],opret[offset+2]);
} else printf("opret[0] %d\n",opret[0]);
if ( err < 0 || PEGS == 0 )
return(0);
mindenom.Pval = PRICE_RESOLUTION;
spread.Pval = PERCENTAGE(1);
for (i=1; i<sizeof(peggy_bases)/sizeof(*peggy_bases)+28; i++)
{
price.Pval = 0;
if ( i < sizeof(peggy_bases)/sizeof(*peggy_bases) )
{
if ( peggy_bases[i] == 0 )
continue;
peggy_mapname(base,rel,i);
price.Pval = Ptx.details.price.feed[i];
if ( i <= 8 )
maxmargin = 25;
else if ( i < 16 )
maxmargin = 15;
else maxmargin = 10;
peggymils = peggy_mils(i);
if ( (mindenom.Pval= ((double)PRICE_RESOLUTION * peggymils) / 10000.) == 0 )
mindenom.Pval = PRICE_RESOLUTION;
strcpy(name,base);
if ( strcmp(rel,"BTCD") != 0 && is_decimalstr(base+strlen(base)-2) == 0 && strncmp(rel,"yield",5) != 0 && strcmp(base,"Copper") != 0 && strcmp(base,"NGAS") != 0 && strcmp(base,"UKOil") != 0 && strcmp(base,"USOil") != 0 )
strcat(name,rel);
maxsupply = SATOSHIDEN * 10000, maxnetbalance = SATOSHIDEN * 1000;
if ( strcmp(base,"BTC") == 0 || strcmp(base,"NXT") == 0 || strcmp(base,"USD") == 0 || strcmp(base,"CNY") == 0 )
maxsupply *= 10, maxnetbalance *= 10;
price.Pval = Ptx.details.price.feed[i];
peggy_mapname(base,rel,i);
pval = Ptx.details.price.feed[i];
}
else if ( i-sizeof(peggy_bases)/sizeof(*peggy_bases) < PEGGY_MAXPAIREDPEGS )
{
extern short Contract_base[],Contract_rel[];
maxsupply = SATOSHIDEN * 10000, maxnetbalance = SATOSHIDEN * 1000;
mindenom.Pval = PRICE_RESOLUTION * 10;
c = i - (int32_t)(sizeof(peggy_bases)/sizeof(*peggy_bases));
strcpy(base,CURRENCIES[Contract_base[c]]), strcpy(rel,CURRENCIES[Contract_rel[c]]);
strcpy(name,base), strcat(name,rel);
baseid = Contract_base[c]+1, relid = Contract_rel[c]+1;
peggymils = (PEGS->contracts[baseid]->peggymils * 10000) / PEGS->contracts[relid]->peggymils;
if ( strcmp(PEGS->contracts[baseid]->name.base,base) == 0 && strcmp(PEGS->contracts[relid]->name.base,rel) == 0 )
price.Pval = (PRICE_RESOLUTION * Ptx.details.price.feed[baseid]) / Ptx.details.price.feed[relid];
else printf("mismatched %p base.(%s) baseid.%d (%s) or %p rel.(%s) relid.%d (%s)\n",PEGS->contracts[baseid],PEGS->contracts[baseid]->name.base,baseid,base,PEGS->contracts[relid],PEGS->contracts[relid]->name.base,relid,rel);
pval = (uint32_t)price.Pval;
} else printf("peggy_genesis RAN out of space\n");
if ( (PEG= peggy_createpair(PEGS,0,0,name,base,rel,maxsupply,maxnetbalance,0,SATOSHIDEN*10,PEGGY_RATE_777,firsttimestamp,&price,numprices,spread,maxmargin,mindenom,i,i<sizeof(peggy_bases)/sizeof(*peggy_bases),peggymils)) != 0 )
{
price = peggy_scaleprice(price,peggymils);
struct price_resolution x = peggy_price(PEG,0);
printf("%9s.(%-8s %5s) %17.10f %.10f %-10d maxmargin %2dx maxsupply %6.0f BTCD maxdiff %7.0f spread %.3f denom %-10.6f mils.%d\n",PEG->name.name,PEG->name.base,PEG->name.rel,Pval(&price),Pval(&x),pval,maxmargin,dstr(maxsupply),dstr(maxnetbalance),Pval(&spread),Pval(&mindenom),PEG->peggymils);
n++;
}
}
printf("genesis prices t%u vs %u\n",Ptx.timestamp,firsttimestamp);
return(PEGS);
}
char *peggybase(uint32_t blocknum,uint32_t blocktimestamp)
{
int32_t nonz; struct peggy_info *PEGS = opreturns_context("peggy",0);
if ( PEGS != 0 )
return(peggy_emitprices(&nonz,PEGS,blocktimestamp,PEGS->genesis != 0 ? 0 : PEGGY_MAXLOCKDAYS));
return(0);
}
char *peggypayments(uint32_t blocknum,uint32_t blocktimestamp)
{
int32_t peggy_payments(queue_t *PaymentsQ,struct opreturn_payment *payments,int32_t max,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp);
struct opreturn_payment payments[8192]; cJSON *json;
int32_t i,n; struct peggy_info *PEGS = opreturns_context("peggy",0);
memset(payments,0,sizeof(payments));
if ( PEGS != 0 && PEGS->accts != 0 && (n= peggy_payments(&PEGS->accts->PaymentsQ,payments,sizeof(payments)/sizeof(*payments),blocknum,blocknum,blocktimestamp)) > 0 )
{
json = cJSON_CreateObject();
for (i=0; i<n; i++)
jaddnum(json,payments[i].coinaddr,payments[i].value);
return(jprint(json,1));
}
return(clonestr("{}"));
}
int32_t peggyblock(char *jsonstr)
{
printf("got peggyblock.(%s)\n",jsonstr);
return(0);
}
void peggy()
{
int32_t lookbacks[OPRETURNS_CONTEXTS],nonz,num,peggylen; uint32_t timestamp;// = (uint32_t)time(0);
FILE *fp; uint8_t opret[8192]; char fname[512],*opreturnstr; struct peggy_info *PEGS = opreturns_context("peggy",0);
if ( 0 && PEGS != 0 )
{
opreturnstr = peggy_emitprices(&nonz,PEGS,timestamp,PEGS->genesis != 0 ? 0 : PEGGY_MAXLOCKDAYS);
if ( opreturnstr != 0 )
{
printf("OPRETURN.(%s)\n",opreturnstr);
//if ( Debuglevel > 2 )
printf("update.%d opreturns.(%s) t%u\n",PEGS->numopreturns,opreturnstr,timestamp);
sprintf(fname,"opreturns/%d",PEGS->numopreturns);
if ( (fp= fopen(fname,"wb")) != 0 )
{
fwrite(opreturnstr,1,strlen(opreturnstr)+1,fp);
fclose(fp);
}
if ( nonz == 64 && PEGS->genesis == 0 )
peggy_genesis(lookbacks,PEGS,PEGS->path,timestamp,opreturnstr);
else
{
num = 1;
peggylen = (int32_t)strlen(opreturnstr) / 2;
decode_hex(opret,peggylen,opreturnstr);
opreturns_process(1,PEGS->numopreturns,PEGS->numopreturns,timestamp,0,0,opret,peggylen);
free(opreturnstr);
PEGS->numopreturns++;
}
}
}
}
uint64_t map_apr(uint64_t *spreadp,int32_t maxdays,double apr)
{
int64_t bestdiff,diff; int32_t i; uint64_t rate,bestsatoshis,satoshis,bestrate = 0,target;
target = PRICE_RESOLUTION * (1. + apr/100.);
bestrate = ((PRICE_RESOLUTION * log(apr)/10) / (365-1));
satoshis = peggy_compound(0,PRICE_RESOLUTION,bestrate,365);
bestdiff = (satoshis - target);
if ( bestdiff < 0 )
bestdiff = -bestdiff;
//err = ((double)bestdiff / target);
//n = (int32_t)(err * 4. * bestrate);
//if ( n < 1000 )
// n = 1000;
//printf("err %f %d: new bestdiff %llu, bestrate %llu, satoshis %.8f target %.8f\n",err,n,(long long)bestdiff,(long long)bestrate,(double)satoshis/PRICE_RESOLUTION,(double)target/PRICE_RESOLUTION);
//for (i=0,rate=bestrate-n; rate<=bestrate+2*n; rate++,i++)
for (i=0,rate=1; rate<PRICE_RESOLUTION/100; rate++,i++)
{
satoshis = peggy_compound(0,PRICE_RESOLUTION,rate,365);
diff = (satoshis - target);
if ( diff < 0 )
diff = -diff;
if ( diff < bestdiff )
{
//printf("i.%d of %d: new bestdiff %llu -> %llu, rate %llu -> %llu, satoshis %.8f target %.8f\n",i,n,(long long)bestdiff,(long long)diff,(long long)bestrate,(long long)rate,(double)satoshis/PRICE_RESOLUTION,(double)target/PRICE_RESOLUTION);
bestdiff = diff, bestrate = rate, bestsatoshis = satoshis;
if ( diff == 0 )
break;
}
}
//printf("\nnew bestdiff %llu rate %llu, satoshis %.8f target %.8f\n",(long long)bestdiff,(long long)bestrate,(double)bestsatoshis/PRICE_RESOLUTION,(double)target/PRICE_RESOLUTION);
*spreadp = PERCENTAGE((apr * maxdays)/365);
return(bestrate);
}
uint64_t peggy_dailyrates()
{
//struct peggy_limits limits = { { PERCENTAGE(10), PERCENTAGE(25), PERCENTAGE(33), PERCENTAGE(50) }, SATOSHIDEN * 10000, SATOSHIDEN * 1000, { 0, 30, 90, 180 }, 4 };
uint64_t satoshis,maxspread; int64_t err,errsum; int32_t i,milliperc;
dailyrates[0] = (int32_t)map_apr(&maxspread,PEGGY_MAXLOCKDAYS,(double)7770/1000);
satoshis = peggy_compound(0,SATOSHIDEN,dailyrates[0],365);
printf("%.2f%% %d %llu -> %llu %.2f%%\n",(double)7770/1000,dailyrates[0],(long long)SATOSHIDEN,(long long)satoshis,100. * ((double)(satoshis-SATOSHIDEN)/SATOSHIDEN));
for (errsum=i=0; i<=100; i++)
{
satoshis = peggy_compound(0,SATOSHIDEN,dailyrates[i],365);
//printf("%.1f%%: %d %llu -> %llu %.3f%%\n",(double)i*.1,dailyrates[i],(long long)PRICE_RESOLUTION,(long long)satoshis,100. * (double)satoshis/PRICE_RESOLUTION - 100.);
printf("%.2f%% ",100. * (double)satoshis/SATOSHIDEN - 100.);
err = (satoshis - SATOSHIDEN) - (i == 0 ? 7770000 : i*100000);
errsum += err < 0 ? -err : err;
//printf("i.%d err %lld sum %lld\n",i,(long long)err,(long long)errsum);
}
errsum /= 101;
printf("dailyrate check errsum %lld %f%% ave err\n",(long long)errsum,100*dstr(errsum));
if ( errsum > 10000 )
{
//int32_t dailyrates[101];
for (milliperc=100; milliperc<=10000; milliperc+=100)
{
dailyrates[milliperc/100] = (int32_t)map_apr(&maxspread,PEGGY_MAXLOCKDAYS,(double)milliperc/1000);
satoshis = peggy_compound(0,SATOSHIDEN,dailyrates[milliperc/100],365);
printf("%.2f%% %d %llu -> %llu %.3f%%\n",(double)milliperc/1000,dailyrates[milliperc/100],(long long)SATOSHIDEN,(long long)satoshis,100. * ((double)(satoshis-SATOSHIDEN)/SATOSHIDEN));
}
for (i=0; i<=100; i++)
printf("%d, ",dailyrates[i]);
printf("dailyrates in 0.1%% incr\n");
printf("root.%lld resolution.%lld squared.%llu maxPval.%llu maxunits.%d\n",(long long)PRICE_RESOLUTION_ROOT,(long long)PRICE_RESOLUTION,(long long)PRICE_RESOLUTION2,(long long)PRICE_RESOLUTION_MAXPVAL,PRICE_RESOLUTION_MAXUNITS);
}
return(errsum);
}
void *peggy_replay(char *path,struct txinds777_info *opreturns,void *_PEGS,uint32_t blocknum,char *opreturnstr,uint8_t *data,int32_t datalen)
{
int32_t lookbacks[OPRETURNS_CONTEXTS]; long allocsize; uint64_t len; int32_t n,signedcount,valid=0;
long offset; struct price_resolution tmp;
char fname[512]; uint8_t opret[8192]; struct peggy_tx Ptx; struct peggy_info *PEGS = _PEGS;
if ( blocknum == 0 )
opreturnstr = PEGGY_GENESIS;
//printf("replay genesis.%p opreturnstr.%p data.%p\n",PEGGY_GENESIS,opreturnstr,data);
if ( data == 0 )
{
data = opret;
if ( opreturnstr == 0 )
{
sprintf(fname,"%s/%d",path,blocknum);
if ( (opreturnstr= OS_filestr(&allocsize,fname)) != 0 )
{
//printf("loaded.(%s) %s\n",fname,opreturnstr);
if ( is_hexstr(opreturnstr,(int32_t)strlen(opreturnstr)) != 0 )
valid = 1;
} //else printf("couldnt find.(%s)\n",fname);
} else valid = 1;
if ( valid != 0 )
{
datalen = (int32_t)strlen(opreturnstr) / 2;
decode_hex(opret,datalen,opreturnstr);
} else return(0);
}
if ( data != 0 && data[0] == OP_RETURN_OPCODE )
{
offset = hdecode_varint(&len,data,1,sizeof(opret));
if ( data[offset] == 'P' && data[offset+1] == 'A' && data[offset+2] == 'X' )
{
if ( (n= serdes777_deserialize(&signedcount,&Ptx,0,&data[offset+3],(int32_t)(len - 3))) < 0 )
printf("peggy_process.%d peggy_deserialize error datalen.%d t%d\n",blocknum,datalen,Ptx.timestamp);
else
{
int32_t j,nonz = 0;
for (j=0; j<Ptx.details.price.num; j++)
{
if ( Ptx.details.price.feed[j] != 0 )
{
tmp.Pval = Ptx.details.price.feed[j];
tmp = peggy_scaleprice(tmp,peggy_mils(j));
nonz++;
fprintf(stderr,"(%s %u %.6f) ",peggy_bases[j],Ptx.details.price.feed[j],Pval(&tmp));
}
}
//fprintf(stderr,"%d ",nonz);
printf("PEGS.%p PEGGY type.%d %u num.%d nonz.%d\n",PEGS,Ptx.txtype,Ptx.timestamp,Ptx.details.price.num,nonz);
if ( PEGS == 0 && nonz == Ptx.details.price.num )
PEGS = peggy_genesis(lookbacks,PEGS,path,Ptx.timestamp,opreturnstr);
else if ( PEGS != 0 && Ptx.timestamp > PEGS->genesistime )
{
Ptx.flags |= PEGGY_FLAGS_PEGGYBASE;
if ( peggy_process(PEGS,1,&Ptx.funding.src.coinaddr,Ptx.funding.amount,&data[offset+3],(int32_t)len-3,blocknum,Ptx.timestamp,blocknum) < 0 )
{
printf("error processing blocknum.%u Ptx.blocknum %u\n",blocknum,blocknum);
}
}
if ( PEGS != 0 )
PEGS->numopreturns++;
}
} else printf("illegal.(%c%c%c)\n",data[offset],data[offset+1],data[offset+2]);
} else printf("missing OP_RETURN_OPCODE [%02x]\n",data[0]);
return(PEGS);
}
uint32_t peggy_currentblock(void *_PEGS) { struct peggy_info *PEGS; if ( (PEGS= _PEGS) != 0 ) return(PEGS->numopreturns); return(0); }
void peggy_geninds()
{
int32_t inds[PEGGY_NUMCOEFFS],tmp,i,n = PEGGY_NUMCOEFFS;
for (i=0; i<n; i++)
inds[i] = i;
printf("int32_t Peggy_inds[%d] = {",PEGGY_NUMCOEFFS);
while ( n > 0 )
{
i = ((rand() >> 8) % n);
//printf("(n.%d [%d] i.%d [%d]) ",n,inds[n],i,inds[i]);
n--;
tmp = inds[n];
inds[n] = inds[i];
inds[i] = tmp;
}
for (i=0; i<PEGGY_NUMCOEFFS; i++)
printf("%d, ",inds[i]);
printf("};\n");
}
struct peggy_info *peggy_lchain(struct txinds777_info *opreturns,char *path)
{
double startmilli; int32_t i; struct peggy_info *tmp,*PEGS = 0;
startmilli = OS_milliseconds();
printf("about to replay\n");
for (i=0; i<1000000; i++)
{
if ( PEGS == 0 && (PEGS= peggy_replay(path,opreturns,PEGS,0,0,0,0)) == 0 )
break;
else if ( (tmp= peggy_replay(path,opreturns,PEGS,i,0,0,0)) != PEGS )
break;
}
if ( PEGS != 0 )
printf("loaded %d in %.3f millis per opreturn\n",PEGS->numopreturns,(OS_milliseconds() - startmilli)/PEGS->numopreturns);// getchar();
return(PEGS);
}
int32_t peggy_init_contexts(struct txinds777_info *opreturns,uint32_t RTblocknum,uint32_t RTblocktimestamp,char *path,void *globals[OPRETURNS_CONTEXTS],int32_t lookbacks[OPRETURNS_CONTEXTS],int32_t maxcontexts)
{
double startmilli; char buf[512]; struct price_resolution spread; struct peggy_info *PEGS=0,*PEGS2=0;
if ( maxcontexts != 2 )
{
printf("peggy needs 2 contexts\n");
exit(-1);
}
calc_smooth_code(127,7);
if ( sizeof(Peggy_inds)/sizeof(*Peggy_inds) != PEGGY_NUMCOEFFS )
{
peggy_geninds();
printf("need to update Peggy_inds with above\n");
exit(-1);
}
peggy_dailyrates();
spread.Pval = PERCENTAGE(1);
//if ( (PEGS= peggy_lchain(opreturns,"opreturns")) == 0 )
PEGS = peggy_init(path,PEGGY_MAXLOCKDAYS,"BTCD",SATOSHIDEN/100,100,10,spread,PEGGY_RATE_777,40,10,2,5,2,0,0);
globals[0] = PEGS;
sprintf(buf,"%s_PERM",path);
globals[1] = PEGS2 = peggy_init(buf,PEGGY_MAXLOCKDAYS,"BTCD",SATOSHIDEN/100,1,1,spread,PEGGY_RATE_777,40,10,2,5,2,PEGS->genesistime,PEGS->BTCD_price0);
startmilli = OS_milliseconds();
peggy_clone(buf,PEGS2,PEGS);
printf("cloned %d in %.3f millis per opreturn\n",PEGS->numopreturns,(OS_milliseconds() - startmilli)/PEGS->numopreturns); sleep(3);
return(2);
}

375
iguana/peggy.h

@ -0,0 +1,375 @@
/******************************************************************************
* 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. *
* *
******************************************************************************/
#ifndef INCLUDE_PAX_H
#define INCLUDE_PAX_H
#define PEGGY_GENESIS "6aef504158ec0014fee05dc20a0006048ed63e523f6d1062feb23622da928cf23ddcc3b53f23566bc6cab5ebd77cfbf8f0bccb34bff73c55d742dd232994bfbffe1cbab7119ab3d653a256b02d5b6f56c05b8817799f0d242f48c26d35c992ebfff14acdefbe253345d394e84d975334cd55f7d6cbad5a7bd9425b1d5db44944d40be5304b7b62ba0dbc20d3323d2b35f05f654bc95a5a2fdb5a30e46c6fd33b5ea078255f7cad9fd0dbd2fa5031ada4474cbba7b2ee64ef35df06bf3fd3eef6cd3f48339f3c0e080158a92862bbf20bc6702018effbaee525502eb463c74f7ca0dff4ae7cb55ee55ef7cb1c915e655649"
#include "iguana777.h"
// CfB "the rule is simple = others can know the redemption day only AFTER the price for that day is set in stone."
#define PEGGY_NUMCOEFFS 539
#define ACCTS777_MAXRAMKVS 8
#define BTCDADDRSIZE 36
#define HASH_SIZE 32
#define PEGGY_MINUTE 60
#define PEGGY_HOURTICKS (PEGGY_MINUTE * 60)
#define PEGGY_DAYTICKS (24 * PEGGY_HOURTICKS)
#define MAX_TIMEFRAME (24 * 3600 * 365)
#define MAX_PEGGYDAYS (365)
#define PEGGY_MINEXTRADAYS 3
#define PEGGY_MAXPRICEDPEGS 64
#define PEGGY_MAXPAIREDPEGS 4096
#define PEGGY_MAXPEGS (PEGGY_MAXPRICEDPEGS + PEGGY_MAXPAIREDPEGS)
#define PEGGY_MAXVOTERS 4096
#define PEGGY_MARGINMAX 100
#define PEGGY_MIXRANGE 7777
#define PEGGY_MARGINLOCKDAYS 30
#define PEGGY_MARGINGAPDAYS 7
#define PEGGY_RATE_777 2052
#define OP_RETURN_OPCODE 0x6a
#define OPRETURNS_CONTEXTS 2
#define MAX_OPRETURNSIZE 4096
#define PEGGY_MAXLOCKDAYS 180
#define PEGGY_PASTSTAMP 3600
#define PEGGY_FUTURESTAMP 60
#define PEGGY_RSTATUS_REDEEMED 0
#define PEGGY_RSTATUS_AUTOPURGED 1
#define PEGGY_RSTATUS_MARGINCALL 2
#define PEGGY_FLAGS_HASFUNDING 1
#define PEGGY_FLAGS_PEGGYBASE 2
#define PEGGY_ADDRBTCD 0
#define PEGGY_ADDRCREATE 1
#define PEGGY_ADDRNXT 2
#define PEGGY_ADDRUNIT 3
#define PEGGY_ADDRPUBKEY 4
#define PEGGY_ADDR777 5
#define PEGGY_ADDRFUNDING 6
#define USD 0
#define EUR 1
#define JPY 2
#define GBP 3
#define AUD 4
#define CAD 5
#define CHF 6
#define NZD 7
#define CNY 8
#define RUB 9
#define NZDUSD 0
#define NZDCHF 1
#define NZDCAD 2
#define NZDJPY 3
#define GBPNZD 4
#define EURNZD 5
#define AUDNZD 6
#define CADJPY 7
#define CADCHF 8
#define USDCAD 9
#define EURCAD 10
#define GBPCAD 11
#define AUDCAD 12
#define USDCHF 13
#define CHFJPY 14
#define EURCHF 15
#define GBPCHF 16
#define AUDCHF 17
#define EURUSD 18
#define EURAUD 19
#define EURJPY 20
#define EURGBP 21
#define GBPUSD 22
#define GBPJPY 23
#define GBPAUD 24
#define USDJPY 25
#define AUDJPY 26
#define AUDUSD 27
#define USDNUM 28
#define EURNUM 29
#define JPYNUM 30
#define GBPNUM 31
#define AUDNUM 32
#define CADNUM 33
#define CHFNUM 34
#define NZDNUM 35
#define NUM_CONTRACTS 28
#define NUM_CURRENCIES 8
#define NUM_COMBINED (NUM_CONTRACTS + NUM_CURRENCIES)
#define MAX_SPLINES 64
#define MAX_LOOKAHEAD 48
#define MAX_EXCHANGES 64
#define MAX_CURRENCIES 32
#define PRICE_RESOLUTION_ROOT ((int64_t)3163)
#define PRICE_RESOLUTION (PRICE_RESOLUTION_ROOT * PRICE_RESOLUTION_ROOT) // 10004569
#define PRICE_RESOLUTION2 (PRICE_RESOLUTION * PRICE_RESOLUTION) // 100091400875761
#define PRICE_RESOLUTION_MAXPVAL ((int64_t)3037000500u) // 303.5613528178975 vs 64 bits: 4294967295 429.30058206405493,
#define PRICE_RESOLUTION_MAXUNITS ((int16_t)((int64_t)0x7fffffffffffffffLLu / (SATOSHIDEN * PRICE_RESOLUTION))) // 9219
#define SCALED_PRICE(val,scale) (((scale) * (val)) / PRICE_RESOLUTION)
#define Pval(r) ((double)(r)->Pval / PRICE_RESOLUTION) // for display only!
#define PERCENTAGE(perc) (((perc) * PRICE_RESOLUTION) / 100)
struct price_resolution { int64_t Pval; };
struct peggy_lock { int16_t peg,denom; uint16_t minlockdays,maxlockdays,clonesmear,mixrange,redemptiongapdays; uint8_t extralockdays,margin; };
struct peggy_newunit { bits256 sha256; struct peggy_lock newlock; };
struct peggy_univaddr { uint8_t addrtype,rmd160[20]; char coin[7]; };
union peggy_addr { struct peggy_univaddr coinaddr; struct peggy_newunit newunit; bits256 sha256; bits384 SaMbits; uint64_t nxt64bits; };
struct peggy_input { uint8_t type,chainlen; union peggy_addr src; uint64_t amount; };
struct peggy_output { uint8_t type,vin; union peggy_addr dest; uint32_t ratio; };
struct peggy_txprices { uint16_t num,maxlockdays; uint32_t timestamp; uint32_t feed[256]; };
struct peggy_txbet { struct price_resolution prediction; char peg[15],binary; };
struct peggy_txmicropay { bits256 claimhash,refundhash; uint32_t expiration; uint8_t chainlen,vin,vout; };
struct peggy_time { uint32_t blocknum,blocktimestamp; };
struct peggy_units { int64_t num,numoppo; };
struct peggy_margin { int64_t deposits,margindeposits,marginvalue; };
struct peggy_description { char name[32],base[16],rel[16]; uint64_t basebits,relbits,assetbits; int16_t id,baseid,relid; int8_t hasprice,enabled; };
struct peggy_pool { struct peggy_margin funds; struct peggy_units liability; uint64_t quorum,decisionthreshold,mainunitsize,mainbits; };
//struct peggy_limits { int64_t scales[MAX_TIMEFRAMES],maxsupply,maxnetbalance; uint32_t timeframes[MAX_TIMEFRAMES],numtimeframes; };
#define PEGGY_MAXSIGS 16
#define PEGGY_MAXINPUTS 15
#define PEGGY_MAXOUTPUTS 16
#define PEGGY_TXNORMAL 0
#define PEGGY_TXBET 1
#define PEGGY_TXPRICES 2
#define PEGGY_TXTUNE 3
#define PEGGY_TXMICROPAY 4
union peggy_bytes8 { uint8_t bytes[8]; uint64_t val; };
struct peggy_txtune { char type,peg[15]; uint64_t val; union peggy_bytes8 B; };
union peggy_txtype
{
struct peggy_txprices price; struct peggy_txbet bets[64]; struct peggy_txtune tune[64];
struct peggy_txmicropay micropays[16];
};
struct PAX_sig { bits256 sigbits,pubkey; uint64_t signer64bits; uint32_t timestamp,allocsize; };
struct peggy_tx
{
uint16_t datalen; uint8_t numinputs,numoutputs,txtype,flags,msglen,numdetails; uint32_t timestamp,activation,expiration;
struct peggy_input inputs[PEGGY_MAXINPUTS],funding; struct peggy_output outputs[PEGGY_MAXOUTPUTS];
union peggy_txtype details; char hexstr[512];
uint8_t data[4096];
struct PAX_sig sigs[PEGGY_MAXSIGS];
//uint64_t required;
};
struct peggy_unit
{
int64_t estimated_interest,costbasis,amount,marginamount; uint32_t timestamp; int16_t dailyrate; uint8_t baseid,relid;
struct peggy_lock lock; bits256 lockhash;
};
struct peggy
{
struct peggy_description name; struct peggy_pool pool; struct peggy_lock lockparms; int64_t maxsupply,maxnetbalance;
struct price_resolution spread,mindenomination,genesisprice,price,dayprice; uint32_t day,genesistime,maxdailyrate,unitincr,peggymils;
uint32_t dayprices[MAX_PEGGYDAYS],*baseprices,*relprices; int32_t RTminute;
};
struct peggy_pricedpeg
{
struct peggy PEG;
uint32_t prices[MAX_PEGGYDAYS * 1440]; // In main currency units
};
union peggy_pair { struct peggy PEG; struct peggy_pricedpeg pricedPEG; };
struct peggy_bet { struct price_resolution prediction; uint64_t distbet,dirbet,payout,shares,dist; uint32_t timestamp,minutes; };
struct peggy_vote { int32_t pval,tolerance; };//struct price_resolution price,tolerance; uint64_t nxt64bits,weight; };
struct peggy_entry
{
int64_t total,costbasis,satoshis,royalty,fee,estimated_interest,interest_unlocked,interestpaid,supplydiff,denomination;
int16_t dailyrate,baseid,relid,polarity;
struct peggy_units supply; struct price_resolution price,oppoprice;
};
struct peggy_balances { struct peggy_margin funds; int64_t privatebetfees,crypto777_royalty,APRfund,APRfund_reserved; };
struct PAX_data
{
uint32_t ttimestamps[128]; double tbids[128],tasks[128];
uint32_t ftimestamps[128]; double fbids[128],fasks[128];
uint32_t itimestamps[128]; double ibids[128],iasks[128];
char edate[128]; double ecbmatrix[32][32],dailyprices[MAX_CURRENCIES * MAX_CURRENCIES],metals[4];
int32_t ecbdatenum,ecbyear,ecbmonth,ecbday; double RTmatrix[32][32],RTprices[128],RTmetals[4];
double btcusd,btcdbtc,cryptos[8];
};
struct PAX_spline { char name[64]; int32_t splineid,lasti,basenum,num,firstx,dispincr,spline32[MAX_SPLINES][4]; uint32_t utc32[MAX_SPLINES]; int64_t spline64[MAX_SPLINES][4]; double dSplines[MAX_SPLINES][4],pricevals[MAX_SPLINES+MAX_LOOKAHEAD],lastutc,lastval,aveslopeabs; };
struct peggy_info
{
char maincurrency[16]; uint64_t basebits[256],mainbits,mainunitsize,quorum,decisionthreshold; int64_t hwmbalance,worstbalance,maxdrawdown;
struct price_resolution default_spread; struct peggy_lock default_lockparms;
struct peggy_balances bank,basereserves[256];
int32_t default_dailyrate,interesttenths,posboost,negpenalty,feediv,feemult;
int32_t numpegs,numpairedpegs,numpricedpegs,numopreturns,numvoters;
struct accts777_info *accts;
struct PAX_data data,tmp; double cryptovols[2][8][2],btcusd,btcdbtc,cnyusd;
char path[512],*genesis; uint32_t genesistime,BTCD_price0,lastupdate;
struct PAX_spline splines[128];
struct peggy_vote votes[PEGGY_MAXPRICEDPEGS][PEGGY_MAXVOTERS];
struct peggy *contracts[PEGGY_MAXPEGS];
struct peggy pairedpegs[PEGGY_MAXPRICEDPEGS + PEGGY_MAXPAIREDPEGS];
struct peggy_pricedpeg pricedpegs[PEGGY_MAXPRICEDPEGS];
};
struct txinds777_hdr { int64_t num,nextpos; uint32_t blocknum,timestamp,firstblocknum,lastblocknum; struct sha256_vstate state; bits256 sha256; };
struct txinds777_info
{
struct txinds777_hdr H;
FILE *txlogfp,*indexfp,*fp; char path[512],name[64]; int64_t curitem,*blockitems;
};
int64_t txind777_bundle(struct txinds777_info *txinds,uint32_t blocknum,uint32_t timestamp,int64_t *bundle,int32_t numtx);
int64_t txind777_create(struct txinds777_info *txinds,uint32_t blocknum,uint32_t timestamp,void *txdata,uint16_t len);
int32_t txind777_txbuf(uint8_t *txbuf,int32_t len,uint64_t val,int32_t size);
int32_t txinds777_flush(struct txinds777_info *txinds,uint32_t blocknum,uint32_t blocktimestamp);
struct txinds777_info *txinds777_init(char *path,char *name);
int64_t txinds777_seek(struct txinds777_info *txinds,uint32_t blocknum);
void *txinds777_read(int32_t *lenp,uint8_t *buf,struct txinds777_info *txinds);
void txinds777_purge(struct txinds777_info *txinds);
struct ramkv777_item { UT_hash_handle hh; uint16_t valuesize,tbd; uint32_t rawind; uint8_t keyvalue[]; };
struct ramkv777
{
char name[63],threadsafe;
portable_mutex_t mutex;
struct ramkv777_item *table;
void **list; int32_t listsize,listmax;
struct sha256_vstate state; bits256 sha256;
int32_t numkeys,keysize,dispflag; uint8_t kvind;
};
#define ramkv777_itemsize(kv,valuesize) (sizeof(struct ramkv777_item) + (kv)->keysize + valuesize)
#define ramkv777_itemkey(item) (item)->keyvalue
#define ramkv777_itemvalue(kv,item) (&(item)->keyvalue[(kv)->keysize])
struct ramkv777_item *ramkv777_itemptr(struct ramkv777 *kv,void *value);
int32_t ramkv777_clone(struct ramkv777 *clone,struct ramkv777 *kv);
void ramkv777_free(struct ramkv777 *kv);
int32_t ramkv777_delete(struct ramkv777 *kv,void *key);
void *ramkv777_write(struct ramkv777 *kv,void *key,void *value,int32_t valuesize);
void *ramkv777_read(int32_t *valuesizep,struct ramkv777 *kv,void *key);
void *ramkv777_iterate(struct ramkv777 *kv,void *args,void *(*iterator)(struct ramkv777 *kv,void *args,void *key,void *value,int32_t valuesize));
struct ramkv777 *ramkv777_init(int32_t kvind,char *name,int32_t keysize,int32_t threadsafe);
struct acct777 { uint32_t firstblocknum,firsttimestamp; int64_t balance; };
struct accts777_info
{
queue_t PaymentsQ;
uint64_t balance;
struct peggy_unit *units;
int32_t numunits; uint8_t numkvs;
struct ramkv777 *bets,*pricefeeds,*hashaddrs,*coinaddrs,*SaMaddrs,*nxtaddrs,*addrkvs[16];
bits256 peggyhash;
struct txinds777_info *txinds;
};
struct accts777_info *accts777_init(char *dirname,struct txinds777_info *txinds);
#define YAHOO_METALS "XAU", "XAG", "XPT", "XPD"
extern char *peggy_bases[64],CURRENCIES[][8];
extern int32_t MINDENOMS[],Peggy_inds[],dailyrates[];
struct price_resolution peggy_scaleprice(struct price_resolution price,int64_t peggymils);
char *peggy_tx(char *jsonstr);
void _crypto_update(struct peggy_info *PEGS,double cryptovols[2][8][2],struct PAX_data *dp,int32_t selector,int32_t peggyflag);
int32_t PAX_idle(struct peggy_info *PEGS,int32_t peggyflag,int32_t idlegap);
int32_t PAX_genspline(struct PAX_spline *spline,int32_t splineid,char *name,uint32_t *utc32,double *splinevals,int32_t maxsplines,double *refvals);
int32_t PAX_contractnum(char *base,char *rel);
int32_t PAX_basenum(char *base);
int32_t PAX_ispair(char *base,char *rel,char *contract);
void PAX_init(struct peggy_info *PEGS);
uint32_t peggy_mils(int32_t i);
void calc_smooth_code(int32_t smoothwidth,int32_t _maxprimes);
struct peggy *peggy_find(struct peggy_entry *entry,struct peggy_info *PEGS,char *name,int32_t polarity);
struct price_resolution peggy_priceconsensus(struct peggy_info *PEGS,struct peggy_time T,uint64_t seed,int16_t pricedpeg,struct peggy_vote *votes,uint32_t numvotes,struct peggy_bet *bets,uint32_t numbets);
struct price_resolution peggy_price(struct peggy *PEG,int32_t minute);
struct price_resolution peggy_shortprice(struct peggy *PEG,struct price_resolution price);
void peggy_delete(struct accts777_info *accts,struct peggy_unit *U,int32_t reason);
int32_t peggy_setprice(struct peggy *PEG,struct price_resolution price,int32_t minute);
int32_t peggy_pegstr(char *buf,struct peggy_info *PEGS,char *name);
struct acct777 *accts777_find(int32_t *valuesizep,struct accts777_info *accts,union peggy_addr *addr,int32_t type);
struct acct777 *accts777_create(struct accts777_info *accts,union peggy_addr *addr,int32_t type,uint32_t blocknum,uint32_t blocktimestamp);
int64_t acct777_balance(struct accts777_info *accts,uint32_t blocknum,uint32_t blocktimestamp,union peggy_addr *addr,int32_t type);
uint64_t peggy_redeem(struct peggy_info *PEGS,struct peggy_time T,int32_t readonly,char *name,int32_t polarity,uint64_t nxt64bits,bits256 pubkey,uint16_t lockdays,uint8_t chainlen);
#define accts777_getaddrkv(accts,type) ((accts != 0) ? (accts)->addrkvs[type] : 0)
uint64_t peggy_poolmainunits(struct peggy_entry *entry,int32_t dir,int32_t polarity,struct price_resolution price,struct price_resolution oppoprice,struct price_resolution spread,uint64_t poolincr,int16_t denomunits);
int32_t acct777_pay(struct accts777_info *accts,struct acct777 *srcacct,struct acct777 *acct,int64_t value,uint32_t blocknum,uint32_t blocktimestamp);
struct peggy *peggy_findpeg(struct peggy_entry *entry,struct peggy_info *PEGS,int32_t peg);
void peggy_thanks_you(struct peggy_info *PEGS,int64_t tip);
uint64_t peggy_createunit(struct peggy_info *PEGS,struct peggy_time T,struct peggy_unit *readU,uint64_t seed,char *name,uint64_t nxt64bits,bits256 lockhash,struct peggy_lock *lock,uint64_t amount,uint64_t marginamount);
int32_t peggy_swap(struct accts777_info *accts,uint64_t signerA,uint64_t signerB,bits256 hashA,bits256 hashB);
int32_t peggy_aprpercs(int64_t dailyrate);
int64_t peggy_lockrate(struct peggy_entry *entry,struct peggy_info *PEGS,struct peggy *PEG,uint64_t satoshis,uint16_t numdays);
char *peggy_emitprices(int32_t *nonzp,struct peggy_info *PEGS,uint32_t blocktimestamp,int32_t maxlockdays);
int64_t peggy_compound(int32_t dispflag,int64_t satoshis,int64_t dailyrate,int32_t n);
#define MAX_OPRETURNSIZE 4096
struct opreturn_payment { struct queueitem DL; uint64_t value; char coinaddr[BTCDADDRSIZE]; };
struct opreturn_entry { struct opreturn_payment vout; uint32_t timestamp,blocknum; uint16_t isstaked,txind,v,datalen; uint8_t data[MAX_OPRETURNSIZE]; };
int64_t peggy_process(void *context,int32_t flags,void *fundedcoinaddr,uint64_t fundedvalue,uint8_t *data,int32_t datalen,uint32_t currentblocknum,uint32_t blocktimestamp,uint32_t stakedblock);
int32_t opreturns_gotnewblock(uint32_t blocknum,uint32_t blocktimestamp,char *opreturns[],int32_t numopreturns,char *peggybase_opreturnstr);
char *opreturns_stakinginfo(char opreturnstr[8192],uint32_t blocknum,uint32_t blocktimestamp);
int32_t opreturns_process(int32_t flags,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp,struct opreturn_entry *list,int32_t num,uint8_t *peggyopreturn,int32_t peggylen);
int32_t opreturns_queue_payment(queue_t *PaymentsQ,uint32_t blocktimestamp,char *coinaddr,int64_t value);
int32_t opreturns_init(uint32_t blocknum,uint32_t blocktimestamp,char *path);
void *opreturns_context(char *name,int32_t context);
long hdecode_varint(uint64_t *valp,uint8_t *ptr,long offset,long mappedsize);
uint64_t conv_acctstr(char *acctstr);
int32_t serdes777_deserialize(int32_t *signedcountp,struct peggy_tx *Ptx,uint32_t blocktimestamp,uint8_t *data,int32_t totallen);
int32_t serdes777_serialize(struct peggy_tx *Ptx,uint32_t blocktimestamp,bits256 privkey,uint32_t timestamp);
int32_t peggy_univ2addr(char *coinaddr,struct peggy_univaddr *ua);
int32_t peggy_addr2univ(struct peggy_univaddr *ua,char *coinaddr,char *coin);
uint64_t PAX_validate(struct PAX_sig *sig,uint32_t timestamp,uint8_t *data,int32_t datalen);
uint64_t PAX_signtx(struct PAX_sig *sig,bits256 privkey,uint32_t timestamp,uint8_t *data,int32_t datalen);
int64_t peggy_process(void *context,int32_t flags,void *fundedcoinaddr,uint64_t fundedvalue,uint8_t *data,int32_t datalen,uint32_t currentblocknum,uint32_t blocktimestamp,uint32_t stakedblock);
int32_t peggy_emit(void *context,uint8_t opreturndata[MAX_OPRETURNSIZE],struct opreturn_payment *payments,int32_t max,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp);
int32_t peggy_flush(void *context,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp);
int32_t peggy_init_contexts(struct txinds777_info *opreturns,uint32_t blocknum,uint32_t blocktimestamp,char *path,void *globals[OPRETURNS_CONTEXTS],int32_t lookbacks[OPRETURNS_CONTEXTS],int32_t maxcontexts);
uint32_t peggy_clone(char *path,void *dest,void *src);
void *peggy_replay(char *path,struct txinds777_info *opreturns,void *_PEGS,uint32_t blocknum,char *opreturnstr,uint8_t *data,int32_t datalen);
uint32_t peggy_currentblock(void *globals);
struct peggy_unit *peggy_match(struct accts777_info *accts,int32_t peg,uint64_t nxt64bits,bits256 lockhash,uint16_t lockdays);
int32_t peggy_addunit(struct accts777_info *accts,struct peggy_unit *U,bits256 lockhash);
#endif

325
iguana/peggy_accts.c

@ -0,0 +1,325 @@
/******************************************************************************
* 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 "peggy.h"
#define accts777_getaddrkv(accts,type) ((accts != 0) ? (accts)->addrkvs[type] : 0)
bits256 PAX_hashiter(bits256 privkey,bits256 pubkey,int32_t lockdays,uint8_t chainlen)
{
uint16_t lockseed,signlen = 0; uint8_t signbuf[16]; bits256 shared,lockhash;
lockseed = (chainlen & 0x7f) | (lockdays << 7);
signlen = 0, signbuf[signlen++] = lockseed & 0xff, signbuf[signlen++] = (lockseed >> 8) & 0xff;
privkey.bytes[0] &= 248, privkey.bytes[31] &= 127, privkey.bytes[31] |= 64;
shared = curve25519(privkey,pubkey);
vcalc_sha256cat(lockhash.bytes,shared.bytes,sizeof(shared),signbuf,signlen);
return(lockhash);
}
bits256 PAX_lockhash(bits256 pubkey,int32_t lockdays,uint8_t chainlen)
{
bits256 lockhash = GENESIS_PRIVKEY;
while ( chainlen > 0 )
lockhash = PAX_hashiter(lockhash,pubkey,lockdays,chainlen--);
return(lockhash);
}
bits256 PAX_invoicehash(bits256 *invoicehash,uint16_t lockdays,uint8_t chainlen)
{
int32_t i; bits256 lockhash,privkey;
OS_randombytes(privkey.bytes,sizeof(privkey)); // both privkey and pubkey are sensitive. pubkey allows verification, privkey proves owner
lockhash = privkey;
for (i=0; i<chainlen; i++)
lockhash = PAX_hashiter(lockhash,GENESIS_PUBKEY,chainlen - i,lockdays);
*invoicehash = lockhash;
return(privkey);
}
uint64_t PAX_sign(struct PAX_sig *sig,bits256 privkey,bits256 otherpubkey,uint32_t timestamp,uint8_t *data,int32_t datalen)
{
int32_t i; bits256 shared; uint8_t buf[sizeof(shared) + sizeof(timestamp)]; uint32_t t = timestamp;
for (i=0; i<sizeof(t); i++,t>>=8)
buf[i] = (t & 0xff);
sig->timestamp = timestamp;
shared = curve25519(privkey,otherpubkey);
memcpy(&buf[sizeof(timestamp)],shared.bytes,sizeof(shared));
vcalc_sha256cat(sig->sigbits.bytes,buf,sizeof(buf),data,datalen);
sig->pubkey = acct777_pubkey(privkey), sig->signer64bits = acct777_nxt64bits(sig->pubkey);
//printf(" calcsig.%llx pubkey.%llx signer.%llu | t%u crc.%08x len.%d shared.%llx <- %llx * %llx\n",(long long)sig->sigbits.txid,(long long)sig->pubkey.txid,(long long)sig->signer64bits,timestamp,_crc32(0,data,datalen),datalen,(long long)shared.txid,(long long)privkey.txid,(long long)otherpubkey.txid);
return(sig->signer64bits);
}
uint64_t PAX_validate(struct PAX_sig *sig,uint32_t timestamp,uint8_t *data,int32_t datalen)
{
struct PAX_sig checksig;
PAX_sign(&checksig,GENESIS_PRIVKEY,sig->pubkey,timestamp,data,datalen);
if ( memcmp(checksig.sigbits.bytes,sig->sigbits.bytes,sizeof(checksig.sigbits)) != 0 )
{
printf("sig compare error using sig->pub from %llu\n",(long long)acct777_nxt64bits(sig->pubkey));
return(0);
}
return(acct777_nxt64bits(sig->pubkey));
}
uint64_t PAX_signtx(struct PAX_sig *sig,bits256 privkey,uint32_t timestamp,uint8_t *data,int32_t datalen)
{
return(PAX_sign(sig,privkey,GENESIS_PUBKEY,timestamp,data,datalen));
}
uint64_t PAX_swaptx(bits256 privkey,struct PAX_sig *sig,uint32_t timestamp,uint8_t *data,int32_t datalen)
{
uint64_t othernxt;
if ( (othernxt= PAX_validate(sig,timestamp,data,datalen)) != sig->signer64bits )
return(0);
return(PAX_sign(sig,privkey,GENESIS_PUBKEY,timestamp,data,datalen));
}
struct accts777_info *accts777_init(char *dirname,struct txinds777_info *txinds)
{
struct accts777_info *accts = calloc(1,sizeof(*accts));
accts->hashaddrs = ramkv777_init(accts->numkvs++,"hashaddrs",sizeof(bits256),1);
accts->coinaddrs = ramkv777_init(accts->numkvs++,"coinaddrs",BTCDADDRSIZE,1);
accts->nxtaddrs = ramkv777_init(accts->numkvs++,"nxtaddrs",sizeof(uint64_t),1);
accts->SaMaddrs = ramkv777_init(accts->numkvs++,"SaMaddrs",sizeof(bits384),1);
accts->bets = ramkv777_init(accts->numkvs++,"bets",BTCDADDRSIZE,1);
accts->pricefeeds = ramkv777_init(accts->numkvs++,"pricefeeds",sizeof(uint32_t) * 2,1);//, accts->pricefeeds->dispflag = 0;
if ( accts->numkvs > ACCTS777_MAXRAMKVS )
{
printf("too many ramkvs for accts %d vs %d\n",accts->numkvs,ACCTS777_MAXRAMKVS);
exit(-1);
}
accts->addrkvs[PEGGY_ADDRFUNDING] = accts->addrkvs[PEGGY_ADDRBTCD] = accts->coinaddrs;
accts->addrkvs[PEGGY_ADDR777] = accts->SaMaddrs;
accts->addrkvs[PEGGY_ADDRNXT] = accts->nxtaddrs;
accts->addrkvs[PEGGY_ADDRCREATE] = accts->addrkvs[PEGGY_ADDRUNIT] = accts->addrkvs[PEGGY_ADDRPUBKEY] = accts->hashaddrs;
if ( (accts->txinds= txinds) == 0 )
accts->txinds = txinds777_init(dirname,"txinds");
return(accts);
}
void accts777_free(struct accts777_info *accts)
{
int32_t i;
queue_free(&accts->PaymentsQ);
for (i=0; i<sizeof(accts->addrkvs)/sizeof(*accts->addrkvs); i++)
if ( accts->addrkvs[i] != 0 )
ramkv777_free(accts->addrkvs[i]);
free(accts);
}
struct accts777_info *accts777_clone(char *path,struct accts777_info *accts)
{
struct accts777_info *clone;
clone = accts777_init(path,accts->txinds);
queue_clone(&clone->PaymentsQ,&accts->PaymentsQ,sizeof(struct opreturn_payment));
if ( accts->numunits > 0 && accts->units != 0 )
{
clone->units = calloc(accts->numunits,sizeof(*accts->units));
memcpy(clone->units,accts->units,accts->numunits * sizeof(*accts->units));
}
clone->peggyhash = accts->peggyhash;
ramkv777_clone(clone->bets,accts->bets);
ramkv777_clone(clone->pricefeeds,accts->pricefeeds);
ramkv777_clone(clone->hashaddrs,accts->hashaddrs);
ramkv777_clone(clone->coinaddrs,accts->coinaddrs);
ramkv777_clone(clone->SaMaddrs,accts->SaMaddrs);
ramkv777_clone(clone->nxtaddrs,accts->nxtaddrs);
return(clone);
}
void *accts777_key(union peggy_addr *addr,int32_t type)
{
void *key;
switch ( type )
{
case PEGGY_ADDRFUNDING: case PEGGY_ADDRBTCD: key = &addr->coinaddr; break;
case PEGGY_ADDRNXT: key = &addr->nxt64bits; break;
case PEGGY_ADDR777: key = &addr->SaMbits; break;
case PEGGY_ADDRCREATE: key = &addr->newunit.sha256; break;
case PEGGY_ADDRUNIT: key = &addr->sha256; break;
case PEGGY_ADDRPUBKEY: key = &addr->sha256; break;
default: key = 0; break;
}
return(key);
}
struct acct777 *accts777_find(int32_t *valuesizep,struct accts777_info *accts,union peggy_addr *addr,int32_t type)
{
void *key;
if ( (key= accts777_key(addr,type)) != 0 )
return(ramkv777_read(valuesizep,accts->addrkvs[type],key));
else
{
if ( valuesizep != 0 )
*valuesizep = 0;
return(0);
}
}
struct acct777 *accts777_create(struct accts777_info *accts,union peggy_addr *addr,int32_t type,uint32_t blocknum,uint32_t blocktimestamp)
{
struct acct777 *acct,A;
if ( (acct= accts777_find(0,accts,addr,type)) == 0 )
{
memset(&A,0,sizeof(A));
A.firstblocknum = blocknum, A.firsttimestamp = blocktimestamp;
acct = ramkv777_write(accts->addrkvs[type],accts777_key(addr,type),&A,sizeof(A));
}
else if ( blocknum < acct->firstblocknum || blocktimestamp < acct->firsttimestamp )
{
printf("accts777_create: already exists but with an earlier block/timestamp? %u:%u vs %u:%u\n",blocknum,acct->firstblocknum,blocktimestamp,acct->firsttimestamp);
return(0);
}
return(acct);
}
void peggy_delete(struct accts777_info *accts,struct peggy_unit *U,int32_t reason)
{
memcpy(U,&accts->units[--accts->numunits],sizeof(struct peggy_unit));
//U->redeemed = (uint32_t)time(NULL);
//if ( PEGS->lockhashes != 0 )
// kv777_delete(PEGS->lockhashes,U->lockPeriodHash,HASH_SIZE);
}
int32_t peggy_addunit(struct accts777_info *accts,struct peggy_unit *U,bits256 lockhash)
{
U->lockhash = lockhash;
accts->units = realloc(accts->units,sizeof(*accts->units) * (accts->numunits + 1));
accts->units[accts->numunits] = *U;
//if ( PEGS->lockhashes != 0 )
// kv777_write(PEGS->lockhashes,lockPeriodHash,HASH_SIZE,U,sizeof(*U));
return(accts->numunits++);
}
struct peggy_unit *peggy_match(struct accts777_info *accts,int32_t peg,uint64_t nxt64bits,bits256 lockhash,uint16_t lockdays)
{
int32_t i,size; struct peggy_unit *U;
if ( accts->hashaddrs == 0 )
{
for (i=0,U=&accts->units[0]; i<accts->numunits; i++,U++)
{
//if ( U->nxt64bits == 0 || U->nxt64bits == nxt64bits )
{
if ( U->lock.peg == peg && lockdays >= U->lock.minlockdays && lockdays <= U->lock.maxlockdays )
{
if ( memcmp(lockhash.bytes,U->lockhash.bytes,sizeof(lockhash)) == 0 )
return(U);
return(0);
}
}
}
}
else
{
size = sizeof(*U);
if ( (U= ramkv777_read(&size,accts->hashaddrs,lockhash.bytes)) != 0 && size == sizeof(U) )
{
//if ( U->nxt64bits == 0 || U->nxt64bits == nxt64bits )
{
if ( U->lock.peg == peg && lockdays >= U->lock.minlockdays && lockdays <= U->lock.maxlockdays )
return(U);
}
}
}
return(0);
}
int32_t peggy_swap(struct accts777_info *accts,uint64_t signerA,uint64_t signerB,bits256 hashA,bits256 hashB)
{
struct peggy_unit *U,*U2; int32_t size; uint64_t nxtA,nxtB;
size = sizeof(*U);
if ( (U= ramkv777_read(&size,accts->hashaddrs,hashA.bytes)) != 0 && size == sizeof(U) )
{
if ( (U2= ramkv777_read(&size,accts->hashaddrs,hashB.bytes)) != 0 && size == sizeof(U2) )
{
nxtA = acct777_nxt64bits(hashA), nxtB = acct777_nxt64bits(hashB);
if ( (nxtA == signerA && nxtB == signerB) || (nxtA == signerB && nxtB == signerA) )
{
// need to verify ownership
U2->lockhash = hashA, U->lockhash = hashB;
return(0);
}
}
}
return(-1);
}
int32_t acct777_pay(struct accts777_info *accts,struct acct777 *srcacct,struct acct777 *acct,int64_t value,uint32_t blocknum,uint32_t blocktimestamp)
{
if ( srcacct != 0 )
{
if ( srcacct->balance < value )
return(-1);
srcacct->balance -= value;
}
acct->balance += value;
return(0);
}
int64_t acct777_balance(struct accts777_info *accts,uint32_t blocknum,uint32_t blocktimestamp,union peggy_addr *addr,int32_t type)
{
int64_t balance = 0;
struct acct777 *acct;
if ( (acct= accts777_find(0,accts,addr,type)) != 0 )
balance = acct->balance;
return(balance);
}
int32_t peggy_flush(void *_PEGS,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp)
{
struct peggy_info *PEGS = _PEGS;
if ( PEGS != 0 && PEGS->accts != 0 )
return(txinds777_flush(PEGS->accts->txinds,blocknum,blocktimestamp));
else return(-1);
}
int32_t peggy_payments(queue_t *PaymentsQ,struct opreturn_payment *payments,int32_t max,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp)
{
struct opreturn_payment *payment; int32_t n = 0;
while ( max > 0 && (payment= queue_dequeue(PaymentsQ,0)) != 0 )
{
if ( payment->value != 0 && payment->coinaddr[0] != 0 )
*payments++ = *payment;
free(payment);
n++;
}
return(n);
}
int32_t peggy_emit(void *_PEGS,uint8_t opreturndata[MAX_OPRETURNSIZE],struct opreturn_payment *payments,int32_t max,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp)
{
char *opreturnstr; int32_t nonz,len = 0; struct peggy_info *PEGS = _PEGS;
if ( payments != 0 && max > 1 && PEGS->accts != 0 && peggy_payments(&PEGS->accts->PaymentsQ,payments,max,currentblocknum,blocknum,blocktimestamp) < 0 )
return(-1);
if ( opreturndata != 0 && (opreturnstr= peggy_emitprices(&nonz,PEGS,blocktimestamp,0)) != 0 )
{
memset(opreturndata,0,MAX_OPRETURNSIZE);
len = (int32_t)strlen(opreturnstr) / 2;
decode_hex(opreturndata,len,opreturnstr);
free(opreturnstr);
}
return(len);
}
uint32_t peggy_clone(char *path,void *dest,void *src)
{
struct peggy_info *destPEGS,*srcPEGS;
printf("inside peggy_clone sizeof peggy_info %d %d %d\n",(int32_t)sizeof(*destPEGS),(int32_t)sizeof(destPEGS->pricedpegs),(int32_t)sizeof(destPEGS->pairedpegs));//, getchar();
destPEGS = dest, srcPEGS = src;
*destPEGS = *srcPEGS;
destPEGS->accts = accts777_clone(path,srcPEGS->accts);
return(0);
}

829
iguana/peggy_consensus.c

@ -0,0 +1,829 @@
/******************************************************************************
* 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 "peggy.h"
uint64_t peggy_smooth_coeffs[PEGGY_NUMCOEFFS] = // numprimes.13
{
962714545, 962506087, 962158759, 961672710, 961048151, 960285354, 959384649, 958346426, 957171134, // x.8
955859283, 954411438, 952828225, 951110328, 949258485, 947273493, 945156207, 942907532, 940528434, // x.17
938019929, 935383089, 932619036, 929728945, 926714044, 923575608, 920314964, 916933485, 913432593, // x.26
909813756, 906078486, 902228342, 898264923, 894189872, 890004874, 885711650, 881311964, 876807614, // x.35
872200436, 867492300, 862685110, 857780804, 852781347, 847688737, 842505000, 837232189, 831872382, // x.44
826427681, 820900212, 815292123, 809605581, 803842772, 798005901, 792097186, 786118864, 780073180, // x.53
773962395, 767788778, 761554609, 755262175, 748913768, 742511686, 736058231, 729555707, 723006417, // x.62
716412665, 709776755, 703100984, 696387648, 689639036, 682857428, 676045100, 669204315, 662337327, // x.71
655446378, 648533696, 641601496, 634651978, 627687325, 620709702, 613721256, 606724115, 599720386, // x.80
592712154, 585701482, 578690411, 571680955, 564675105, 557674825, 550682053, 543698699, 536726645, // x.89
529767743, 522823816, 515896658, 508988029, 502099660, 495233249, 488390461, 481572928, 474782249, // x.98
468019988, 461287675, 454586804, 447918836, 441285195, 434687268, 428126409, 421603932, 415121117, // x.107
408679208, 402279408, 395922888, 389610779, 383344175, 377124134, 370951677, 364827785, 358753406, // x.116
352729449, 346756785, 340836251, 334968645, 329154729, 323395230, 317690838, 312042206, 306449955, // x.125
300914667, 295436891, 290017141, 284655897, 279353604, 274110676, 268927490, 263804394, 258741701, // x.134
253739694, 248798623, 243918709, 239100140, 234343077, 229647649, 225013957, 220442073, 215932043, // x.143
211483883, 207097585, 202773112, 198510404, 194309373, 190169909, 186091877, 182075118, 178119452, // x.152
174224676, 170390565, 166616873, 162903335, 159249664, 155655556, 152120688, 148644718, 145227287, // x.161
141868021, 138566528, 135322401, 132135218, 129004542, 125929924, 122910901, 119946997, 117037723, // x.170
114182582, 111381062, 108632643, 105936795, 103292978, 100700645, 98159238, 95668194, 93226942, // x.179
90834903, 88491495, 86196126, 83948203, 81747126, 79592292, 77483092, 75418916, 73399150, // x.188
71423178, 69490383, 67600142, 65751837, 63944844, 62178541, 60452305, 58765515, 57117547, // x.197
55507781, 53935597, 52400377, 50901505, 49438366, 48010349, 46616844, 45257246, 43930951, // x.206
42637360, 41375878, 40145912, 38946876, 37778185, 36639262, 35529533, 34448428, 33395384, // x.215
32369842, 31371249, 30399057, 29452725, 28531717, 27635503, 26763558, 25915365, 25090413, // x.224
24288196, 23508216, 22749980, 22013003, 21296806, 20600917, 19924870, 19268206, 18630475, // x.233
18011231, 17410035, 16826458, 16260073, 15710466, 15177224, 14659944, 14158231, 13671694, // x.242
13199950, 12742625, 12299348, 11869759, 11453500, 11050225, 10659590, 10281262, 9914910, // x.251
9560213, 9216856, 8884529, 8562931, 8251764, 7950739, 7659571, 7377984, 7105706, // x.260
6842471, 6588020, 6342099, 6104460, 5874861, 5653066, 5438844, 5231969, 5032221, // x.269
4839386, 4653254, 4473620, 4300287, 4133059, 3971747, 3816167, 3666139, 3521488, // x.278
3382043, 3247640, 3118115, 2993313, 2873079, 2757266, 2645728, 2538325, 2434919, // x.287
2335380, 2239575, 2147382, 2058677, 1973342, 1891262, 1812325, 1736424, 1663453, // x.296
1593311, 1525898, 1461118, 1398879, 1339091, 1281666, 1226519, 1173569, 1122736, // x.305
1073944, 1027117, 982185, 939076, 897725, 858065, 820033, 783568, 748612, // x.314
715108, 682999, 652233, 622759, 594527, 567488, 541597, 516808, 493079, // x.323
470368, 448635, 427841, 407948, 388921, 370725, 353326, 336692, 320792, // x.332
305596, 291075, 277202, 263950, 251292, 239204, 227663, 216646, 206130, // x.341
196094, 186517, 177381, 168667, 160356, 152430, 144874, 137671, 130806, // x.350
124264, 118031, 112093, 106437, 101050, 95921, 91039, 86391, 81968, // x.359
77759, 73755, 69945, 66322, 62877, 59602, 56488, 53528, 50716, // x.368
48043, 45505, 43093, 40803, 38629, 36564, 34604, 32745, 30980, // x.377
29305, 27717, 26211, 24782, 23428, 22144, 20927, 19774, 18681, // x.386
17646, 16665, 15737, 14857, 14025, 13237, 12491, 11786, 11118, // x.395
10487, 9890, 9325, 8791, 8287, 7810, 7359, 6933, 6531, // x.404
6151, 5792, 5453, 5133, 4831, 4547, 4278, 4024, 3785, // x.413
3560, 3347, 3147, 2958, 2779, 2612, 2454, 2305, 2164, // x.422
2032, 1908, 1791, 1681, 1577, 1480, 1388, 1302, 1221, // x.431
1145, 1073, 1006, 942, 883, 827, 775, 725, 679, // x.440
636, 595, 557, 521, 487, 456, 426, 399, 373, // x.449
348, 325, 304, 284, 265, 248, 231, 216, 202, // x.458
188, 175, 164, 153, 142, 133, 124, 115, 107, // x.467
100, 93, 87, 81, 75, 70, 65, 61, 56, // x.476
53, 49, 45, 42, 39, 36, 34, 31, 29, // x.485
27, 25, 23, 22, 20, 19, 17, 16, 15, // x.494
14, 13, 12, 11, 10, 9, 9, 8, 7, // x.503
7, 6, 6, 5, 5, 5, 4, 4, 4, // x.512
3, 3, 3, 3, 2, 2, 2, 2, 2, // x.521
2, 2, 1, 1, 1, 1, 1, 1, 1, // x.530
1, 1, 1, 1, 1, 1, 0, 0, // isum 100000000000
};
int32_t dailyrates[101] =
{
0, 27, 55, 82, 110, 137, 164, 192, 219, 246, 273, 300, 327, 355, 382, 409, 436, 463, 489, 516, 543, 570, 597, 624, 651, 677, 704, 731, 757, 784, 811, 837, 864, 890, 917, 943, 970, 996, 1023, 1049, 1076, 1102, 1128, 1155, 1181, 1207, 1233, 1259, 1286, 1312, 1338, 1364, 1390, 1416, 1442, 1468, 1494, 1520, 1546, 1572, 1598, 1624, 1649, 1675, 1701, 1727, 1752, 1778, 1804, 1830, 1855, 1881, 1906, 1932, 1957, 1983, 2008, 2034, 2059, 2085, 2110, 2136, 2161, 2186, 2212, 2237, 2262, 2287, 2313, 2338, 2363, 2388, 2413, 2438, 2463, 2488, 2513, 2538, 2563, 2588, 2613
};
int32_t peggy_setprice(struct peggy *PEG,struct price_resolution price,int32_t minute)
{
if ( PEG->name.hasprice != 0 )
{
if ( price.Pval > PRICE_RESOLUTION_MAXPVAL )
{
printf("peggy_setdayprice clip.%lld with %lld\n",(long long)price.Pval,(long long)PRICE_RESOLUTION_MAXPVAL);
price.Pval = PRICE_RESOLUTION_MAXPVAL;
}
else if ( price.Pval <= 0 )
{
printf("peggy_setdayprice illegal negative of zeroprice %lld %s\n",(long long)price.Pval,PEG->name.name);
price.Pval = 0;
}
if ( PEG->baseprices[minute] != 0 )
price.Pval = (uint32_t)(price.Pval + PEG->baseprices[minute]) >> 1;
else if ( minute > PEG->RTminute )
PEG->RTminute = minute;
PEG->baseprices[minute] = (uint32_t)price.Pval;
while ( --minute > 0 && PEG->baseprices[minute] == 0 )
PEG->baseprices[minute] = (uint32_t)price.Pval;
}
return(minute);
}
struct price_resolution peggy_shortprice(struct peggy *PEG,struct price_resolution price)
{
struct price_resolution shortprice;
memset(&shortprice,0,sizeof(shortprice));
if ( price.Pval != 0 )
shortprice.Pval = ((PRICE_RESOLUTION * PEG->genesisprice.Pval) / price.Pval);
return(shortprice);
}
struct price_resolution peggy_price(struct peggy *PEG,int32_t minute)
{
struct price_resolution relprice,price;
memset(&price,0,sizeof(price));
if ( minute == PEG->RTminute )
minute--;
while ( (price.Pval= PEG->baseprices[minute]) == 0 && minute >= 0 )
minute--;
if ( PEG->name.hasprice == 0 )
{
relprice.Pval = PEG->relprices[minute];
if ( relprice.Pval != 0 )
{
if ( price.Pval < PRICE_RESOLUTION_MAXPVAL )
price.Pval = (PRICE_RESOLUTION * price.Pval) / relprice.Pval;
else price.Pval = PRICE_RESOLUTION_ROOT * ((PRICE_RESOLUTION_ROOT * price.Pval) / relprice.Pval);
} else price.Pval = 0;
}
return(price);
}
struct price_resolution peggy_aveprice(struct peggy *PEG,int32_t day,int32_t width)
{
int32_t i,n; struct price_resolution price,aveprice;
aveprice.Pval = 0;
for (i=n=0; i<width; i++,day++)
{
price.Pval = PEG->dayprices[day];
if ( price.Pval != 0 )
aveprice.Pval += price.Pval, n++;
}
if ( n != 0 )
aveprice.Pval /= n;
return(aveprice);
}
int32_t peggy_aprpercs(int64_t dailyrate)
{
int32_t i;
if ( dailyrate == PEGGY_RATE_777 )
return(777);
else if ( dailyrate == -PEGGY_RATE_777 )
return(-777);
for (i=0; i<sizeof(dailyrates)/sizeof(*dailyrates)-1; i++)
if ( dailyrate >= dailyrates[i] && dailyrate < dailyrates[i+1] )
return(i*10);
return(0);
}
char *peggy_aprstr(int64_t dailyrate)
{
static char aprstr[16];
int32_t apr,dir = 1;
if ( dailyrate < 0 )
dir = -1, dailyrate = -dailyrate;
apr = peggy_aprpercs(dailyrate);
sprintf(aprstr,"%c%d.%02d%% APR",dir<0?'-':'+',apr/100,(apr%100));
return(aprstr);
}
int64_t peggy_compound(int32_t dispflag,int64_t satoshis,int64_t dailyrate,int32_t n)
{
int32_t i; int64_t compounded = satoshis;
if ( dailyrate == 0 )
return(satoshis);
if ( dispflag != 0 )
printf("peggy_compound rate.%lld n.%d %.8f %lld %lld -> ",(long long)dailyrate,n,dstr(satoshis),(long long)compounded,(long long)SCALED_PRICE(compounded,dailyrate));
for (i=0; i<n; i++)
{
//tmp = (compounded * (PRICE_RESOLUTION + dailyrate)) / PRICE_RESOLUTION; // WARNING: Do not use floating-point math!
compounded += SCALED_PRICE(compounded,dailyrate);
if ( dispflag != 0 )
printf("%.8f ",dstr(compounded));
}
if ( dispflag != 0 )
printf("%.8f %.8f\n",dstr(compounded),(double)compounded/satoshis);
if ( compounded < 0 )
compounded = 0;
return(compounded);
}
void peggy_updatemargin(struct peggy_margin *funds,int64_t satoshis,uint16_t margin,int64_t amount)
{
if ( margin == 0 )
funds->deposits += satoshis;
else
{
funds->margindeposits += amount;
funds->marginvalue += (amount * margin);
}
}
void peggy_thanks_you(struct peggy_info *PEGS,int64_t tip) { PEGS->bank.crypto777_royalty += tip; }
void peggy_changereserve(struct peggy_info *PEGS,struct peggy *PEG,int32_t dir,struct peggy_entry *entry,int64_t satoshis,uint16_t margin,int64_t marginamount)
{
int64_t *dest; uint64_t replenish = 0,fee = 0;
if ( Debuglevel > 2 )
printf("CHANGE %.8f: %c%s: %lld costbasis %.8f %s fee %.8f royalty %.8f estimated %.8f unlocked %.8f, interestpaid %.8f | units.%lld oppo.%lld\n",dstr(satoshis),entry->polarity<0?'-':'+',PEG->name.name,(long long)entry->denomination,dstr(entry->costbasis),peggy_aprstr(entry->dailyrate),dstr(entry->fee),dstr(entry->royalty),dstr(entry->estimated_interest),dstr(entry->interest_unlocked),dstr(entry->interestpaid),(long long)entry->supply.num,(long long)entry->supply.numoppo);
PEGS->bank.APRfund_reserved += (entry->estimated_interest - entry->interest_unlocked);
if ( PEG->pool.funds.deposits > 0 && PEGS->bank.funds.deposits > 0 )
{
if ( PEGS->bank.APRfund < 0 )
PEGS->bank.APRfund += entry->fee;
else
{
fee = entry->fee / PEGS->feediv, fee *= PEGS->feemult;
PEGS->bank.APRfund += ((entry->fee - fee) - entry->interestpaid);
}
} else replenish = entry->fee;
peggy_thanks_you(PEGS,entry->royalty + fee);
peggy_updatemargin(&PEG->pool.funds,satoshis + replenish,margin,marginamount);
peggy_updatemargin(&PEGS->bank.funds,satoshis + replenish,margin,marginamount);
peggy_updatemargin(&PEGS->basereserves[entry->baseid].funds,dir * satoshis,margin,dir * marginamount);
peggy_updatemargin(&PEGS->basereserves[entry->relid].funds,-dir * satoshis,margin,-dir * marginamount);
//printf("dir.%d polarity.%d baseid.%d relid.%d sats %.8f [%.8f %.8f]\n",dir,entry->polarity,entry->baseid,entry->relid,dstr(satoshis),dstr(PEGS->basereserves[entry->baseid]),dstr(PEGS->basereserves[entry->relid]));
dest = (entry->polarity < 0) ? &PEG->pool.liability.numoppo : &PEG->pool.liability.num;
*dest += (dir * entry->denomination);
if ( Debuglevel > 2 || (rand() % 1000) == 0 )
printf(">>>>>>> %c%s %lld: cost %11.8f %s royalties %.8f APR.(R%.8f B%.8f) satoshis %11.8f %s.(+%lld -%lld) base.(%.8f %.8f) total %s (%.8f %.8f %.8f) (%.8f %.8f %.8f)\n",entry->polarity<0?'-':'+',PEG->name.name,(long long)entry->denomination,dstr(entry->costbasis),peggy_aprstr(entry->dailyrate),dstr(PEGS->bank.crypto777_royalty),dstr(PEGS->bank.APRfund_reserved),dstr(PEGS->bank.APRfund),dstr(satoshis),PEG->name.name,(long long)PEG->pool.liability.num,(long long)PEG->pool.liability.numoppo,dstr(PEGS->basereserves[entry->baseid].funds.deposits),dstr(PEGS->basereserves[entry->relid].funds.deposits),PEG->name.name,dstr(PEG->pool.funds.deposits),dstr(PEG->pool.funds.margindeposits),dstr(PEG->pool.funds.marginvalue),dstr(PEGS->bank.funds.deposits),dstr(PEGS->bank.funds.margindeposits),dstr(PEGS->bank.funds.marginvalue));
}
uint64_t peggy_satoshis(int32_t polarity,int16_t denomination,int64_t price,int64_t oppoprice)
{
uint64_t satoshi;
if ( polarity < 0 )
{
//satoshi = (denomination * price) / PRICE_RESOLUTION;
//satoshi = (satoshi * oppoprice) / PRICE_RESOLUTION;
//return((SATOSHIDEN * satoshi) / PRICE_RESOLUTION);
satoshi = (oppoprice * price) / PRICE_RESOLUTION_ROOT;
satoshi = ((SATOSHIDEN / PRICE_RESOLUTION_ROOT) * (satoshi * denomination)) / PRICE_RESOLUTION;
return(satoshi);
//return(denomination * price * oppoprice * (10 / (PRICE_RESOLUTION * PRICE_RESOLUTION * PRICE_RESOLUTION)));
}
else
{
//satoshi = (denomination * price) / PRICE_RESOLUTION;
//return((SATOSHIDEN * satoshi) / PRICE_RESOLUTION);
return((SATOSHIDEN * denomination * price) / PRICE_RESOLUTION);
}
}
uint64_t peggy_poolmainunits(struct peggy_entry *entry,int32_t dir,int32_t polarity,struct price_resolution price,struct price_resolution oppoprice,struct price_resolution spread,uint64_t poolincr,int16_t denomunits)
{
uint64_t mainunits,satoshis; struct price_resolution fee;
entry->denomination = denomunits;
entry->costbasis = peggy_satoshis(polarity,denomunits,price.Pval,oppoprice.Pval);
if ( (entry->baseid != 0 || entry->relid != 0) && spread.Pval != 0 && (fee.Pval= SCALED_PRICE(price.Pval,spread.Pval)) != 0 )
price.Pval += dir * fee.Pval;
else fee.Pval = 0;
satoshis = peggy_satoshis(polarity,denomunits,price.Pval,oppoprice.Pval);
if ( (satoshis % poolincr) == 0 )
dir = 0;
mainunits = dir + (satoshis / poolincr);
entry->total = poolincr * mainunits;
entry->fee = (entry->total - entry->costbasis);
if ( Debuglevel > 2 )
printf("mainunits %llu: origcost %.8f [%.8f] denomination %d poolincr %.8f price %.6f spread %.6f fee %.8f\n",(long long)mainunits,dstr(entry->costbasis),dstr(entry->fee),denomunits,dstr(poolincr),Pval(&price),Pval(&spread),Pval(&fee));
return(entry->total);
}
int64_t peggy_pairabs(int64_t basebalance,int64_t relbalance)
{
int64_t baserelbalance;
if ( (baserelbalance= basebalance) < 0 )
baserelbalance = -baserelbalance;
if ( relbalance < 0 )
baserelbalance -= relbalance;
else baserelbalance += relbalance;
return(baserelbalance);
}
int64_t peggy_lockrate(struct peggy_entry *entry,struct peggy_info *PEGS,struct peggy *PEG,uint64_t satoshis,uint16_t numdays)
{
int64_t diff,compounded,prod,dailyrate=0,both,needed = 0;
if ( (both= entry->supply.num + entry->supply.numoppo) != 0 )
{
if ( (diff= (entry->supply.numoppo - entry->supply.num)) < 0 )
entry->supplydiff = -diff;
else entry->supplydiff = diff;
prod = (PEG->maxdailyrate * diff);
if ( prod > 0 )
prod *= PEGS->posboost;
dailyrate = (prod / both) + dailyrates[PEGS->interesttenths];
if ( dailyrate > PEGGY_RATE_777 )
dailyrate = PEGGY_RATE_777;
else if ( dailyrate < -PEGGY_RATE_777 )
dailyrate = -PEGGY_RATE_777;
if ( prod < 0 && dailyrate > 0 )
dailyrate /= PEGS->negpenalty;
compounded = peggy_compound(0,satoshis,dailyrate,numdays);
needed = (compounded - satoshis);
needed *= 3, needed /= 2;
if ( Debuglevel > 2 )
printf("2x needed %.8f dailyrate.%lld compounded %lld <- %lld diff.%lld prod.%lld both.%lld -> %lld %s\n",dstr(needed),(long long)dailyrate,(long long)compounded,(long long)satoshis,(long long)diff,(long long)prod,(long long)both,(long long)dailyrate,peggy_aprstr(dailyrate));
if ( (PEGS->bank.APRfund_reserved + needed) > PEGS->bank.APRfund )
{
compounded = peggy_compound(1,satoshis,dailyrate,numdays);
printf("reserved %.8f + needed %.8f) > APRfund %.8f\n",dstr(PEGS->bank.APRfund_reserved),dstr(needed),dstr(PEGS->bank.APRfund));
needed = dailyrate = 0;
} else entry->estimated_interest = needed;
}
entry->dailyrate = dailyrate;
return(dailyrate);
}
int32_t peggy_islegal_amount(struct peggy_entry *entry,struct peggy_info *PEGS,struct peggy *PEG,int32_t dir,int64_t satoshis,int32_t numdays,uint16_t margin,struct price_resolution price)
{
uint64_t newsupply; int64_t baserelbalance,newbaserel;
if ( margin == 0 )
entry->dailyrate = peggy_lockrate(entry,PEGS,PEG,satoshis,numdays);
if ( entry->baseid == entry->relid )
{
printf("illegal baseid.%d relid.%d (%s)\n",PEG->name.baseid,PEG->name.relid,PEG->name.name);
//getchar();
return(1);
}
if ( PEG->name.id == 0 )
{
printf("BTCD is legal\n");
return(1);
}
if ( (newsupply= ((PEG->pool.funds.deposits + PEG->pool.funds.marginvalue) + satoshis)) > PEG->maxsupply )
{
printf("peggy_islegal_amount %.8f %.8f newsupply %.8f > limits %.8f\n",dstr(PEG->pool.funds.deposits),dstr(PEG->pool.funds.marginvalue),dstr(newsupply),dstr(PEG->maxsupply));
return(0);
}
//printf("baseid.%d relid.%d\n",entry->baseid,entry->relid);
baserelbalance = peggy_pairabs(PEGS->basereserves[entry->baseid].funds.deposits,PEGS->basereserves[entry->relid].funds.deposits);
newbaserel = peggy_pairabs(PEGS->basereserves[entry->baseid].funds.deposits + satoshis,PEGS->basereserves[entry->relid].funds.deposits - satoshis);
if ( Debuglevel > 2 )
printf("baseid.%d relid.%d satoshis %.8f baserelbalance %.8f newbaserel %.8f\n",entry->baseid,entry->relid,dstr(satoshis),dstr(baserelbalance),dstr(newbaserel));
if ( newbaserel <= baserelbalance )
return(1);
//printf("entry->supplydiff.%lld diff %.8f vs maxnetbalance %.8f\n",(long long)entry->supplydiff,(double)(price.Pval*entry->supplydiff)/PRICE_RESOLUTION,dstr(PEG->limits.maxnetbalance));
if ( PEG->maxnetbalance != 0 && (price.Pval * entry->supplydiff) / PRICE_RESOLUTION > PEG->maxnetbalance/SATOSHIDEN )
{
printf("entry->supplydiff.%lld diff %.8f vs maxnetbalance %.8f\n",(long long)entry->supplydiff,(double)(price.Pval*entry->supplydiff)/PRICE_RESOLUTION,dstr(PEG->maxnetbalance));
return(0);
}
return(1);
}
static uint64_t peggy_assetbits(char *name) { return((is_decimalstr(name) != 0) ? calc_nxt64bits(name) : stringbits(name)); }
struct peggy *peggy_findpair(struct peggy_info *PEGS,char *name)
{
int32_t i; uint64_t assetbits;
if ( (assetbits= peggy_assetbits(name)) != 0 )
{
for (i=0; i<PEGS->numpegs; i++)
{
if ( PEGS->contracts[i]->name.assetbits == assetbits )
return(PEGS->contracts[i]);
}
}
return(0);
}
struct peggy *peggy_found(struct peggy_entry *entry,struct peggy *PEG,int32_t polarity)
{
int64_t num,numoppo;
memset(entry,0,sizeof(*entry));
num = PEG->pool.liability.num, numoppo = PEG->pool.liability.numoppo;
if ( polarity >= 0 )
entry->polarity = 1, entry->baseid = PEG->name.baseid, entry->relid = PEG->name.relid, entry->supply.num = num, entry->supply.numoppo = numoppo;
else entry->polarity = -1, entry->baseid = PEG->name.relid, entry->relid = PEG->name.baseid, entry->supply.num = numoppo, entry->supply.numoppo = num;
//printf("(%s) -> baseid.%d relid.%d\n",PEG->name.name,entry->baseid,entry->relid);
return(PEG);
}
struct peggy *peggy_find(struct peggy_entry *entry,struct peggy_info *PEGS,char *name,int32_t polarity)
{
struct peggy *PEG;
if ( (PEG= peggy_findpair(PEGS,name)) != 0 )
return(peggy_found(entry,PEG,polarity));
return(0);
}
struct peggy *peggy_findpeg(struct peggy_entry *entry,struct peggy_info *PEGS,int32_t peg)
{
if ( peg >= 0 )
return(peggy_found(entry,PEGS->contracts[peg],peg));
else return(peggy_found(entry,PEGS->contracts[-peg],peg));
}
int32_t peggy_pegstr(char *buf,struct peggy_info *PEGS,char *name)
{
int32_t peg=0; struct peggy *PEG;
buf[0] = 0;
if ( name != 0 )
{
strcpy(buf,name);
if ( (PEG= peggy_findpair(PEGS,name)) != 0 )
return(PEG->name.id);
}
return(peg);
}
int32_t peggy_setname(char *buf,char *name)
{
return(peggy_pegstr(buf,opreturns_context("peggy",0),name));
}
int64_t peggy_calcspread(int64_t spread,int32_t lockdays) { return((lockdays < 30) ? spread : ((30 * spread) / lockdays)); }
uint64_t peggy_setunit(struct peggy_unit *U,struct peggy_entry *entry,struct peggy_info *PEGS,struct peggy_time T,struct peggy *PEG,uint64_t seed,uint64_t nxt64bits,struct peggy_lock *lock)
{
int32_t numdays,polarity; uint64_t poolincr; int16_t denom; struct price_resolution spread;
memset(U,0,sizeof(*U));
U->lock = *lock;
if ( (denom= lock->denom) < 0 )
polarity = -1, denom = -denom;
else polarity = 1;
if ( denom >= PRICE_RESOLUTION_MAXUNITS )
{
printf("denom.%d is too big max %lld\n",denom,(long long)PRICE_RESOLUTION_MAXUNITS);
return(0);
}
if ( U->lock.margin != 0 )
{
if ( U->lock.maxlockdays > PEGGY_MARGINLOCKDAYS )
{
printf("error: maxlockdays cant be more than PEGGY_MARGINLOCKDAYS %d for margin trading\n",PEGGY_MARGINLOCKDAYS);
return(0);
}
else if ( U->lock.margin > PEG->lockparms.margin )
{
printf("error: margin.%d cant be more than %d for margin trading %s\n",U->lock.margin,PEG->lockparms.margin,PEG->name.name);
return(0);
}
else if ( denom < U->lock.margin )
{
printf("error: denomination %lld must be >= margin %dx trading %s\n",(long long)denom,U->lock.margin,PEG->name.name);
return(0);
}
else if ( (denom + entry->supply.num) > entry->supply.numoppo )
{
//printf("error: denom.%d supply %d %d > oppo %d -> balance violation %s\n",denom,entry->supply.num,denom+entry->supply.num,entry->supply.numoppo,PEG->name.name);
return(0);
}
U->lock.redemptiongapdays = PEGGY_MARGINGAPDAYS;
} else U->lock.redemptiongapdays = PEG->lockparms.redemptiongapdays;
if ( U->lock.maxlockdays <= PEG->lockparms.maxlockdays )
U->lock.maxlockdays = PEG->lockparms.maxlockdays;
if ( U->lock.minlockdays >= PEG->lockparms.minlockdays )
U->lock.minlockdays = PEG->lockparms.minlockdays;
if ( U->lock.minlockdays > U->lock.maxlockdays )
U->lock.minlockdays = U->lock.maxlockdays;
if ( U->lock.clonesmear > PEG->lockparms.clonesmear )
U->lock.clonesmear = PEG->lockparms.clonesmear;
if ( U->lock.mixrange > PEG->lockparms.mixrange )
U->lock.mixrange = PEG->lockparms.mixrange;
U->lock.extralockdays = PEGGY_MINEXTRADAYS + (seed % PEG->lockparms.extralockdays);
entry->price = PEG->dayprice;//peggy_nonzprice(PEGS,T,PEG,1,day);
entry->oppoprice = peggy_shortprice(PEG,entry->price);//peggy_nonzprice(PEGS,T,PEG,-1,day);
poolincr = PEG->pool.mainunitsize;
U->timestamp = T.blocktimestamp, U->baseid = entry->baseid, U->relid = entry->relid; //, U->nxt64bits = nxt64bits,
U->lock.peg = PEG->name.id * polarity;
spread.Pval = peggy_calcspread(PEG->spread.Pval,U->lock.minlockdays + U->lock.extralockdays);
peggy_poolmainunits(entry,1,polarity,entry->price,entry->oppoprice,spread,poolincr,denom);
U->costbasis = entry->costbasis;
numdays = (polarity > 0) ? (U->lock.maxlockdays + PEG->lockparms.extralockdays) : (U->lock.minlockdays + PEG->lockparms.extralockdays);
return(entry->total * peggy_islegal_amount(entry,PEGS,PEG,polarity,entry->total,numdays,U->lock.margin,entry->price));
}
int64_t peggy_redeemhash(struct peggy_entry *entry,struct peggy_info *PEGS,struct peggy_time T,struct peggy_unit *U,int32_t lockdays)
{
struct price_resolution price,oppoprice,spread; struct peggy *PEG; int32_t n,delta; uint64_t poolincr,interest,satoshis = 0;
if ( (PEG= peggy_findpeg(entry,PEGS,U->lock.peg)) != 0 )
{
poolincr = PEG->pool.mainunitsize, oppoprice.Pval = spread.Pval = 0;
delta = (T.blocktimestamp - U->timestamp) / PEGGY_DAYTICKS;
lockdays += U->lock.extralockdays;
if ( delta < lockdays )
return(0);
else if ( delta > (lockdays + U->lock.redemptiongapdays) )
return(-1);
T.blocktimestamp = U->timestamp + (lockdays * PEGGY_DAYTICKS);
if ( (n= (int32_t)(U->costbasis / PEG->unitincr)) > 0 )
T.blocktimestamp -= (n * PEGGY_DAYTICKS) / 2;
else n = 1;
price = peggy_aveprice(PEG,(T.blocktimestamp - PEG->genesistime) / PEGGY_DAYTICKS,n);
if ( entry->polarity < 0 )
oppoprice = peggy_shortprice(PEG,price);
spread.Pval = peggy_calcspread(PEG->spread.Pval,lockdays);
satoshis = peggy_poolmainunits(entry,-1,entry->polarity,price,oppoprice,spread,poolincr,U->lock.denom);
entry->costbasis = U->costbasis;
if ( U->estimated_interest != 0 )
{
interest = peggy_compound(0,satoshis,U->dailyrate,lockdays + U->lock.extralockdays) - satoshis;
entry->interestpaid = (interest / poolincr) * poolincr;
if ( entry->interestpaid > U->estimated_interest )
entry->interestpaid = U->estimated_interest;
entry->royalty += (interest - entry->interestpaid);
entry->interest_unlocked = U->estimated_interest;
}
if ( U->lock.margin == 0 )
{
if ( PEG->pool.funds.deposits < satoshis )
satoshis = PEG->pool.funds.deposits;
else if (PEG->pool.funds.deposits >= (satoshis + entry->interestpaid) )
satoshis += entry->interestpaid;
}
else
{
if ( PEG->pool.funds.margindeposits < satoshis )
satoshis = PEG->pool.funds.margindeposits;
}
}
return(satoshis);
}
uint64_t peggy_redeem(struct peggy_info *PEGS,struct peggy_time T,int32_t readonly,char *name,int32_t polarity,uint64_t nxt64bits,bits256 pubkey,uint16_t lockdays,uint8_t chainlen)
{
struct peggy_entry entry; struct peggy_unit *U; struct peggy *PEG; int32_t peg; int64_t satoshis = 0; bits256 lockhash;
if ( (PEG= peggy_findpair(PEGS,name)) != 0 )
{
peg = PEG->name.id * polarity;
lockhash = acct777_lockhash(pubkey,lockdays,chainlen);
if ( (U= peggy_match(PEGS->accts,peg,nxt64bits,lockhash,lockdays)) != 0 )
{
if ( (satoshis= peggy_redeemhash(&entry,PEGS,T,U,lockdays)) < 0 )
{
printf("Autopurge unit.%p\n",U);
satoshis = 0;
}
if ( readonly == 0 )
{
peggy_changereserve(PEGS,PEG,-1,&entry,satoshis,U->lock.margin,U->marginamount);
peggy_delete(PEGS->accts,U,satoshis == 0 ? PEGGY_RSTATUS_AUTOPURGED : PEGGY_RSTATUS_REDEEMED);
}
}
}
return(satoshis);
}
uint64_t peggy_createunit(struct peggy_info *PEGS,struct peggy_time T,struct peggy_unit *readU,uint64_t seed,char *name,uint64_t nxt64bits,bits256 lockhash,struct peggy_lock *lock,uint64_t amount,uint64_t marginamount)
{
struct peggy_entry entry; struct peggy_unit U; int32_t peg,polarity; int16_t denomination; int64_t satoshis = 0; struct peggy *PEG = 0;
denomination = lock->denom;
if ( denomination < 0 )
polarity = -1, denomination = -denomination;
else polarity = 1;
if ( denomination >= PRICE_RESOLUTION_MAXUNITS )
{
printf("denomination.%d is too big max %lld\n",denomination,(long long)PRICE_RESOLUTION_MAXUNITS);
return(0);
}
if ( name == 0 )
{
if ( (peg= lock->peg) == 0 )
PEG = PEGS->contracts[0];
else if ( lock->peg < 0 )
peg = -peg, polarity = -polarity;
if ( peg >= PEGS->numpegs )
{
printf("illegal peg id.%d\n",lock->peg);
return(0);
}
PEG = PEGS->contracts[peg];
PEG = peggy_find(&entry,PEGS,PEG->name.name,polarity);
} else PEG = peggy_find(&entry,PEGS,name,polarity);
if ( PEG != 0 )
{
if ( (satoshis= peggy_setunit(&U,&entry,PEGS,T,PEG,seed,nxt64bits,lock)) != 0 )
{
U.estimated_interest = entry.estimated_interest, U.amount = amount, U.marginamount = marginamount;
if ( readU == 0 )
{
if ( Debuglevel > 2 )
printf("%s.%d amount %.8f satoshis %.8f incr.%.8f price.%.8f\n",PEG->name.name,PEG->name.id,dstr(amount),dstr(satoshis),dstr(PEG->pool.mainunitsize),Pval(&entry.price));
if ( (lock->margin == 0 && amount >= satoshis) || (marginamount * lock->margin) >= satoshis )
{
peggy_changereserve(PEGS,PEG,1,&entry,entry.costbasis,lock->margin,marginamount);
peggy_addunit(PEGS->accts,&U,lockhash);
if ( Debuglevel > 2 )
printf("id.%d needed for interest reserved %.8f BTCD, royalty %.8f | dailyrate %lld %s\n",PEG->name.id,dstr(U.estimated_interest),dstr(amount) - dstr(satoshis),(long long)U.dailyrate,peggy_aprstr(U.dailyrate));
} else printf("%s amount %.8f not enough for unit %.8f or margin.%d %llu %.8f\n",PEG->name.name,dstr(amount),dstr(satoshis),lock->margin,(long long)marginamount,dstr(marginamount * lock->margin)), satoshis = 0;
}
}
if ( readU != 0 ) *readU = U, printf("%c%s cost %.8f %s\n",polarity < 0 ? '-' : '+',PEG->name.name,dstr(satoshis),peggy_aprstr(U.dailyrate));
} else printf("peggy_createunit: cant find.(%s)\n",name);
return(satoshis);
}
uint64_t peggy_gamblers(struct peggy_info *PEGS,struct peggy_time T,struct price_resolution prevprice,struct price_resolution newprice,struct peggy_bet *bets,int32_t numbets)
{
int32_t i,j,match,oppo,numbest = 0; int64_t diff,preddiff,tmp,dist,bestdist;
uint64_t bet,payout,totalbets,losingbets,winningbets,totalpayout,matchbets,oppobets,matchshares;
matchshares = matchbets = oppobets = losingbets = winningbets = bestdist = totalpayout = match = oppo = 0;
if ( bets != 0 )
{
for (totalbets=i=0; i<numbets; i++)
if ( (bet= (bets[i].dirbet + bets[i].distbet)) != 0 )
totalbets += bet;
} else return(0);
if ( (diff= (newprice.Pval - prevprice.Pval)) < 0 )
diff = -1;
else if ( diff > 0 )
diff = 1;
for (j=0; j<numbets; j++)
{
bets[j].minutes = (T.blocktimestamp - bets[j].timestamp) / PEGGY_MINUTE;
bets[j].shares = bets[j].dist = 0;
if ( (bet= bets[j].dirbet) != 0 )
{
if ( (preddiff= (bets[j].prediction.Pval - prevprice.Pval)) < 0 )
preddiff = -1;
else if ( preddiff > 0 )
preddiff = 1;
if ( (tmp= diff*preddiff) > 0 )
match++, matchbets += bet, bets[j].shares = (bet * bets[j].minutes), matchshares += (bet * (1 + bets[j].minutes));
else if ( tmp < 0 )
oppo++, oppobets += bet;
}
if ( (bet= bets[j].distbet) != 0 )
{
if ( (dist= ((int64_t)newprice.Pval - bets[j].prediction.Pval)) < 0 )
dist = -dist;
bets[j].dist = ++dist;
if ( bestdist == 0 || dist < bestdist )
bestdist = dist;
}
bets[j].payout = 0;
}
for (j=0; j<numbets; j++)
{
if ( bets[j].dist == bestdist )
winningbets += bets[j].distbet, numbest++;
else losingbets += bets[j].distbet;
}
winningbets += (winningbets / 100);
for (j=0; j<numbets; j++)
{
if ( bets[j].dist == bestdist && winningbets != 0 )
bets[j].payout = bets[j].distbet + ((bets[j].distbet * losingbets) / winningbets);
}
matchshares += (matchshares / 100);
for (payout=j=0; j<numbets; j++)
{
if ( bets[j].shares != 0 )
bets[j].payout = bets[j].dirbet + ((bets[j].shares * oppobets) / matchshares);
payout += bets[j].payout;
}
PEGS->bank.privatebetfees += (totalbets - payout);
if ( numbets != 0 )
printf("royalty %.8f (%.8f - payout %.8f) numbest.%d winningbets %.8f vs losingbets %.8f | match.%d %.8f, oppo.%d %.8f\n",dstr(totalbets - payout),dstr(totalbets),dstr(payout),numbest,dstr(winningbets),dstr(losingbets),match,dstr(matchbets),oppo,dstr(oppobets));
return(totalpayout);
}
struct price_resolution peggy_newprice(struct peggy_info *PEGS,struct peggy *PEG,struct peggy_time T,uint32_t newpval)
{
uint64_t sum,den,gap; int64_t diff; int32_t i,j,minute,iter; struct price_resolution price,shortprice,newprice;
gap = (PEG->spread.Pval * newpval) / PRICE_RESOLUTION;
if ( (newprice.Pval= newpval) != 0 )
{
for (iter=0; iter<1; iter++)
{
sum = den = 0;
sum = (((uint64_t)peggy_smooth_coeffs[0]) * newprice.Pval);
den = peggy_smooth_coeffs[0];
minute = (T.blocktimestamp - PEG->genesistime) / PEGGY_MINUTE;
//printf("peggy_newprice day.%d: %u sum %lld\n",day,newpval,(long long)sum);
for (i=1; i<PEGGY_NUMCOEFFS; i++)
{
j = (minute - i);
if ( j > 0 )
{
price = peggy_price(PEG,j);
if ( price.Pval != 0 )
{
sum += (((uint64_t)peggy_smooth_coeffs[i]) * price.Pval);
den += peggy_smooth_coeffs[i];
}
//printf("i.%d ind.%d coeff.%llu add.%lld sum %lld den %lld %.6f -> %.7f\n",i,j,(long long)peggy_smooth_coeffs[i],(long long)price.Pval,(long long)sum,(long long)den,Pval(&price),(double)sum/(den));
} else break;
}
price.Pval = newpval;
//printf("sum %lld den %lld %.10f -> %.10f || ",(long long)sum,(long long)den,Pval(&price),(double)sum/(den));
if ( den != 0 )
price.Pval = (sum / den);
else break;
newprice = price;
diff = (newprice.Pval - newpval);
if ( diff < 0 )
diff = -diff;
if ( diff < gap )
break;
newprice.Pval = (newprice.Pval*7 + newpval) / 8;
//printf("%.8f ",Pval(&newprice));
}
peggy_setprice(PEG,newprice,minute);
shortprice = peggy_shortprice(PEG,newprice);
price.Pval = newpval;
if ( Debuglevel > 2 )
fprintf(stderr,"t.%u M%d day.%-4d new %.8f short.%.8f pval.%.8f | first %.10f ",T.blocktimestamp,minute,minute/1440,Pval(&newprice),Pval(&shortprice),Pval(&price),Pval(&PEG->genesisprice));
}
return(newprice);
}
void peggy_margincalls(struct peggy_info *PEGS,struct peggy_time T,struct peggy *PEG,struct price_resolution newprice,struct price_resolution shortprice)
{
int32_t i; struct peggy_unit *U; int64_t satoshis,gain,threshold; struct peggy_entry entry;
for (i=0,U=&PEGS->accts->units[0]; i<PEGS->accts->numunits; i++,U++)
{
if ( U->lock.margin != 0 && PEG != 0 && (PEG->name.id == U->lock.peg || PEG->name.id == -U->lock.peg) )
{
if ( (PEG= peggy_findpeg(&entry,PEGS,U->lock.peg)) != 0 )
{
satoshis = peggy_poolmainunits(&entry,-1,entry.polarity,newprice,shortprice,PEG->spread,PEG->pool.mainunitsize,U->lock.denom);
gain = entry.polarity * (satoshis - U->costbasis), threshold = -U->costbasis/U->lock.margin;
if ( gain < threshold )
{
printf("%s %8.6f %8.6f %2dx gain %11.8f polarity.%-2d (%11.8f - cost %11.8f) -> profit %11.8f margincall %11.8f ",PEG->name.name,Pval(&newprice),Pval(&shortprice),U->lock.margin,dstr(gain),entry.polarity,dstr(satoshis),dstr(U->costbasis),dstr(gain),dstr(threshold));
printf("MARGINCALLED\n");
peggy_changereserve(PEGS,PEG,-1,&entry,satoshis,U->lock.margin,U->marginamount);
peggy_delete(PEGS->accts,U,PEGGY_RSTATUS_MARGINCALL);
}
}
}
}
}
struct price_resolution peggy_priceconsensus(struct peggy_info *PEGS,struct peggy_time T,uint64_t seed,int16_t pricedpeg,struct peggy_vote *votes,uint32_t numvotes,struct peggy_bet *bets,uint32_t numbets)
{
struct peggy_entry entry; struct price_resolution newprice,dayprice,tmp; struct peggy *PEG;
int64_t delta,weight,totalwt = 0; int32_t i,j,n,minute,day,wts[PEGGY_NUMCOEFFS]; uint32_t start,k; uint64_t ind;
newprice.Pval = 0;
if ( (PEG= peggy_find(&entry,PEGS,PEGS->contracts[pricedpeg]->name.name,1)) != 0 )
{
for (i=n=0; i<numvotes; i++)
{
if ( votes[i].pval != 0 )
{
wts[i] = 1;//n + 1;
n++;
totalwt += wts[i];
}
}
if ( n < PEG->pool.quorum || totalwt < PEG->pool.decisionthreshold )
return(PEG->price);
start = (uint32_t)(pricedpeg * seed);
for (k=0; k<numvotes; k++)
{
if ( numvotes == PEGGY_NUMCOEFFS )
ind = Peggy_inds[(k + start) % PEGGY_NUMCOEFFS];
else ind = (start + k);
i = (int32_t)(ind % numvotes);
//fprintf(stderr,"(%d %d) ",i,k);
weight = 0;
if ( votes[i].pval != 0 )
{
for (j=0; j<numvotes; j++)
{
if ( votes[j].pval != 0 )
{
//fprintf(stderr,"%lld ",(long long)(j*incr + seed) % numvotes);
if ( (delta= (votes[i].pval - votes[j].pval)) < 0 )//votes[j].price.Pval)) < 0 )
delta = -delta;
//printf("(%lld %llu %u).%lld ",(long long)delta,(long long)votes[i].pval,votes[j].tolerance,(long long)weight);
if ( delta <= votes[j].tolerance )//votes[j].tolerance.Pval )
{
weight += wts[j];
if ( weight > (totalwt >> 1) ) ////votes[j].weight;
break;
}
}
}
}
//if ( strcmp("SuperNET",PEG->name.name) == 0 )
// fprintf(stderr,"%d.(%.6f %llu) ",i,(double)votes[i].pval/PRICE_RESOLUTION,(long long)weight);
if ( weight > (totalwt >> 1) )
{
if ( Debuglevel > 2 )
fprintf(stderr,"%6d k%-4d %4d-> %.6f wt.%-4lld/%4lld ",votes[i].pval,k,i,Pval(&PEG->price),(long long)weight,(long long)totalwt);
PEG->price = peggy_newprice(PEGS,PEG,T,votes[i].pval);
break;
}
}
if ( 0 && k == numvotes )
fprintf(stderr,"no consensus for %s %6d k%-4d %4d-> %.6f wt.%-4lld/%4lld ",PEG->name.name,votes[i].tolerance,k,i,Pval(&PEG->price),(long long)weight,(long long)totalwt);
if ( (day= (T.blocktimestamp - PEG->genesistime)/PEGGY_DAYTICKS) != PEG->day )
{
peggy_gamblers(PEGS,T,PEG->dayprice,PEG->price,bets,numbets);
dayprice.Pval = 0;
for (minute=PEG->day*1440,i=n=0; i<1440; i++,minute++)
{
tmp = peggy_price(PEG,minute);
if ( tmp.Pval != 0 )
dayprice.Pval += tmp.Pval, n++;
}
if ( n != 0 )
dayprice.Pval /= n;
PEG->dayprice = dayprice;
PEG->day = day;
PEG->dayprices[day] = (uint32_t)dayprice.Pval;
if ( Debuglevel > 2 )
printf(">>>>>>>>>>>> DAY PRICE.%d %s %.8f\n",day,PEG->name.name,Pval(&dayprice));
while ( --day > 0 && PEG->dayprices[day] == 0 )
PEG->dayprices[day] = (uint32_t)dayprice.Pval;
}
peggy_margincalls(PEGS,T,PEG,PEG->price,peggy_shortprice(PEG,PEG->price));
newprice = PEG->price;
} else printf("cant find peg.%d\n",pricedpeg);
return(newprice);
}

837
iguana/peggy_price.c

@ -0,0 +1,837 @@
/******************************************************************************
* 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 "peggy.h"
#define _extrapolate_Spline(Splines,gap) ((double)(Splines)[0] + ((gap) * ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3]))))))
#define _extrapolate_Slope(Splines,gap) ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3]))))
#define PRICE_BLEND(oldval,newval,decay,oppodecay) ((oldval == 0.) ? newval : ((oldval * decay) + (oppodecay * newval)))
#define PRICE_BLEND64(oldval,newval,decay,oppodecay) ((oldval == 0) ? newval : ((oldval * decay) + (oppodecay * newval) + 0.499))
#define dto64(x) ((int64_t)((x) * (double)SATOSHIDEN * SATOSHIDEN))
#define dto32(x) ((int32_t)((x) * (double)SATOSHIDEN))
#define i64tod(x) ((double)(x) / ((double)SATOSHIDEN * SATOSHIDEN))
#define i32tod(x) ((double)(x) / (double)SATOSHIDEN)
#define _extrapolate_spline64(spline64,gap) ((double)i64tod((spline64)[0]) + ((gap) * ((double)i64tod(.001*.001*(spline64)[1]) + ((gap) * ((double)i64tod(.001*.001*.001*.001*(spline64)[2]) + ((gap) * (double)i64tod(.001*.001*.001*.001*.001*.001*(spline64)[3])))))))
#define _extrapolate_spline32(spline32,gap) ((double)i32tod((spline32)[0]) + ((gap) * ((double)i32tod(.001*.001*(spline32)[1]) + ((gap) * ((double)i32tod(.001*.001*.001*.001*(spline32)[2]) + ((gap) * (double)i32tod(.001*.001*.001*.001*.001*.001*(spline32)[3])))))))
static char *Yahoo_metals[] = { YAHOO_METALS };
uint64_t Currencymasks[NUM_CURRENCIES+1];
short Contract_base[NUM_COMBINED+1] = { 7, 7, 7, 7, 3, 1, 4, 5, 5, 0, 1, 3, 4, 0, 6, 1, 3, 4, 1, 1, 1, 1, 3, 3, 3, 0, 4, 4, 0,1,2,3,4,5,6,7, 8 };// Contract_base };
short Contract_rel[NUM_COMBINED+1] = { 0, 6, 5, 2, 7, 7, 7, 2, 6, 5, 5, 5, 5, 6, 2, 6, 6, 6, 0, 4, 2, 3, 0, 2, 4, 2, 2, 0, 0,1,2,3,4,5,6,7,8 };// Contract_rel
short Baserel_contractdir[NUM_CURRENCIES+1][NUM_CURRENCIES+1] =
{
{ 1, -1, 1, -1, -1, 1, 1, -1, -1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, -1 },
{ -1, -1, 1, -1, -1, -1, -1, -1, 0 },
{ 1, -1, 1, 1, 1, 1, 1, 1, -1 },
{ 1, -1, 1, -1, 1, 1, 1, 1, -1 },
{ -1, -1, 1, -1, -1, 1, 1, -1, 0 },
{ -1, -1, 1, -1, -1, -1, 1, -1, -1 },
{ 1, -1, 1, -1, -1, 1, 1, 1, 0 },
{ -1, -1, 0, -1, -1, 0, -1, 0, 1 },
};
short Currency_contracts[NUM_CURRENCIES+1][NUM_CURRENCIES] =
{
{ 0, 9, 13, 18, 22, 25, 27, 28, },
{ 5, 10, 15, 18, 19, 20, 21, 29, },
{ 3, 7, 14, 20, 23, 25, 26, 30, },
{ 4, 11, 16, 21, 22, 23, 24, 31, },
{ 6, 12, 17, 19, 24, 26, 27, 32, },
{ 2, 7, 8, 9, 10, 11, 12, 33, },
{ 1, 8, 13, 14, 15, 16, 17, 34, },
{ 0, 1, 2, 3, 4, 5, 6, 35, },
{ 36, 37, -1, 38, 39, -1, 40, 41, },
};
short Currency_contractothers[NUM_CURRENCIES+1][NUM_CURRENCIES] = // buggy!
{
{ 7, 5, 6, 1, 3, 2, 4, 0, },
{ 7, 5, 6, 0, 4, 2, 3, 1, },
{ 7, 5, 6, 1, 3, 0, 4, 2, },
{ 7, 5, 6, 1, 0, 2, 4, 3, },
{ 7, 5, 6, 1, 3, 2, 0, 4, },
{ 7, 2, 6, 0, 1, 3, 4, 5, },
{ 7, 5, 0, 2, 1, 3, 4, 6, },
{ 0, 6, 5, 2, 1, 3, 4, 7, },
{ 0, 1,-1, 3, 4,-1, 5,-1, },
};
int32_t MINDENOMS[] = { 1000, 1000, 100000, 1000, 1000, 1000, 1000, 1000, // major currencies
10000, 100000, 10000, 1000, 100000, 10000, 1000, 10000, 1000, 10000, 10000, 10000, 10000, 100000, 1000, 1000000, 1000, 10000, 1000, 1000, 10000, 1000, 10000000, 10000, // end of currencies
1, 100, 1, 1, // metals, gold must be first
1, 10, 100000, 100, 100, 10000000, 10000, 1000, 1000, 1000, 100000, 100000, 1000000 // cryptos
};
int32_t PAX_mindenomination(int32_t base)
{
return(MINDENOMS[base]);
}
void norm_smooth_wts(int32_t j,double *smoothwts,int32_t n)
{
double wt; int32_t iter,i;
for (iter=0; iter<13; iter++)
{
wt = 0.;
for (i=0; i<n; i++)
wt += smoothwts[i];
//printf("wtsum.j%d %.40f ",j,wt);
for (i=0; i<n; i++)
smoothwts[i] /= wt;
}
//printf("\n");
}
void calc_smooth_code(int32_t smoothwidth,int32_t _maxprimes)
{
double _coeffs[5000],sum,coeffs[60][10000],smoothbuf[10000]; int32_t x,p,prime,numprimes; uint64_t val,isum = 0;
_maxprimes = MIN((int32_t)(sizeof(coeffs)/(sizeof(double)*10000))-1,_maxprimes);
smoothwidth = MIN((int32_t)(sizeof(_coeffs)/sizeof(*_coeffs)),smoothwidth);
x = 5000;
memset(smoothbuf,0,sizeof(smoothbuf));
coeffs[0][x-2] = coeffs[0][x] = coeffs[0][x+2] = 1./3.;
for (numprimes=_maxprimes; numprimes>=3; numprimes--)
{
for (p=1; p<numprimes; p++)
{
memcpy(coeffs[p],coeffs[p-1],sizeof(coeffs[p]));
prime = smallprimes[p];
for (x=0; x<10000; x++)
{
coeffs[p][x] += (coeffs[p-1][x - prime] / 3.);
coeffs[p][x] += (coeffs[p-1][x] / 3.);
coeffs[p][x] += (coeffs[p-1][x + prime] / 3.);
}
}
memcpy(smoothbuf,coeffs[numprimes-1],sizeof(smoothbuf));
memset(coeffs,0,sizeof(coeffs));
sum = 0.;
for (x=0; x<10000; x++)
{
if ( smoothbuf[x] != 0. )
{
sum += smoothbuf[x];
//printf("(%d %f) ",x-5000,smoothbuf[x]);
}
}
//printf("maxprimes.%d\n",maxprimes);
for (x=0; x<10000; x++)
coeffs[0][x] = (smoothbuf[x] / sum);
}
sum = 0.;
for (x=0; x<10000; x++)
sum += smoothbuf[x];
memset(coeffs,0,sizeof(coeffs));
if ( sum != 0. )
{
printf("double Smooth_coeffs[%d] = // numprimes.%d\n{\n",smoothwidth,_maxprimes);
for (x=0; x<10000; x++)
{
if ( smoothbuf[x] != 0. )
{
smoothbuf[x] = (1000000. * 1000000. * smoothbuf[x]) / sum;
//printf("(%d %f) ",x-5000,smoothbuf[x]);
}
}
_coeffs[0] = smoothbuf[5000];
for (x=1; x<=smoothwidth; x++)
{
if ( fabs(smoothbuf[5000 - x] - smoothbuf[5000 + x]) > SMALLVAL )
printf("x.%d error %.20f != %.20f [%.20f]\n",x,smoothbuf[5000 - x],smoothbuf[5000 + x],smoothbuf[5000 - x] - smoothbuf[5000 + x]);
_coeffs[x-1] = (smoothbuf[5000 - x] + smoothbuf[5000 + x]) / 2.;
}
sum = 0.;
for (x=0; x<smoothwidth; x++)
sum += _coeffs[x];
if ( sum != 0. )
{
for (x=0; x<smoothwidth; x++)
{
val = ((SATOSHIDEN * 1000. * _coeffs[x] + sum*.4825) / sum);
printf("%lld, ",(long long)val);
isum += val;
//printf("%.0f, ",SATOSHIDEN*1000*_coeffs[x]/sum);
if ( (x%9) == 8 )
printf("// x.%d\n",x);
}
printf("// isum %lld\n",(long long)isum);
}
}
printf("\n}; // %llu\n",(long long)isum);
//printf("_Constants size %d\n",(int)__constant_size);
}
uint32_t peggy_mils(int32_t i)
{
uint32_t minmils = 0;
if ( i == 0 )
return(1000000);
else if ( i <= 32 )
minmils = 10 * PAX_mindenomination(i-1);
else if ( i >= 64 )
return(10000);
else if ( peggy_bases[i] != 0 )
{
if ( is_decimalstr(peggy_bases[i]+strlen(peggy_bases[i])-2) != 0 || strcmp(peggy_bases[i],"BTCRUB") == 0 )
minmils = 1;
else if ( strncmp(peggy_bases[i],"XAU",3) == 0 || strcmp(peggy_bases[i],"BTCCNY") == 0 || strcmp(peggy_bases[i],"BTCUSD") == 0 || strncmp(peggy_bases[i],"XPD",3) == 0 || strncmp(peggy_bases[i],"XPT",3) == 0 )
minmils = 10;
else if ( strcmp(peggy_bases[i],"BUND") == 0 || strcmp(peggy_bases[i],"UKOIL") == 0 || strcmp(peggy_bases[i],"USOIL") == 0 )
minmils = 100;
else if ( strncmp(peggy_bases[i],"LTC",3) == 0 || strcmp(peggy_bases[i],"SuperNET") == 0 || strncmp(peggy_bases[i],"XAG",3) == 0 || strncmp(peggy_bases[i],"ETH",3) == 0 || strncmp(peggy_bases[i],"XCP",3) == 0 )
minmils = 1000;
else if ( strncmp(peggy_bases[i],"XMR",3) == 0 )
minmils = 10000;
else if ( strncmp(peggy_bases[i],"NXT",3) == 0 || strncmp(peggy_bases[i],"BTS",3) == 0 )
minmils = 1000000;
else if ( strncmp(peggy_bases[i],"DOGE",3) == 0 )
minmils = 100000000;
else minmils = 10000;
}
return(minmils);
}
int32_t peggy_prices(struct price_resolution prices[64],double btcusd,double btcdbtc,char *contracts[],int32_t num,double *cprices,double *basevals)
{
double btcdusd,price_in_btcd,dprice,usdcny,usdrub,btccny,btcrub,xauusd,usdprice=0.,usdval,btcprice=0.; int32_t contractnum,base,nonz = 0;
if ( btcusd > SMALLVAL && btcdbtc > SMALLVAL && (usdval= basevals[0]) > SMALLVAL )
{
xauusd = usdcny = usdrub = btccny = btcrub = 0.;
for (contractnum=0; contractnum<num; contractnum++)
if ( strcmp(contracts[contractnum],"XAUUSD") == 0 )
{
xauusd = cprices[contractnum];
break;
}
if ( basevals[8] > SMALLVAL )
{
usdcny = (basevals[0] * peggy_mils(8)) / (basevals[8] * peggy_mils(0));
btccny = 1000 * btcusd * usdcny;
}
if ( basevals[9] > SMALLVAL )
{
usdrub = (basevals[0] * peggy_mils(9)) / (basevals[9] * peggy_mils(0));
btcrub = 1000 * btcusd * usdrub;
}
btcdusd = (btcusd * btcdbtc);
printf("xauusd %f usdval %f %f %f usdcny %f usdrub %f btcusd %f btcdbtc %f btcdusd %f btccny %f btcrub %f\n",xauusd,usdval,basevals[8],basevals[9],usdcny,usdrub,btcusd,btcdbtc,btcdusd,btccny,btcrub);
prices[0].Pval = (PRICE_RESOLUTION * 100. * btcdbtc);
for (base=0,contractnum=1; base<32; base++,contractnum++)
{
if ( strcmp(contracts[contractnum],CURRENCIES[base]) == 0 )
{
if ( (dprice= basevals[base]) > SMALLVAL )
{
nonz++;
if ( base == 0 )
usdprice = price_in_btcd = (1. / btcdusd);
else price_in_btcd = (dprice / (btcdusd * usdval));
prices[contractnum].Pval = (PRICE_RESOLUTION * price_in_btcd);
}
} else printf("unexpected list entry %s vs %s at %d\n",contracts[contractnum],CURRENCIES[base],contractnum);
}
if ( strcmp(contracts[contractnum],"BTCUSD") != 0 )
printf("unexpected contract (%s) at %d\n",contracts[contractnum],contractnum);
btcprice = (1. / btcdbtc);
prices[contractnum++].Pval = (PRICE_RESOLUTION / btcdbtc) / 1000.;
printf("btcprice %f = 1/%f %llu\n",btcprice,1./btcdbtc,(long long)prices[contractnum-1].Pval);
for (; contractnum<64; contractnum++)
{
//dprice = 0;
if ( contractnum == 63 && strcmp(contracts[contractnum],"BTCUSD") == 0 )
dprice = btcusd;
else if ( contractnum == 62 && strcmp(contracts[contractnum],"BTCCNY") == 0 )
dprice = btccny;
else if ( contractnum == 61 && strcmp(contracts[contractnum],"BTCRUB") == 0 )
dprice = btcrub;
else if ( contractnum == 60 && strcmp(contracts[contractnum],"XAUUSD") == 0 )
dprice = xauusd;
else
{
dprice = cprices[contractnum];
if ( dprice > SMALLVAL && strlen(contracts[contractnum]) > 3 )
{
if ( strcmp(contracts[contractnum]+strlen(contracts[contractnum])-3,"USD") == 0 || strcmp(contracts[contractnum],"COPPER") == 0 || strcmp(contracts[contractnum],"NGAS") == 0 || strcmp(contracts[contractnum],"UKOIL") == 0 || strcmp(contracts[contractnum],"USOIL") == 0 )
dprice *= usdprice;
else if ( strcmp(contracts[contractnum],"SuperNET") == 0 )
{
printf("SuperNET %f -> %f\n",dprice,dprice*btcprice);
dprice *= btcprice;
}
else if ( strcmp(contracts[contractnum]+strlen(contracts[contractnum])-3,"BTC") == 0 )
dprice *= btcprice;
}
}
prices[contractnum].Pval = (uint64_t)((PRICE_RESOLUTION * dprice) * ((double)peggy_mils(contractnum) / 10000.));
//if ( Debuglevel > 2 )
{
struct price_resolution tmp;
tmp = peggy_scaleprice(prices[contractnum],peggy_mils(contractnum));
printf("%.8f btcprice %.6f %f -->>> %s %.6f -> %llu %.6f mils.%d\n",cprices[contractnum],btcprice,cprices[contractnum]*btcprice,contracts[contractnum],Pval(&tmp),(long long)prices[contractnum].Pval,Pval(&prices[contractnum]),peggy_mils(contractnum));
}
}
}
return(nonz);
}
void init_Currencymasks()
{
int32_t base,j,c; uint64_t basemask;
for (base=0; base<NUM_CURRENCIES; base++)
{
basemask = 0L;
for (j=0; j<7; j++)
{
if ( (c= Currency_contracts[base][j]) >= 0 )
{
basemask |= (1L << c);
//printf("(%s %lx) ",CONTRACTS[c],1L<<c);
}
}
Currencymasks[base] = basemask;
printf("0x%llx, ",(long long)basemask);
}
}
double calc_primary_currencies(double logmatrix[8][8],double *bids,double *asks)
{
uint64_t nonzmask; int32_t c,base,rel; double bid,ask;
memset(logmatrix,0,sizeof(double)*8*8);
nonzmask = 0;
for (c=0; c<28; c++)
{
bid = bids[c];
ask = asks[c];
if ( bid != 0 && ask != 0 )
{
base = Contract_base[c];
rel = Contract_rel[c];
nonzmask |= (1L << c);
logmatrix[base][rel] = log(bid);
logmatrix[rel][base] = -log(ask);
//printf("[%f %f] ",bid,ask);
}
}
//printf("%07lx\n",nonzmask);
if ( nonzmask != 0 )
{
bids[USDNUM] = (logmatrix[USD][EUR] + logmatrix[USD][JPY] + logmatrix[USD][GBP] + logmatrix[USD][AUD] + logmatrix[USD][CAD] + logmatrix[USD][CHF] + logmatrix[USD][NZD]) / 8.;
asks[USDNUM] = -(logmatrix[EUR][USD] + logmatrix[JPY][USD] + logmatrix[GBP][USD] + logmatrix[AUD][USD] + logmatrix[CAD][USD] + logmatrix[CHF][USD] + logmatrix[NZD][USD]) / 8.;
bids[EURNUM] = (logmatrix[EUR][USD] + logmatrix[EUR][JPY] + logmatrix[EUR][GBP] + logmatrix[EUR][AUD] + logmatrix[EUR][CAD] + logmatrix[EUR][CHF] + logmatrix[EUR][NZD]) / 8.;
asks[EURNUM] = -(logmatrix[USD][EUR] + logmatrix[JPY][EUR] + logmatrix[GBP][EUR] + logmatrix[AUD][EUR] + logmatrix[CAD][EUR] + logmatrix[CHF][EUR] + logmatrix[NZD][EUR]) / 8.;
bids[JPYNUM] = (logmatrix[JPY][USD] + logmatrix[JPY][EUR] + logmatrix[JPY][GBP] + logmatrix[JPY][AUD] + logmatrix[JPY][CAD] + logmatrix[JPY][CHF] + logmatrix[JPY][NZD]) / 8.;
asks[JPYNUM] = -(logmatrix[USD][JPY] + logmatrix[EUR][JPY] + logmatrix[GBP][JPY] + logmatrix[AUD][JPY] + logmatrix[CAD][JPY] + logmatrix[CHF][JPY] + logmatrix[NZD][JPY]) / 8.;
bids[GBPNUM] = (logmatrix[GBP][USD] + logmatrix[GBP][EUR] + logmatrix[GBP][JPY] + logmatrix[GBP][AUD] + logmatrix[GBP][CAD] + logmatrix[GBP][CHF] + logmatrix[GBP][NZD]) / 8.;
asks[GBPNUM] = -(logmatrix[USD][GBP] + logmatrix[EUR][GBP] + logmatrix[JPY][GBP] + logmatrix[AUD][GBP] + logmatrix[CAD][GBP] + logmatrix[CHF][GBP] + logmatrix[NZD][GBP]) / 8.;
bids[AUDNUM] = (logmatrix[AUD][USD] + logmatrix[AUD][EUR] + logmatrix[AUD][JPY] + logmatrix[AUD][GBP] + logmatrix[AUD][CAD] + logmatrix[AUD][CHF] + logmatrix[AUD][NZD]) / 8.;
asks[AUDNUM] = -(logmatrix[USD][AUD] + logmatrix[EUR][AUD] + logmatrix[JPY][AUD] + logmatrix[GBP][AUD] + logmatrix[CAD][AUD] + logmatrix[CHF][AUD] + logmatrix[NZD][AUD]) / 8.;
bids[CADNUM] = (logmatrix[CAD][USD] + logmatrix[CAD][EUR] + logmatrix[CAD][JPY] + logmatrix[CAD][GBP] + logmatrix[CAD][AUD] + logmatrix[CAD][CHF] + logmatrix[CAD][NZD]) / 8.;
asks[CADNUM] = -(logmatrix[USD][CAD] + logmatrix[EUR][CAD] + logmatrix[JPY][CAD] + logmatrix[GBP][CAD] + logmatrix[AUD][CAD] + logmatrix[CHF][CAD] + logmatrix[NZD][CAD]) / 8.;
bids[CHFNUM] = (logmatrix[CHF][USD] + logmatrix[CHF][EUR] + logmatrix[CHF][JPY] + logmatrix[CHF][GBP] + logmatrix[CHF][AUD] + logmatrix[CHF][CAD] + logmatrix[CHF][NZD]) / 8.;
asks[CHFNUM] = -(logmatrix[USD][CHF] + logmatrix[EUR][CHF] + logmatrix[JPY][CHF] + logmatrix[GBP][CHF] + logmatrix[AUD][CHF] + logmatrix[CAD][CHF] + logmatrix[NZD][CHF]) / 8.;
bids[NZDNUM] = (logmatrix[NZD][USD] + logmatrix[NZD][EUR] + logmatrix[NZD][JPY] + logmatrix[NZD][GBP] + logmatrix[NZD][AUD] + logmatrix[NZD][CAD] + logmatrix[NZD][CHF]) / 8.;
asks[NZDNUM] = -(logmatrix[USD][NZD] + logmatrix[EUR][NZD] + logmatrix[JPY][NZD] + logmatrix[GBP][NZD] + logmatrix[AUD][NZD] + logmatrix[CAD][NZD] + logmatrix[CHF][NZD]) / 8.;
if ( nonzmask != ((1<<28)-1) )
{
for (base=0; base<8; base++)
{
if ( (nonzmask & Currencymasks[base]) != Currencymasks[base] )
bids[base+28] = asks[base+28] = 0;
//else printf("%s %9.6f | ",CONTRACTS[base+28],_pairaved(bids[base+28],asks[base+28]));
}
//printf("keep.%07lx\n",nonzmask);
return(0);
}
if ( 0 && nonzmask != 0 )
{
for (base=0; base<8; base++)
printf("%9.6f | ",_pairaved(bids[base+28],asks[base+28]));
printf("%07llx\n",(long long)nonzmask);
}
}
return(0);
}
double PAX_splineval(struct PAX_spline *spline,uint32_t timestamp,int32_t lookahead)
{
int32_t i,gap,ind = (spline->num - 1);
if ( timestamp >= spline->utc32[ind] )
{
gap = (timestamp - spline->utc32[ind]);
if ( gap < lookahead )
return(_extrapolate_spline64(spline->spline64[ind],gap));
else return(0.);
}
else if ( timestamp <= spline->utc32[0] )
{
gap = (spline->utc32[0] - timestamp);
if ( gap < lookahead )
return(_extrapolate_spline64(spline->spline64[0],gap));
else return(0.);
}
for (i=0; i<spline->num-1; i++)
{
ind = (i + spline->lasti) % (spline->num - 1);
if ( timestamp >= spline->utc32[ind] && timestamp < spline->utc32[ind+1] )
{
spline->lasti = ind;
return(_extrapolate_spline64(spline->spline64[ind],timestamp - spline->utc32[ind]));
}
}
return(0.);
}
double PAX_calcspline(struct PAX_spline *spline,double *outputs,double *slopes,int32_t dispwidth,uint32_t *utc32,double *splinevals,int32_t num)
{
static double errsums[3]; static int errcount;
double c[MAX_SPLINES],f[MAX_SPLINES],dd[MAX_SPLINES],dl[MAX_SPLINES],du[MAX_SPLINES],gaps[MAX_SPLINES];
int32_t n,i,lasti,x,numsplines,nonz; double vx,vy,vw,vz,gap,sum,xval,yval,abssum,lastval,lastxval,yval64,yval32,yval3; uint32_t gap32;
sum = lastxval = n = lasti = nonz = 0;
for (i=0; i<MAX_SPLINES&&i<num; i++)
{
if ( (f[n]= splinevals[i]) != 0. && utc32[i] != 0 )
{
//printf("i%d.(%f %f) ",i,utc[i],splinevals[i]);
if ( n > 0 )
{
if ( (gaps[n-1]= utc32[i] - lastxval) < 0 )
{
printf("illegal gap %f to t%d\n",lastxval,utc32[i]);
return(0);
}
}
spline->utc32[n] = lastxval = utc32[i];
n++;
}
}
if ( (numsplines= n) < 4 )
return(0);
for (i=0; i<n-3; i++)
dl[i] = du[i] = gaps[i+1];
for (i=0; i<n-2; i++)
{
dd[i] = 2.0 * (gaps[i] + gaps[i+1]);
c[i] = (3.0 / (double)gaps[i+1]) * (f[i+2] - f[i+1]) - (3.0 / (double)gaps[i]) * (f[i+1] - f[i]);
}
//for (i=0; i<n; i++) printf("%f ",f[i]);
//printf("F2[%d]\n",n);
dd[0] += (gaps[0] + (double)gaps[0]*gaps[0] / gaps[1]);
du[0] -= ((double)gaps[0]*gaps[0] / gaps[1]);
dd[n-3] += (gaps[n-2] + (double)gaps[n-2]*gaps[n-2] / gaps[n-3]);
dl[n-4] -= ((double)gaps[n-2]*gaps[n-2] / gaps[n-3]);
//tridiagonal(n-2, dl, dd, du, c);
for (i=0; i<n-1-2; i++)
{
du[i] /= dd[i];
dd[i+1] -= dl[i]*du[i];
}
c[0] /= dd[0];
for (i=1; i<n-2; i++)
c[i] = (c[i] - dl[i-1] * c[i-1]) / dd[i];
for (i=n-2-4; i>=0; i--)
c[i] -= c[i+1] * du[i];
//tridiagonal(n-2, dl, dd, du, c);
for (i=n-3; i>=0; i--)
c[i+1] = c[i];
c[0] = (1.0 + (double)gaps[0] / gaps[1]) * c[1] - ((double)gaps[0] / gaps[1] * c[2]);
c[n-1] = (1.0 + (double)gaps[n-2] / gaps[n-3] ) * c[n-2] - ((double)gaps[n-2] / gaps[n-3] * c[n-3]);
//printf("c[n-1] %f, n-2 %f, n-3 %f\n",c[n-1],c[n-2],c[n-3]);
abssum = nonz = lastval = 0;
outputs[spline->firstx] = f[0];
spline->num = numsplines;
for (i=0; i<n; i++)
{
vx = f[i];
vz = c[i];
if ( i < n-1 )
{
gap = gaps[i];
vy = ((f[i+1] - f[i]) / gap) - (gap * (c[i+1] + 2.*c[i]) / 3.);
vw = (c[i+1] - c[i]) / (3. * gap);
}
else
{
vy = 0;
vw = 0;
}
//printf("%3d: t%u [%14.11f %14.11f %14.11f %14.11f] gap %f | %d\n",i,spline->utc32[i],(vx),vy*1000*1000,vz*1000*1000*1000*1000,vw*1000*1000*1000*1000*1000*1000,gap,conv_unixtime(&tmp,spline->utc32[i]));
spline->dSplines[i][0] = vx, spline->dSplines[i][1] = vy, spline->dSplines[i][2] = vz, spline->dSplines[i][3] = vw;
spline->spline64[i][0] = dto64(vx), spline->spline64[i][1] = dto64(vy*1000*1000), spline->spline64[i][2] = dto64(vz*1000*1000*1000*1000), spline->spline64[i][3] = dto64(vw*1000*1000*1000*1000*1000*1000);
spline->spline32[i][0] = dto32(vx), spline->spline32[i][1] = dto32(vy*1000*1000), spline->spline32[i][2] = dto32(vz*1000*1000*1000*1000), spline->spline32[i][3] = dto32(vw*1000*1000*1000*1000*1000*1000);
gap32 = gap = spline->dispincr;
xval = spline->utc32[i] + gap;
lastval = vx;
while ( i < n-1 )
{
x = spline->firstx + ((xval - spline->utc32[0]) / spline->dispincr);
if ( x > dispwidth-1 ) x = dispwidth-1;
if ( x < 0 ) x = 0;
if ( (i < n-2 && gap > gaps[i] + spline->dispincr) )
break;
if ( i == n-2 && xval > spline->utc32[n-1] + MAX_LOOKAHEAD*spline->dispincr )
{
//printf("x.%d dispwidth.%d xval %f > utc[n-1] %f + %f\n",x,dispwidth,xval,utc[n-1],MAX_LOOKAHEAD*incr);
break;
}
if ( x >= 0 )
{
yval = _extrapolate_Spline(spline->dSplines[i],gap);
yval64 = _extrapolate_spline64(spline->spline64[i],gap32);
if ( (yval3 = PAX_splineval(spline,gap32 + spline->utc32[i],MAX_LOOKAHEAD*spline->dispincr)) != 0 )
{
yval32 = _extrapolate_spline32(spline->spline32[i],gap32);
errsums[0] += fabs(yval - yval64), errsums[1] += fabs(yval - yval32), errsums[2] += fabs(yval - yval3), errcount++;
if ( fabs(yval - yval3) > SMALLVAL )
printf("(%.10f vs %.10f %.10f %.10f [%.16f %.16f %.16f]) ",yval,yval64,yval32,yval3, errsums[0]/errcount,errsums[1]/errcount,errsums[2]/errcount);
}
if ( yval > 5000. ) yval = 5000.;
else if ( yval < -5000. ) yval = -5000.;
if ( isnan(yval) == 0 )
{
outputs[x] = yval;
spline->lastval = outputs[x], spline->lastutc = xval;
if ( 1 && fabs(lastval) > SMALLVAL )
{
if ( lastval != 0 && outputs[x] != 0 )
{
if ( slopes != 0 )
slopes[x] = (outputs[x] - lastval), abssum += fabs(slopes[x]);
nonz++;
}
}
}
//else outputs[x] = 0.;
//printf("x.%-4d %d %f %f %f i%-4d: gap %9.6f %9.6f last %9.6f slope %9.6f | %9.1f [%9.1f %9.6f %9.6f %9.6f %9.6f]\n",x,firstx,xval,utc[0],incr,i,gap,yval,lastval,slopes[x],xval,utc[i+1],dSplines[i][0],dSplines[i][1]*1000*1000,dSplines[i][2]*1000*1000*1000*1000,dSplines[i][3]*1000*1000*1000*1000*1000*1000);
}
gap32 += spline->dispincr, gap += spline->dispincr, xval += spline->dispincr;
}
//double pred = (i>0) ? _extrapolate_Spline(dSplines[i-1],gaps[i-1]) : 0.;
//printf("%2d: w%8.1f [gap %f -> %9.6f | %9.6f %9.6f %9.6f %9.6f %9.6f]\n",i,weekinds[i],gap,pred,f[i],dSplines[i].x,1000000*dSplines[i].y,1000000*1000000*dSplines[i].z,1000000*1000000*1000*dSplines[i].w);
}
if ( nonz != 0 )
abssum /= nonz;
spline->aveslopeabs = abssum;
return(lastval);
}
int32_t PAX_genspline(struct PAX_spline *spline,int32_t splineid,char *name,uint32_t *utc32,double *splinevals,int32_t maxsplines,double *refvals)
{
int32_t i; double output[2048],slopes[2048],origvals[MAX_SPLINES];
memset(spline,0,sizeof(*spline)), memset(output,0,sizeof(output)), memset(slopes,0,sizeof(slopes));
spline->dispincr = 3600, spline->basenum = splineid, strcpy(spline->name,name);
memcpy(origvals,splinevals,sizeof(*splinevals) * MAX_SPLINES);
spline->lastval = PAX_calcspline(spline,output,slopes,sizeof(output)/sizeof(*output),utc32,splinevals,maxsplines);
for (i=0; i<spline->num+3; i++)
{
if ( i < spline->num )
{
if ( refvals[i] != 0 && output[i * 24] != refvals[i] )
printf("{%.8f != %.8f}.%d ",output[i * 24],refvals[i],i);
}
else printf("{%.8f %.3f} ",output[i * 24],slopes[i * 24]/spline->aveslopeabs);
spline->pricevals[i] = output[i * 24];
}
printf("spline.%s num.%d\n",name,spline->num);
return(spline->num);
}
int32_t PAX_calcmatrix(double matrix[32][32])
{
int32_t basenum,relnum,nonz,vnum,iter,numbase,numerrs = 0; double sum,vsum,price,price2,basevals[32],errsum=0;
memset(basevals,0,sizeof(basevals));
for (iter=0; iter<2; iter++)
{
numbase = 32;
for (basenum=0; basenum<numbase; basenum++)
{
for (vsum=sum=vnum=nonz=relnum=0; relnum<numbase; relnum++)
{
if ( basenum != relnum )
{
if ( (price= matrix[basenum][relnum]) != 0. )
{
price /= (MINDENOMS[relnum] * .001);
price *= (MINDENOMS[basenum] * .001);
if ( iter == 0 )
sum += (price), nonz++;//, printf("%.8f ",price);
else sum += fabs((price) - (basevals[basenum] / basevals[relnum])), nonz++;
}
if ( (price2= matrix[relnum][basenum]) != 0. )
{
price2 *= (MINDENOMS[relnum] * .001);
price2 /= (MINDENOMS[basenum] * .001);
if ( iter == 0 )
vsum += (price2), vnum++;
else vsum += fabs(price2 - (basevals[relnum] / basevals[basenum])), vnum++;
}
//if ( iter == 0 && 1/price2 > price )
// printf("base.%d rel.%d price2 %f vs %f\n",basenum,relnum,1/price2,price);
}
}
if ( iter == 0 )
sum += 1., vsum += 1.;
if ( nonz != 0 )
sum /= nonz;
if ( vnum != 0 )
vsum /= vnum;
if ( iter == 0 )
basevals[basenum] = (sum + 1./vsum) / 2.;
else errsum += (sum + vsum)/2, numerrs++;//, printf("(%.8f %.8f) ",sum,vsum);
//printf("date.%d (%.8f/%d %.8f/%d).%02d -> %.8f\n",i,sum,nonz,vsum,vnum,basenum,basevals[basenum]);
}
if ( iter == 0 )
{
for (sum=relnum=0; relnum<numbase; relnum++)
sum += (basevals[relnum]);//, printf("%.8f ",(basevals[relnum]));
//printf("date.%d sums %.8f and vsums iter.%d\n",i,sum/7,iter);
sum /= (numbase - 1);
for (relnum=0; relnum<numbase; relnum++)
basevals[relnum] /= sum;//, printf("%.8f ",basevals[relnum]);
//printf("date.%d sums %.8f and vsums iter.%d\n",i,sum,iter);
}
else
{
for (basenum=0; basenum<numbase; basenum++)
matrix[basenum][basenum] = basevals[basenum];
}
}
if ( numerrs != 0 )
errsum /= numerrs;
return(errsum);
}
int32_t PAX_getmatrix(double *basevals,struct peggy_info *PEGS,double Hmatrix[32][32],double *RTprices,char *contracts[],int32_t num,uint32_t timestamp)
{
int32_t i,j,c; char name[16]; double btcusd,btcdbtc;
memcpy(Hmatrix,PEGS->data.ecbmatrix,sizeof(PEGS->data.ecbmatrix));
PAX_calcmatrix(Hmatrix);
/*for (i=0; i<32; i++)
{
for (j=0; j<32; j++)
printf("%.6f ",Hmatrix[i][j]);
printf("%s\n",CURRENCIES[i]);
}*/
btcusd = PEGS->data.btcusd;
btcdbtc = PEGS->data.btcdbtc;
if ( btcusd > SMALLVAL )
dxblend(&PEGS->btcusd,btcusd,.9);
if ( btcdbtc > SMALLVAL )
dxblend(&PEGS->btcdbtc,btcdbtc,.9);
// char *cryptostrs[8] = { "btc", "nxt", "unity", "eth", "ltc", "xmr", "bts", "xcp" };
// "BTCUSD", "NXTBTC", "SuperNET", "ETHBTC", "LTCBTC", "XMRBTC", "BTSBTC", "XCPBTC", // BTC priced
for (i=0; i<num; i++)
{
if ( contracts[i] == 0 )
continue;
if ( i == num-1 && strcmp(contracts[i],"BTCUSD") == 0 )
{
RTprices[i] = PEGS->btcusd;
continue;
}
else if ( i == num-2 && strcmp(contracts[i],"BTCCNY") == 0 )
{
continue;
}
else if ( i == num-3 && strcmp(contracts[i],"BTCRUB") == 0 )
{
continue;
}
else if ( i == num-4 && strcmp(contracts[i],"XAUUSD") == 0 )
{
continue;
}
if ( strcmp(contracts[i],"NXTBTC") == 0 )
RTprices[i] = PEGS->data.cryptos[1];
else if ( strcmp(contracts[i],"SuperNET") == 0 )
RTprices[i] = PEGS->data.cryptos[2];
else if ( strcmp(contracts[i],"ETHBTC") == 0 )
RTprices[i] = PEGS->data.cryptos[3];
else if ( strcmp(contracts[i],"LTCBTC") == 0 )
RTprices[i] = PEGS->data.cryptos[4];
else if ( strcmp(contracts[i],"XMRBTC") == 0 )
RTprices[i] = PEGS->data.cryptos[5];
else if ( strcmp(contracts[i],"BTSBTC") == 0 )
RTprices[i] = PEGS->data.cryptos[6];
else if ( strcmp(contracts[i],"XCPBTC") == 0 )
RTprices[i] = PEGS->data.cryptos[7];
else if ( i < 32 )
{
basevals[i] = Hmatrix[i][i];
//if ( Debuglevel > 2 )
printf("(%s %f).%d ",CURRENCIES[i],basevals[i],i);
}
else if ( (c= PAX_contractnum(contracts[i],0)) >= 0 )
{
RTprices[i] = PEGS->data.RTprices[c];
//if ( is_decimalstr(contracts[i]+strlen(contracts[i])-2) != 0 )
// cprices[i] *= .0001;
}
else
{
for (j=0; j<sizeof(Yahoo_metals)/sizeof(*Yahoo_metals); j++)
{
sprintf(name,"%sUSD",Yahoo_metals[j]);
if ( contracts[i] != 0 && strcmp(name,contracts[i]) == 0 )
{
RTprices[i] = PEGS->data.RTmetals[j];
break;
}
}
}
//if ( Debuglevel > 2 )
printf("(%f %f) i.%d num.%d %s %f\n",PEGS->btcusd,PEGS->btcdbtc,i,num,contracts[i],RTprices[i]);
//printf("RT.(%s %f) ",contracts[i],RTprices[i]);
}
return(PEGS->data.ecbdatenum);
}
char *peggy_emitprices(int32_t *nonzp,struct peggy_info *PEGS,uint32_t blocktimestamp,int32_t maxlockdays)
{
double matrix[32][32],RTmatrix[32][32],cprices[64],basevals[64]; struct price_resolution prices[256];
cJSON *json,*array; char *jsonstr,*opreturnstr = 0; int32_t i,nonz = 0;
memset(cprices,0,sizeof(cprices));
//printf("peggy_emitprices\n");
if ( PAX_getmatrix(basevals,PEGS,matrix,cprices+1,peggy_bases+1,sizeof(peggy_bases)/sizeof(*peggy_bases)-1,blocktimestamp) > 0 )
{
cprices[0] = PEGS->btcdbtc;
/*for (i=0; i<32; i++)
printf("%f ",basevals[i]);
printf("basevals\n");
for (i=0; i<64; i++)
printf("%f ",cprices[i]);
printf("cprices\n");*/
json = cJSON_CreateObject(), array = cJSON_CreateArray();
memset(prices,0,sizeof(prices));
memset(matrix,0,sizeof(matrix));
memset(RTmatrix,0,sizeof(RTmatrix));
peggy_prices(prices,PEGS->btcusd,PEGS->btcdbtc,peggy_bases,sizeof(peggy_bases)/sizeof(*peggy_bases),cprices,basevals);
for (i=0; i<sizeof(peggy_bases)/sizeof(*peggy_bases); i++)
{
jaddinum(array,prices[i].Pval);
if ( prices[i].Pval != 0 )
nonz++;
//if ( Debuglevel > 2 )
printf("{%s %.6f %u}.%d ",peggy_bases[i],Pval(&prices[i]),(uint32_t)prices[i].Pval,peggy_mils(i));
}
jaddnum(json,"txtype",PEGGY_TXPRICES);
//jaddnum(json,"btcusd",btc.Pval);
if ( maxlockdays != 0 )
{
jaddnum(json,"timestamp",blocktimestamp);
jaddnum(json,"maxlockdays",maxlockdays);
}
//jaddstr(json,"privkey","1259ec21d31a30898d7cd1609f80d9668b4778e3d97e941044b39f0c44d2e51b");
jadd(json,"details",array);
jsonstr = jprint(json,1);
//printf("%s\n",jsonstr);
opreturnstr = peggy_tx(jsonstr);
free(jsonstr);
} else printf("pricematrix returned null\n");
*nonzp = nonz;
//printf("nonz.%d\n",nonz);
return(opreturnstr);
}
double PAX_baseprice(struct peggy_info *PEGS,uint32_t timestamp,int32_t basenum)
{
double btc,btcd,btcdusd,usdval;
btc = 1000. * _pairaved(PAX_splineval(&PEGS->splines[MAX_CURRENCIES+0],timestamp,0),PAX_splineval(&PEGS->splines[MAX_CURRENCIES+1],timestamp,0));
btcd = .01 * PAX_splineval(&PEGS->splines[MAX_CURRENCIES+2],timestamp,0);
if ( btc != 0. && btcd != 0. )
{
btcdusd = (btc * btcd);
usdval = PAX_splineval(&PEGS->splines[USD],timestamp,0);
if ( basenum == USD )
return(1. / btcdusd);
else return(PAX_splineval(&PEGS->splines[basenum],timestamp,0) / (btcdusd * usdval));
}
return(0.);
}
double PAX_getprice(char *retbuf,char *base,char *rel,char *contract,struct peggy_info *PEGS)
{
int32_t i,c,basenum,relnum,n = 0; double yprice,daily,revdaily,price;
struct PAX_data *dp = &PEGS->data;
price = yprice = daily = revdaily = 0.;
PAX_ispair(base,rel,contract);
if ( base[0] != 0 && rel[0] != 0 )
{
basenum = PAX_basenum(base), relnum = PAX_basenum(rel);
if ( basenum >= 0 && relnum >= 0 && basenum < MAX_CURRENCIES && relnum < MAX_CURRENCIES )
daily = dp->dailyprices[basenum*MAX_CURRENCIES + relnum], revdaily = dp->dailyprices[relnum*MAX_CURRENCIES + basenum];
}
for (i=0; i<sizeof(Yahoo_metals)/sizeof(*Yahoo_metals); i++)
if ( strncmp(Yahoo_metals[i],contract,3) == 0 && strcmp(contract+3,"USD") == 0 )
{
yprice = dp->metals[i];
break;
}
sprintf(retbuf,"{\"result\":\"success\",\"contract\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\"",contract,base,rel);
if ( (c= PAX_contractnum(contract,0)) >= 0 )
{
if ( dp->tbids[c] != 0. && dp->tasks[c] != 0. )
{
price += (dp->tbids[c] + dp->tasks[c]), n += 2;
sprintf(retbuf+strlen(retbuf),",\"truefx\":{\"timestamp\":\"%u\",\"bid\":%.8f,\"ask\":%.8f}",dp->ttimestamps[c],dp->tbids[c],dp->tasks[c]);
}
if ( dp->fbids[c] != 0. && dp->fasks[c] != 0. )
{
price += (dp->fbids[c] + dp->fasks[c]), n += 2;
sprintf(retbuf+strlen(retbuf),",\"fxcm\":{\"bid\":%.8f,\"ask\":%.8f}",dp->fbids[c],dp->fasks[c]);
}
if ( dp->ibids[c] != 0. && dp->iasks[c] != 0. )
{
price += (dp->ibids[c] + dp->iasks[c]), n += 2;
sprintf(retbuf+strlen(retbuf),",\"instaforex\":{\"timestamp\":%u,\"bid\":%.8f,\"ask\":%.8f}",dp->itimestamps[c],dp->ibids[c],dp->iasks[c]);
}
if ( yprice != 0. )
sprintf(retbuf+strlen(retbuf),",\"yahoo\":{\"price\":%.8f}",yprice);
if ( daily != 0. || revdaily != 0. )
sprintf(retbuf+strlen(retbuf),",\"ecb\":{\"date\":\"%s\",\"daily\":%.8f,\"reverse\":%.8f}",dp->edate,daily,revdaily);
}
if ( n > 0 )
price /= n;
sprintf(retbuf+strlen(retbuf),",\"aveprice\":%.8f,\"n\":%d}",price,n);
return(price);
}
#include "../includes/iguana_apidefs.h"
#include "../includes/iguana_apideclares.h"
void PAX_init(struct peggy_info *PEGS)
{
double commission = 0.;
init_Currencymasks();
tradebot_monitorall(0,0,0,0,"fxcm",commission);
tradebot_monitorall(0,0,0,0,"truefx",commission);
tradebot_monitorall(0,0,0,0,"instaforex",commission);
}
#include "../includes/iguana_apiundefs.h"

243
iguana/peggy_ramkv.c

@ -0,0 +1,243 @@
/******************************************************************************
* Copyright © 2014-2015 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 "peggy.h"
void ramkv777_lock(struct ramkv777 *kv)
{
if ( kv->threadsafe != 0 )
portable_mutex_lock(&kv->mutex);
}
void ramkv777_unlock(struct ramkv777 *kv)
{
if ( kv->threadsafe != 0 )
portable_mutex_unlock(&kv->mutex);
}
int32_t ramkv777_delete(struct ramkv777 *kv,void *key)
{
int32_t retval = -1; struct ramkv777_item *ptr = 0;
if ( kv == 0 )
return(-1);
ramkv777_lock(kv);
HASH_FIND(hh,kv->table,key,kv->keysize,ptr);
if ( ptr != 0 )
{
HASH_DELETE(hh,kv->table,ptr);
free(ptr);
retval = 0;
}
ramkv777_lock(kv);
return(retval);
}
void *ramkv777_read(int32_t *valuesizep,struct ramkv777 *kv,void *key)
{
struct ramkv777_item *item = 0;
if ( kv == 0 )
{
printf("ramkv777_read: null ramkv??\n");
return(0);
}
//printf("search for [%llx] keysize.%d\n",*(long long *)key,keysize);
ramkv777_lock(kv);
HASH_FIND(hh,kv->table,key,kv->keysize,item);
ramkv777_unlock(kv);
if ( item != 0 )
{
if ( valuesizep != 0 )
*valuesizep = item->valuesize;
return(ramkv777_itemvalue(kv,item));
} //else printf("cant find key.%llx keysize.%d\n",*(long long *)key,kv->keysize);
if ( valuesizep != 0 )
*valuesizep = 0;
return(0);
}
void *ramkv777_write(struct ramkv777 *kv,void *key,void *value,int32_t valuesize)
{
struct ramkv777_item *item = 0; int32_t keysize = kv->keysize;
if ( kv == 0 )
return(0);
ramkv777_lock(kv);
HASH_FIND(hh,kv->table,key,keysize,item);
if ( item != 0 )
{
printf("item being added, already there\n");
if ( valuesize == item->valuesize )
{
if ( memcmp(ramkv777_itemvalue(kv,item),value,valuesize) != 0 )
{
vupdate_sha256(kv->sha256.bytes,&kv->state,key,kv->keysize);
vupdate_sha256(kv->sha256.bytes,&kv->state,value,valuesize);
memcpy(ramkv777_itemvalue(kv,item),value,valuesize);
}
ramkv777_unlock(kv);
return(item);
}
HASH_DELETE(hh,kv->table,item);
free(item);
vupdate_sha256(kv->sha256.bytes,&kv->state,key,kv->keysize);
}
item = calloc(1,ramkv777_itemsize(kv,valuesize));
memcpy(item->keyvalue,key,kv->keysize);
memcpy(ramkv777_itemvalue(kv,item),value,valuesize);
item->valuesize = valuesize;
item->rawind = (kv->numkeys++ * ACCTS777_MAXRAMKVS) | kv->kvind;
//printf("add.(%s) kv->numkeys.%d keysize.%d valuesize.%d [%llx]\n",kv->name,kv->numkeys,keysize,valuesize,*(long long *)ramkv777_itemkey(item));
HASH_ADD_KEYPTR(hh,kv->table,ramkv777_itemkey(item),kv->keysize,item);
vupdate_sha256(kv->sha256.bytes,&kv->state,key,kv->keysize);
vupdate_sha256(kv->sha256.bytes,&kv->state,value,valuesize);
ramkv777_unlock(kv);
if ( kv->dispflag != 0 )
fprintf(stderr,"%016llx ramkv777_write numkeys.%d kv.%p table.%p write kep.%p key.%llx size.%d, value.(%08x) size.%d\n",(long long)kv->sha256.txid,kv->numkeys,kv,kv->table,key,*(long long *)key,keysize,calc_crc32(0,value,valuesize),valuesize);
return(ramkv777_itemvalue(kv,item));
}
void *ramkv777_iterate(struct ramkv777 *kv,void *args,void *(*iterator)(struct ramkv777 *kv,void *args,void *key,void *value,int32_t valuesize))
{
struct ramkv777_item *item,*tmp; void *retval = 0;
if ( kv == 0 )
return(0);
ramkv777_lock(kv);
HASH_ITER(hh,kv->table,item,tmp)
{
if ( (retval= (*iterator)(kv,args!=0?args:item,item->keyvalue,ramkv777_itemvalue(kv,item),item->valuesize)) != 0 )
{
ramkv777_unlock(kv);
return(retval);
}
}
ramkv777_unlock(kv);
return(0);
}
void *ramkv777_saveiterator(struct ramkv777 *kv,void *args,void *key,void *value,int32_t valuesize)
{
FILE *fp = args;
if ( args != 0 )
{
if ( fwrite(key,1,kv->keysize,fp) != kv->keysize )
{
printf("Error saving key.[%d]\n",kv->keysize);
return(key);
}
}
return(0);
}
/*char *OS_mvstr()
{
#ifdef __WIN32
return("rename");
#else
return("mv");
#endif
}*/
char *OS_mvstr();
long ramkv777_save(struct ramkv777 *kv)
{
FILE *fp; long retval = -1; char fname[512],oldfname[512],cmd[512];
sprintf(fname,"%s.tmp",kv->name);
if ( (fp= fopen(fname,"wb")) != 0 )
{
if ( ramkv777_iterate(kv,fp,ramkv777_saveiterator) == 0 )
{
printf("save %ld to HDD\n",ftell(fp));
retval = ftell(fp);
}
else printf("error saving item at %ld\n",ftell(fp));
fclose(fp);
} else printf("error creating(%s)\n",fname);
if ( retval > 0 )
{
sprintf(oldfname,"%s.%u",kv->name,(uint32_t)time(NULL));
sprintf(cmd,"%s %s %s",OS_mvstr(),kv->name,oldfname), system(cmd);
sprintf(cmd,"%s %s %s",OS_mvstr(),fname,kv->name), system(cmd);
}
return(retval);
}
struct ramkv777 *ramkv777_init(int32_t kvind,char *name,int32_t keysize,int32_t threadsafe)
{
struct ramkv777 *kv;
printf("ramkv777_init.(%s)\n",name);
kv = calloc(1,sizeof(*kv));
strcpy(kv->name,name);
kv->threadsafe = threadsafe, kv->keysize = keysize, kv->kvind = kvind;//, kv->dispflag = 1;
portable_mutex_init(&kv->mutex);
vupdate_sha256(kv->sha256.bytes,&kv->state,0,0);
return(kv);
}
int32_t ramkv777_disp(struct ramkv777 *kv)
{
struct ramkv777_item *item,*tmp; int32_t n = 0;
printf("ramkv777_disp.(%s)\n",kv->name);
if ( kv == 0 )
return(0);
ramkv777_lock(kv);
HASH_ITER(hh,kv->table,item,tmp)
{
n++;
printf("%llx: %llx\n",*(long long *)ramkv777_itemkey(item),*(long long *)ramkv777_itemvalue(kv,item));
}
ramkv777_unlock(kv);
printf("ramkv777_disp.(%s) n.%d items\n",kv->name,n);
return(n);
}
void ramkv777_free(struct ramkv777 *kv)
{
struct ramkv777_item *ptr,*tmp;
if ( kv != 0 )
{
HASH_ITER(hh,kv->table,ptr,tmp)
{
HASH_DEL(kv->table,ptr);
free(ptr);
}
free(kv);
}
}
int32_t ramkv777_clone(struct ramkv777 *clone,struct ramkv777 *kv)
{
struct ramkv777_item *item,*tmp; int32_t n = 0;
if ( kv != 0 )
{
HASH_ITER(hh,kv->table,item,tmp)
{
ramkv777_write(clone,item->keyvalue,ramkv777_itemvalue(kv,item),item->valuesize);
n++;
}
}
return(n);
}
struct ramkv777_item *ramkv777_itemptr(struct ramkv777 *kv,void *value)
{
struct ramkv777_item *item = 0;
if ( kv != 0 && value != 0 )
{
value = (void *)((long)value - (kv)->keysize);
item = (void *)((long)value - ((long)item->keyvalue - (long)item));
}
return(item);
}

812
iguana/peggy_serdes.c

@ -0,0 +1,812 @@
/******************************************************************************
* Copyright © 2014-2015 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 "peggy.h"
int32_t serdes777_rwbits(int32_t rwflag,void *ptr,int32_t len,HUFF *hp)
{
int32_t i,bit;
if ( rwflag == 0 )
{
for (i=0; i<len; i++)
{
if ( (bit= hgetbit(hp)) < 0 )
return(-1);
if ( bit != 0 )
SETBIT(ptr,i);
else CLEARBIT(ptr,i);
}
//printf("rbits.%d (%02x)\n",len,*(uint8_t *)ptr);
}
else
{
//printf("wbits.%d (%02x)\n",len,*(uint8_t *)ptr);
for (i=0; i<len; i++)
if ( hputbit(hp,GETBIT(ptr,i) != 0) < 0 )
return(-100*i-100);
}
//printf("rwbits len.%d (%02x)\n",len,*(uint8_t *)dest);
//printf("(%d) ",*(uint8_t *)ptr);
return(len);
}
int32_t serdes777_rwsizebits(int32_t rwflag,void *xptr,uint64_t xval,int32_t sizebits,HUFF *hp)
{
int32_t numbits = 0;
if ( 1 && sizebits == 3 )
{
if ( rwflag != 0 )
{
if ( xval == 0 )
{
hputbit(hp,0);
return(1);
}
else
{
hputbit(hp,1);
if ( xval < 3 )
{
hputbit(hp,(xval&1) != 0);
hputbit(hp,(xval&2) != 0);
//hputbit(hp,(xval&4) != 0);
return(3);
}
else
{
hputbit(hp,1), hputbit(hp,1);//, hputbit(hp,1);
if ( serdes777_rwbits(1,xptr,8,hp) != 8 )
return(-30);
return(11);
}
}
}
else
{
if ( hgetbit(hp) == 0 )
{
*(uint8_t *)xptr = 0;
return(1);
}
else
{
numbits = hgetbit(hp) + (hgetbit(hp) << 1);// + (hgetbit(hp) << 2);
if ( numbits < 3 )
{
*(uint8_t *)xptr = numbits;
return(3);
}
else
{
if ( serdes777_rwbits(0,xptr,8,hp) != 8 )
return(-4);
return(11);
}
}
}
}
else
{
if ( rwflag != 0 )
{
numbits = hcalc_bitsize(xval) - 1;
//printf("rwsizebits.%d numbits.%d %02x %llu\n",sizebits,numbits,*(uint8_t *)xptr,(long long)xval);
if ( numbits >= (1 << sizebits) )
{
printf("numbits overflow.%d doesnt fit into sizebits.%d\n",numbits,sizebits);
return(-10);
}
}
if ( serdes777_rwbits(rwflag,&numbits,sizebits,hp) != sizebits )
return(-20);
if ( serdes777_rwbits(rwflag,xptr,numbits+1,hp) != numbits+1 )
return(-30);
//printf("return.(%02x) numbits.%d + 1 + sizebits.%d\n",*(uint8_t *)xptr,numbits,sizebits);
//printf("(%02x) ",*(uint8_t *)xptr);
return(numbits + 1 + sizebits);
}
}
#define serdes777_rwchar(rwflag,x,hp) serdes777_rwsizebits(rwflag,xptr,*(uint8_t *)xptr,3,hp)
#define serdes777_rwshort(rwflag,x,hp) serdes777_rwsizebits(rwflag,xptr,*(uint16_t *)xptr,4,hp)
#define serdes777_rwint(rwflag,x,hp) serdes777_rwsizebits(rwflag,xptr,*(uint32_t *)xptr,5,hp)
#define serdes777_rwlong(rwflag,x,hp) serdes777_rwsizebits(rwflag,xptr,*(uint64_t *)xptr,6,hp)
int32_t serdes777_convstr(int32_t encoding,void *dest,void *src,int32_t len)
{
if ( encoding == 16 )
{
len >>= 1;
decode_hex(dest,len,src);
return(8 * len);
}
else if ( encoding == -16 )
{
init_hexbytes_noT(dest,src,len);
return(8 * ((len << 1) + 1));
}
else if ( encoding == 32 )
return(decode_base32(dest,src,len));
else if ( encoding == -32 )
return(init_base32(dest,src,len));
return(-1);
}
int32_t serdes777_rwvarstr(int32_t rwflag,uint8_t *data,int32_t *lenp,HUFF *hp)
{
int32_t i,n,numbits,total; void *xptr = lenp;
if ( (total= serdes777_rwchar(rwflag,lenp,hp)) < 0 )
return(total);
n = *lenp;
for (i=0; i<n; i++)
{
xptr = &data[i];
if ( (numbits= serdes777_rwchar(rwflag,&data[i],hp)) < 0 )
return(-1);
total += numbits;
}
return(total);
}
int32_t serdes777_rwstr(int32_t rwflag,uint8_t *data,HUFF *hp,int32_t encoding)
{
int32_t total,len; uint8_t *ptr,buf[MAX_OPRETURNSIZE*2 + 1];
if ( rwflag == 0 )
{
ptr = (encoding != 0) ? buf : data;
if ( (total= serdes777_rwvarstr(rwflag,ptr,&len,hp)) < 0 )
return(-1);
if ( encoding != 0 )
total = serdes777_convstr(-encoding,data,ptr,total);
}
else
{
len = (int32_t)strlen((void *)data);
if ( encoding != 0 )
{
if ( (len= serdes777_convstr(encoding,buf,data,len)) < 0 )
{
printf("serdes777_writestr error doing serdes777_convstr encoding.%d len.%d\n",encoding,len);
return(-1);
}
if ( (len & 7) != 0 )
{
printf("serdes777_writestr error doing serdes777_convstr encoding.%d len.%d unaligned return\n",encoding,len);
return(-1);
}
data = (void *)buf;
}
total = serdes777_rwvarstr(rwflag,data,&len,hp);
}
return(total);
}
int32_t serdes777_rw(int32_t rwflag,void *xptr,int32_t size,HUFF *hp)
{
if ( size < 0 ) // high entropy
return(serdes777_rwbits(rwflag,xptr,-size*8,hp));
//else return(serdes777_rwbits(rwflag,xptr,size*8,hp));
switch ( size )
{
case 1: return(serdes777_rwchar(rwflag,xptr,hp)); break;
case 2: return(serdes777_rwshort(rwflag,xptr,hp)); break;
case 4: return(serdes777_rwint(rwflag,xptr,hp)); break;
case 8: return(serdes777_rwlong(rwflag,xptr,hp)); break;
default: return(serdes777_rwstr(rwflag,xptr,hp,size)); break;
}
return(-1);
}
int32_t serdes777_codec(int32_t rwflag,void *ptr,int32_t maxlen,long tokens[][2],long numtokens,HUFF *hp)
{
int32_t i,numbits,totalbits = 0;
// printf("peggy_rwtx.%d %p max.%d %p numtokens.%ld %p\n",rwflag,tx,maxlen,txtokens,numtokens,hp);
for (i=0; i<numtokens; i++)
{
//printf("i.%d peggy_rwtx.%d %p max.%d %p numtokens.%ld %p (%ld %ld)\n",i,rwflag,ptr,maxlen,tokens,numtokens,hp,tokens[i][0],tokens[i][1]);
if ( (numbits= serdes777_rw(rwflag,(void *)((long)ptr + tokens[i][0]),(int32_t)tokens[i][1],hp)) < 0 )
return(-i-1);
totalbits += numbits;
}
return(totalbits);
}
int32_t serdes777_rwlock(int32_t rwflag,struct peggy_lock *lock,HUFF *TX)
{
long serdes777_locktokens[][2] =
{
{ 0, sizeof(lock->peg) }, { (long)&lock->denom - (long)lock, sizeof(lock->denom) },
{ (long)&lock->minlockdays - (long)lock, sizeof(lock->minlockdays) }, { (long)&lock->maxlockdays - (long)lock, sizeof(lock->maxlockdays) },
{ (long)&lock->clonesmear - (long)lock, sizeof(lock->clonesmear) }, { (long)&lock->mixrange - (long)lock, sizeof(lock->mixrange) },
{ (long)&lock->margin - (long)lock, sizeof(lock->margin) },
};
return(serdes777_codec(rwflag,lock,sizeof(*lock),serdes777_locktokens,sizeof(serdes777_locktokens)/sizeof(*serdes777_locktokens),TX));
}
int32_t serdes777_rwaddr(int32_t rwflag,union peggy_addr *addr,int32_t type,HUFF *TX)
{
int32_t n,numbits = 0;
switch ( type )
{
case PEGGY_ADDRBTCD: numbits = serdes777_rw(rwflag,&addr->coinaddr,0,TX); break;
case PEGGY_ADDRNXT: numbits = serdes777_rw(rwflag,&addr->nxt64bits,(int32_t)-sizeof(addr->nxt64bits),TX); break;
case PEGGY_ADDRCREATE:
if ( (numbits= serdes777_rw(rwflag,&addr->newunit.sha256.bytes,(int32_t)-sizeof(addr->newunit.sha256),TX)) < 0 )
return(-3);
if ( (n= serdes777_rwlock(rwflag,&addr->newunit.newlock,TX)) < 0 )
return(-2);
numbits += n;
break;
case PEGGY_ADDRUNIT:
case PEGGY_ADDRPUBKEY:
if ( (numbits= serdes777_rw(rwflag,&addr->newunit.sha256.bytes,(int32_t)-sizeof(addr->newunit.sha256),TX)) < 0 )
return(-3);
if ( (n= serdes777_rw(rwflag,&addr->newunit.newlock.peg,sizeof(addr->newunit.newlock.peg),TX)) < 0 )
return(-2);
if ( (n= serdes777_rw(rwflag,&addr->newunit.newlock.minlockdays,sizeof(addr->newunit.newlock.minlockdays),TX)) < 0 )
return(-2);
case PEGGY_ADDR777:
numbits = serdes777_rw(rwflag,&addr->SaMbits.bytes,(int32_t)-sizeof(addr->SaMbits),TX); break;
default: numbits = -1; break;
}
return(numbits);
}
int32_t serdes777_rwbets(int32_t rwflag,struct peggy_txbet *bets,int32_t numbets,HUFF *TX)
{
long serdes777_bettokens[][2] =
{
{ 0, sizeof(bets[0].prediction) },
{ (long)&bets[0].peg - (long)bets, 0 },
{ (long)&bets[0].binary - (long)bets, sizeof(bets[0].binary) }
};
int32_t i,n,numbits = 0;
if ( numbets <= 0 )
return(0);
for (i=0; i<numbets; i++)
{
if ( (n= serdes777_codec(rwflag,&bets[i],sizeof(bets[i]),serdes777_bettokens,sizeof(serdes777_bettokens)/sizeof(*serdes777_bettokens),TX)) < 0 )
return(-1);
numbits += n;
}
return(numbits);
}
int32_t serdes777_rwmicropay(int32_t rwflag,struct peggy_txmicropay *micropay,int32_t num,HUFF *TX)
{
long serdes777_mptokens[][2] =
{
{ 0, sizeof(micropay[0].claimhash) },
{ (long)&micropay[0].refundhash - (long)micropay, sizeof(micropay[0].refundhash) },
{ (long)&micropay[0].expiration - (long)micropay, sizeof(micropay[0].expiration) },
{ (long)&micropay[0].chainlen - (long)micropay, sizeof(micropay[0].chainlen) },
{ (long)&micropay[0].vin - (long)micropay, sizeof(micropay[0].vin) },
{ (long)&micropay[0].vout - (long)micropay, sizeof(micropay[0].vout) },
};
int32_t i,n,numbits = 0;
if ( num <= 0 )
return(0);
for (i=0; i<num; i++)
{
if ( (n= serdes777_codec(rwflag,&micropay[i],sizeof(micropay[i]),serdes777_mptokens,sizeof(serdes777_mptokens)/sizeof(*serdes777_mptokens),TX)) < 0 )
return(-1);
numbits += n;
}
return(numbits);
}
int32_t serdes777_rwinout(int32_t rwflag,int32_t inoutflag,void *inout,HUFF *TX)
{
int32_t type,a,b,c,d; struct peggy_input *in; struct peggy_output *out;
if ( inoutflag == 0 )
{
in = inout;
a = serdes777_rw(rwflag,&in->type,sizeof(in->type),TX);
b = serdes777_rw(rwflag,&in->chainlen,sizeof(in->chainlen),TX);
c = serdes777_rwaddr(rwflag,&in->src,in->type,TX);
d = serdes777_rw(rwflag,&in->amount,sizeof(in->amount),TX);
type = in->type;
}
else
{
out = inout;
a = serdes777_rw(rwflag,&out->type,sizeof(out->type),TX);
b = serdes777_rw(rwflag,&out->vin,sizeof(out->vin),TX);
c = serdes777_rwaddr(rwflag,&out->dest,out->type,TX);
d = serdes777_rw(rwflag,&out->ratio,sizeof(out->ratio),TX);
type = out->type;
}
if ( a < 0 || b < 0 || c < 0 || d < 0 )
{
printf("serdes777_rwinput.%d error encoding type.%d %d %d %d %d\n",rwflag,type,a,b,c,d);
//getchar();
return(-1);
}
return(a + b + c + d);
}
int32_t serdes777_rwprices(int32_t rwflag,struct peggy_txprices *price,HUFF *TX)
{
long serdes777_pricetokens[][2] =
{
{ 0, sizeof(price->num) }, //{ (long)&prices->btcusd - (long)prices, sizeof(prices->btcusd) },
{ (long)&price->timestamp - (long)price, sizeof(price->timestamp) },
{ (long)&price->maxlockdays - (long)price, sizeof(price->maxlockdays) }
};
long serdes777_pricetoken2[][2] = { { 0, sizeof(price->feed[0]) } };
int32_t i,n,numbits = -1;
if ( (numbits= serdes777_codec(rwflag,&price->num,sizeof(price->num),serdes777_pricetokens,sizeof(serdes777_pricetokens)/sizeof(*serdes777_pricetokens),TX)) < 0 )
return(-1);
//printf("numprices.%u btcusd %.6f: ",prices->num,(double)1000.*prices->btcusd);
for (i=0; i<price->num; i++)
{
if ( (n= serdes777_codec(rwflag,&price->feed[i],sizeof(price->feed[i]),serdes777_pricetoken2,sizeof(serdes777_pricetoken2)/sizeof(*serdes777_pricetoken2),TX)) < 0 )
return(-1);
//printf("(%d of %d %u) ",i,prices->num,prices->prices[i]);
numbits += n;
}
return(numbits);
}
int32_t serdes777_rwtune(int32_t rwflag,struct peggy_txtune *tune,int32_t numtunes,HUFF *TX)
{
long serdes777_tunetokens[][2] =
{
{ 0, sizeof(tune[0].type) },
{ (long)&tune[0].peg - (long)tune, 0 },
{ (long)&tune[0].val - (long)tune, sizeof(tune[0].val) },
{ (long)&tune[0].B - (long)tune, sizeof(tune[0].B) },
};
int32_t i,n,numbits = -1;
if ( numtunes <= 0 )
return(0);
for (i=0; i<numtunes; i++)
{
if ( (n= serdes777_codec(rwflag,&tune[i],sizeof(tune[i]),serdes777_tunetokens,sizeof(serdes777_tunetokens)/sizeof(*serdes777_tunetokens),TX)) < 0 )
return(-1);
numbits += n;
}
return(numbits);
}
int32_t serdes777_rwdetails(int32_t rwflag,struct peggy_tx *Ptx,HUFF *TX)
{
int32_t n,numbits = 0;
//printf("rwdetails.%d offset.%d txtype.%d\n",rwflag,TX->bitoffset,Ptx->txtype);
switch ( Ptx->txtype )
{
case PEGGY_TXBET: numbits = serdes777_rwbets(rwflag,Ptx->details.bets,Ptx->numdetails,TX); break;
case PEGGY_TXPRICES: numbits = serdes777_rwprices(rwflag,&Ptx->details.price,TX); break;
case PEGGY_TXTUNE: break; numbits = serdes777_rwtune(rwflag,Ptx->details.tune,Ptx->numdetails,TX); break;
case PEGGY_TXMICROPAY: numbits = serdes777_rwmicropay(rwflag,Ptx->details.micropays,Ptx->numdetails,TX); break;
}
if ( numbits < 0 )
return(-1);
if ( Ptx->msglen != 0 )
{
if ( (n = serdes777_rwstr(rwflag,(uint8_t *)Ptx->hexstr,TX,16)) < 0 )
return(-1);
numbits += n;
}
return(numbits);
}
int32_t serdes777_sethdrtokens(long serdes777_hdrtokens[][2],struct peggy_tx *Ptx)
{
long hdrtokens[][2] =
{
{ 0, -sizeof(Ptx->datalen) },
{ (long)&Ptx->numinputs - (long)Ptx, sizeof(Ptx->numinputs) },
{ (long)&Ptx->numoutputs - (long)Ptx, sizeof(Ptx->numoutputs) },
{ (long)&Ptx->txtype - (long)Ptx, sizeof(Ptx->txtype) },
{ (long)&Ptx->flags - (long)Ptx, sizeof(Ptx->flags) },
{ (long)&Ptx->msglen - (long)Ptx, sizeof(Ptx->msglen) },
{ (long)&Ptx->numdetails - (long)Ptx, sizeof(Ptx->numdetails) },
{ (long)&Ptx->timestamp - (long)Ptx, sizeof(Ptx->timestamp) },
{ (long)&Ptx->activation - (long)Ptx, sizeof(Ptx->activation) },
{ (long)&Ptx->expiration - (long)Ptx, sizeof(Ptx->expiration) },
};
memcpy(serdes777_hdrtokens,hdrtokens,sizeof(hdrtokens));
return((int32_t)(sizeof(hdrtokens)/sizeof(*hdrtokens)));
}
int32_t serdes777_rwtx(int32_t rwflag,struct peggy_tx *Ptx,HUFF *TX)
{
int32_t i,n,iter,numbits,totalbits = 0; void *ptr; long serdes777_hdrtokens[16][2];
//printf("peggy_rwtx.%d %p %p size.%d\n",rwflag,Ptx,TX,TX->endpos);
if ( (totalbits= serdes777_codec(rwflag,Ptx,sizeof(*Ptx),serdes777_hdrtokens,serdes777_sethdrtokens(serdes777_hdrtokens,Ptx),TX)) < 0 )
{
printf("serdes777_process error decoding opreturn datalen.%d hdrtokens\n",totalbits);
return(-1);
}
if ( (Ptx->flags & PEGGY_FLAGS_HASFUNDING) != 0 )
{
if ( (numbits= serdes777_rwinout(rwflag,0,&Ptx->funding,TX)) < 0 )
{
printf("serdes777_process error serdes.%d funding %.8f %p\n",rwflag,dstr(Ptx->funding.amount),&Ptx->funding.src.coinaddr);
return(-1);
}
totalbits += numbits;
}
n = Ptx->numinputs;
for (iter=0; iter<2; iter++)
{
for (i=0; i<n; i++)
{
if ( iter == 0 )
ptr = &Ptx->inputs[i];
else ptr = &Ptx->outputs[i];
if ( (numbits= serdes777_rwinout(rwflag,iter,ptr,TX)) < 0 )
{
printf("serdes777_process error serdes.%d input.%d\n",rwflag,i);
return(-1);
}
totalbits += numbits;
printf("%d iter.%d .%d\n",i,iter,totalbits/8);
}
n = Ptx->numoutputs;
}
if ( (numbits= serdes777_rwdetails(rwflag,Ptx,TX)) < 0 )
{
printf("serdes777_process error serdes777_rwdetails.%d datalen.%d\n",i,totalbits);
return(-1);
}
totalbits += numbits;
return(totalbits);
}
int serdes777_checktimestamp(uint32_t blocktimestamp,uint32_t timestamp)
{
if ( blocktimestamp == 0 || timestamp == 0 )
return(0);
else if ( timestamp < ((int64_t)blocktimestamp - PEGGY_PASTSTAMP) || timestamp > ((int64_t)blocktimestamp + PEGGY_FUTURESTAMP) )
return(-1);
return(0);
}
int32_t serdes777_deserialize(int32_t *signedcountp,struct peggy_tx *Ptx,uint32_t blocktimestamp,uint8_t *data,int32_t totallen)
{
int32_t i,n,len,totalbits,remains; HUFF TX;
memset(Ptx,0,sizeof(*Ptx));
memcpy(Ptx->data,data,totallen);
memset(&TX,0,sizeof(TX)), _init_HUFF(&TX,totallen,data), TX.endpos = (totallen * 8);
if ( (totalbits= serdes777_rwtx(0,Ptx,&TX)) < 0 )
return(-1);
if ( serdes777_checktimestamp(blocktimestamp,Ptx->timestamp) < 0 )
{
printf("serdes777_deserialize: timestamp.%u too different from Ptx %u %d\n",blocktimestamp,Ptx->timestamp,blocktimestamp - Ptx->timestamp);
return(-1);
}
if ( (len= (int32_t)hconv_bitlen(totalbits)) > totallen )
{
printf("serdes777_process error totalbits.%d len.%d exceeded totallen.%d\n",totalbits,len,totallen);
return(-1);
}
Ptx->datalen = len;
//for (i=0; i<len; i++)
// printf("%02x",Ptx->data[i]);
//printf(" crc.%08x datalen.%d vs totallen.%d\n",_crc32(0,Ptx->data,len),len,totallen);
remains = (totallen - len);
if ( (remains % sizeof(bits256)) != 0 )
{
printf("serdes777_process error totalbits.%d remains.%d nonzero modval.%d\n",totalbits,remains,(int32_t)(remains % sizeof(bits256)));
return(-1);
}
n = (int32_t)(remains / sizeof(bits256));
//printf("n.%d remains.%d\n",n,remains);
if ( n > 0 )
{
if ( Ptx->numinputs == 1 && Ptx->inputs[0].type == PEGGY_ADDRPUBKEY && n == 1 )
{
memcpy(Ptx->sigs[0].sigbits.bytes,&data[len],sizeof(bits256)), len += sizeof(bits256);
Ptx->sigs[0].pubkey = Ptx->inputs[0].src.sha256;
}
else
{
for (i=0; i<n; i++,len+=sizeof(bits256))
memcpy((i & 1) == 0 ? Ptx->sigs[i/2].sigbits.bytes : Ptx->sigs[i/2].pubkey.bytes,&data[len],sizeof(bits256));
}
for (i=0; i<n; i++)
{
if ( Ptx->sigs[i].sigbits.txid != 0 )
{
if ( (Ptx->sigs[i].signer64bits= PAX_validate(&Ptx->sigs[i],Ptx->timestamp,Ptx->data,Ptx->datalen)) == 0 )
{
printf("Tx validation error at sig.%d\n",i);
return(-1);
}
(*signedcountp)++;
printf("len.%d verify.%d t%u %llx %llu\n",len,i,Ptx->timestamp,(long long)Ptx->sigs[i].sigbits.txid,(long long)Ptx->sigs[i].signer64bits);
}
else break;
}
}
return(len);
}
int32_t serdes777_serialize(struct peggy_tx *Ptx,uint32_t blocktimestamp,bits256 privkey,uint32_t timestamp)
{
int32_t i,len,numbits; HUFF TX;
memset(Ptx->data,0,sizeof(Ptx->data));
memset(&TX,0,sizeof(TX)), _init_HUFF(&TX,sizeof(Ptx->data),Ptx->data);
if ( Ptx->timestamp == 0 )
Ptx->timestamp = timestamp;
else if ( timestamp != 0 && serdes777_checktimestamp(blocktimestamp,timestamp) < 0 )
{
printf("serdes777_serialize: timestamp.%u too different from Ptx %u %d\n",timestamp,Ptx->timestamp,timestamp - Ptx->timestamp);
return(-1);
}
if ( (numbits= serdes777_rwtx(1,Ptx,&TX)) < 0 )
return(-1);
//printf("TX.bitoffset.%d\n",TX.bitoffset);
len = (int32_t)hconv_bitlen(TX.bitoffset);
Ptx->datalen = len;
hseek(&TX,0,SEEK_SET);
if ( serdes777_rw(1,&Ptx->datalen,-(int32_t)sizeof(Ptx->datalen),&TX) < 0 )
return(-1);
//for (i=0; i<len; i++)
// printf("%02x",Ptx->data[i]);
//printf(" crc.%08x datalen.%d\n",_crc32(0,Ptx->data,len),len);
for (i=0; i<sizeof(Ptx->sigs)/sizeof(*Ptx->sigs); i++)
{
//printf("scan sig.%d\n",i);
if ( Ptx->sigs[i].sigbits.txid == 0 )
break;
if ( PAX_validate(&Ptx->sigs[i],Ptx->timestamp,Ptx->data,len) != Ptx->sigs[i].signer64bits )
{
printf("Tx validation error at sig.%d\n",i);
return(-1);
}
memcpy(&Ptx->data[len],Ptx->sigs[i].sigbits.bytes,sizeof(Ptx->sigs[i].sigbits)), len += sizeof(Ptx->sigs[i].sigbits);
memcpy(&Ptx->data[len],Ptx->sigs[i].pubkey.bytes,sizeof(Ptx->sigs[i].pubkey)), len += sizeof(Ptx->sigs[i].pubkey);
}
if ( i < sizeof(Ptx->sigs)/sizeof(*Ptx->sigs)-1 && Ptx->timestamp != 0 && privkey.txid != 0 )
{
Ptx->sigs[i].signer64bits = PAX_signtx(&Ptx->sigs[i],privkey,Ptx->timestamp,Ptx->data,len);
printf("len.%d sign sig.%d %llx %llu t%u\n",len,i,(long long)Ptx->sigs[i].sigbits.txid,(long long)Ptx->sigs[i].signer64bits,Ptx->timestamp);
memcpy(&Ptx->data[len],Ptx->sigs[i].sigbits.bytes,sizeof(Ptx->sigs[i].sigbits)), len += sizeof(Ptx->sigs[i].sigbits);
memcpy(&Ptx->data[len],Ptx->sigs[i].pubkey.bytes,sizeof(Ptx->sigs[i].pubkey)), len += sizeof(Ptx->sigs[i].pubkey);
if ( Ptx->sigs[i].signer64bits != PAX_validate(&Ptx->sigs[i],Ptx->timestamp,Ptx->data,Ptx->datalen) )
{
printf("Tx validation error at sig.%d\n",i);
//return(-1);
}
printf("len.%d verify.%d t%u %llx %llu\n",len,i,Ptx->timestamp,(long long)Ptx->sigs[i].sigbits.txid,(long long)Ptx->sigs[i].signer64bits);
} //else printf("skip signing t%u %llu\n",timestamp,(long long)privkey.txid);
return(len);
}
int32_t accts777_parse(union peggy_addr *addr,cJSON *item,int32_t type)
{
int32_t peggy_setname(char *buf,char *name);
char name[16],*coinaddr,*hashstr; struct peggy_lock *lock;
if ( item == 0 )
return(-1);
switch ( type )
{
case PEGGY_ADDRBTCD:
if ( (coinaddr= jstr(item,"BTCD")) != 0 && peggy_addr2univ(&addr->coinaddr,coinaddr,"BTCD") < 0 )
{
printf("illegal coinaddr.(%s)\n",coinaddr);
return(-1);
}
break;
case PEGGY_ADDRCREATE:
if ( (hashstr= jstr(item,"lockhash")) != 0 && strlen(hashstr) == 64 )
decode_hex(addr->newunit.sha256.bytes,sizeof(bits256),hashstr);
lock = &addr->newunit.newlock;
lock->peg = peggy_setname(name,jstr(item,"peg"));
lock->denom = jint(item,"denom");
lock->minlockdays = jint(item,"minlockdays");
lock->maxlockdays = jint(item,"maxlockdays");
lock->clonesmear = jint(item,"clonesmear");
lock->mixrange = jint(item,"mixrange");
lock->margin = jint(item,"margin");
break;
case PEGGY_ADDRNXT:
addr->nxt64bits = j64bits(item,"NXT");
break;
case PEGGY_ADDRUNIT:
if ( (hashstr= jstr(item,"unithash")) != 0 && strlen(hashstr) == 64 )
decode_hex(addr->sha256.bytes,sizeof(bits256),hashstr);
break;
case PEGGY_ADDR777:
if ( (hashstr= jstr(item,"SaMbits")) != 0 && strlen(hashstr) == 96 )
decode_hex(addr->SaMbits.bytes,sizeof(bits384),hashstr);
break;
case PEGGY_ADDRPUBKEY:
if ( (hashstr= jstr(item,"unlockpubkey")) != 0 && strlen(hashstr) == 64 )
decode_hex(addr->newunit.sha256.bytes,sizeof(bits256),hashstr);
lock = &addr->newunit.newlock;
lock->peg = peggy_setname(name,jstr(item,"peg"));
lock->minlockdays = lock->maxlockdays = jint(item,"lockdays");
if ( jint(item,"denom") < 0 )
lock->peg = -lock->peg;
break;
}
return(0);
}
int32_t peggy_inputs(struct peggy_tx *Ptx,cJSON *array)
{
int32_t i,n = 0; cJSON *item;
if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n&&i<PEGGY_MAXINPUTS; i++)
{
item = jitem(array,i);
Ptx->inputs[i].type = juint(item,"type");
Ptx->inputs[i].chainlen = juint(item,"chainlen");
Ptx->inputs[i].amount = juint(item,"amount");
accts777_parse(&Ptx->inputs[i].src,item,Ptx->inputs[i].type);
}
}
return(n);
}
int32_t peggy_outputs(struct peggy_tx *Ptx,cJSON *array)
{
int32_t i,n=0; cJSON *item;
if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n&&i<PEGGY_MAXOUTPUTS; i++)
{
item = jitem(array,i);
Ptx->outputs[i].type = juint(item,"type");
Ptx->outputs[i].vin = juint(item,"vin");
Ptx->outputs[i].ratio = juint(item,"ratio");
accts777_parse(&Ptx->outputs[i].dest,item,Ptx->outputs[i].type);
}
}
return(n);
}
int32_t peggy_details(struct peggy_tx *Ptx,cJSON *json,int32_t txtype,uint32_t btcusd)
{
struct destbuf name;
int32_t i,n=0; cJSON *item,*array; char *hashstr,*refundstr; struct peggy_txtune *tune; struct peggy_txmicropay *mp; struct peggy_txbet *bet;
Ptx->details.price.timestamp = juint(json,"genesistime");
Ptx->details.price.maxlockdays = juint(json,"maxlockdays");
//printf("BTCUSD.%d vs %d\n",Ptx->details.prices.btcusd,btcusd);
if ( (array= jarray(&n,json,"details")) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
if ( txtype == PEGGY_TXPRICES )
Ptx->details.price.num = n;
for (i=0; i<n; i++)
{
item = jitem(array,i);
switch ( txtype )
{
case PEGGY_TXNORMAL:
break;
case PEGGY_TXBET:
bet = &Ptx->details.bets[i];
copy_cJSON(&name,jobj(item,"peg"));
safecopy(bet->peg,name.buf,sizeof(bet->peg));
bet->binary = juint(item,"binary");
bet->prediction.Pval = juint(item,"prediction");
break;
case PEGGY_TXPRICES:
Ptx->details.price.feed[i] = juint(item,0);
break;
case PEGGY_TXTUNE:
tune = &Ptx->details.tune[i];
copy_cJSON(&name,jobj(item,"peg"));
safecopy(tune->peg,name.buf,sizeof(bet->peg));
tune->type = juint(item,"type");
tune->val = j64bits(item,"val");
tune->B.val = j64bits(item,"valB");
tune->B.bytes[0] = j64bits(item,"interesttenths");
tune->B.bytes[1] = j64bits(item,"posboost");
tune->B.bytes[2] = j64bits(item,"negpenalty");
tune->B.bytes[3] = j64bits(item,"feediv");
tune->B.bytes[4] = j64bits(item,"feemult");
break;
case PEGGY_TXMICROPAY:
mp = &Ptx->details.micropays[i];
if ( (hashstr= jstr(item,"claimhash")) != 0 && strlen(hashstr) == 64 )
decode_hex(mp->claimhash.bytes,sizeof(bits256),hashstr);
if ( (refundstr= jstr(item,"refundhash")) != 0 && strlen(refundstr) == 64 )
decode_hex(mp->refundhash.bytes,sizeof(bits256),refundstr);
mp->expiration = juint(item,"expiration");
mp->chainlen = juint(item,"chainlen");
mp->vin = juint(item,"vin");
mp->vout = juint(item,"vout");
break;
}
}
}
return(0);
}
char *peggy_tx(char *jsonstr)
{
cJSON *json; int32_t i,n,len,signedcount; char *hexstr,opreturnstr[8192],retbuf[4096],retbufstr[8192],checkstr[8192];
struct peggy_tx Ptx,checkPtx; bits256 privkey; struct destbuf tmp;
memset(&Ptx,0,sizeof(Ptx));
opreturnstr[0] = 0;
memset(privkey.bytes,0,sizeof(privkey));
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
printf("(%s)\n",jsonstr);
Ptx.flags = juint(json,"flags");
Ptx.txtype = juint(json,"txtype");
Ptx.numinputs = peggy_inputs(&Ptx,jarray(&n,json,"inputs"));
Ptx.numoutputs = peggy_outputs(&Ptx,jarray(&n,json,"outputs"));
if ( Ptx.txtype != PEGGY_TXNORMAL )
Ptx.numdetails = peggy_details(&Ptx,json,Ptx.txtype,juint(json,"btcusd"));
if ( (hexstr= jstr(json,"privkey")) != 0 && strlen(hexstr) == 64 )
decode_hex(privkey.bytes,sizeof(privkey),hexstr);
//else printf("no privkey.%p (%s)\n",hexstr,jsonstr);
if ( (hexstr= jstr(json,"hexstr")) != 0 && strlen(hexstr) < sizeof(Ptx.hexstr) )
strcpy(Ptx.hexstr,hexstr), Ptx.msglen = (int32_t)strlen(hexstr)/2;
Ptx.activation = juint(json,"activation");
Ptx.expiration = juint(json,"expiration");
if ( (Ptx.funding.amount= juint(json,"funds")) != 0 )
{
copy_cJSON(&tmp,jobj(json,"fundsaddr"));
//safecopy(Ptx.funding.src.coinaddr,tmp.buf,sizeof(Ptx.funding.src.coinaddr));
if ( peggy_addr2univ(&Ptx.funding.src.coinaddr,tmp.buf,"BTCD") < 0 )
{
printf("warning: illegal funding address.(%s)\n",tmp.buf);
}
Ptx.flags |= PEGGY_FLAGS_HASFUNDING;
Ptx.funding.type = PEGGY_ADDRFUNDING;
}
Ptx.timestamp = (uint32_t)time(NULL);
len = serdes777_serialize(&Ptx,Ptx.timestamp,privkey,Ptx.timestamp);
init_hexbytes_noT(opreturnstr,Ptx.data,len);
//printf("datalen.%d (%s).%ld\n",Ptx.datalen,opreturnstr,strlen(opreturnstr));
/*if ( PEGS != 0 && peggy_txind(&tipvalue,PEGS->accts,0,Ptx.timestamp,0,&Ptx,fundsvalue,fundsaddr) < 0 )
{
printf("%s\nerror validating tx\n",opreturnstr);
//return(clonestr("\"error\":\"error validating tx\"}"));
}*/
len = serdes777_deserialize(&signedcount,&checkPtx,Ptx.timestamp,Ptx.data,len);
retbuf[0] = OP_RETURN_OPCODE;
if ( len+3 < 0xfe )
{
retbuf[1] = len+3;
strcpy(retbuf+2,"PAX");
memcpy(retbuf+5,Ptx.data,len);
init_hexbytes_noT(retbufstr,(void *)retbuf,len+5);
}
else
{
retbuf[1] = 0xfe;
retbuf[2] = (len+3) & 0xff;
retbuf[3] = ((len+3) >> 8) & 0xff;
strcpy(retbuf+4,"PAX");
memcpy(retbuf+7,Ptx.data,len);
init_hexbytes_noT(retbufstr,(void *)retbuf,len+7);
}
init_hexbytes_noT(checkstr,checkPtx.data,len);
if ( strcmp(checkstr,opreturnstr) != 0 )
{
for (i=0; i<Ptx.datalen; i++)
if ( checkstr[i] != opreturnstr[i] )
printf("(%02x != %02x).%d ",checkstr[i],opreturnstr[i],i);
printf("%s Ptx\n%s check\npeggy_tx ser/deser error datalen.%d\n",opreturnstr,checkstr,checkPtx.datalen);
return(clonestr("\"error\":\"ser/deser error\"}"));
}
//else printf("peggy_tx success\n%s\n%s\n",opreturnstr,checkstr);
free_json(json);
//printf("%s\n",retbufstr);
return(clonestr(retbufstr));
}
return(clonestr("\"error\":\"couldnt create opreturn\"}"));
}

769
iguana/peggy_tx.c

@ -0,0 +1,769 @@
/******************************************************************************
* 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 "peggy.h"
int32_t peggy_create_micropay(uint8_t *txbuf,int32_t len,struct accts777_info *accts,uint32_t blocknum,uint32_t blocktimestamp,uint64_t nxt64bits,struct peggy_txmicropay *micropay,struct peggy_input *in,struct peggy_output *out)
{
//struct peggy_txmicropay { bits256 claimhash,refundhash; uint32_t expiration,chainlen; uint8_t vin,vout; };
return(len);
}
int32_t peggy_create_micropair(uint8_t *txbuf,int32_t len,struct accts777_info *accts,uint32_t blocknum,uint32_t blocktimestamp,uint64_t nxt64bitsA,struct peggy_txmicropay *micropayA,struct peggy_input *inA,struct peggy_output *outA,uint64_t nxt64bitsB,struct peggy_txmicropay *micropayB,struct peggy_input *inB,struct peggy_output *outB)
{
return(len);
}
int32_t peggy_create_prices(uint8_t *txbuf,int32_t len,struct accts777_info *accts,uint32_t blocknum,uint32_t blocktimestamp,uint64_t nxt64bits,struct peggy_txprices *price,uint32_t stakedblock)
{
uint32_t key[2]; int32_t i,size = price->num * sizeof(price->feed[0]);
if ( stakedblock != 0 || nxt64bits != 0 )
{
for (i=0; i<price->num; i++)
len = txind777_txbuf(txbuf,len,price->feed[i],sizeof(price->feed[i]));//, fprintf(stderr,"%d ",price->feed[i]);
key[0] = blocknum, key[1] = 0;
ramkv777_write(accts->pricefeeds,key,price->feed,size);
return(len);
} else printf("unsigned pricefeed not staked blocknum.%d t%u\n",blocknum,blocktimestamp);
// add to daily list for eval in daily settlement
return(-1);
}
int32_t peggy_create_bet(uint8_t *txbuf,struct accts777_info *accts,uint32_t blocknum,uint32_t blocktimestamp,uint64_t nxt64bits,uint64_t value,char *coinaddr,struct peggy_txbet *bet)
{
uint64_t key[2];
key[0] = blocktimestamp, key[1] = nxt64bits;
// add to daily list for eval in daily settlement
return(0);
}
int32_t peggy_enable(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->name.enabled = (int32_t)val;
return(0);
}
int32_t peggy_dailyrate(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->maxdailyrate = (int32_t)val;
return(0);
}
int32_t peggy_quorum(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->pool.quorum = val;
return(0);
}
int32_t peggy_decisionthreshold(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->pool.decisionthreshold = val;
return(0);
}
int32_t peggy_maxnetbalance(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->maxnetbalance = val;
return(0);
}
int32_t peggy_maxsupply(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->maxsupply = val;
return(0);
}
/*int32_t peggy_numtimeframes(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->limits.numtimeframes = (int32_t)val;
return(0);
}
int32_t peggy_timeframe(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
if ( val < PEG->limits.numtimeframes )
PEG->limits.timeframes[val] = (int32_t)valB;
return(0);
}
int32_t peggy_timescale(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
if ( val < PEG->limits.numtimeframes )
PEG->limits.scales[val] = valB;
return(0);
}*/
int32_t peggy_lockdays(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->lockparms.minlockdays = val, PEG->lockparms.maxlockdays = valB;
return(0);
}
int32_t peggy_clonesmear(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->lockparms.clonesmear = val;
return(0);
}
int32_t peggy_mixrange(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->lockparms.mixrange = val;
return(0);
}
int32_t peggy_redemptiongap(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->lockparms.redemptiongapdays = val;
return(0);
}
int32_t peggy_extralockdays(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->lockparms.extralockdays = val;
return(0);
}
int32_t peggy_maxmargin(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->lockparms.margin = val;
return(0);
}
int32_t peggy_mindenomination(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->mindenomination.Pval = val;
return(0);
}
int32_t peggy_spread(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB)
{
PEG->spread.Pval = val;
return(0);
}
int32_t peggy_fees(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint8_t interesttenths,uint8_t posboost,uint8_t negpenalty,uint8_t feediv,uint8_t feemult)
{
PEGS->interesttenths = interesttenths, PEGS->posboost = posboost, PEGS->negpenalty = negpenalty, PEGS->feediv = feediv, PEGS->feemult = feemult;
return(0);
}
int32_t (*tunefuncs[])(struct peggy_info *PEGS,struct peggy *PEG,uint32_t blocktimestamp,int32_t actionflag,uint64_t val,uint64_t valB) =
{
peggy_enable, peggy_dailyrate, peggy_quorum, peggy_decisionthreshold, peggy_maxnetbalance, peggy_maxsupply, peggy_lockdays, peggy_clonesmear, peggy_mixrange, peggy_redemptiongap, peggy_extralockdays, peggy_maxmargin, peggy_mindenomination, peggy_spread
};
uint64_t peggy_onesigner(struct peggy_tx *Ptx)
{
if ( Ptx->sigs[0].signer64bits != 0 && Ptx->sigs[1].signer64bits == 0 )
return(Ptx->sigs[0].signer64bits);
else return(0);
}
int32_t peggy_twosigners(uint64_t signers[2],struct peggy_tx *Ptx)
{
if ( Ptx->sigs[0].signer64bits != 0 && Ptx->sigs[1].signer64bits != 0 && Ptx->sigs[2].signer64bits == 0 )
{
signers[0] = Ptx->sigs[0].signer64bits;
signers[1] = Ptx->sigs[1].signer64bits;
return(2);
}
else return(-1);
}
int64_t peggy_txind_tune(struct peggy_info *PEGS,uint32_t blocknum,uint32_t blocktimestamp,int32_t actionflag,struct peggy_tx *Ptx,struct peggy_txtune *tune,int32_t numtunes)
{
static char *accts[] = { "NXT-SQ9J-JCAN-8XVY-5XN7K", "NXT-J698-WN8Q-XR8A-92TLD", "NXT-JNES-HJ86-KNXQ-AQ33Z", "NXT-RQYG-UPJP-HMMH-7WHFZ" };
char name[16]; int32_t i,peg,flag = 0; uint64_t nxt64bits; struct peggy *PEG; int64_t txind=0,txinds[256];
if ( Ptx->numoutputs != 0 || Ptx->numinputs != 0 || (nxt64bits= peggy_onesigner(Ptx)) == 0 )
return(-1);
for (i=0; i<sizeof(accts)/sizeof(*accts); i++)
if ( nxt64bits == conv_acctstr(accts[i]) )
flag = 1;
if ( flag == 0 )
return(-1);
if ( numtunes > 0 )
{
for (i=0; i<numtunes; i++)
{
peg = peggy_pegstr(name,PEGS,tune[i].peg);
if ( peg < 0 || peg >= PEGS->numpegs )
return(-1);
if ( actionflag <= 0 )
continue;
PEG = PEGS->contracts[peg];
if ( tune[i].type == 77 && peggy_fees(PEGS,PEG,blocktimestamp,actionflag,tune[i].B.bytes[0],tune[i].B.bytes[1],tune[i].B.bytes[2],tune[i].B.bytes[3],tune[i].B.bytes[4]) < 0 )
return(-1);
else if ( tune[i].type >= sizeof(tunefuncs)/sizeof(*tunefuncs) )
return(-1);
else if ( (*tunefuncs[i])(PEGS,PEG,blocktimestamp,actionflag,tune->val,tune->B.val) < 0 )
return(-1);
txinds[i] = txind777_create(PEGS->accts->txinds,blocknum,blocktimestamp,&tune[i],sizeof(tune[i]));
}
txind = txind777_bundle(PEGS->accts->txinds,blocknum,blocktimestamp,txinds,numtunes);
}
return(txind);
}
int64_t peggy_txind_micropay(uint8_t *txbuf,int32_t len,struct accts777_info *accts,uint32_t blocknum,uint32_t blocktimestamp,int32_t actionflag,struct peggy_tx *Ptx,struct peggy_txmicropay *micropays,int32_t num)
{
uint64_t nxt64bits,both[2];
if ( (nxt64bits= peggy_onesigner(Ptx)) != 0 )
{
if ( Ptx->numoutputs != 1 || Ptx->numinputs != 1 || micropays[0].vin != 0 || micropays[0].vout != 0 || num != 1 )
return(-1);
if ( actionflag != 0 && (len= peggy_create_micropay(txbuf,len,accts,blocknum,blocktimestamp,nxt64bits,micropays,Ptx->inputs,Ptx->outputs)) < 0 )
return(-1);
}
else if ( peggy_twosigners(both,Ptx) > 0 )
{
if ( Ptx->numoutputs != 2 || Ptx->numinputs != 2 || num != 2 )
return(-1);
if ( micropays[0].vin != 0 || micropays[0].vout != 0 || micropays[1].vin != 1 || micropays[1].vout != 1 )
return(-1);
if ( actionflag != 0 )
{
if ( (len= peggy_create_micropair(txbuf,len,accts,blocknum,blocktimestamp,both[0],&micropays[0],&Ptx->inputs[0],&Ptx->outputs[0],both[1],&micropays[1],&Ptx->inputs[1],&Ptx->outputs[1])) < 0 )
return(-1);
}
}
if ( len > 0 )
return(txind777_create(accts->txinds,blocknum,blocktimestamp,txbuf,len));
return(-1);
}
int64_t peggy_txind_prices(uint8_t *txbuf,int32_t len,struct accts777_info *accts,uint32_t blocknum,uint32_t blocktimestamp,int32_t actionflag,struct peggy_tx *Ptx,struct peggy_txprices *prices,uint32_t stakedblock)
{
if ( Ptx->numoutputs != 0 || Ptx->numinputs != 0 )
{
printf("peggy_txind_prices: unexpected numinputs.%d numoutputs.%d\n",Ptx->numoutputs,Ptx->numinputs);
return(-1);
}
if ( actionflag != 0 )
{
if ( (len= peggy_create_prices(txbuf,len,accts,blocknum,blocktimestamp,stakedblock == 0 ? peggy_onesigner(Ptx) : 0,prices,stakedblock)) < 0 )
return(-1);
// printf("len.%d txinds.%p\n",len,accts->txinds);
return(txind777_create(accts->txinds,blocknum,blocktimestamp,txbuf,len));
}
return(-1);
}
int32_t txind777_txbuf_lock(uint8_t *txbuf,int32_t len,struct peggy_lock *lock)
{
if ( txbuf != 0 )
{
len = txind777_txbuf(txbuf,len,lock->peg,sizeof(lock->peg));
len = txind777_txbuf(txbuf,len,lock->denom,sizeof(lock->denom));
len = txind777_txbuf(txbuf,len,lock->minlockdays,sizeof(lock->minlockdays));
len = txind777_txbuf(txbuf,len,lock->maxlockdays,sizeof(lock->maxlockdays));
len = txind777_txbuf(txbuf,len,lock->clonesmear,sizeof(lock->clonesmear));
len = txind777_txbuf(txbuf,len,lock->redemptiongapdays,sizeof(lock->redemptiongapdays));
len = txind777_txbuf(txbuf,len,lock->extralockdays,sizeof(lock->extralockdays));
len = txind777_txbuf(txbuf,len,lock->margin,sizeof(lock->margin));
}
return(len);
}
int64_t peggy_txind_bets(uint8_t *txbuf,int32_t len,struct accts777_info *accts,uint32_t blocknum,uint32_t blocktimestamp,int32_t actionflag,struct peggy_tx *Ptx,uint64_t value,char *voutcoinaddr,struct peggy_txbet *bets,int32_t numbets)
{
uint64_t nxt64bits; int32_t i; int64_t txind=0,txinds[256];
if ( Ptx->numoutputs != 0 || Ptx->numinputs != 0 || (nxt64bits= peggy_onesigner(Ptx)) == 0 )
return(-1);
if ( actionflag != 0 )
{
for (i=0; i<numbets; i++)
{
if ( (len= peggy_create_bet(txbuf,accts,blocknum,blocktimestamp,nxt64bits,value,voutcoinaddr,&bets[i])) < 0 )
return(-1);
txinds[i] = txind777_create(accts->txinds,blocknum,blocktimestamp,txbuf,len);
}
txind = txind777_bundle(accts->txinds,blocknum,blocktimestamp,txinds,numbets);
}
return(0);
}
int32_t peggy_univ2addr(char *coinaddr,struct peggy_univaddr *ua)
{
return(btc_convrmd160(coinaddr,ua->addrtype,ua->rmd160));
}
int32_t peggy_addr2univ(struct peggy_univaddr *ua,char *coinaddr,char *coin)
{
char hexstr[512]; uint8_t hex[21];
if ( btc_convaddr(hexstr,coinaddr) == 0 )
{
decode_hex(hex,21,hexstr);
memset(ua,0,sizeof(*ua));
ua->addrtype = hex[0];
memcpy(ua->rmd160,hex+1,20);
strncpy(ua->coin,coin,sizeof(ua->coin)-1);
return(0);
}
return(-1);
}
int64_t peggy_txind_send(uint8_t *txbuf,int32_t len,struct peggy_info *PEGS,uint32_t blocknum,uint32_t blocktimestamp,uint64_t signer64bits,uint64_t signer64bitsB,int64_t fundedvalue,struct peggy_input *in,uint32_t ratio,struct peggy_output *out)
{
struct acct777 *acct; struct ramkv777 *kv; struct ramkv777_item *item;
int64_t value = 0; int32_t i,chainlen,polarity,peg; uint32_t rawind; uint64_t satoshis,amount=0,marginamount = 0;
struct peggy_unit readU; struct accts777_info *accts; struct peggy_time T; union peggy_addr *addr = &out->dest;
if ( (accts= PEGS->accts) == 0 )
return(-1);
acct = accts777_find(0,accts,addr,out->type);
if ( acct == 0 )
acct = accts777_create(accts,addr,out->type,blocknum,blocktimestamp);
if ( acct == 0 )
return(-1);
T.blocknum = blocknum, T.blocktimestamp = blocktimestamp;
if ( in == 0 && fundedvalue != 0 )
value = fundedvalue;
else if ( in != 0 )
{
if ( (in->type == PEGGY_ADDRNXT || in->type == PEGGY_ADDR777) && acct777_balance(accts,blocknum,blocktimestamp,&in->src,in->type) >= in->amount )
value = in->amount;
else if ( in->type == PEGGY_ADDRPUBKEY )
{
if ( in->src.newunit.newlock.minlockdays != 0 )
{
if ( ratio != PRICE_RESOLUTION )
return(-1);
chainlen = 1;
if ( (peg= in->src.newunit.newlock.peg) < 0 )
peg = -peg, polarity = -1;
else polarity = 1;
value = peggy_redeem(PEGS,T,amount == 0,PEGS->contracts[peg]->name.name,polarity,signer64bits,in->src.sha256,in->src.newunit.newlock.minlockdays,chainlen);
}
else if ( acct777_balance(accts,blocknum,blocktimestamp,&in->src,in->type) >= in->amount )
value = in->amount;
}
else if ( in->type == PEGGY_ADDRUNIT )
{
if ( ratio != PRICE_RESOLUTION || (out->type != PEGGY_ADDRCREATE && out->type != PEGGY_ADDRUNIT) ) // rollover or swap only
return(-1);
} else return(-1);
}
if ( (kv= accts777_getaddrkv(accts,out->type)) != 0 && (item= ramkv777_itemptr(kv,acct)) != 0 )
rawind = item->rawind;
else rawind = 0;
len = txind777_txbuf(txbuf,len,rawind,sizeof(uint32_t));
if ( out->type == PEGGY_ADDRBTCD )
{
char coinaddr[64];
if ( peggy_univ2addr(coinaddr,&addr->coinaddr) < 0 || acct == 0 || opreturns_queue_payment(&accts->PaymentsQ,blocktimestamp,coinaddr,value) < 0 )
return(-1);
}
else if ( out->type == PEGGY_ADDRCREATE )
{
if ( value > 0 )
{
if ( addr->newunit.newlock.margin == 0 )
amount = value;
else marginamount = value;
satoshis = peggy_createunit(PEGS,T,0,accts->peggyhash.txid,0,signer64bits,addr->newunit.sha256,&addr->newunit.newlock,amount,marginamount);
len = txind777_txbuf_lock(txbuf,len,&addr->newunit.newlock);
if ( in != 0 && in->type == PEGGY_ADDRUNIT )
{
for (i=0; i<sizeof(bits256); i++)
txbuf[len++] = in->src.sha256.bytes[i];
if ( peggy_swap(accts,signer64bits,signer64bitsB,in->src.sha256,addr->newunit.sha256) < 0 )
return(-1);
}
} else return((int32_t)peggy_createunit(PEGS,T,&readU,accts->peggyhash.txid,0,signer64bits,addr->newunit.sha256,&addr->newunit.newlock,amount,marginamount));
}
else if ( acct != 0 )
{
if ( in != 0 && in->type == PEGGY_ADDRUNIT )
{
for (i=0; i<sizeof(bits256); i++)
txbuf[len++] = in->src.sha256.bytes[i];
if ( peggy_swap(accts,signer64bits,signer64bitsB,in->src.sha256,addr->sha256) < 0 )
return(-1);
}
else if ( acct777_pay(accts,0,acct,value,blocknum,blocktimestamp) < 0 )
return(-1);
}
return(txind777_create(accts->txinds,blocknum,blocktimestamp,txbuf,len));
}
int32_t peggy_checktx(struct price_resolution vinsums[PEGGY_MAXINPUTS],struct accts777_info *accts,int32_t actionflag,struct peggy_tx *Ptx,uint32_t blocknum,uint32_t blocktimestamp)
{
int32_t i;
if ( Ptx->numoutputs == 0 && Ptx->numinputs == 0 )
return(0);
else if ( Ptx->numoutputs != 0 && Ptx->numinputs == 0 )
return(-1);
memset(vinsums,0,sizeof(*vinsums) * PEGGY_MAXINPUTS);
if ( Ptx->numoutputs > 0 )
{
for (i=0; i<Ptx->numoutputs; i++)
{
if ( Ptx->outputs[i].vin < 0 || Ptx->outputs[i].vin >= Ptx->numinputs || Ptx->outputs[i].ratio > PRICE_RESOLUTION )
return(-1);
vinsums[Ptx->outputs[i].vin].Pval += Ptx->outputs[i].ratio;
//if ( acct777_balance(&PEGS->accts,blocktimestamp,&Ptx->outputs[i].dest,Ptx->outputs[i].type) < 0 )
// return(-1);
}
}
for (i=0; i<Ptx->numinputs; i++)
if ( vinsums[i].Pval != PRICE_RESOLUTION )
{
printf("mismatched vinsum[%d] %.6f\n",i,Pval(&vinsums[i]));
return(-1);
}
if ( Ptx->numinputs > 0 )
{
for (i=0; i<Ptx->numinputs; i++)
{
if ( acct777_balance(accts,blocknum,blocktimestamp,&Ptx->inputs[i].src,Ptx->inputs[i].type) < 0 )
return(-1);
}
}
return(0);
}
int64_t peggy_txind(int64_t *tipvaluep,struct peggy_info *PEGS,uint32_t blocknum,uint32_t blocktimestamp,int32_t actionflag,struct peggy_tx *Ptx,int32_t stakedblock)
{
int32_t i,len = 0; uint64_t signer64bits,both[2]; int64_t txind=0,txinds[PEGGY_MAXOUTPUTS*2]; uint8_t txbuf[65536];
struct price_resolution vinsums[PEGGY_MAXINPUTS]; struct accts777_info *accts;
if ( (accts= PEGS->accts) == 0 )
{
printf("no PEGS->accts\n");
return(-1);
}
if ( actionflag < 0 )
{
printf("undo not supported, rewind and redo\n");
return(-1);
}
txbuf[len++] = Ptx->txtype, txbuf[len++] = Ptx->txtype, txbuf[len++] = Ptx->numinputs, txbuf[len++] = Ptx->numoutputs;
len = txind777_txbuf(txbuf,len,blocknum,sizeof(blocknum));
len = txind777_txbuf(txbuf,len,blocktimestamp,sizeof(blocktimestamp));
if ( Ptx->txtype == PEGGY_TXNORMAL )
{
if ( (signer64bits= peggy_onesigner(Ptx)) != 0 )
{
txbuf[len++] = 1;
len = txind777_txbuf(txbuf,len,signer64bits,sizeof(signer64bits));
printf("peggy_onesigner\n");
if ( Ptx->numinputs == 0 )
{
if ( Ptx->numoutputs == 1 )
{
len = txind777_txbuf(txbuf,len,Ptx->funding.amount,sizeof(Ptx->funding.amount));
memcpy(txbuf,&Ptx->funding.src.coinaddr,sizeof(Ptx->funding.src.coinaddr)), len += sizeof(Ptx->funding.src.coinaddr);
if ( (txind= peggy_txind_send(txbuf,len,PEGS,blocknum,blocktimestamp,signer64bits,0,actionflag*Ptx->funding.amount,0,PRICE_RESOLUTION,&Ptx->outputs[0])) > 0 )
*tipvaluep = 0;
}
else return(-2);
}
else if ( Ptx->numinputs == 1 )
{
if ( Ptx->numoutputs >= 1 )
{
if ( peggy_checktx(vinsums,accts,actionflag,Ptx,blocknum,blocktimestamp) < 0 )
return(-3);
if ( actionflag != 0 )
{
for (i=0; i<Ptx->numoutputs; i++)
if ( (txinds[i] = peggy_txind_send(txbuf,len,PEGS,blocknum,blocktimestamp,signer64bits,0,0,Ptx->inputs,(uint32_t)vinsums[i].Pval,&Ptx->outputs[i])) < 0 )
return(-1);
txind = txind777_bundle(accts->txinds,blocknum,blocktimestamp,txinds,Ptx->numoutputs);
}
return(txind);
}
}
else if ( Ptx->numoutputs == 1 )
{
if ( Ptx->outputs[0].ratio == PRICE_RESOLUTION )
{
if ( actionflag != 0 )
{
for (i=0; i<Ptx->numoutputs; i++)
if ( (txinds[i]= peggy_txind_send(txbuf,len,PEGS,blocknum,blocktimestamp,signer64bits,0,0,&Ptx->inputs[i],Ptx->outputs[0].ratio,Ptx->outputs)) < 0 )
return(-1);
txind = txind777_bundle(accts->txinds,blocknum,blocktimestamp,txinds,Ptx->numinputs);
}
return(txind);
} else printf("error non unit ratio\n");
}
return(-1);
}
else if ( peggy_twosigners(both,Ptx) > 0 )
{
txbuf[len++] = 2;
len = txind777_txbuf(txbuf,len,both[0],sizeof(both[0]));
len = txind777_txbuf(txbuf,len,both[1],sizeof(both[1]));
printf("peggy_twosigners\n");
if ( Ptx->numoutputs != 1 || Ptx->numinputs != 1 || both[0] != Ptx->sigs[0].signer64bits || both[1] != Ptx->sigs[1].signer64bits )
return(-1);
if ( actionflag != 0 )
{
if ( (txind= peggy_txind_send(txbuf,len,PEGS,blocknum,blocktimestamp,both[0],both[1],0,&Ptx->inputs[0],PRICE_RESOLUTION,&Ptx->outputs[0])) < 0 )
return(-1);
}
return(txind);
} else printf("neither one or two signers\n");
return(-1);
}
else if ( Ptx->txtype == PEGGY_TXPRICES )
return(peggy_txind_prices(txbuf,len,accts,blocknum,blocktimestamp,actionflag,Ptx,&Ptx->details.price,stakedblock));
else
{
printf("details tx\n");
if ( peggy_checktx(vinsums,accts,actionflag,Ptx,blocknum,blocktimestamp) < 0 )
return(-1);
else if ( Ptx->txtype == PEGGY_TXBET )
{
char coinaddr[64];
len = txind777_txbuf(txbuf,len,Ptx->funding.amount,sizeof(Ptx->funding.amount));
memcpy(txbuf,&Ptx->funding.src.coinaddr,sizeof(Ptx->funding.src.coinaddr)), len += sizeof(Ptx->funding.src.coinaddr);
//for (i=0; i<BTCDADDRSIZE; i++)
// txbuf[len++] = Ptx->funding.src.coinaddr[i];
if ( peggy_univ2addr(coinaddr,&Ptx->funding.src.coinaddr) < 0 )
{
printf("illegal coinaddr\n");
return(-1);
}
if ( (txind= peggy_txind_bets(txbuf,len,accts,blocknum,blocktimestamp,actionflag,Ptx,Ptx->funding.amount,coinaddr,Ptx->details.bets,Ptx->numdetails)) > 0 )
*tipvaluep = 0;
}
else if ( Ptx->txtype == PEGGY_TXMICROPAY )
return(peggy_txind_micropay(txbuf,len,accts,blocknum,blocktimestamp,actionflag,Ptx,Ptx->details.micropays,Ptx->numdetails));
}
return(txind);
}
int64_t peggy_process(void *_PEGS,int32_t flags,void *fca,uint64_t fundedvalue,uint8_t *data,int32_t datalen,uint32_t blocknum,uint32_t blocktimestamp,uint32_t stakedblock)
{
struct peggy_tx Ptx; int32_t len,signedcount; int64_t txind = -1,tipvalue; struct peggy_info *PEGS = _PEGS;
tipvalue = fundedvalue;
if ( (len= serdes777_deserialize(&signedcount,&Ptx,blocktimestamp,data,datalen)) < 0 )
{
printf("peggy_process peggy_deserialize error datalen.%d (%d %d %d)\n",datalen,stakedblock,blocknum,blocktimestamp);
txind = -1;
}
else if ( Ptx.expiration != 0 && Ptx.expiration < blocktimestamp )
{
printf("peggy_process peggytx already expired at %u vs %u\n",Ptx.expiration,blocktimestamp);
txind = -1;
}
else if ( Ptx.txtype == PEGGY_TXTUNE )
txind = peggy_txind_tune(PEGS,blocknum,blocktimestamp,flags,&Ptx,Ptx.details.tune,Ptx.numdetails);
else txind = peggy_txind(&tipvalue,PEGS,blocknum,blocktimestamp,flags,&Ptx,stakedblock);
if ( txind < 0 )
tipvalue = fundedvalue;
if ( tipvalue != 0 )
peggy_thanks_you(PEGS,tipvalue);
if ( stakedblock != 0 )
{
uint64_t sums[PEGGY_MAXPRICEDPEGS]; struct price_resolution price,aveprice; struct peggy_time T;
uint32_t key[2],nonz[PEGGY_MAXPRICEDPEGS],i,j,block,numprices=0,n,*feed; double startmilli;
struct peggy_vote vote;//{ struct price_resolution price,tolerance; uint64_t nxt64bits,weight; };
price.Pval = 0;
memset(sums,0,sizeof(sums)), memset(nonz,0,sizeof(nonz));
if ( blocknum <= PEGGY_NUMCOEFFS )
block = 1;
else block = blocknum - PEGGY_NUMCOEFFS + 1;
startmilli = OS_milliseconds();
for (n=i=0; block<=blocknum&&i<PEGGY_NUMCOEFFS; i++,block++)
{
key[0] = block, key[1] = 0;
if ( (feed= ramkv777_read(&len,PEGS->accts->pricefeeds,key)) != 0 )
{
numprices = (uint32_t)(len / sizeof(len));
for (j=0; j<numprices; j++)
{
if ( feed[j] != 0 )
{
//int32_t den = 1;
//if ( PEGS->contracts[j]->name.baseid <= 8 )
// den *= 5;
memset(&vote,0,sizeof(vote));
vote.pval = feed[j], vote.tolerance = (uint32_t)(((uint64_t)3 * PEGS->default_spread.Pval * feed[j])/PRICE_RESOLUTION);
PEGS->votes[j][nonz[j]++] = vote;
sums[j] += feed[j];
}
}
n++;
}
}
for (j=0; j<numprices; j++)
{
if ( nonz[j] != 0 )
{
sums[j] /= nonz[j];
price.Pval = sums[j];
}
aveprice = peggy_scaleprice(price,PEGS->contracts[j]->peggymils);
if ( j > 0 )
{
T.blocknum = PEGS->numopreturns-1, T.blocktimestamp = blocktimestamp;
price = peggy_priceconsensus(PEGS,T,PEGS->accts->pricefeeds->sha256.txid,j,PEGS->votes[j],nonz[j],0,0);
price = peggy_scaleprice(price,PEGS->contracts[j]->peggymils);
if ( Debuglevel > 2 )
fprintf(stderr,"%d %10s.{%14.6f} %7.4f%%\n",T.blocknum,PEGS->contracts[j]->name.name,Pval(&price),(fabs(Pval(&price)/Pval(&aveprice))-1)*100);
}
}
if ( Debuglevel > 2 || blocktimestamp+600 > time(NULL) )
printf("staked.%u n.%d i.%d blocknum.%d t%u | processed in %.3f microseconds | pricehash.%llx\n",stakedblock,n,i,blocknum,blocktimestamp,1000*(OS_milliseconds() - startmilli),(long long)PEGS->accts->pricefeeds->sha256.txid);
}
return(txind);
}
int64_t peggy_covercost(int32_t *nump,int64_t *posinterests,int64_t *neginterests,struct peggy_info *PEGS,struct peggy *PEG,struct price_resolution price,struct price_resolution shortprice)
{
int32_t i,id; struct peggy_entry entry; struct peggy_unit *U; int64_t satoshis,covercost = 0;
id = PEG->name.id;
*posinterests = *neginterests = *nump = 0;
for (i=0; i<PEGS->accts->numunits; i++)
{
U = &PEGS->accts->units[i];
if ( (U->lock.peg == id || U->lock.peg == -id) && (PEG= peggy_findpeg(&entry,PEGS,U->lock.peg)) != 0 )
{
if ( U->estimated_interest > 0 )
(*posinterests) += U->estimated_interest, (*nump)++;
else if ( U->estimated_interest < 0 )
(*neginterests) += U->estimated_interest, (*nump)++;
if ( entry.polarity < 0 && U->lock.peg == -id )
{
satoshis = peggy_poolmainunits(&entry,-1,entry.polarity,price,shortprice,PEG->spread,PEG->pool.mainunitsize,U->lock.denom);
covercost += satoshis;
//printf("covercost price %.6f shortprice %.6f (%.8f - costbasis %.8f) %.8f -> %.8f price %.6f -> %.6f change %.8f est %.8f\n",Pval(&price),Pval(&shortprice),dstr(satoshis),dstr(U->costbasis),dstr(satoshis)-dstr(U->costbasis),dstr(covercost),dstr(U->costbasis)/Pval(&U->denomination),Pval(&shortprice),Pval(&shortprice)/(dstr(U->costbasis)/Pval(&U->denomination)),Pval(&price)*Pval(&price)*Pval(&U->denomination)*(Pval(&shortprice)/(dstr(U->costbasis)/Pval(&U->denomination))));
}
}
}
return(covercost);
}
double peggy_status(char **jsonstrp,struct peggy_info *PEGS,double *rates,uint32_t timestamp,char *name)
{
int32_t j,rate,num,count,opporate,datenum,seconds,n = 0; struct price_resolution liability,liabilities,price,shortprice;
int64_t pos,neg,possum,negsum,netbalance; struct tai t;
double aprsum,depositsum,covercost,covercosts; struct peggy_entry entry; char numstr[64];
struct peggy *PEG; cJSON *item,*array,*json = cJSON_CreateObject();
array = cJSON_CreateArray();
rates[0] = rates[1] = 0;
for (pos=possum=neg=negsum=liabilities.Pval=liability.Pval=covercost=covercosts=depositsum=aprsum=count=0,j=1; j<PEGS->numpegs; j++)
{
item = cJSON_CreateObject();
if ( (PEG= PEGS->contracts[j]) == 0 )
continue;
if ( (name != 0 && strcmp(PEG->name.name,name) != 0) || (PEG= peggy_find(&entry,PEGS,PEG->name.name,1)) == 0 )
continue;
rate = peggy_aprpercs(peggy_lockrate(&entry,PEGS,PEG,1,1));
if ( (PEG= peggy_find(&entry,PEGS,PEG->name.name,-1)) == 0 )
continue;
opporate = peggy_aprpercs(peggy_lockrate(&entry,PEGS,PEG,1,1));
rates[j*2] = (double)rate / 100.;
rates[j*2+1] = (double)opporate / 100.;
if ( rate != 0 )
n++;
if ( opporate != 0 )
n++;
aprsum += (rate + opporate);
price = peggy_price(PEG,(timestamp - PEG->genesistime) / PEGGY_MINUTE);
shortprice = peggy_shortprice(PEG,PEG->price);
liability.Pval = (PEG->pool.liability.num * price.Pval);
liabilities.Pval += liability.Pval;
covercost = peggy_covercost(&num,&pos,&neg,PEGS,PEG,price,shortprice);
covercosts += covercost, possum += pos, negsum += neg, count += num;
jaddstr(item,"base",PEG->name.name);
jaddnum(item,"maxsupply",dstr(PEG->maxsupply));
jaddnum(item,"maxnetbalance",dstr(PEG->maxnetbalance));
jaddnum(item,"numunits",num);
jaddnum(item,"pendinginterests",dstr(pos));
jaddnum(item,"pendinginterest_fees",dstr(neg));
price = peggy_scaleprice(price,PEG->peggymils);
jaddnum(item,"price",Pval(&price));
price = peggy_scaleprice(PEG->dayprice,PEG->peggymils);
jaddnum(item,"dayprice",Pval(&price));
jaddnum(item,"longunits",PEG->pool.liability.num);
price = peggy_scaleprice(liability,PEG->peggymils);
jaddnum(item,"liability",Pval(&price));
jaddnum(item,"antiprice",Pval(&shortprice));
jaddnum(item,"shortunits",PEG->pool.liability.numoppo);
jaddnum(item,"covercost",dstr(covercost));
jaddnum(item,"deposits",dstr(PEG->pool.funds.deposits));
jaddnum(item,"margindeposits",dstr(PEG->pool.funds.margindeposits));
jaddnum(item,"marginvalue",dstr(PEG->pool.funds.marginvalue));
jaddnum(item,"basereserve",dstr(PEGS->basereserves[PEG->name.baseid].funds.deposits));
sprintf(numstr,"%.2f%%",(double)rate/100.), jaddstr(item,"buy",numstr);
sprintf(numstr,"%.2f%%",(double)opporate/100.), jaddstr(item,"sell",numstr);
jaddi(array,item);
depositsum += PEG->pool.funds.deposits;
}
jadd(json,"rates",array);
datenum = OS_conv_unixtime(&t,&seconds,PEGS->genesistime);
jaddnum(json,"start",(uint64_t)datenum*1000000 + (seconds/3600)*10000 + ((seconds%3600)/60)*100 + (seconds%60));
datenum = OS_conv_unixtime(&t,&seconds,timestamp);
jaddnum(json,"timestamp",(uint64_t)datenum*1000000 + (seconds/3600)*10000 + ((seconds%3600)/60)*100 + (seconds%60));
jaddnum(json,"default_interest",(dailyrates[PEGS->interesttenths]));
jaddnum(json,"posboost",PEGS->posboost);
jaddnum(json,"negpenalty",PEGS->negpenalty);
jaddnum(json,"numunits",PEGS->accts->numunits);
jaddnum(json,"sumunits",count);
jaddnum(json,"unitinterests",dstr(possum));
jaddnum(json,"unitinterestfees",dstr(negsum));
jaddnum(json,"netunitinterest",dstr(possum + negsum));
jaddnum(json,"APR_reserves",dstr(PEGS->bank.APRfund_reserved));
jaddnum(json,"APRfund",dstr(PEGS->bank.APRfund));
jaddnum(json,"liabilities",Pval(&liabilities));
jaddnum(json,"covercosts",dstr(covercosts));
jaddnum(json,"depositsum",dstr(depositsum));
jaddnum(json,"deposits",dstr(PEGS->bank.funds.deposits));
jaddnum(json,"margindeposits",dstr(PEGS->bank.funds.margindeposits));
jaddnum(json,"marginvalue",dstr(PEGS->bank.funds.marginvalue));
jaddnum(json,"royalties",dstr(PEGS->bank.crypto777_royalty));
jaddnum(json,"fees",dstr(PEGS->bank.privatebetfees));
netbalance = (depositsum) + (PEGS->bank.funds.margindeposits) + (PEGS->bank.APRfund) - (PEGS->bank.APRfund_reserved) - SATOSHIDEN*(liabilities.Pval/PRICE_RESOLUTION) - (covercosts);
jaddnum(json,"cashbalance",dstr(netbalance));
netbalance = (depositsum) + (PEGS->bank.funds.marginvalue) + (PEGS->bank.APRfund) - (PEGS->bank.APRfund_reserved) - SATOSHIDEN*(liabilities.Pval/PRICE_RESOLUTION) - (covercosts);
jaddnum(json,"netbalance",dstr(netbalance));
if ( netbalance > PEGS->hwmbalance )
PEGS->hwmbalance = netbalance;
if ( netbalance < PEGS->worstbalance )
PEGS->worstbalance = netbalance;
if ( -(PEGS->hwmbalance - netbalance) < PEGS->maxdrawdown )
PEGS->maxdrawdown = -(PEGS->hwmbalance - netbalance);
jaddnum(json,"hwmbalance",dstr(PEGS->hwmbalance));
jaddnum(json,"maxdrawdown",dstr(PEGS->maxdrawdown));
jaddnum(json,"worstbalance",dstr(PEGS->worstbalance));
if ( jsonstrp != 0 )
*jsonstrp = jprint(json,1);
if ( n != 0 )
aprsum /= n;
return(aprsum/100.);
}
char *peggyrates(uint32_t timestamp,char *name)
{
char *jsonstr = 0; double rates[2 * PEGGY_MAXPEGS]; struct peggy_info *PEGS = opreturns_context("peggy",0);
if ( timestamp == 0 )
timestamp = (uint32_t)time(NULL);
if ( PEGS != 0 )
peggy_status(&jsonstr,PEGS,rates,timestamp,name);
return(jsonstr);
}
void peggy_test()
{
opreturns_init(0,(uint32_t)time(NULL),"PEGS");
peggy_tx("{\"txtype\":0,\"outputs\":[{\"lockhash\":\"1259ec21d31a30898d7cd1609f80d9668b4778e3d97e941044b39f0c44d2e51b\",\"type\":1,\"denom\":10,\"margin\":0,\"minlockdays\":7,\"maxlockdays\":20,\"peg\":\"USD\"}],\"privkey\":\"1259ec21d31a30898d7cd1609f80d9668b4778e3d97e941044b39f0c44d2e51b\"}");
getchar();
}

474
iguana/peggy_txind.c

@ -0,0 +1,474 @@
/******************************************************************************
* Copyright © 2014-2015 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 "peggy.h"
struct opreturn_protocol
{
uint8_t id[3]; char name[16];
int64_t (*process)(void *context,int32_t flags,void *fundedcoinaddr,uint64_t fundedvalue,uint8_t *data,int32_t datalen,uint32_t currentblocknum,uint32_t blocktimestamp,uint32_t isstaked);
int32_t (*emit)(void *context,uint8_t opreturndata[MAX_OPRETURNSIZE],struct opreturn_payment *payments,int32_t max,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp);
int32_t (*flush)(void *context,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp);
int32_t (*init)(struct txinds777_info *opreturns,uint32_t blocknum,uint32_t blocktimestamp,char *path,void *globals[OPRETURNS_CONTEXTS],int32_t lookbacks[OPRETURNS_CONTEXTS],int32_t max);
uint32_t (*clone)(char *path,void *dest,void *src);
uint32_t (*currentblock)(void *globals);
void *(*replay)(char *path,struct txinds777_info *opreturns,void *_PEGS,uint32_t blocknum,char *opreturnstr,uint8_t *data,int32_t datalen);
void *globals[OPRETURNS_CONTEXTS]; int32_t lookbacks[OPRETURNS_CONTEXTS],numcontexts; uint32_t pastblocknums[OPRETURNS_CONTEXTS];
struct txinds777_info *opreturns;
} OPRETURN_PROTOCOLS[8] = { { { 'P', 'A', 'X' }, "peggy", peggy_process, peggy_emit, peggy_flush, peggy_init_contexts, peggy_clone, peggy_currentblock, peggy_replay } };
int32_t opreturns_init(uint32_t blocknum,uint32_t blocktimestamp,char *path)
{
int32_t i;
for (i=0; i<sizeof(OPRETURN_PROTOCOLS)/sizeof(*OPRETURN_PROTOCOLS); i++)
{
if ( OPRETURN_PROTOCOLS[i].init == 0 )
break;
else
{
OPRETURN_PROTOCOLS[i].opreturns = txinds777_init(path,"opreturns");
printf("txinds init.%p\n",OPRETURN_PROTOCOLS[i].opreturns);
(*OPRETURN_PROTOCOLS[i].init)(OPRETURN_PROTOCOLS[i].opreturns,blocknum,blocktimestamp,path,OPRETURN_PROTOCOLS[i].globals,OPRETURN_PROTOCOLS[i].lookbacks,OPRETURNS_CONTEXTS);
}
}
return(i);
}
struct opreturn_protocol *opreturns_find(uint8_t id[3],char *name)
{
int32_t i;
for (i=0; i<sizeof(OPRETURN_PROTOCOLS)/sizeof(*OPRETURN_PROTOCOLS); i++)
if ( (id != 0 && memcmp(OPRETURN_PROTOCOLS[i].id,id,3) == 0) || (name != 0 && strcmp(name,OPRETURN_PROTOCOLS[i].name) == 0) )
return(&OPRETURN_PROTOCOLS[i]);
return(0);
}
void *opreturns_context(char *name,int32_t context)
{
struct opreturn_protocol *protocol;
if ( (protocol= opreturns_find(0,name)) != 0 )
return(protocol->globals[context]);
return(0);
}
int32_t opreturns_process(int32_t flags,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp,struct opreturn_entry *list,int32_t num,uint8_t *peggyopreturn,int32_t peggylen)
{
static uint32_t prevblocknum; struct opreturn_entry stakedblock;
int32_t i,iter,size,isstaked,lookback,numvalid = 0; uint64_t len; uint32_t pastblocknum; uint8_t buf[16384]; long offset = 1;
struct opreturn_protocol *protocol; struct opreturn_entry *opreturn = list;
if ( prevblocknum != 0 && currentblocknum != prevblocknum+1 )
{
if ( currentblocknum > prevblocknum+1 )
printf("skipped block? currentblocknum %u > %u prevblocknum\n",currentblocknum,prevblocknum);
else
{
for (i=0; i<sizeof(OPRETURN_PROTOCOLS)/sizeof(*OPRETURN_PROTOCOLS); i++)
{
protocol = &OPRETURN_PROTOCOLS[i];
(*protocol->clone)("opreturns_PERM",protocol->globals[0],protocol->globals[1]);
while ( (blocknum= (*protocol->currentblock)(protocol->globals[0])) < currentblocknum )
(*protocol->replay)("opreturns",protocol->opreturns,protocol->globals[0],blocknum,0,0,0);
}
}
}
prevblocknum = blocknum = currentblocknum;
for (i=0; i<sizeof(OPRETURN_PROTOCOLS)/sizeof(*OPRETURN_PROTOCOLS); i++)
{
if ( OPRETURN_PROTOCOLS[i].opreturns != 0 )
{
txinds777_flush(OPRETURN_PROTOCOLS[i].opreturns,blocknum,blocktimestamp);
printf("flush.%p globals.%p %u %u %u\n",OPRETURN_PROTOCOLS[i].flush,OPRETURN_PROTOCOLS[i].globals[0],currentblocknum,blocknum,blocktimestamp);
if ( OPRETURN_PROTOCOLS[i].flush != 0 )
(*OPRETURN_PROTOCOLS[i].flush)(OPRETURN_PROTOCOLS[i].globals[0],currentblocknum,blocknum,blocktimestamp);
}
}
for (i=0; i<sizeof(OPRETURN_PROTOCOLS)/sizeof(*OPRETURN_PROTOCOLS); i++)
{
protocol = &OPRETURN_PROTOCOLS[i];
for (iter=1; iter<protocol->numcontexts; iter++)
{
lookback = protocol->lookbacks[iter];
if ( blocknum > lookback )
{
pastblocknum = blocknum - lookback;
while ( protocol->pastblocknums[iter] <= pastblocknum )
{
txinds777_seek(protocol->opreturns,pastblocknum);
while ( (opreturn= txinds777_read(&size,buf,protocol->opreturns)) != 0 )
{
if ( opreturn->blocknum != pastblocknum )
break;
if ( opreturn->data[0] == OP_RETURN_OPCODE )
{
offset = hdecode_varint(&len,opreturn->data,offset,sizeof(opreturn->data));
if ( len == (opreturn->datalen + offset) && protocol->id[0] == opreturn->data[offset] && protocol->id[1] == opreturn->data[offset+1] && protocol->id[2] == opreturn->data[offset+2] )
{
if ( (*protocol->process)(protocol->globals[1],flags,opreturn->vout.coinaddr,opreturn->vout.value,&opreturn->data[offset+3],(int32_t)len-3,pastblocknum,opreturn->timestamp,opreturn->isstaked) < 0 )
{
printf("process_opreturns[%d]: protocol.%s rejects entry\n",i,protocol->name);
}
}
}
}
protocol->pastblocknums[iter] = pastblocknum++;
}
}
}
}
for (i=0; i<=num; i++)
{
isstaked = 0;
if ( i == 0 )
{
if ( peggyopreturn != 0 )
{
opreturn = &stakedblock;
memset(&stakedblock,0,sizeof(stakedblock));
memcpy(stakedblock.data,peggyopreturn,peggylen);
stakedblock.datalen = peggylen;
isstaked = 1;
} else continue;
}
else opreturn = &list[i-1];
opreturn->isstaked = isstaked;
if ( opreturn->data[0] == OP_RETURN_OPCODE )
{
offset = hdecode_varint(&len,opreturn->data,offset,sizeof(opreturn->data));
if ( (len + offset) == opreturn->datalen )
{
if ( (protocol= opreturns_find(&opreturn->data[offset],0)) != 0 )
{
txind777_create(OPRETURN_PROTOCOLS[i].opreturns,currentblocknum,blocktimestamp,opreturn,(int32_t)(sizeof(*opreturn)-sizeof(opreturn->data) + opreturn->datalen + 8));
if ( (*protocol->process)(protocol->globals[0],flags,opreturn->vout.coinaddr,opreturn->vout.value,&opreturn->data[offset+3],(int32_t)len-3,currentblocknum,blocktimestamp,isstaked) < 0 )
{
printf("process_opreturns[%d]: protocol.%s rejects entry\n",i,protocol->name);
}
numvalid++;
}
} else printf("process_opreturns[%d]: unexpected datalen.%d vs x.%llu at offset.%ld\n",i,opreturn->datalen,(long long)len,offset);
} else printf("process_opreturns[%d]: unexpected opcode.%d != OP_RETURN %d\n",i,opreturn->data[0],OP_RETURN_OPCODE);
}
return(numvalid);
}
int32_t opreturns_emit(char *name,uint8_t opreturndata[MAX_OPRETURNSIZE],struct opreturn_payment *payments,int32_t max,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp)
{
struct opreturn_protocol *protocol;
if ( (protocol= opreturns_find(0,name)) != 0 )
{
if ( payments != 0 && max != 0 )
memset(payments,0,sizeof(*payments) * max);
return((*protocol->emit)(protocol->globals[0],opreturndata,payments,max,currentblocknum,blocknum,blocktimestamp));
}
printf("opreturns_emit: couldnt find opreturn protocol.(%s)\n",name);
return(-1);
}
void opreturns_emitloop(char *protocols[],int32_t numprotocols,uint8_t opreturndata[MAX_OPRETURNSIZE],struct opreturn_payment *payments,int32_t max,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp)
{
static int lastopreturni;
int32_t i,j,opreturnlen;
for (j=0; j<numprotocols; j++)
{
i = (j + lastopreturni + 1) % numprotocols;
if ( (opreturnlen= opreturns_emit(protocols[i],opreturndata,payments,max,currentblocknum,blocknum,blocktimestamp)) < 0 )
{
printf("opreturns_emitloop: error on protocol.(%s)\n",protocols[i]);
exit(-1);
}
if ( opreturnlen > 0 )
{
lastopreturni = i;
opreturndata = 0;
}
while ( payments != 0 && max > 0 && payments[0].value != 0 )
payments++, max--;
if ( max <= 0 )
max = 0, payments = 0;
}
}
int32_t opreturns_queue_payment(queue_t *PaymentsQ,uint32_t blocktimestamp,char *coinaddr,int64_t value)
{
int32_t len = 0; struct opreturn_payment *item=0,*payment = calloc(1,sizeof(*payment));
payment->value = value;
strcpy(payment->coinaddr,coinaddr);
if ( value < 0 )
{
payment->value = -value;
if ( (item= queue_delete(PaymentsQ,&payment->DL,sizeof(*payment),1)) != 0 )
free(item);
else printf("couldnt find queued payment %.8f -> %s t%u\n",dstr(value),coinaddr,blocktimestamp);
free(payment);
return(item == 0 ? -1 : 0);
}
else queue_enqueue("PaymentsQ",PaymentsQ,&payment->DL,0);
return(len);
}
void txinds777_purge(struct txinds777_info *txinds)
{
if ( txinds->fp != 0 )
fclose(txinds->fp);
if ( txinds->txlogfp != 0 )
fclose(txinds->txlogfp);
if ( txinds->indexfp != 0 )
fclose(txinds->indexfp);
if ( txinds->blockitems != 0 )
free(txinds->blockitems);
memset(txinds,0,sizeof(*txinds));
}
int64_t txinds777_seek(struct txinds777_info *txinds,uint32_t blocknum)
{
if ( txinds->blockitems != 0 && blocknum >= txinds->H.firstblocknum && blocknum <= txinds->H.lastblocknum )
txinds->curitem = txinds->blockitems[blocknum - txinds->H.firstblocknum];
else txinds->curitem = 0;
return(txinds->curitem);
}
void *txinds777_read(int32_t *lenp,uint8_t *buf,struct txinds777_info *txinds)
{
int64_t txind,fpos; int32_t len; uint32_t triplet[3];
*lenp = 0;
if ( txinds->indexfp == 0 || txinds->txlogfp == 0 )
return(0);
fseek(txinds->indexfp,txinds->curitem * sizeof(int64_t),SEEK_SET);
if ( fread(&txind,1,sizeof(txind),txinds->indexfp) != sizeof(txind) )
{
printf("error reading txindex.%lld file at pos %lld\n",(long long)txinds->curitem,(long long)(txinds->curitem * sizeof(txind)));
return(0);
}
len = txind & 0xffff;
fpos = (txind >> 16);
if ( fpos+len <= txinds->H.nextpos )
{
printf("load %ld for item.%d log.%ld\n",ftell(txinds->indexfp),(int32_t)txinds->curitem,(long)fpos);
fseek(txinds->txlogfp,fpos,SEEK_SET);
if ( len >= sizeof(triplet) && fread(triplet,1,sizeof(triplet),txinds->txlogfp) == sizeof(triplet) && len > sizeof(triplet) )
{
len -= sizeof(triplet);
if ( fread(buf,1,len,txinds->txlogfp) == len )
{
*lenp = len;
return(buf);
}
}
}
return(0);
}
void txinds777_ensure(struct txinds777_info *txinds,uint32_t blocknum,uint64_t curitem)
{
int32_t offset,oldrange,newrange;
if ( txinds->blockitems == 0 )
{
txinds->blockitems = realloc(txinds->blockitems,sizeof(*txinds->blockitems));
txinds->H.firstblocknum = txinds->H.lastblocknum = blocknum;
}
else if ( blocknum > txinds->H.lastblocknum )
{
oldrange = (txinds->H.lastblocknum - txinds->H.firstblocknum + 1);
newrange = (blocknum - txinds->H.firstblocknum + 1);
txinds->blockitems = realloc(txinds->blockitems,sizeof(*txinds->blockitems) * newrange);
if ( newrange > oldrange+1 )
memset(&txinds->blockitems[oldrange],0,(newrange - oldrange));
txinds->H.lastblocknum = blocknum;
}
offset = (blocknum - txinds->H.firstblocknum);
txinds->blockitems[offset] = curitem;
}
int64_t txind777_create(struct txinds777_info *txinds,uint32_t blocknum,uint32_t timestamp,void *txdata,uint16_t len)
{
int64_t txind = -1; uint32_t triplet[3];
if ( txdata == 0 || txinds == 0 )
return(0);
if ( len != 0 )
{
txind = (txinds->H.nextpos << 16) | (len + sizeof(triplet));
if ( txinds->txlogfp != 0 )
{
triplet[0] = len, triplet[1] = blocknum, triplet[2] = timestamp;
//printf("triplet.(%d %d %d)\n",len,blocknum,timestamp);
fseek(txinds->txlogfp,txinds->H.nextpos,SEEK_SET);
if ( fwrite(triplet,1,sizeof(triplet),txinds->txlogfp) != sizeof(triplet) || fwrite(txdata,1,len,txinds->txlogfp) != len )
{
printf("error updating txlog file at pos %lld\n",(long long)txinds->H.nextpos);
return(-1);
}
}
if ( txinds->indexfp != 0 )
{
txinds777_ensure(txinds,blocknum,txinds->H.num);
fseek(txinds->indexfp,txinds->H.num * sizeof(txind),SEEK_SET);
if ( fwrite(&txind,1,sizeof(txind),txinds->indexfp) != sizeof(txind) )
{
printf("error updating txindex file at pos %lld\n",(long long)(txinds->H.num * sizeof(txind)));
return(-1);
}
txinds->H.num++;
// printf("H.num %d: indexfp %ld\n",(int32_t)txinds->H.num,ftell(txinds->indexfp));
}
vupdate_sha256(txinds->H.sha256.bytes,&txinds->H.state,txdata,len);
txinds->H.nextpos += len + sizeof(triplet);
//printf("H.num %d, nextpos %ld (len %ld) indexfp %ld logfp %ld\n",(int32_t)txinds->H.num,(long)txinds->H.nextpos,len + sizeof(triplet),ftell(txinds->indexfp),ftell(txinds->txlogfp));
} else printf("cant txlog no data\n");
return(txind);
}
int64_t txind777_bundle(struct txinds777_info *txinds,uint32_t blocknum,uint32_t timestamp,int64_t *bundle,int32_t numtx)
{
if ( bundle != 0 )
return(txind777_create(txinds,blocknum,timestamp,bundle,numtx * sizeof(*txinds)));
else return(0);
}
FILE *txinds777_initfile(long *fposp,char *path,char *name,char *suffix,uint64_t expected)
{
FILE *fp; char fname[512]; long fpos = 0;
sprintf(fname,"%s/%s%s",path,name,suffix), OS_compatible_path(fname);
if ( (fp= fopen(fname,"rb+")) != 0 )
{
fseek(fp,0,SEEK_END);
if ( (fpos= ftell(fp)) != expected )
{
printf("txinds777_init: warning mismatched position %ld vs %lld\n",fpos,(long long)expected);
fseek(fp,expected,SEEK_SET);
if ( (fpos= ftell(fp)) != expected )
printf("txinds777_init: error mismatched position %ld vs %lld after set fpos\n",fpos,(long long)expected);
}
}
else fp = fopen(fname,"wb+");
*fposp = fpos;
return(fp);
}
struct txinds777_info *txinds777_init(char *path,char *name)
{
FILE *fp; char fname[512]; int64_t txind,checktxind; long logfpos,indexfpos; struct txinds777_hdr H,goodH; uint32_t triplet[3];
struct txinds777_info *txinds = calloc(1,sizeof(*txinds));
strcpy(txinds->path,path), strcpy(txinds->name,name);
sprintf(fname,"%s/%s",path,name), OS_compatible_path(fname);
printf("txinds777_init(%s,%s)\n",path,name);
if ( (fp= fopen(fname,"rb+")) != 0 )
{
if ( fread(&txinds->H,1,sizeof(txinds->H),fp) == sizeof(txinds->H) )
{
txinds->txlogfp = txinds777_initfile(&logfpos,path,name,".log",txinds->H.nextpos);
txinds->indexfp = txinds777_initfile(&indexfpos,path,name,".index",sizeof(uint64_t) * txinds->H.num);
if ( txinds->txlogfp != 0 && txinds->indexfp != 0 )
{
memset(&goodH,0,sizeof(goodH));
while ( fread(&H,1,sizeof(H),fp) == sizeof(H) )
{
if ( H.num*sizeof(uint64_t) > indexfpos || H.nextpos > logfpos )
break;
goodH = H;
//printf("loaded H nextpos %d num.%d\n",(int32_t)H.nextpos,(int32_t)H.num);
}
txinds->H = goodH;
if ( txinds->H.nextpos > 0 )
{
txinds->curitem = 0;
rewind(txinds->txlogfp);
rewind(txinds->indexfp);
while ( txinds->curitem < txinds->H.num )
{
if ( fread(&txind,1,sizeof(txind),txinds->indexfp) != sizeof(txind) )
break;
logfpos = ftell(txinds->txlogfp);
if ( fread(triplet,1,sizeof(triplet),txinds->txlogfp) == sizeof(triplet) )
{
//printf("triplet.(%d %d %d)\n",triplet[0],triplet[1],triplet[2]);
if ( (triplet[0] + logfpos) > txinds->H.nextpos )
break;
checktxind = (logfpos << 16) | (triplet[0] + sizeof(triplet));
if ( checktxind != txind )
{
printf("checktxind error item.%lld %llx != %llx\n",(long long)txinds->curitem,(long long)checktxind,(long long)txind);
txinds->H.num = txinds->curitem;
txinds->H.nextpos = logfpos;
break;
}
txinds777_ensure(txinds,triplet[1],txinds->curitem++);
fseek(txinds->txlogfp,logfpos + (triplet[0] + sizeof(triplet)),SEEK_SET);
}
}
printf("verified %lld items, curpos %ld %ld\n",(long long)txinds->curitem,ftell(txinds->indexfp),ftell(txinds->txlogfp));
}
}
else
{
if ( txinds->txlogfp != 0 )
fclose(txinds->txlogfp), txinds->txlogfp = 0;
if ( txinds->indexfp != 0 )
fclose(txinds->indexfp), txinds->indexfp = 0;
}
}
txinds->fp = fp;
}
else if ( (txinds->fp= fopen(fname,"wb+")) != 0 )
fwrite(&txinds->H,1,sizeof(txinds->H),txinds->fp);
if ( txinds->txlogfp == 0 || txinds->indexfp == 0 )
vupdate_sha256(txinds->H.sha256.bytes,&txinds->H.state,0,0);
if ( txinds->txlogfp == 0 )
txinds->txlogfp = txinds777_initfile(&logfpos,path,name,".log",0);
if ( txinds->indexfp == 0 )
txinds->indexfp = txinds777_initfile(&indexfpos,path,name,".index",0);
//printf("fps %p %p %p\n",txinds->fp,txinds->txlogfp,txinds->indexfp);
return(txinds);
}
int32_t txind777_txbuf(uint8_t *txbuf,int32_t len,uint64_t val,int32_t size)
{
int32_t i;
if ( txbuf != 0 )
for (i=0; i<size; i++,val>>=8)
txbuf[len++] = (val & 0xff);
return(len);
}
int32_t txinds777_flush(struct txinds777_info *txinds,uint32_t blocknum,uint32_t blocktimestamp)
{
long fpos;
if ( txinds != 0 )
{
if ( txinds->txlogfp != 0 )
fflush(txinds->txlogfp);
if ( txinds->indexfp != 0 )
fflush(txinds->indexfp);
txinds->H.blocknum = blocknum, txinds->H.timestamp = blocktimestamp;
if ( txinds->fp != 0 )
{
fwrite(&txinds->H,1,sizeof(txinds->H),txinds->fp);
fpos = ftell(txinds->fp);
rewind(txinds->fp);
fwrite(&txinds->H,1,sizeof(txinds->H),txinds->fp);
fseek(txinds->fp,fpos,SEEK_SET);
fflush(txinds->fp);
}
//printf("txinds777_flush.(%s)\n",txinds->name);
}
else
{
printf("txinds777_flush null ptr\n");
//getchar();
}
return(0);
}

767
iguana/peggy_update.c

@ -0,0 +1,767 @@
/******************************************************************************
* 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 "peggy.h"
#include "exchanges777.h"
short Baserel_contractnum[NUM_CURRENCIES+1][NUM_CURRENCIES+1] =
{
{ 28, 18, 25, 22, 27, 9, 13, 0, 36 },
{ 18, 29, 20, 21, 19, 10, 15, 5, 37 },
{ 25, 20, 30, 23, 26, 7, 14, 3, -1 },
{ 22, 21, 23, 31, 24, 11, 16, 4, 38 },
{ 27, 19, 26, 24, 32, 12, 17, 6, 39 },
{ 9, 10, 7, 11, 12, 33, 8, 2, -1 },
{ 13, 15, 14, 16, 17, 8, 34, 1, 40 },
{ 0, 5, 3, 4, 6, 2, 1, 35, -1 },
{ 36, 37, -1, 38, 39, -1, 40, -1, 74 },
};
short Currency_contractdirs[NUM_CURRENCIES+1][NUM_CURRENCIES] =
{
{ -1, 1, 1, -1, -1, 1, -1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1 },
{ -1, -1, -1, -1, -1, -1, -1, 1 },
{ 1, 1, 1, -1, 1, 1, 1, 1 },
{ 1, 1, 1, -1, -1, 1, 1, 1 },
{ -1, 1, 1, -1, -1, -1, -1, 1 },
{ -1, -1, -1, 1, -1, -1, -1, 1 },
{ 1, 1, 1, 1, -1, -1, -1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1 },
};
static char *Yahoo_metals[] = { YAHOO_METALS };
char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", // end of currencies
"XAU", "XAG", "XPT", "XPD", // metals, gold must be first
"BTCD", "BTC", "NXT", "LTC", "ETH", "DOGE", "BTS", "MAID", "XCP", "XMR" // cryptos
};
char CONTRACTS[][16] = { "NZDUSD", "NZDCHF", "NZDCAD", "NZDJPY", "GBPNZD", "EURNZD", "AUDNZD", "CADJPY", "CADCHF", "USDCAD", "EURCAD", "GBPCAD", "AUDCAD", "USDCHF", "CHFJPY", "EURCHF", "GBPCHF", "AUDCHF", "EURUSD", "EURAUD", "EURJPY", "EURGBP", "GBPUSD", "GBPJPY", "GBPAUD", "USDJPY", "AUDJPY", "AUDUSD", "USDCNY", "USDHKD", "USDMXN", "USDZAR", "USDTRY", "EURTRY", "TRYJPY", "USDSGD", "EURNOK", "USDNOK","USDSEK","USDDKK","EURSEK","EURDKK","NOKJPY","SEKJPY","USDPLN","EURPLN","USDILS", // no more currencies
"XAUUSD", "XAGUSD", "XPTUSD", "XPDUSD", "COPPER", "NGAS", "UKOIL", "USOIL", // commodities
// cryptos
"NAS100", "SPX500", "US30", "BUND", "EUSTX50", "UK100", "JPN225", "GER30", "SUI30", "AUS200", "HKG33", "FRA40", "ESP35", "ITA40", "USDOLLAR", // indices
"SuperNET" // assets
};
int32_t PAX_ispair(char *base,char *rel,char *contract)
{
int32_t i,j;
base[0] = rel[0] = 0;
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
{
if ( strncmp(CURRENCIES[i],contract,strlen(CURRENCIES[i])) == 0 )
{
for (j=0; j<sizeof(CURRENCIES)/sizeof(*CURRENCIES); j++)
if ( strcmp(CURRENCIES[j],contract+strlen(CURRENCIES[i])) == 0 )
{
strcpy(base,CURRENCIES[i]);
strcpy(rel,CURRENCIES[j]);
/*USDCNY 6.209700 -> 0.655564
USDCNY 6.204146 -> 0.652686
USDHKD 7.753400 -> 0.749321
USDHKD 7.746396 -> 0.746445
USDZAR 12.694000 -> 1.101688
USDZAR 12.682408 -> 1.098811
USDTRY 2.779700 -> 0.341327
EURTRY 3.048500 -> 0.386351
TRYJPY 44.724000 -> 0.690171
TRYJPY 44.679966 -> 0.687290
USDSGD 1.375200 -> 0.239415*/
//if ( strcmp(contract,"USDCNY") == 0 || strcmp(contract,"TRYJPY") == 0 || strcmp(contract,"USDZAR") == 0 )
// printf("i.%d j.%d base.%s rel.%s\n",i,j,base,rel);
return((i<<8) | j);
}
break;
}
}
return(-1);
}
int32_t PAX_basenum(char *base)
{
int32_t i,j;
if ( 1 )
{
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
for (j=0; j<sizeof(CURRENCIES)/sizeof(*CURRENCIES); j++)
if ( i != j && strcmp(CURRENCIES[i],CURRENCIES[j]) == 0 )
printf("duplicate.(%s)\n",CURRENCIES[i]);//, getchar();
}
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
if ( strcmp(CURRENCIES[i],base) == 0 )
return(i);
return(-1);
}
int32_t PAX_contractnum(char *base,char *rel)
{
int32_t i,j,c; char contractstr[16],*contract = 0;
if ( 0 )
{
for (i=0; i<sizeof(CONTRACTS)/sizeof(*CONTRACTS); i++)
for (j=0; j<sizeof(CONTRACTS)/sizeof(*CONTRACTS); j++)
if ( i != j && strcmp(CONTRACTS[i],CONTRACTS[j]) == 0 )
printf("duplicate.(%s)\n",CONTRACTS[i]);//, getchar();
}
if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 )
{
for (i=0; i<NUM_CURRENCIES; i++)
if ( strcmp(base,CURRENCIES[i]) == 0 )
{
for (j=0; j<NUM_CURRENCIES; j++)
if ( strcmp(rel,CURRENCIES[j]) == 0 )
return(Baserel_contractnum[i][j]);
break;
}
sprintf(contractstr,"%s%s",base,rel);
contract = contractstr;
} else contract = base;
if ( contract != 0 && contract[0] != 0 )
{
for (c=0; c<sizeof(CONTRACTS)/sizeof(*CONTRACTS); c++)
if ( strcmp(CONTRACTS[c],contract) == 0 )
return(c);
}
return(-1);
}
cJSON *url_json(char *url)
{
char *jsonstr; cJSON *json = 0;
if ( (jsonstr= issue_curl(url)) != 0 )
{
//printf("(%s) -> (%s)\n",url,jsonstr);
json = cJSON_Parse(jsonstr);
free(jsonstr);
}
return(json);
}
cJSON *url_json2(char *url)
{
char *jsonstr; cJSON *json = 0;
if ( (jsonstr= issue_curl(url)) != 0 )
{
//printf("(%s) -> (%s)\n",url,jsonstr);
json = cJSON_Parse(jsonstr);
free(jsonstr);
}
return(json);
}
double PAX_yahoo(char *metal)
{
// http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json
// http://finance.yahoo.com/webservice/v1/symbols/XAU=X/quote?format=json
// http://finance.yahoo.com/webservice/v1/symbols/XAG=X/quote?format=json
// http://finance.yahoo.com/webservice/v1/symbols/XPT=X/quote?format=json
// http://finance.yahoo.com/webservice/v1/symbols/XPD=X/quote?format=json
char url[1024],*jsonstr; cJSON *json,*obj,*robj,*item,*field; double price = 0.;
sprintf(url,"http://finance.yahoo.com/webservice/v1/symbols/%s=X/quote?format=json",metal);
if ( (jsonstr= issue_curl(url)) != 0 )
{
//printf("(%s)\n",jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
if ( (obj= jobj(json,"list")) != 0 && (robj= jobj(obj,"resources")) != 0 && (item= jitem(robj,0)) != 0 )
{
if ( (robj= jobj(item,"resource")) != 0 && (field= jobj(robj,"fields")) != 0 && (price= jdouble(field,"price")) != 0 )
price = 1. / price;
}
free_json(json);
}
free(jsonstr);
}
//if ( Debuglevel > 2 )
printf("(%s %f) ",metal,price);
return(price);
}
void PAX_btcprices(struct peggy_info *PEGS,int32_t enddatenum,int32_t numdates)
{
int32_t i,n,year,month,day,seconds,datenum; char url[1024],date[64],*dstr,*str;
uint32_t timestamp,utc32[MAX_SPLINES]; struct tai t;
cJSON *coindesk,*quandl,*btcdhist,*bpi,*array,*item;
double btcddaily[MAX_SPLINES],cdaily[MAX_SPLINES],qdaily[MAX_SPLINES],ask,high,low,bid,close,vol,quotevol,open,price = 0.;
coindesk = url_json("http://api.coindesk.com/v1/bpi/historical/close.json");
sprintf(url,"https://poloniex.com/public?command=returnChartData&currencyPair=BTC_BTCD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-numdates*3600*24));
if ( (bpi= jobj(coindesk,"bpi")) != 0 )
{
datenum = enddatenum;
memset(utc32,0,sizeof(utc32));
memset(cdaily,0,sizeof(cdaily));
if ( datenum == 0 )
{
datenum = OS_conv_unixtime(&t,&seconds,(uint32_t)time(NULL));
printf("got datenum.%d %d %d %d\n",datenum,seconds/3600,(seconds/60)%24,seconds%60);
}
for (i=0; i<numdates; i++)
{
expand_datenum(date,datenum);
if ( (price= jdouble(bpi,date)) != 0 )
{
utc32[numdates - 1 - i] = OS_conv_datenum(datenum,12,0,0);
cdaily[numdates - 1 - i] = price * .001;
//printf("(%s %u %f) ",date,utc32[numdates - 1 - i],price);
}
datenum = ecb_decrdate(&year,&month,&day,date,datenum);
}
PAX_genspline(&PEGS->splines[MAX_CURRENCIES],MAX_CURRENCIES,"coindesk",utc32,cdaily,numdates,cdaily);
} else printf("no bpi\n");
quandl = url_json("https://www.quandl.com/api/v1/datasets/BAVERAGE/USD.json?rows=64");
if ( (str= jstr(quandl,"updated_at")) != 0 && (datenum= conv_date(&seconds,str)) > 0 && (array= jarray(&n,quandl,"data")) != 0 )
{
printf("datenum.%d data.%d %d\n",datenum,n,cJSON_GetArraySize(array));
memset(utc32,0,sizeof(utc32)), memset(qdaily,0,sizeof(qdaily));
for (i=0; i<n&&i<MAX_SPLINES; i++)
{
// ["Date","24h Average","Ask","Bid","Last","Total Volume"]
// ["2015-07-25",289.27,288.84,288.68,288.87,44978.61]
item = jitem(array,i);
//if ( Debuglevel > 2 )
printf("(%s) ",cJSON_Print(item));
if ( (dstr= jstr(jitem(item,0),0)) != 0 && (datenum= conv_date(&seconds,dstr)) > 0 )
{
price = jdouble(jitem(item,1),0), ask = jdouble(jitem(item,2),0), bid = jdouble(jitem(item,3),0);
close = jdouble(jitem(item,4),0), vol = jdouble(jitem(item,5),0);
//if ( Debuglevel > 2 )
fprintf(stderr,"%d.[%d %f %f %f %f %f].%d ",i,datenum,price,ask,bid,close,vol,n);
utc32[numdates - 1 - i] = OS_conv_datenum(datenum,12,0,0), qdaily[numdates - 1 - i] = price * .001;
}
}
PAX_genspline(&PEGS->splines[MAX_CURRENCIES+1],MAX_CURRENCIES+1,"quandl",utc32,qdaily,n<MAX_SPLINES?n:MAX_SPLINES,qdaily);
}
btcdhist = url_json(url);
//{"date":1406160000,"high":0.01,"low":0.00125,"open":0.01,"close":0.001375,"volume":1.50179994,"quoteVolume":903.58818412,"weightedAverage":0.00166204},
if ( (array= jarray(&n,btcdhist,0)) != 0 )
{
memset(utc32,0,sizeof(utc32)), memset(btcddaily,0,sizeof(btcddaily));
//printf("GOT.(%s)\n",cJSON_Print(array));
for (i=0; i<n; i++)
{
item = jitem(array,i);
timestamp = juint(item,"date"), high = jdouble(item,"high"), low = jdouble(item,"low"), open = jdouble(item,"open");
close = jdouble(item,"close"), vol = jdouble(item,"volume"), quotevol = jdouble(item,"quoteVolume"), price = jdouble(item,"weightedAverage");
//printf("[%u %f %f %f %f %f %f %f]",timestamp,high,low,open,close,vol,quotevol,price);
//if ( Debuglevel > 2 )
printf("[%u %d %f]",timestamp,OS_conv_unixtime(&t,&seconds,timestamp),price);
utc32[i] = timestamp - 12*3600, btcddaily[i] = price * 100.;
}
//if ( Debuglevel > 2 )
printf("poloniex.%d\n",n);
PAX_genspline(&PEGS->splines[MAX_CURRENCIES+2],MAX_CURRENCIES+2,"btcdhist",utc32,btcddaily,n<MAX_SPLINES?n:MAX_SPLINES,btcddaily);
}
// https://poloniex.com/public?command=returnChartData&currencyPair=BTC_BTCD&start=1405699200&end=9999999999&period=86400
}
int32_t PAX_ecbparse(char *date,double *prices,char *url,int32_t basenum)
{
char *jsonstr,*relstr,*basestr; int32_t count=0,i,relnum; cJSON *json,*ratesobj,*item; struct destbuf tmp;
if ( (jsonstr= issue_curl(url)) != 0 )
{
//if ( Debuglevel > 2 )
printf("(%s)\n",jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
copy_cJSON(&tmp,jobj(json,"date")), safecopy(date,tmp.buf,64);
if ( (basestr= jstr(json,"base")) != 0 && strcmp(basestr,CURRENCIES[basenum]) == 0 && (ratesobj= jobj(json,"rates")) != 0 && (item= ratesobj->child) != 0 )
{
while ( item != 0 )
{
if ( (relstr= get_cJSON_fieldname(item)) != 0 && (relnum= PAX_basenum(relstr)) >= 0 )
{
i = basenum*MAX_CURRENCIES + relnum;
prices[i] = item->valuedouble;
//if ( basenum == JPYNUM )
// prices[i] *= 100.;
// else if ( relnum == JPYNUM )
// prices[i] /= 100.;
count++;
//if ( Debuglevel > 2 )
printf("(%02d:%02d %f) ",basenum,relnum,prices[i]);
} else printf("cant find.(%s)\n",relstr);//, getchar();
item = item->next;
}
}
free_json(json);
}
free(jsonstr);
}
return(count);
}
int32_t PAX_ecbprices(char *date,double *prices,int32_t year,int32_t month,int32_t day)
{
// http://api.fixer.io/latest?base=CNH
// http://api.fixer.io/2000-01-03?base=USD
// "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD"
char baseurl[512],tmpdate[64],url[512],checkdate[16]; int32_t basenum,count,i,iter,nonz;
checkdate[0] = 0;
if ( year == 0 )
strcpy(baseurl,"http://api.fixer.io/latest?base=");
else
{
sprintf(checkdate,"%d-%02d-%02d",year,month,day);
sprintf(baseurl,"http://api.fixer.io/%s?base=",checkdate);
}
count = 0;
for (iter=0; iter<2; iter++)
{
for (basenum=0; basenum<sizeof(CURRENCIES)/sizeof(*CURRENCIES); basenum++)
{
if ( strcmp(CURRENCIES[basenum],"XAU") == 0 )
break;
if ( iter == 0 )
{
sprintf(url,"%s%s",baseurl,CURRENCIES[basenum]);
count += PAX_ecbparse(basenum == 0 ? date : tmpdate,prices,url,basenum);
if ( (basenum != 0 && strcmp(tmpdate,date) != 0) || (checkdate[0] != 0 && strcmp(checkdate,date) != 0) )
{
printf("date mismatch (%s) != (%s) or checkdate.(%s)\n",tmpdate,date,checkdate);
return(-1);
}
}
else
{
for (nonz=i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
{
if ( strcmp(CURRENCIES[i],"XAU") == 0 )
break;
if ( prices[MAX_CURRENCIES*basenum + i] != 0. )
nonz++;
//if ( Debuglevel > 2 )
printf("%8.5f ",prices[MAX_CURRENCIES*basenum + i]);
}
//if ( Debuglevel > 2 )
printf("%s.%d %d\n",CURRENCIES[basenum],basenum,nonz);
}
}
}
return(count);
}
int32_t ecb_matrix(double matrix[32][32],char *date)
{
FILE *fp=0; int32_t n=0,datenum,year=0,seconds,month=0,day=0,loaded = 0; char fname[64],_date[64];
if ( date == 0 )
date = _date, memset(_date,0,sizeof(_date));
sprintf(fname,"DB/ECB/%s",date), OS_compatible_path(fname);
if ( date[0] != 0 && (fp= fopen(fname,"rb")) != 0 )
{
if ( fread(matrix,1,sizeof(matrix[0][0])*32*32,fp) == sizeof(matrix[0][0])*32*32 )
loaded = 1;
else printf("fread error\n");
fclose(fp);
} else printf("ecb_matrix.(%s) load error fp.%p\n",fname,fp);
if ( loaded == 0 )
{
datenum = conv_date(&seconds,date);
year = datenum / 10000, month = (datenum / 100) % 100, day = (datenum % 100);
if ( (n= PAX_ecbprices(date,&matrix[0][0],year,month,day)) > 0 )
{
sprintf(fname,"DB/ECB/%s",date), OS_compatible_path(fname);
if ( (fp= fopen(fname,"wb")) != 0 )
{
if ( fwrite(matrix,1,sizeof(matrix[0][0])*32*32,fp) == sizeof(matrix[0][0])*32*32 )
loaded = 1;
fclose(fp);
}
} else printf("peggy_matrix error loading %d.%d.%d\n",year,month,day);
}
if ( loaded == 0 && n == 0 )
{
printf("peggy_matrix couldnt process loaded.%d n.%d\n",loaded,n);
return(-1);
}
//"2000-01-03"
if ( (datenum= conv_date(&seconds,date)) < 0 )
return(-1);
printf("loaded.(%s) nonz.%d (%d %d %d) datenum.%d\n",date,n,year,month,day,datenum);
return(datenum);
}
void PAX_update(struct peggy_info *PEGS,double *btcusdp,double *btcdbtcp)
{
int32_t i,n,seconds,datenum; uint32_t timestamp; char url[1024],*dstr,*str;
double btcddaily=0.,btcusd=0.,ask,high,low,bid,close,vol,quotevol,open,price = 0.;
//cJSON *btcdtrades,*btcdtrades2,*,*bitcoincharts,;
cJSON *quandl,*btcdhist,*array,*item,*bitcoinave,*blockchaininfo,*coindesk=0;
//btcdtrades = url_json("https://poloniex.com/public?command=returnTradeHistory&currencyPair=BTC_BTCD");
//btcdtrades2 = url_json("https://bittrex.com/api/v1.1/public/getmarkethistory?market=BTC-BTCD&count=50");
bitcoinave = url_json("https://api.bitcoinaverage.com/ticker/USD/");
//bitcoincharts = url_json("http://api.bitcoincharts.com/v1/weighted_prices.json");
blockchaininfo = url_json("https://blockchain.info/ticker");
coindesk = url_json("http://api.coindesk.com/v1/bpi/historical/close.json");
sprintf(url,"https://poloniex.com/public?command=returnChartData&currencyPair=BTC_BTCD&start=%ld&end=9999999999&period=86400",(long)(time(NULL)-2*3600*24));
quandl = url_json("https://www.quandl.com/api/v1/datasets/BAVERAGE/USD.json?rows=1");
if ( quandl != 0 && (str= jstr(quandl,"updated_at")) != 0 && (datenum= conv_date(&seconds,str)) > 0 && (array= jarray(&n,quandl,"data")) != 0 )
{
//printf("datenum.%d data.%d %d\n",datenum,n,cJSON_GetArraySize(array));
for (i=0; i<1; i++)
{
// ["Date","24h Average","Ask","Bid","Last","Total Volume"]
// ["2015-07-25",289.27,288.84,288.68,288.87,44978.61]
item = jitem(array,i);
if ( (dstr= jstr(jitem(item,0),0)) != 0 && (datenum= conv_date(&seconds,dstr)) > 0 )
{
btcusd = price = jdouble(jitem(item,1),0), ask = jdouble(jitem(item,2),0), bid = jdouble(jitem(item,3),0);
close = jdouble(jitem(item,4),0), vol = jdouble(jitem(item,5),0);
//fprintf(stderr,"%d.[%d %f %f %f %f %f].%d ",i,datenum,price,ask,bid,close,vol,n);
}
}
}
{
double avebid,aveask,bidvol,askvol; struct exchange_quote sortbuf[512];
struct supernet_info *myinfo = SuperNET_MYINFO(0); cJSON *argjson = cJSON_Parse("{}");
aveask = instantdex_aveprice(myinfo,sortbuf,(int32_t)(sizeof(sortbuf)/sizeof(*sortbuf)),&askvol,"BTCD","BTC",1,argjson);
avebid = instantdex_aveprice(myinfo,sortbuf,(int32_t)(sizeof(sortbuf)/sizeof(*sortbuf)),&bidvol,"BTCD","BTC",-1,argjson);
if ( avebid > SMALLVAL && aveask > SMALLVAL )
{
price = (avebid*bidvol + aveask*askvol) / (bidvol + askvol);
*btcdbtcp = price;
printf("set BTCD price %f\n",price);
PEGS->btcdbtc = price;
}
else
{
btcdhist = url_json(url);
//{"date":1406160000,"high":0.01,"low":0.00125,"open":0.01,"close":0.001375,"volume":1.50179994,"quoteVolume":903.58818412,"weightedAverage":0.00166204},
if ( btcdhist != 0 && (array= jarray(&n,btcdhist,0)) != 0 )
{
//printf("GOT.(%s)\n",cJSON_Print(array));
for (i=0; i<1; i++)
{
item = jitem(array,i);
timestamp = juint(item,"date"), high = jdouble(item,"high"), low = jdouble(item,"low"), open = jdouble(item,"open");
close = jdouble(item,"close"), vol = jdouble(item,"volume"), quotevol = jdouble(item,"quoteVolume"), price = jdouble(item,"weightedAverage");
//printf("[%u %f %f %f %f %f %f %f]",timestamp,high,low,open,close,vol,quotevol,price);
//printf("[%u %d %f]",timestamp,OS_conv_unixtime(&seconds,timestamp),price);
btcddaily = price;
if ( btcddaily != 0 )
PEGS->btcdbtc = *btcdbtcp = btcddaily;
}
//printf("poloniex.%d\n",n);
}
if ( btcdhist != 0 )
free_json(btcdhist);
}
}
if ( bitcoinave != 0 )
{
if ( (price= jdouble(bitcoinave,"24h_avg")) > SMALLVAL )
{
//printf("bitcoinave %f %f\n",btcusd,price);
dxblend(&btcusd,price,0.5);
}
free_json(bitcoinave);
}
if ( quandl != 0 )
free_json(quandl);
if ( coindesk != 0 )
free_json(coindesk);
if ( blockchaininfo != 0 )
{
if ( (item= jobj(blockchaininfo,"USD")) != 0 && item != 0 && (price= jdouble(item,"15m")) > SMALLVAL )
{
//printf("blockchaininfo %f %f\n",btcusd,price);
dxblend(&btcusd,price,0.5);
}
free_json(blockchaininfo);
}
if ( btcusd != 0 )
PEGS->btcusd = *btcusdp = btcusd;
}
double blend_price(double *volp,double wtA,cJSON *jsonA,double wtB,cJSON *jsonB)
{
//A.{"ticker":{"base":"BTS","target":"CNY","price":"0.02958291","volume":"3128008.39295500","change":"0.00019513","markets":[{"market":"BTC38","price":"0.02960000","volume":3051650.682955},{"market":"Bter","price":"0.02890000","volume":76357.71}]},"timestamp":1438490881,"success":true,"error":""}
// B.{"id":"bts\/cny","price":"0.02940000","price_before_24h":"0.02990000","volume_first":"3048457.6857147217","volume_second":"90629.45859575272","volume_btc":"52.74","best_market":"btc38","latest_trade":"2015-08-02 03:57:38","coin1":"BitShares","coin2":"CNY","markets":[{"market":"btc38","price":"0.02940000","volume":"3048457.6857147217","volume_btc":"52.738317962865"},{"market":"bter","price":"0.04350000","volume":"0","volume_btc":"0"}]}
double priceA,priceB,priceB24,price,volA,volB; cJSON *obj;
priceA = priceB = priceB24= price = volA = volB = 0.;
if ( jsonA != 0 && (obj= jobj(jsonA,"ticker")) != 0 )
{
priceA = jdouble(obj,"price");
volA = jdouble(obj,"volume");
}
if ( jsonB != 0 )
{
priceB = jdouble(jsonB,"price");
priceB24 = jdouble(jsonB,"price_before_24h");
volB = jdouble(jsonB,"volume_first");
}
//printf("priceA %f volA %f, priceB %f %f volB %f\n",priceA,volA,priceB,priceB24,volB);
if ( priceB > SMALLVAL && priceB24 > SMALLVAL )
priceB = (priceB * .1) + (priceB24 * .9);
else if ( priceB < SMALLVAL )
priceB = priceB24;
if ( priceA*volA < SMALLVAL )
price = priceB;
else if ( priceB*volB < SMALLVAL )
price = priceA;
else price = (wtA * priceA) + (wtB * priceB);
*volp = (volA + volB);
return(price);
}
void _crypto_update(struct peggy_info *PEGS,double cryptovols[2][8][2],struct PAX_data *dp,int32_t selector,int32_t peggyflag)
{
char *cryptonatorA = "https://www.cryptonator.com/api/full/%s-%s"; //unity-btc
char *cryptocoinchartsB = "http://api.cryptocoincharts.info/tradingPair/%s_%s"; //bts_btc
char *cryptostrs[9] = { "btc", "nxt", "unity", "eth", "ltc", "xmr", "bts", "xcp", "etc" };
int32_t iter,i,j; double btcusd,btcdbtc,cnyusd,prices[8][2],volumes[8][2];
char base[16],rel[16],url[512],*str; cJSON *jsonA,*jsonB;
if ( peggyflag != 0 )
{
cnyusd = PEGS->cnyusd;
btcusd = PEGS->btcusd;
btcdbtc = PEGS->btcdbtc;
//printf("update with btcusd %f btcd %f cnyusd %f cnybtc %f\n",btcusd,btcdbtc,cnyusd,cnyusd/btcusd);
if ( btcusd < SMALLVAL || btcdbtc < SMALLVAL )
{
PAX_update(PEGS,&btcusd,&btcdbtc);
printf("PAX_update with btcusd %f btcd %f\n",btcusd,btcdbtc);
}
memset(prices,0,sizeof(prices));
memset(volumes,0,sizeof(volumes));
for (j=0; j<sizeof(cryptostrs)/sizeof(*cryptostrs); j++)
{
str = cryptostrs[j];
if ( strcmp(str,"etc") == 0 )
{
if ( prices[3][0] > SMALLVAL )
break;
i = 3;
} else i = j;
for (iter=0; iter<1; iter++)
{
if ( i == 0 && iter == 0 )
strcpy(base,"btcd"), strcpy(rel,"btc");
else strcpy(base,str), strcpy(rel,iter==0?"btc":"cny");
//if ( selector == 0 )
{
sprintf(url,cryptonatorA,base,rel);
jsonA = url_json(url);
}
//else
{
sprintf(url,cryptocoinchartsB,base,rel);
jsonB = url_json(url);
}
prices[i][iter] = blend_price(&volumes[i][iter],0.4,jsonA,0.6,jsonB);
if ( iter == 1 )
{
if ( btcusd > SMALLVAL )
{
prices[i][iter] *= cnyusd / btcusd;
volumes[i][iter] *= cnyusd / btcusd;
} else prices[i][iter] = volumes[i][iter] = 0.;
}
cryptovols[0][i][iter] = _pairaved(cryptovols[0][i][iter],prices[i][iter]);
cryptovols[1][i][iter] = _pairaved(cryptovols[1][i][iter],volumes[i][iter]);
//if ( Debuglevel > 2 )
printf("(%f %f).%d:%d ",cryptovols[0][i][iter],cryptovols[1][i][iter],i,iter);
//if ( cnyusd < SMALLVAL || btcusd < SMALLVAL )
// break;
}
}
}
}
void PAX_RTupdate(struct peggy_info *PEGS,double cryptovols[2][8][2],double RTmetals[4],double *RTprices,struct PAX_data *dp)
{
char *cryptostrs[8] = { "btc", "nxt", "unity", "eth", "ltc", "xmr", "bts", "xcp" };
int32_t iter,i,c,baserel,basenum,relnum; double cnyusd,btcusd,btcdbtc,bid,ask,price,vol,prices[8][2],volumes[8][2];
char base[16],rel[16];
PAX_update(PEGS,&btcusd,&btcdbtc);
memset(prices,0,sizeof(prices));
memset(volumes,0,sizeof(volumes));
for (i=0; i<sizeof(cryptostrs)/sizeof(*cryptostrs); i++)
for (iter=0; iter<2; iter++)
prices[i][iter] = cryptovols[0][i][iter], volumes[i][iter] = cryptovols[1][i][iter];
if ( prices[0][0] > SMALLVAL )
dxblend(&btcdbtc,prices[0][0],.9);
dxblend(&dp->btcdbtc,btcdbtc,.995);
if ( PEGS->btcdbtc < SMALLVAL )
PEGS->btcdbtc = dp->btcdbtc;
if ( (cnyusd= PEGS->cnyusd) > SMALLVAL )
{
if ( prices[0][1] > SMALLVAL )
{
//printf("cnyusd %f, btccny %f -> btcusd %f %f\n",cnyusd,prices[0][1],prices[0][1]*cnyusd,btcusd);
btcusd = prices[0][1] * cnyusd;
if ( dp->btcusd < SMALLVAL )
dp->btcusd = btcusd;
else dxblend(&dp->btcusd,btcusd,.995);
if ( PEGS->btcusd < SMALLVAL )
PEGS->btcusd = dp->btcusd;
if ( PEGS->data.btcusd < SMALLVAL )
PEGS->data.btcusd = dp->btcusd;
printf("cnyusd %f, btccny %f -> btcusd %f %f -> %f %f %f\n",cnyusd,prices[0][1],prices[0][1]*cnyusd,btcusd,dp->btcusd,PEGS->btcusd,PEGS->data.btcusd);
}
}
for (i=1; i<sizeof(cryptostrs)/sizeof(*cryptostrs); i++)
{
if ( (vol= volumes[i][0]+volumes[i][1]) > SMALLVAL )
{
price = ((prices[i][0] * volumes[i][0]) + (prices[i][1] * volumes[i][1])) / vol;
//if ( Debuglevel > 2 )
printf("%s %f v%f + %f v%f -> %f %f\n",cryptostrs[i],prices[i][0],volumes[i][0],prices[i][1],volumes[i][1],price,dp->cryptos[i]);
dxblend(&dp->cryptos[i],price,.995);
}
}
btcusd = PEGS->btcusd;
btcdbtc = PEGS->btcdbtc;
//if ( Debuglevel > 2 )
printf(" update with btcusd %f btcd %f\n",btcusd,btcdbtc);
if ( btcusd < SMALLVAL || btcdbtc < SMALLVAL )
{
PAX_update(PEGS,&btcusd,&btcdbtc);
//if ( Debuglevel > 2 )
printf(" price777_update with btcusd %f btcd %f\n",btcusd,btcdbtc);
} else PEGS->btcusd = btcusd, PEGS->btcdbtc = btcdbtc;
for (c=0; c<sizeof(CONTRACTS)/sizeof(*CONTRACTS); c++)
{
for (iter=0; iter<3; iter++)
{
switch ( iter )
{
case 0: bid = dp->tbids[c], ask = dp->tasks[c]; break;
case 1: bid = dp->fbids[c], ask = dp->fasks[c]; break;
case 2: bid = dp->ibids[c], ask = dp->iasks[c]; break;
}
if ( (price= _pairaved(bid,ask)) > SMALLVAL )
{
//if ( Debuglevel > 2 )
printf("%.6f ",price);
dxblend(&RTprices[c],price,.995);
if ( 0 && (baserel= PAX_ispair(base,rel,CONTRACTS[c])) >= 0 )
{
basenum = (baserel >> 8) & 0xff, relnum = baserel & 0xff;
if ( basenum < 32 && relnum < 32 )
{
//printf("%s.%d %f <- %f\n",CONTRACTS[c],c,RTmatrix[basenum][relnum],RTprices[c]);
//dxblend(&RTmatrix[basenum][relnum],RTprices[c],.999);
}
}
if ( strcmp(CONTRACTS[c],"XAUUSD") == 0 )
dxblend(&RTmetals[0],price,.995);
}
}
}
for (i=0; i<sizeof(Yahoo_metals)/sizeof(*Yahoo_metals); i++)
if ( PEGS->data.metals[i] != 0 )
dxblend(&RTmetals[i],PEGS->data.metals[i],.995);
}
void PAX_bidask(struct exchange_info *exchange,uint32_t *timestamps,double *bids,double *asks,int32_t baseid,int32_t relid)
{
int32_t contractnum; struct exchange_quote bidasks[2];
contractnum = Baserel_contractnum[baseid][relid];
(*exchange->issue.price)(exchange,CURRENCIES[baseid],CURRENCIES[relid],bidasks,1,0.,0,0);
bids[contractnum] = bidasks[0].price;
asks[contractnum] = bidasks[1].price;
timestamps[contractnum] = bidasks[0].timestamp;
printf("%.6f ",_pairaved(bids[contractnum],asks[contractnum]));
}
struct exchange_info *PAX_bidasks(char *exchangestr,uint32_t *timestamps,double *bids,double *asks)
{
int32_t baseid,relid; struct exchange_info *exchange;
if ( (exchange= exchanges777_find(exchangestr)) != 0 )
{
for (baseid=0; baseid<8; baseid++)
{
for (relid=0; relid<8; relid++)
{
if ( Currency_contractdirs[baseid][relid] > 0 )
PAX_bidask(exchange,timestamps,bids,asks,baseid,relid);
}
}
} else printf("cant find (%s) exchange\n",exchangestr);
printf("%s\n",exchangestr);
return(exchange);
}
int32_t PAX_idle(struct peggy_info *PEGS,int32_t peggyflag,int32_t idlegap)
{
static double lastupdate,lastdayupdate; static int32_t didinit; static portable_mutex_t mutex;
struct exchange_info *exchange; struct exchange_quote bidasks[2]; double btcdbtc,btcusd;
int32_t i,datenum,contractnum; struct PAX_data *dp = &PEGS->tmp;
*dp = PEGS->data;
if ( didinit == 0 )
{
portable_mutex_init(&mutex);
//prices777_init(BUNDLE.jsonstr,peggyflag);
didinit = 1;
if ( peggyflag != 0 )
{
//int32_t opreturns_init(uint32_t blocknum,uint32_t blocktimestamp,char *path);
//opreturns_init(0,(uint32_t)time(NULL),"peggy");
}
}
if ( peggyflag != 0 && OS_milliseconds() > lastupdate + (1000*idlegap) )
{
lastupdate = OS_milliseconds();
if ( OS_milliseconds() > lastdayupdate + 60000*60 )
{
lastdayupdate = OS_milliseconds();
if ( (datenum= ecb_matrix(dp->ecbmatrix,dp->edate)) > 0 )
{
dp->ecbdatenum = datenum;
dp->ecbyear = dp->ecbdatenum / 10000, dp->ecbmonth = (dp->ecbdatenum / 100) % 100, dp->ecbday = (dp->ecbdatenum % 100);
expand_datenum(dp->edate,datenum);
memcpy(dp->RTmatrix,dp->ecbmatrix,sizeof(dp->RTmatrix));
}
}
for (i=0; i<sizeof(Yahoo_metals)/sizeof(*Yahoo_metals); i++)
dp->metals[i] = PAX_yahoo(Yahoo_metals[i]);
PAX_bidasks("truefx",dp->ttimestamps,dp->tbids,dp->tasks);
PAX_bidasks("fxcm",dp->ftimestamps,dp->fbids,dp->fasks);
if ( (exchange= PAX_bidasks("instaforex",dp->itimestamps,dp->ibids,dp->iasks)) != 0 )
{
if ( (contractnum= PAX_contractnum("XAU","USD")) >= 0 )
{
(*exchange->issue.price)(exchange,"XAU","USD",bidasks,1,0.,0,0);
dp->ibids[contractnum] = bidasks[0].price;
dp->iasks[contractnum] = bidasks[1].price;
dp->itimestamps[contractnum] = bidasks[0].timestamp;
}
}
PAX_update(PEGS,&btcusd,&btcdbtc);
if ( btcusd > SMALLVAL )
dxblend(&dp->btcusd,btcusd,0.99);
if ( btcdbtc > SMALLVAL )
dxblend(&dp->btcdbtc,btcdbtc,0.99);
if ( dp->btcusd == 0 )
dp->btcusd = dp->btcusd;
if ( dp->btcdbtc == 0 )
dp->btcdbtc = dp->btcdbtc;
if ( dp->ecbmatrix[USD][USD] > SMALLVAL && dp->ecbmatrix[CNY][CNY] > SMALLVAL )
PEGS->cnyusd = (dp->ecbmatrix[CNY][CNY] / dp->ecbmatrix[USD][USD]);
portable_mutex_lock(&mutex);
PEGS->data = *dp;
portable_mutex_unlock(&mutex);
//kv777_write(PEGS->kv,"data",5,&PEGS->data,sizeof(BUNDLE.data));
PAX_RTupdate(PEGS,PEGS->cryptovols,dp->RTmetals,dp->RTprices,dp);
//printf("update finished\n");
void peggy();
peggy();
didinit = 1;
}
return(0);
}

BIN
iguana/pnacl/Release/iguana.pexe

Binary file not shown.

27
includes/iguana_apideclares.h

@ -20,8 +20,11 @@ HASH_AND_INT(ramchain,getrawtransaction,txid,verbose);
HASH_ARG(ramchain,gettransaction,txid);
STRING_ARG(ramchain,decoderawtransaction,rawtx);
THREE_STRINGS(InstantDEX,encryptjson,passphrase,permanentfile,anything);
TWO_STRINGS(InstantDEX,decryptjson,passphrase,permanentfile);
FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase);
ZERO_ARGS(SuperNET,logout);
ZERO_ARGS(SuperNET,activehandle);
THREE_STRINGS(SuperNET,encryptjson,password,permanentfile,anything);
TWO_STRINGS(SuperNET,decryptjson,password,permanentfile);
THREE_STRINGS_AND_THREE_INTS(InstantDEX,orderbook,exchange,base,rel,depth,allfields,invert);
THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,buy,exchange,base,rel,price,volume,dotrade);
@ -41,11 +44,11 @@ STRING_ARG(InstantDEX,allpairs,exchange);
THREE_STRINGS_AND_DOUBLE(InstantDEX,request,reference,base,rel,volume);
TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,proposal,reference,message,basetxid,reltxid,duration,flags);
TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,accept,reference,message,basetxid,reltxid,duration,flags);
TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,confirm,reference,message,basetxid,reltxid,baseheight,relheight);
THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission);
STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission);
THREE_STRINGS(tradebot,unmonitor,exchange,base,rel);
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,price,volume,duration);
THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price,volume,duration);
@ -55,15 +58,21 @@ TWO_STRINGS(tradebot,pause,exchange,botid);
TWO_STRINGS(tradebot,stop,exchange,botid);
TWO_STRINGS(tradebot,resume,exchange,botid);
/*HASH_AND_ARRAY(pangea,userturn,tablehash,params);
HASH_AND_ARRAY(pangea,status,tableid,params);
HASH_AND_ARRAY(pangea,mode,tableid,params);
HASH_AND_ARRAY(pangea,buyin,tableid,params);
HASH_AND_ARRAY(pangea,history,tableid,params);*/
HASH_ARG(pangea,call,tablehash);
HASH_AND_INT(pangea,raise,tablehash,numchips);
HASH_AND_INT(pangea,bet,tablehash,numchips);
HASH_ARG(pangea,check,tablehash);
HASH_ARG(pangea,fold,tablehash);
HASH_ARG(pangea,allin,tablehash);
HASH_ARG(pangea,status,tablehash);
HASH_AND_STRING(pangea,mode,tablehash,params);
HASH_ARG(pangea,history,tablehash);
HASH_AND_INT(pangea,handhistory,tablehash,hand);
INT_AND_ARRAY(pangea,host,minplayers,params);
ZERO_ARGS(pangea,lobby);
HASH_AND_STRING(pangea,join,tablehash,handle);
HASH_AND_ARRAY(pangea,start,tablehash,params);
HASH_AND_INT(pangea,buyin,tablehash,numchips);
HASH_ARG(pangea,start,tablehash);
ZERO_ARGS(SuperNET,help);
STRING_ARG(SuperNET,utime2utc,utime);

4
includes/iguana_apidefs.h

@ -5,6 +5,7 @@
#define IGUANA_CFUNC_S(agent,name,str) char *agent ## _ ## name(IGUANA_ARGS,char *str)
#define IGUANA_CFUNC_I(agent,name,val) char *agent ## _ ## name(IGUANA_ARGS,int32_t val)
#define IGUANA_CFUNC_SA(agent,name,str,array) char *agent ## _ ## name(IGUANA_ARGS,char *str,cJSON *array)
#define IGUANA_CFUNC_SD(agent,name,str,val) char *agent ## _ ## name(IGUANA_ARGS,char *str,double val)
#define IGUANA_CFUNC_AA(agent,name,array,array2) char *agent ## _ ## name(IGUANA_ARGS,cJSON *array,cJSON *array2)
#define IGUANA_CFUNC_SAA(agent,name,str,array,array2) char *agent ## _ ## name(IGUANA_ARGS,char *str,cJSON *array,cJSON *array2)
@ -24,6 +25,7 @@
#define IGUANA_CFUNC_SSHII(agent,name,str,str2,hash,val,val2) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,bits256 hash,int32_t val,int32_t val2)
#define IGUANA_CFUNC_SSHHII(agent,name,str,str2,hash,hash2,val,val2) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,bits256 hash,bits256 hash2,int32_t val,int32_t val2)
#define IGUANA_CFUNC_SSS(agent,name,str,str2,str3) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3)
#define IGUANA_CFUNC_SSSS(agent,name,str,str2,str3,str4) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3,char *str4)
#define IGUANA_CFUNC_SSSD(agent,name,str,str2,str3,val) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3,double val)
#define IGUANA_CFUNC_SSSDDD(agent,name,str,str2,str3,val,val2,val3) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3,double val,double val2,double val3)
#define IGUANA_CFUNC_SSSIII(agent,name,str,str2,str3,val,val2,val3) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3,int32_t val,int32_t val2,int32_t val3)
@ -51,7 +53,9 @@
#define STRING_ARG IGUANA_CFUNC_S
#define TWO_STRINGS IGUANA_CFUNC_SS
#define THREE_STRINGS IGUANA_CFUNC_SSS
#define FOUR_STRINGS IGUANA_CFUNC_SSSS
#define STRING_AND_INT IGUANA_CFUNC_SI
#define STRING_AND_DOUBLE IGUANA_CFUNC_SD
#define STRING_AND_TWOINTS IGUANA_CFUNC_SII
#define HASH_AND_INT IGUANA_CFUNC_HI
#define HASH_AND_STRING IGUANA_CFUNC_HS

2
includes/iguana_apiundefs.h

@ -36,6 +36,8 @@
#undef THREE_STRINGS_AND_THREE_INTS
#undef THREE_STRINGS_AND_THREE_DOUBLES
#undef THREE_STRINGS_AND_DOUBLE
#undef STRING_AND_DOUBLE
#undef FOUR_STRINGS
#undef IGUANA_ARGS
#undef IGUANA_CALLARGS

90
prices/prices777.c

@ -1068,7 +1068,7 @@ cJSON *url_json2(char *url)
return(json);
}
void prices777_btcprices(int32_t enddatenum,int32_t numdates)
void PAX_btcprices(int32_t enddatenum,int32_t numdates)
{
int32_t i,n,year,month,day,seconds,datenum; char url[1024],date[64],*dstr,*str; uint32_t timestamp,utc32[MAX_SPLINES];
cJSON *coindesk,*quandl,*btcdhist,*bpi,*array,*item;
@ -1145,7 +1145,7 @@ void prices777_btcprices(int32_t enddatenum,int32_t numdates)
// https://poloniex.com/public?command=returnChartData&currencyPair=BTC_BTCD&start=1405699200&end=9999999999&period=86400
}
int32_t prices777_calcmatrix(double matrix[32][32])
int32_t PAX_calcmatrix(double matrix[32][32])
{
int32_t basenum,relnum,nonz,vnum,iter,numbase,numerrs = 0; double sum,vsum,price,price2,basevals[32],errsum=0;
memset(basevals,0,sizeof(basevals));
@ -1210,6 +1210,92 @@ int32_t prices777_calcmatrix(double matrix[32][32])
return(errsum);
}
int32_t prices777_ecbparse(char *date,double *prices,char *url,int32_t basenum)
{
char *jsonstr,*relstr,*basestr; int32_t count=0,i,relnum; cJSON *json,*ratesobj,*item; struct destbuf tmp;
if ( (jsonstr= issue_curl(url)) != 0 )
{
//if ( Debuglevel > 2 )
printf("(%s)\n",jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
copy_cJSON(&tmp,jobj(json,"date")), safecopy(date,tmp.buf,64);
if ( (basestr= jstr(json,"base")) != 0 && strcmp(basestr,CURRENCIES[basenum]) == 0 && (ratesobj= jobj(json,"rates")) != 0 && (item= ratesobj->child) != 0 )
{
while ( item != 0 )
{
if ( (relstr= get_cJSON_fieldname(item)) != 0 && (relnum= prices777_basenum(relstr)) >= 0 )
{
i = basenum*MAX_CURRENCIES + relnum;
prices[i] = item->valuedouble;
//if ( basenum == JPYNUM )
// prices[i] *= 100.;
// else if ( relnum == JPYNUM )
// prices[i] /= 100.;
count++;
//if ( Debuglevel > 2 )
printf("(%02d:%02d %f) ",basenum,relnum,prices[i]);
} else printf("cant find.(%s)\n",relstr);//, getchar();
item = item->next;
}
}
free_json(json);
}
free(jsonstr);
}
return(count);
}
int32_t prices777_ecb(char *date,double *prices,int32_t year,int32_t month,int32_t day)
{
// http://api.fixer.io/latest?base=CNH
// http://api.fixer.io/2000-01-03?base=USD
// "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD"
char baseurl[512],tmpdate[64],url[512],checkdate[16]; int32_t basenum,count,i,iter,nonz;
checkdate[0] = 0;
if ( year == 0 )
strcpy(baseurl,"http://api.fixer.io/latest?base=");
else
{
sprintf(checkdate,"%d-%02d-%02d",year,month,day);
sprintf(baseurl,"http://api.fixer.io/%s?base=",checkdate);
}
count = 0;
for (iter=0; iter<2; iter++)
{
for (basenum=0; basenum<sizeof(CURRENCIES)/sizeof(*CURRENCIES); basenum++)
{
if ( strcmp(CURRENCIES[basenum],"XAU") == 0 )
break;
if ( iter == 0 )
{
sprintf(url,"%s%s",baseurl,CURRENCIES[basenum]);
count += prices777_ecbparse(basenum == 0 ? date : tmpdate,prices,url,basenum);
if ( (basenum != 0 && strcmp(tmpdate,date) != 0) || (checkdate[0] != 0 && strcmp(checkdate,date) != 0) )
{
printf("date mismatch (%s) != (%s) or checkdate.(%s)\n",tmpdate,date,checkdate);
return(-1);
}
}
else
{
for (nonz=i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
{
if ( strcmp(CURRENCIES[i],"XAU") == 0 )
break;
if ( prices[MAX_CURRENCIES*basenum + i] != 0. )
nonz++;
//if ( Debuglevel > 2 )
printf("%8.5f ",prices[MAX_CURRENCIES*basenum + i]);
}
//if ( Debuglevel > 2 )
printf("%s.%d %d\n",CURRENCIES[basenum],basenum,nonz);
}
}
}
return(count);
}
int32_t ecb_matrix(double matrix[32][32],char *date)
{
FILE *fp=0; int32_t n=0,datenum,year=0,seconds,month=0,day=0,loaded = 0; char fname[64],_date[64];

Loading…
Cancel
Save