@@ -31,7 +31,7 @@ LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
|
||||
LIBBITCOIN_UNIVALUE=univalue/libbitcoin_univalue.a
|
||||
LIBBITCOINQT=qt/libbitcoinqt.a
|
||||
LIBSECP256K1=secp256k1/libsecp256k1.la
|
||||
LIBZCASH=libzcash.a
|
||||
LIBZCASH=libzcash.a -lcurl
|
||||
|
||||
$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
|
||||
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
|
||||
|
||||
1136
src/cJSON.c
Executable file
1136
src/cJSON.c
Executable file
File diff suppressed because it is too large
Load Diff
232
src/cJSON.h
Executable file
232
src/cJSON.h
Executable file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef cJSON__h
|
||||
#define cJSON__h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
#include <memory.h>
|
||||
|
||||
//#include "../crypto777/OS_portable.h"
|
||||
|
||||
#define MAX_JSON_FIELD 4096 // on the big side
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* cJSON Types: */
|
||||
#define cJSON_False 0
|
||||
#define cJSON_True 1
|
||||
#define cJSON_NULL 2
|
||||
#define cJSON_Number 3
|
||||
#define cJSON_String 4
|
||||
#define cJSON_Array 5
|
||||
#define cJSON_Object 6
|
||||
|
||||
#define is_cJSON_Null(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_NULL)
|
||||
#define is_cJSON_Array(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_Array)
|
||||
#define is_cJSON_String(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_String)
|
||||
#define is_cJSON_Number(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_Number)
|
||||
#define is_cJSON_Object(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_Object)
|
||||
#define is_cJSON_True(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_True)
|
||||
#define is_cJSON_False(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_False)
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
|
||||
/* The cJSON structure: */
|
||||
typedef struct cJSON {
|
||||
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||
|
||||
int32_t type; /* The type of the item, as above. */
|
||||
|
||||
char *valuestring; /* The item's string, if type==cJSON_String */
|
||||
int64_t valueint; /* The item's number, if type==cJSON_Number */
|
||||
double valuedouble; /* The item's number, if type==cJSON_Number */
|
||||
|
||||
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||
} cJSON;
|
||||
|
||||
typedef struct cJSON_Hooks {
|
||||
void *(*malloc_fn)(size_t sz);
|
||||
void (*free_fn)(void *ptr);
|
||||
} cJSON_Hooks;
|
||||
|
||||
/* Supply malloc, realloc and free functions to cJSON */
|
||||
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||
|
||||
|
||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
|
||||
extern cJSON *cJSON_Parse(const char *value);
|
||||
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
|
||||
extern char *cJSON_Print(cJSON *item);
|
||||
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
|
||||
extern char *cJSON_PrintUnformatted(cJSON *item);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
extern void cJSON_Delete(cJSON *c);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
extern int cJSON_GetArraySize(cJSON *array);
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
extern cJSON *cJSON_GetArrayItem(cJSON *array,int32_t item);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
|
||||
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||
extern const char *cJSON_GetErrorPtr(void);
|
||||
|
||||
/* These calls create a cJSON item of the appropriate type. */
|
||||
extern cJSON *cJSON_CreateNull(void);
|
||||
extern cJSON *cJSON_CreateTrue(void);
|
||||
extern cJSON *cJSON_CreateFalse(void);
|
||||
extern cJSON *cJSON_CreateBool(int32_t b);
|
||||
extern cJSON *cJSON_CreateNumber(double num);
|
||||
extern cJSON *cJSON_CreateString(const char *string);
|
||||
extern cJSON *cJSON_CreateArray(void);
|
||||
extern cJSON *cJSON_CreateObject(void);
|
||||
|
||||
/* These utilities create an Array of count items. */
|
||||
extern cJSON *cJSON_CreateIntArray(int64_t *numbers,int32_t count);
|
||||
extern cJSON *cJSON_CreateFloatArray(float *numbers,int32_t count);
|
||||
extern cJSON *cJSON_CreateDoubleArray(double *numbers,int32_t count);
|
||||
extern cJSON *cJSON_CreateStringArray(char **strings,int32_t count);
|
||||
|
||||
/* Append item to the specified array/object. */
|
||||
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
|
||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
|
||||
|
||||
/* Remove/Detatch items from Arrays/Objects. */
|
||||
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int32_t which);
|
||||
extern void cJSON_DeleteItemFromArray(cJSON *array,int32_t which);
|
||||
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
|
||||
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
extern void cJSON_ReplaceItemInArray(cJSON *array,int32_t which,cJSON *newitem);
|
||||
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
extern cJSON *cJSON_Duplicate(cJSON *item,int32_t recurse);
|
||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||
|
||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int32_t require_null_terminated);
|
||||
|
||||
extern void cJSON_Minify(char *json);
|
||||
|
||||
/* Macros for creating things quickly. */
|
||||
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
|
||||
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
|
||||
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
|
||||
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
|
||||
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
|
||||
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
|
||||
|
||||
struct destbuf { char buf[MAX_JSON_FIELD]; };
|
||||
|
||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
|
||||
#define jfieldstr get_cJSON_fieldname
|
||||
|
||||
char *cJSON_str(cJSON *json);
|
||||
char *jstr(cJSON *json,char *field);
|
||||
char *jprint(cJSON *json,int32_t freeflag);
|
||||
int32_t jint(cJSON *json,char *field);
|
||||
uint32_t juint(cJSON *json,char *field);
|
||||
char *jstri(cJSON *json,int32_t i);
|
||||
int32_t jinti(cJSON *json,int32_t i);
|
||||
uint32_t juinti(cJSON *json,int32_t i);
|
||||
uint64_t j64bitsi(cJSON *json,int32_t i);
|
||||
double jdoublei(cJSON *json,int32_t i);
|
||||
double jdouble(cJSON *json,char *field);
|
||||
cJSON *jobj(cJSON *json,char *field);
|
||||
cJSON *jarray(int32_t *nump,cJSON *json,char *field);
|
||||
cJSON *jitem(cJSON *array,int32_t i);
|
||||
uint64_t j64bits(cJSON *json,char *field);
|
||||
void jadd(cJSON *json,char *field,cJSON *item);
|
||||
void jaddstr(cJSON *json,char *field,char *str);
|
||||
void jaddnum(cJSON *json,char *field,double num);
|
||||
void jadd64bits(cJSON *json,char *field,uint64_t nxt64bits);
|
||||
void jaddi(cJSON *json,cJSON *item);
|
||||
void jaddistr(cJSON *json,char *str);
|
||||
void jaddinum(cJSON *json,double num);
|
||||
void jaddi64bits(cJSON *json,uint64_t nxt64bits);
|
||||
void jdelete(cJSON *object,char *string);
|
||||
cJSON *jduplicate(cJSON *json);
|
||||
int32_t jnum(cJSON *obj,char *field);
|
||||
|
||||
bits256 jbits256(cJSON *json,char *field);
|
||||
bits256 jbits256i(cJSON *json,int32_t i);
|
||||
void jaddbits256(cJSON *json,char *field,bits256 hash);
|
||||
void jaddibits256(cJSON *json,bits256 hash);
|
||||
void copy_cJSON(struct destbuf *dest,cJSON *obj);
|
||||
void copy_cJSON2(char *dest,int32_t maxlen,cJSON *obj);
|
||||
cJSON *gen_list_json(char **list);
|
||||
int32_t extract_cJSON_str(char *dest,int32_t max,cJSON *json,char *field);
|
||||
|
||||
void free_json(cJSON *json);
|
||||
int64_t _conv_cJSON_float(cJSON *json);
|
||||
int64_t conv_cJSON_float(cJSON *json,char *field);
|
||||
int64_t get_cJSON_int(cJSON *json,char *field);
|
||||
void add_satoshis_json(cJSON *json,char *field,uint64_t satoshis);
|
||||
uint64_t get_satoshi_obj(cJSON *json,char *field);
|
||||
|
||||
int32_t get_API_int(cJSON *obj,int32_t val);
|
||||
uint32_t get_API_uint(cJSON *obj,uint32_t val);
|
||||
uint64_t get_API_nxt64bits(cJSON *obj);
|
||||
double get_API_float(cJSON *obj);
|
||||
char *get_cJSON_fieldname(cJSON *obj);
|
||||
void ensure_jsonitem(cJSON *json,char *field,char *value);
|
||||
int32_t in_jsonarray(cJSON *array,char *value);
|
||||
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params);
|
||||
uint64_t calc_nxt64bits(const char *str);
|
||||
int32_t expand_nxt64bits(char *str,uint64_t nxt64bits);
|
||||
char *nxt64str(uint64_t nxt64bits);
|
||||
char *nxt64str2(uint64_t nxt64bits);
|
||||
cJSON *addrs_jsonarray(uint64_t *addrs,int32_t num);
|
||||
int32_t myatoi(char *str,int32_t range);
|
||||
|
||||
char *stringifyM(char *str);
|
||||
#define replace_backslashquotes unstringify
|
||||
char *unstringify(char *str);
|
||||
#define jtrue cJSON_CreateTrue
|
||||
#define jfalse cJSON_CreateFalse
|
||||
|
||||
#define jfieldname get_cJSON_fieldname
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
193
src/komodo.h
193
src/komodo.h
@@ -22,26 +22,33 @@
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <ctype.h>
|
||||
#include "komodo_utils.h"
|
||||
|
||||
int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals);
|
||||
void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout);
|
||||
void komodo_init();
|
||||
int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp);
|
||||
char *komodo_issuemethod(char *method,char *params,uint16_t port);
|
||||
|
||||
int32_t NOTARIZED_HEIGHT,Num_nutxos;
|
||||
int32_t ASSETCHAINS_SHORTFLAG,NOTARIZED_HEIGHT,Num_nutxos,KMDHEIGHT = 43000;
|
||||
uint256 NOTARIZED_HASH,NOTARIZED_DESTTXID;
|
||||
pthread_mutex_t komodo_mutex;
|
||||
uint32_t KOMODO_INITDONE;
|
||||
char KMDUSERPASS[1024]; uint16_t BITCOIND_PORT = 7771;
|
||||
uint64_t KOMODO_DEPOSIT,PENDING_KOMODO_TX;
|
||||
|
||||
#include "komodo_utils.h"
|
||||
queue_t DepositsQ,PendingsQ;
|
||||
|
||||
#include "cJSON.c"
|
||||
#include "komodo_bitcoind.h"
|
||||
#include "komodo_interest.h"
|
||||
#ifdef KOMODO_PAX
|
||||
#include "komodo_pax.h"
|
||||
#endif
|
||||
#include "komodo_notary.h"
|
||||
#include "komodo_gateway.h"
|
||||
|
||||
int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals)
|
||||
|
||||
void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout)
|
||||
{
|
||||
static FILE *fp; static int32_t errs,didinit; char fname[512]; int32_t ht,k,i,func; uint8_t num,pubkeys[64][33];
|
||||
static FILE *fp; static int32_t errs; char fname[512]; int32_t ht,func; uint8_t num,pubkeys[64][33];
|
||||
#ifdef WIN32
|
||||
sprintf(fname,"%s\\%s",GetDataDir(false).string().c_str(),(char *)"komodostate");
|
||||
#else
|
||||
@@ -55,7 +62,7 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
|
||||
{
|
||||
if ( fread(&ht,1,sizeof(ht),fp) != sizeof(ht) )
|
||||
errs++;
|
||||
//printf("func.(%d %c) ht.%d\n",func,func,ht);
|
||||
//printf("fpos.%ld func.(%d %c) ht.%d ",ftell(fp),func,func,ht);
|
||||
if ( func == 'P' )
|
||||
{
|
||||
if ( (num= fgetc(fp)) < 64 )
|
||||
@@ -93,11 +100,40 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
|
||||
errs++;
|
||||
komodo_nutxoadd(ht,nid,hash,mask,n);
|
||||
}
|
||||
else if ( func == 'K' )
|
||||
{
|
||||
int32_t kheight;
|
||||
if ( fread(&kheight,1,sizeof(kheight),fp) != sizeof(kheight) )
|
||||
errs++;
|
||||
if ( kheight > KMDHEIGHT )
|
||||
{
|
||||
KMDHEIGHT = kheight;
|
||||
}
|
||||
//printf("ht.%d KMDHEIGHT <- %d\n",ht,kheight);
|
||||
}
|
||||
else if ( func == 'R' )
|
||||
{
|
||||
uint16_t olen,v; uint64_t ovalue; uint256 txid; uint8_t opret[10000];
|
||||
if ( fread(&txid,1,sizeof(txid),fp) != sizeof(txid) )
|
||||
errs++;
|
||||
if ( fread(&v,1,sizeof(v),fp) != sizeof(v) )
|
||||
errs++;
|
||||
if ( fread(&ovalue,1,sizeof(ovalue),fp) != sizeof(ovalue) )
|
||||
errs++;
|
||||
if ( fread(&olen,1,sizeof(olen),fp) != sizeof(olen) )
|
||||
errs++;
|
||||
if ( olen < sizeof(opret) )
|
||||
{
|
||||
if ( fread(opret,1,olen,fp) != olen )
|
||||
errs++;
|
||||
komodo_opreturn(ht,ovalue,opret,olen,txid,v);
|
||||
} else printf("illegal olen.%u\n",olen);
|
||||
}
|
||||
else if ( func == 'D' )
|
||||
{
|
||||
//printf("D[%d]\n",ht);
|
||||
}
|
||||
#ifdef KOMODO_PAX
|
||||
//#ifdef KOMODO_PAX
|
||||
else if ( func == 'V' )
|
||||
{
|
||||
int32_t numpvals; uint32_t pvals[128];
|
||||
@@ -108,14 +144,21 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
|
||||
//printf("load pvals ht.%d numpvals.%d\n",ht,numpvals);
|
||||
} else printf("error loading pvals[%d]\n",numpvals);
|
||||
}
|
||||
#endif
|
||||
//#endif
|
||||
else printf("illegal func.(%d %c)\n",func,func);
|
||||
}
|
||||
} else fp = fopen(fname,"wb+");
|
||||
printf("fname.(%s) fpos.%ld\n",fname,ftell(fp));
|
||||
KOMODO_INITDONE = (uint32_t)time(NULL);
|
||||
}
|
||||
if ( height <= 0 )
|
||||
{
|
||||
printf("early return: stateupdate height.%d\n",height);
|
||||
return;
|
||||
}
|
||||
if ( fp != 0 ) // write out funcid, height, other fields, call side effect function
|
||||
{
|
||||
//printf("fpos.%ld ",ftell(fp));
|
||||
if ( height < 0 )
|
||||
{
|
||||
height = -height;
|
||||
@@ -124,9 +167,37 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
|
||||
if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) )
|
||||
errs++;
|
||||
}
|
||||
else if ( KMDheight > 0 )
|
||||
{
|
||||
fputc('K',fp);
|
||||
if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) )
|
||||
errs++;
|
||||
if ( fwrite(&KMDheight,1,sizeof(KMDheight),fp) != sizeof(KMDheight) )
|
||||
errs++;
|
||||
//printf("ht.%d K %d\n",height,KMDheight);
|
||||
}
|
||||
else if ( opretbuf != 0 && opretlen > 0 )
|
||||
{
|
||||
uint16_t olen = opretlen;
|
||||
fputc('R',fp);
|
||||
if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) )
|
||||
errs++;
|
||||
if ( fwrite(&txhash,1,sizeof(txhash),fp) != sizeof(txhash) )
|
||||
errs++;
|
||||
if ( fwrite(&vout,1,sizeof(vout),fp) != sizeof(vout) )
|
||||
errs++;
|
||||
if ( fwrite(&opretvalue,1,sizeof(opretvalue),fp) != sizeof(opretvalue) )
|
||||
errs++;
|
||||
if ( fwrite(&olen,1,sizeof(olen),fp) != olen )
|
||||
errs++;
|
||||
if ( fwrite(opretbuf,1,olen,fp) != olen )
|
||||
errs++;
|
||||
//printf("ht.%d R opret[%d]\n",height,olen);
|
||||
komodo_opreturn(height,opretvalue,opretbuf,olen,txhash,vout);
|
||||
}
|
||||
else if ( notarypubs != 0 && numnotaries > 0 )
|
||||
{
|
||||
//printf("func P[%d] errs.%d\n",numnotaries,errs);
|
||||
//printf("ht.%d func P[%d] errs.%d\n",height,numnotaries,errs);
|
||||
fputc('P',fp);
|
||||
if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) )
|
||||
errs++;
|
||||
@@ -137,7 +208,7 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
|
||||
}
|
||||
else if ( voutmask != 0 && numvouts > 0 )
|
||||
{
|
||||
//printf("func U %d %d errs.%d hashsize.%ld\n",numvouts,notaryid,errs,sizeof(txhash));
|
||||
//printf("ht.%d func U %d %d errs.%d hashsize.%ld\n",height,numvouts,notaryid,errs,sizeof(txhash));
|
||||
fputc('U',fp);
|
||||
if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) )
|
||||
errs++;
|
||||
@@ -149,22 +220,30 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
|
||||
errs++;
|
||||
komodo_nutxoadd(height,notaryid,txhash,voutmask,numvouts);
|
||||
}
|
||||
#ifdef KOMODO_PAX
|
||||
//#ifdef KOMODO_PAX
|
||||
else if ( pvals != 0 && numpvals > 0 )
|
||||
{
|
||||
fputc('V',fp);
|
||||
if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) )
|
||||
errs++;
|
||||
fputc(numpvals,fp);
|
||||
if ( fwrite(pvals,sizeof(uint32_t),numpvals,fp) != numpvals )
|
||||
errs++;
|
||||
komodo_pvals(height,pvals,numpvals);
|
||||
int32_t i,nonz = 0;
|
||||
for (i=0; i<32; i++)
|
||||
if ( pvals[i] != 0 )
|
||||
nonz++;
|
||||
if ( nonz >= 32 )
|
||||
{
|
||||
fputc('V',fp);
|
||||
if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) )
|
||||
errs++;
|
||||
fputc(numpvals,fp);
|
||||
if ( fwrite(pvals,sizeof(uint32_t),numpvals,fp) != numpvals )
|
||||
errs++;
|
||||
komodo_pvals(height,pvals,numpvals);
|
||||
//printf("ht.%d V numpvals[%d]\n",height,numpvals);
|
||||
}
|
||||
//printf("save pvals height.%d numpvals.%d\n",height,numpvals);
|
||||
}
|
||||
#endif
|
||||
//#endif
|
||||
else if ( height != 0 )
|
||||
{
|
||||
//printf("func N ht.%d errs.%d\n",NOTARIZED_HEIGHT,errs);
|
||||
//printf("ht.%d func N ht.%d errs.%d\n",height,NOTARIZED_HEIGHT,errs);
|
||||
fputc('N',fp);
|
||||
if ( fwrite(&height,1,sizeof(height),fp) != sizeof(height) )
|
||||
errs++;
|
||||
@@ -180,9 +259,9 @@ int32_t komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numno
|
||||
}
|
||||
}
|
||||
|
||||
int32_t komodo_voutupdate(int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp)
|
||||
int32_t komodo_voutupdate(int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value)
|
||||
{
|
||||
static uint256 zero; int32_t k,opretlen,nid,len = 0; uint256 kmdtxid,desttxid; uint8_t crypto777[33];
|
||||
static uint256 zero; int32_t opretlen,nid,len = 0; uint256 kmdtxid,desttxid; uint8_t crypto777[33];
|
||||
if ( scriptlen == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac )
|
||||
{
|
||||
decode_hex(crypto777,33,(char *)CRYPTO777_PUBSECPSTR);
|
||||
@@ -217,7 +296,7 @@ int32_t komodo_voutupdate(int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( j == 1 && scriptbuf[len++] == 0x6a )
|
||||
if ( scriptbuf[len++] == 0x6a )
|
||||
{
|
||||
if ( (opretlen= scriptbuf[len++]) == 0x4c )
|
||||
opretlen = scriptbuf[len++];
|
||||
@@ -226,43 +305,55 @@ int32_t komodo_voutupdate(int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,
|
||||
opretlen = scriptbuf[len++];
|
||||
opretlen = (opretlen << 8) + scriptbuf[len++];
|
||||
}
|
||||
if ( opretlen >= 32*2+4 && strcmp(KOMODO_SOURCE,(char *)&scriptbuf[len+32*2+4]) == 0 )
|
||||
//for (k=0; k<scriptlen; k++)
|
||||
// printf("%02x",scriptbuf[k]);
|
||||
//printf(" <- script ht.%d i.%d j.%d value %.8f\n",height,i,j,dstr(value));
|
||||
if ( j == 1 && opretlen >= 32*2+4 && strcmp(KOMODO_SOURCE,(char *)&scriptbuf[len+32*2+4]) == 0 )
|
||||
{
|
||||
len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&kmdtxid);
|
||||
len += iguana_rwnum(0,&scriptbuf[len],4,(uint8_t *)notarizedheightp);
|
||||
len += iguana_rwbignum(0,&scriptbuf[len],32,(uint8_t *)&desttxid);
|
||||
//for (k=0; k<scriptlen; k++)
|
||||
// printf("%02x",scriptbuf[k]);
|
||||
//printf(" <- script ht.%d i.%d j.%d\n",height,i,j);
|
||||
if ( *notarizedheightp > NOTARIZED_HEIGHT && *notarizedheightp < height )
|
||||
{
|
||||
printf("ht.%d NOTARIZED.%d KMD.%s BTCTXID.%s (%s)\n",height,*notarizedheightp,kmdtxid.ToString().c_str(),desttxid.ToString().c_str(),(char *)&scriptbuf[len]);
|
||||
NOTARIZED_HEIGHT = *notarizedheightp;
|
||||
NOTARIZED_HASH = kmdtxid;
|
||||
NOTARIZED_DESTTXID = desttxid;
|
||||
komodo_stateupdate(height,0,0,0,zero,0,0,0,0);
|
||||
komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0);
|
||||
} else printf("reject ht.%d NOTARIZED.%d %s.%s DESTTXID.%s (%s)\n",height,*notarizedheightp,KOMODO_SOURCE,kmdtxid.ToString().c_str(),desttxid.ToString().c_str(),(char *)&scriptbuf[len]);
|
||||
}
|
||||
#ifdef KOMODO_PAX
|
||||
else if ( i == 0 && scriptbuf[len] == 'P' )
|
||||
{
|
||||
double KMDBTC,BTCUSD,CNYUSD; uint32_t numpvals,timestamp,pvals[128];
|
||||
numpvals = dpow_readprices(&scriptbuf[++len],×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals);
|
||||
komodo_stateupdate(height,0,0,0,zero,0,0,pvals,numpvals);
|
||||
//printf("vout OP_RETURN.%d prices numpvals.%d opretlen.%d\n",height,numpvals,opretlen);
|
||||
}
|
||||
#endif
|
||||
else if ( i == 0 && j == 1 && opretlen == 149 )
|
||||
komodo_paxpricefeed(height,&scriptbuf[len],opretlen);
|
||||
else komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,value,&scriptbuf[len],opretlen,j);
|
||||
}
|
||||
return(notaryid);
|
||||
}
|
||||
|
||||
int32_t komodo_isratify(int32_t isspecial,int32_t numvalid)
|
||||
{
|
||||
if ( isspecial != 0 && numvalid > 13 )
|
||||
return(1);
|
||||
else return(0);
|
||||
}
|
||||
|
||||
// Special tx have vout[0] -> CRYPTO777
|
||||
// with more than 13 pay2pubkey outputs -> ratify
|
||||
// if all outputs to notary -> notary utxo
|
||||
// if txi == 0 && 2 outputs and 2nd OP_RETURN, len == 32*2+4 -> notarized, 1st byte 'P' -> pricefeed
|
||||
// OP_RETURN: 'D' -> deposit, 'W' -> withdraw
|
||||
|
||||
void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
|
||||
{
|
||||
static int32_t didinit;
|
||||
char *scriptstr,*opreturnstr; uint64_t signedmask,voutmask;
|
||||
uint64_t signedmask,voutmask;
|
||||
uint8_t scriptbuf[4096],pubkeys[64][33]; uint256 kmdtxid,btctxid,txhash;
|
||||
int32_t i,j,k,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count,flag;
|
||||
int32_t i,j,k,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count;
|
||||
komodo_init();
|
||||
KOMODO_INITDONE = (uint32_t)time(NULL);
|
||||
#ifdef KOMODO_ISSUER
|
||||
komodo_gateway_issuer();
|
||||
#else
|
||||
komodo_gateway_redeemer();
|
||||
#endif
|
||||
if ( pindex != 0 )
|
||||
{
|
||||
height = pindex->nHeight;
|
||||
@@ -278,8 +369,13 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
|
||||
len = block.vtx[i].vout[j].scriptPubKey.size();
|
||||
if ( len <= sizeof(scriptbuf) )
|
||||
{
|
||||
#ifdef KOMODO_ZCASH
|
||||
memcpy(scriptbuf,block.vtx[i].vout[j].scriptPubKey.data(),len);
|
||||
notaryid = komodo_voutupdate(notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight);
|
||||
#else
|
||||
memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len);
|
||||
#endif
|
||||
// signedmask is needed here!
|
||||
notaryid = komodo_voutupdate(notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,¬arizedheight,(uint64_t)block.vtx[i].vout[j].nValue);
|
||||
if ( 0 && i > 0 )
|
||||
{
|
||||
for (k=0; k<len; k++)
|
||||
@@ -290,7 +386,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
|
||||
}
|
||||
if ( i != 0 && notaryid >= 0 && notaryid < 64 && voutmask != 0 )
|
||||
{
|
||||
komodo_stateupdate(height,0,0,notaryid,txhash,voutmask,numvouts,0,0);
|
||||
komodo_stateupdate(height,0,0,notaryid,txhash,voutmask,numvouts,0,0,0,0,0,0,0);
|
||||
//komodo_nutxoadd(height,notaryid,txhash,voutmask,numvouts);
|
||||
}
|
||||
signedmask = 0;
|
||||
@@ -314,7 +410,11 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
|
||||
len = block.vtx[i].vout[j].scriptPubKey.size();
|
||||
if ( len <= sizeof(scriptbuf) )
|
||||
{
|
||||
#ifdef KOMODO_ZCASH
|
||||
memcpy(scriptbuf,block.vtx[i].vout[j].scriptPubKey.data(),len);
|
||||
#else
|
||||
memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len);
|
||||
#endif
|
||||
if ( len == 35 && scriptbuf[0] == 33 && scriptbuf[34] == 0xac )
|
||||
{
|
||||
memcpy(pubkeys[numvalid++],scriptbuf+1,33);
|
||||
@@ -324,16 +424,17 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( numvalid > 13 )
|
||||
if ( komodo_isratify(1,numvalid) > 13 )
|
||||
{
|
||||
memset(&txhash,0,sizeof(txhash));
|
||||
komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0);
|
||||
komodo_stateupdate(height,pubkeys,numvalid,0,txhash,0,0,0,0,0,0,0,0,0);
|
||||
}
|
||||
printf("new notaries.%d newheight.%d from height.%d\n",numvouts-1,KOMODO_PUBKEYS_HEIGHT(height),height);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else printf("komodo_connectblock: unexpected null pindex\n");
|
||||
KOMODO_INITDONE = (uint32_t)time(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,11 +15,345 @@
|
||||
|
||||
// komodo functions that interact with bitcoind C++
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <curl.h>
|
||||
#include <easy.h>
|
||||
#else
|
||||
#include <curl/curl.h>
|
||||
#include <curl/easy.h>
|
||||
#endif
|
||||
|
||||
struct MemoryStruct { char *memory; size_t size; };
|
||||
struct return_string { char *ptr; size_t len; };
|
||||
|
||||
// return data from the server
|
||||
#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
|
||||
#define CURL_GLOBAL_SSL (1<<0)
|
||||
#define CURL_GLOBAL_WIN32 (1<<1)
|
||||
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* Initialize the string handler so that it is thread safe
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
void init_string(struct return_string *s)
|
||||
{
|
||||
s->len = 0;
|
||||
s->ptr = (char *)calloc(1,s->len+1);
|
||||
if ( s->ptr == NULL )
|
||||
{
|
||||
fprintf(stderr,"init_string malloc() failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
s->ptr[0] = '\0';
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* Use the "writer" to accumulate text until done
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s)
|
||||
{
|
||||
size_t new_len = s->len + size*nmemb;
|
||||
s->ptr = (char *)realloc(s->ptr,new_len+1);
|
||||
if ( s->ptr == NULL )
|
||||
{
|
||||
fprintf(stderr, "accumulate realloc() failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
memcpy(s->ptr+s->len,ptr,size*nmemb);
|
||||
s->ptr[new_len] = '\0';
|
||||
s->len = new_len;
|
||||
return(size * nmemb);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* return the current system time in milliseconds
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field
|
||||
#ifdef EXTRACT_BITCOIND_RESULT
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* perform post processing of the results
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params)
|
||||
{
|
||||
long i,j,len; char *retstr = 0; cJSON *json,*result,*error;
|
||||
//printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
|
||||
if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
|
||||
{
|
||||
if ( strcmp(command,"signrawtransaction") != 0 )
|
||||
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
|
||||
return(rpcstr);
|
||||
}
|
||||
json = cJSON_Parse(rpcstr);
|
||||
if ( json == 0 )
|
||||
{
|
||||
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params);
|
||||
free(rpcstr);
|
||||
return(0);
|
||||
}
|
||||
result = cJSON_GetObjectItem(json,"result");
|
||||
error = cJSON_GetObjectItem(json,"error");
|
||||
if ( error != 0 && result != 0 )
|
||||
{
|
||||
if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL )
|
||||
{
|
||||
retstr = cJSON_Print(result);
|
||||
len = strlen(retstr);
|
||||
if ( retstr[0] == '"' && retstr[len-1] == '"' )
|
||||
{
|
||||
for (i=1,j=0; i<len-1; i++,j++)
|
||||
retstr[j] = retstr[i];
|
||||
retstr[j] = 0;
|
||||
}
|
||||
}
|
||||
else if ( (error->type&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL )
|
||||
{
|
||||
if ( strcmp(command,"signrawtransaction") != 0 )
|
||||
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr);
|
||||
}
|
||||
free(rpcstr);
|
||||
} else retstr = rpcstr;
|
||||
free_json(json);
|
||||
//fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr);
|
||||
return(retstr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* perform the query
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
|
||||
char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params)
|
||||
{
|
||||
static int didinit,count,count2; static double elapsedsum,elapsedsum2;
|
||||
struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle;
|
||||
char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime;
|
||||
if ( didinit == 0 )
|
||||
{
|
||||
didinit = 1;
|
||||
curl_global_init(CURL_GLOBAL_ALL); //init the curl session
|
||||
}
|
||||
numretries = 0;
|
||||
if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 )
|
||||
specialcase = 1;
|
||||
else specialcase = 0;
|
||||
if ( url[0] == 0 )
|
||||
strcpy(url,"http://127.0.0.1:7876/nxt");
|
||||
if ( specialcase != 0 && 0 )
|
||||
printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params);
|
||||
try_again:
|
||||
if ( retstrp != 0 )
|
||||
*retstrp = 0;
|
||||
starttime = OS_milliseconds();
|
||||
curl_handle = curl_easy_init();
|
||||
init_string(&s);
|
||||
headers = curl_slist_append(0,"Expect:");
|
||||
|
||||
curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
|
||||
curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(curl_handle,CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function
|
||||
curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback
|
||||
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
|
||||
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
|
||||
if ( strncmp(url,"https",5) == 0 )
|
||||
{
|
||||
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);
|
||||
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0);
|
||||
}
|
||||
if ( userpass != 0 )
|
||||
curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass);
|
||||
databuf = 0;
|
||||
if ( params != 0 )
|
||||
{
|
||||
if ( command != 0 && specialcase == 0 )
|
||||
{
|
||||
len = strlen(params);
|
||||
if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) {
|
||||
bracket0 = bracket1 = (char *)"";
|
||||
}
|
||||
else
|
||||
{
|
||||
bracket0 = (char *)"[";
|
||||
bracket1 = (char *)"]";
|
||||
}
|
||||
|
||||
databuf = (char *)malloc(256 + strlen(command) + strlen(params));
|
||||
sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1);
|
||||
//printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
|
||||
//
|
||||
} //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params);
|
||||
curl_easy_setopt(curl_handle,CURLOPT_POST,1L);
|
||||
if ( databuf != 0 )
|
||||
curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf);
|
||||
else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params);
|
||||
}
|
||||
//laststart = milliseconds();
|
||||
res = curl_easy_perform(curl_handle);
|
||||
curl_slist_free_all(headers);
|
||||
curl_easy_cleanup(curl_handle);
|
||||
if ( databuf != 0 ) // clean up temporary buffer
|
||||
{
|
||||
free(databuf);
|
||||
databuf = 0;
|
||||
}
|
||||
if ( res != CURLE_OK )
|
||||
{
|
||||
numretries++;
|
||||
if ( specialcase != 0 )
|
||||
{
|
||||
printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res);
|
||||
free(s.ptr);
|
||||
return(0);
|
||||
}
|
||||
else if ( numretries >= 1 )
|
||||
{
|
||||
//printf("Maximum number of retries exceeded!\n");
|
||||
free(s.ptr);
|
||||
return(0);
|
||||
}
|
||||
printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries);
|
||||
free(s.ptr);
|
||||
sleep((1<<numretries));
|
||||
goto try_again;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( command != 0 && specialcase == 0 )
|
||||
{
|
||||
count++;
|
||||
elapsedsum += (OS_milliseconds() - starttime);
|
||||
if ( (count % 10000) == 0)
|
||||
printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url);
|
||||
if ( retstrp != 0 )
|
||||
{
|
||||
*retstrp = s.ptr;
|
||||
return(s.ptr);
|
||||
}
|
||||
return(post_process_bitcoind_RPC(debugstr,command,s.ptr,params));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( 0 && specialcase != 0 )
|
||||
fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%s)\n",params,s.ptr);
|
||||
count2++;
|
||||
elapsedsum2 += (OS_milliseconds() - starttime);
|
||||
if ( (count2 % 10000) == 0)
|
||||
printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command);
|
||||
return(s.ptr);
|
||||
}
|
||||
}
|
||||
printf("bitcoind_RPC: impossible case\n");
|
||||
free(s.ptr);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data)
|
||||
{
|
||||
size_t realsize = (size * nmemb);
|
||||
struct MemoryStruct *mem = (struct MemoryStruct *)data;
|
||||
mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1));
|
||||
if ( mem->memory != 0 )
|
||||
{
|
||||
if ( ptr != 0 )
|
||||
memcpy(&(mem->memory[mem->size]),ptr,realsize);
|
||||
mem->size += realsize;
|
||||
mem->memory[mem->size] = 0;
|
||||
}
|
||||
//printf("got %d bytes\n",(int32_t)(size*nmemb));
|
||||
return(realsize);
|
||||
}
|
||||
|
||||
char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3)
|
||||
{
|
||||
struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0;
|
||||
if ( (cHandle= *cHandlep) == NULL )
|
||||
*cHandlep = cHandle = curl_easy_init();
|
||||
else curl_easy_reset(cHandle);
|
||||
//#ifdef DEBUG
|
||||
//curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1);
|
||||
//#endif
|
||||
curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )");
|
||||
curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0);
|
||||
//curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1);
|
||||
curl_easy_setopt(cHandle,CURLOPT_URL,url);
|
||||
curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10);
|
||||
if ( userpass != 0 && userpass[0] != 0 )
|
||||
curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass);
|
||||
if ( postfields != 0 && postfields[0] != 0 )
|
||||
{
|
||||
curl_easy_setopt(cHandle,CURLOPT_POST,1);
|
||||
curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields);
|
||||
}
|
||||
if ( hdr0 != NULL && hdr0[0] != 0 )
|
||||
{
|
||||
//printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:"");
|
||||
headers = curl_slist_append(headers,hdr0);
|
||||
if ( hdr1 != 0 && hdr1[0] != 0 )
|
||||
headers = curl_slist_append(headers,hdr1);
|
||||
if ( hdr2 != 0 && hdr2[0] != 0 )
|
||||
headers = curl_slist_append(headers,hdr2);
|
||||
if ( hdr3 != 0 && hdr3[0] != 0 )
|
||||
headers = curl_slist_append(headers,hdr3);
|
||||
} //headers = curl_slist_append(0,"Expect:");
|
||||
if ( headers != 0 )
|
||||
curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers);
|
||||
//res = curl_easy_perform(cHandle);
|
||||
memset(&chunk,0,sizeof(chunk));
|
||||
curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback);
|
||||
curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk);
|
||||
curl_easy_perform(cHandle);
|
||||
curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code);
|
||||
if ( headers != 0 )
|
||||
curl_slist_free_all(headers);
|
||||
if ( code != 200 )
|
||||
printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory);
|
||||
return(chunk.memory);
|
||||
}
|
||||
|
||||
char *komodo_issuemethod(char *method,char *params,uint16_t port)
|
||||
{
|
||||
//static void *cHandle;
|
||||
char url[512],*retstr=0,*retstr2=0,postdata[8192];
|
||||
if ( params == 0 || params[0] == 0 )
|
||||
params = (char *)"[]";
|
||||
if ( strlen(params) < sizeof(postdata)-128 )
|
||||
{
|
||||
sprintf(url,(char *)"http://127.0.0.1:%u",port);
|
||||
sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params);
|
||||
//printf("postdata.(%s) USERPASS.(%s)\n",postdata,KMDUSERPASS);
|
||||
retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,KMDUSERPASS,method,params);
|
||||
//retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0);
|
||||
}
|
||||
return(retstr2);
|
||||
}
|
||||
//curl --url "http://127.0.0.1:13033" --user "user1557335368:pass111720054" --data "{\"method\":\"getinfo\",\"params\":[]}"
|
||||
|
||||
uint32_t komodo_txtime(uint256 hash)
|
||||
{
|
||||
CTransaction tx;
|
||||
uint256 hashBlock;
|
||||
if (!GetTransaction(hash, tx, hashBlock, true))
|
||||
if (!GetTransaction(hash, tx,
|
||||
#ifndef KOMODO_ZCASH
|
||||
Params().GetConsensus(),
|
||||
#endif
|
||||
hashBlock, true))
|
||||
{
|
||||
//printf("null GetTransaction\n");
|
||||
return(tx.nLockTime);
|
||||
@@ -33,13 +367,18 @@ void komodo_disconnect(CBlockIndex *pindex,CBlock& block)
|
||||
//uint256 zero;
|
||||
//printf("disconnect ht.%d\n",pindex->nHeight);
|
||||
//memset(&zero,0,sizeof(zero));
|
||||
//komodo_stateupdate(-pindex->nHeight,0,0,0,zero,0,0,0,0);
|
||||
//komodo_stateupdate(-pindex->nHeight,0,0,0,zero,0,0,0,0,0,0,0);
|
||||
}
|
||||
|
||||
int32_t komodo_block2height(CBlock *block)
|
||||
{
|
||||
int32_t i,n,height = 0; uint8_t *ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
|
||||
int32_t i,n,height = 0; uint8_t *ptr;
|
||||
komodo_init();
|
||||
#ifdef KOMODO_ZCASH
|
||||
ptr = (uint8_t *)block->vtx[0].vin[0].scriptSig.data();
|
||||
#else
|
||||
ptr = (uint8_t *)&block->vtx[0].vin[0].scriptSig[0];
|
||||
#endif
|
||||
if ( block->vtx[0].vin[0].scriptSig.size() > 5 )
|
||||
{
|
||||
//for (i=0; i<6; i++)
|
||||
@@ -58,7 +397,11 @@ int32_t komodo_block2height(CBlock *block)
|
||||
|
||||
void komodo_block2pubkey33(uint8_t *pubkey33,CBlock& block)
|
||||
{
|
||||
#ifdef KOMODO_ZCASH
|
||||
uint8_t *ptr = (uint8_t *)block.vtx[0].vout[0].scriptPubKey.data();
|
||||
#else
|
||||
uint8_t *ptr = (uint8_t *)&block.vtx[0].vout[0].scriptPubKey[0];
|
||||
#endif
|
||||
komodo_init();
|
||||
memcpy(pubkey33,ptr+1,33);
|
||||
}
|
||||
@@ -70,7 +413,11 @@ void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height)
|
||||
memset(pubkey33,0,33);
|
||||
if ( pindex != 0 )
|
||||
{
|
||||
if ( ReadBlockFromDisk(block,(const CBlockIndex *)pindex) != 0 )
|
||||
if ( ReadBlockFromDisk(block,(const CBlockIndex *)pindex
|
||||
#ifndef KOMODO_ZCASH
|
||||
,Params().GetConsensus()
|
||||
#endif
|
||||
) != 0 )
|
||||
{
|
||||
komodo_block2pubkey33(pubkey33,block);
|
||||
}
|
||||
|
||||
339
src/komodo_gateway.h
Normal file
339
src/komodo_gateway.h
Normal file
@@ -0,0 +1,339 @@
|
||||
/******************************************************************************
|
||||
* 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. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
// paxdeposit equivalent in reverse makes opreturn and KMD does the same in reverse
|
||||
|
||||
struct pax_transaction
|
||||
{
|
||||
struct queueitem DL;
|
||||
uint256 txid;
|
||||
uint64_t komodoshis,fiatoshis;
|
||||
uint16_t vout;
|
||||
char symbol[4]; uint8_t rmd160[20],shortflag;
|
||||
};
|
||||
|
||||
void komodo_gateway_deposits(CMutableTransaction& txNew)
|
||||
{
|
||||
struct pax_transaction *ptr; uint8_t *script,opret[10000],data[10000]; int32_t i,len=0,opretlen=0,numvouts=1;
|
||||
PENDING_KOMODO_TX = 0;
|
||||
while ( (ptr= (struct pax_transaction *)queue_dequeue(&DepositsQ)) != 0 )
|
||||
{
|
||||
txNew.vout.resize(numvouts+1);
|
||||
txNew.vout[numvouts].nValue = ptr->fiatoshis;
|
||||
txNew.vout[numvouts].scriptPubKey.resize(25);
|
||||
script = (uint8_t *)&txNew.vout[numvouts].scriptPubKey[0];
|
||||
*script++ = 0x76;
|
||||
*script++ = 0xa9;
|
||||
*script++ = 20;
|
||||
memcpy(script,ptr->rmd160,20), script += 20;
|
||||
*script++ = 0x88;
|
||||
*script++ = 0xac;
|
||||
for (i=0; i<32; i++)
|
||||
{
|
||||
printf("%02x",((uint8_t *)&ptr->txid)[i]);
|
||||
data[len++] = ((uint8_t *)&ptr->txid)[i];
|
||||
}
|
||||
data[len++] = ptr->vout & 0xff;
|
||||
data[len++] = (ptr->vout >> 8) & 0xff;
|
||||
printf(" vout.%u DEPOSIT %.8f\n",ptr->vout,(double)KOMODO_DEPOSIT/COIN);
|
||||
PENDING_KOMODO_TX += ptr->fiatoshis;
|
||||
numvouts++;
|
||||
queue_enqueue((char *)"PENDINGS",&PendingsQ,&ptr->DL);
|
||||
}
|
||||
if ( numvouts > 1 )
|
||||
{
|
||||
opretlen = komodo_opreturnscript(opret,'I',data,len);
|
||||
txNew.vout.resize(numvouts+1);
|
||||
txNew.vout[numvouts].nValue = 0;
|
||||
txNew.vout[numvouts].scriptPubKey.resize(opretlen);
|
||||
script = (uint8_t *)&txNew.vout[numvouts].scriptPubKey[0];
|
||||
memcpy(script,opret,opretlen);
|
||||
}
|
||||
printf("total numvouts.%d %.8f\n",numvouts,dstr(PENDING_KOMODO_TX));
|
||||
}
|
||||
|
||||
int32_t komodo_check_deposit(CBlock& block)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
void komodo_gateway_deposit(uint64_t value,int32_t shortflag,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout) // assetchain context
|
||||
{
|
||||
struct pax_transaction *ptr;
|
||||
ptr = (struct pax_transaction *)calloc(1,sizeof(*ptr));
|
||||
ptr->komodoshis = value;
|
||||
ptr->fiatoshis = fiatoshis;
|
||||
memcpy(ptr->symbol,symbol,3);
|
||||
memcpy(ptr->rmd160,rmd160,20);
|
||||
ptr->shortflag = shortflag;
|
||||
ptr->txid = txid;
|
||||
ptr->vout = vout;
|
||||
KOMODO_DEPOSIT += fiatoshis;
|
||||
queue_enqueue((char *)"DEPOSITS",&DepositsQ,&ptr->DL);
|
||||
}
|
||||
|
||||
int32_t komodo_gateway_depositremove(uint256 txid,uint16_t vout) // assetchain context
|
||||
{
|
||||
int32_t iter,n=0; queue_t *Q; struct pax_transaction *ptr; struct queueitem *item;
|
||||
for (iter=0; iter<2; iter++)
|
||||
{
|
||||
Q = (iter == 0) ? &DepositsQ : &PendingsQ;
|
||||
portable_mutex_lock(&Q->mutex);
|
||||
if ( Q->list != 0 )
|
||||
{
|
||||
item = &ptr->DL;
|
||||
DL_FOREACH(Q->list,item)
|
||||
{
|
||||
ptr = (struct pax_transaction *)item;
|
||||
if ( memcmp(&ptr->txid,&txid,sizeof(txid)) == 0 && ptr->vout == vout )
|
||||
{
|
||||
if ( KOMODO_DEPOSIT >= ptr->fiatoshis )
|
||||
KOMODO_DEPOSIT -= ptr->fiatoshis;
|
||||
else KOMODO_DEPOSIT = 0;
|
||||
printf("DELETE %.8f DEPOSIT %s %.8f\n",dstr(ptr->komodoshis),ptr->symbol,dstr(ptr->fiatoshis));
|
||||
DL_DELETE(Q->list,&ptr->DL);
|
||||
n++;
|
||||
free(ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
portable_mutex_unlock(&Q->mutex);
|
||||
}
|
||||
if ( queue_size(&DepositsQ) == 0 && queue_size(&PendingsQ) == 0 )
|
||||
KOMODO_DEPOSIT = PENDING_KOMODO_TX = 0;
|
||||
return(n);
|
||||
}
|
||||
|
||||
const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout)
|
||||
{
|
||||
uint8_t rmd160[20],addrtype,shortflag,pubkey33[33]; int32_t i,j,len,tokomodo=0; char base[4],coinaddr[64],destaddr[64]; int64_t fiatoshis,checktoshis; const char *typestr = "unknown";
|
||||
#ifdef KOMODO_ISSUER
|
||||
tokomodo = 1;
|
||||
#endif
|
||||
if ( opretbuf[0] == ((tokomodo != 0) ? 'D' : 'W') )
|
||||
{
|
||||
if ( opretlen == 34 )
|
||||
{
|
||||
memset(base,0,sizeof(base));
|
||||
PAX_pubkey(0,&opretbuf[1],&addrtype,rmd160,base,&shortflag,&fiatoshis);
|
||||
if ( fiatoshis < 0 )
|
||||
fiatoshis = -fiatoshis;
|
||||
bitcoin_address(coinaddr,addrtype,rmd160,20);
|
||||
checktoshis = PAX_fiatdest(tokomodo,destaddr,pubkey33,coinaddr,height,base,fiatoshis);
|
||||
for (i=0; i<opretlen; i++)
|
||||
printf("%02x",opretbuf[i]);
|
||||
printf(" DEPOSIT %.8f %c%s -> %s ",dstr(fiatoshis),shortflag!=0?'-':'+',base,coinaddr);
|
||||
for (i=0; i<32; i++)
|
||||
printf("%02x",((uint8_t *)&txid)[i]);
|
||||
printf(" <- txid.v%u ",vout);
|
||||
for (i=0; i<33; i++)
|
||||
printf("%02x",pubkey33[i]);
|
||||
printf(" checkpubkey check %.8f v %.8f dest.(%s)\n",dstr(checktoshis),dstr(value),destaddr);
|
||||
typestr = "deposit";
|
||||
#ifdef KOMODO_ISSUER
|
||||
if ( strncmp(KOMODO_SOURCE,base,strlen(base)) == 0 && value >= (9999*checktoshis)/10000 && shortflag == ASSETCHAINS_SHORTFLAG )
|
||||
{
|
||||
komodo_gateway_deposit(value,shortflag,base,fiatoshis,rmd160,txid,vout);
|
||||
}
|
||||
#else
|
||||
if ( tokomodo != 0 && value <= (10000*checktoshis)/9999 )
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<opretlen; i++)
|
||||
printf("%02x",opretbuf[i]);
|
||||
printf(" komodo_opreturn[%c]: ht.%d %.8f opretlen.%d\n",opretbuf[0],height,dstr(value),opretlen);
|
||||
|
||||
if ( opretbuf[0] == 'I' )
|
||||
{
|
||||
uint256 issuedtxid; uint16_t issuedvout;
|
||||
opretbuf++, opretlen--;
|
||||
for (i=len=0; i<opretlen/34; i++)
|
||||
{
|
||||
for (j=0; j<32; j++)
|
||||
{
|
||||
((uint8_t *)&issuedtxid)[j] = opretbuf[len++];
|
||||
printf("%02x",((uint8_t *)&issuedtxid)[j]);
|
||||
}
|
||||
issuedvout = opretbuf[len++];
|
||||
issuedvout = (opretbuf[len++] << 8) | vout;
|
||||
printf(" issuedtxid v%d i.%d opretlen.%d\n",issuedvout,i,opretlen);
|
||||
if ( komodo_gateway_depositremove(issuedtxid,issuedvout) == 0 )
|
||||
printf("error removing deposit\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return(typestr);
|
||||
}
|
||||
|
||||
void komodo_gateway_voutupdate(char *symbol,int32_t isspecial,int32_t height,int32_t txi,bits256 txid,int32_t vout,int32_t numvouts,uint64_t value,uint8_t *script,int32_t len)
|
||||
{
|
||||
int32_t i,opretlen,offset = 0; uint256 zero,utxid; const char *typestr;
|
||||
typestr = "unknown";
|
||||
memcpy(&utxid,&txid,sizeof(utxid));
|
||||
if ( 0 )//txi != 0 || vout != 0 )
|
||||
{
|
||||
for (i=0; i<len; i++)
|
||||
printf("%02x",script[i]);
|
||||
printf(" <- %s VOUTUPDATE.%d txi.%d vout.%d %.8f scriptlen.%d OP_RETURN.%d (%s) len.%d\n",symbol,height,txi,vout,dstr(value),len,script[0] == 0x6a,typestr,opretlen);
|
||||
}
|
||||
if ( script[offset++] == 0x6a )
|
||||
{
|
||||
offset += komodo_scriptitemlen(&opretlen,&script[offset]);
|
||||
if ( isspecial != 0 && len >= offset+32*2+4 && strcmp((char *)&script[offset+32*2+4],"KMD") == 0 )
|
||||
typestr = "notarized";
|
||||
else if ( txi == 0 && vout == 1 && opretlen == 149 )
|
||||
{
|
||||
typestr = "pricefeed";
|
||||
komodo_paxpricefeed(height,&script[offset],opretlen);
|
||||
//printf("height.%d pricefeed len.%d\n",height,opretlen);
|
||||
}
|
||||
else komodo_stateupdate(height,0,0,0,utxid,0,0,0,0,0,value,&script[offset],opretlen,vout);
|
||||
}
|
||||
else if ( numvouts > 13 )
|
||||
typestr = "ratify";
|
||||
}
|
||||
|
||||
int32_t komodo_gateway_tx(char *symbol,int32_t height,int32_t txi,char *txidstr,uint32_t port)
|
||||
{
|
||||
char *retstr,params[256],*hexstr; uint8_t script[10000]; cJSON *json,*result,*vouts,*item,*sobj; int32_t vout,n,len,isspecial,retval = -1; uint64_t value; bits256 txid;
|
||||
sprintf(params,"[\"%s\", 1]",txidstr);
|
||||
if ( (retstr= komodo_issuemethod((char *)"getrawtransaction",params,port)) != 0 )
|
||||
{
|
||||
if ( (json= cJSON_Parse(retstr)) != 0 )
|
||||
{
|
||||
if ( (result= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,result,(char *)"vout")) != 0 )
|
||||
{
|
||||
retval = 0;
|
||||
isspecial = 0;
|
||||
txid = jbits256(result,(char *)"txid");
|
||||
for (vout=0; vout<n; vout++)
|
||||
{
|
||||
item = jitem(vouts,vout);
|
||||
value = SATOSHIDEN * jdouble(item,(char *)"value");
|
||||
if ( (sobj= jobj(item,(char *)"scriptPubKey")) != 0 )
|
||||
{
|
||||
if ( (hexstr= jstr(sobj,(char *)"hex")) != 0 )
|
||||
{
|
||||
len = (int32_t)strlen(hexstr) >> 1;
|
||||
if ( vout == 0 && ((memcmp(&hexstr[2],CRYPTO777_PUBSECPSTR,66) == 0 && len == 35) || (memcmp(&hexstr[6],CRYPTO777_RMD160STR,40) == 0 && len == 25)) )
|
||||
isspecial = 1;
|
||||
else if ( len <= sizeof(script) )
|
||||
{
|
||||
decode_hex(script,len,hexstr);
|
||||
komodo_gateway_voutupdate(symbol,isspecial,height,txi,txid,vout,n,value,script,len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free_json(json);
|
||||
}
|
||||
free(retstr);
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
int32_t komodo_gateway_block(char *symbol,int32_t height,uint16_t port)
|
||||
{
|
||||
char *retstr,*retstr2,params[128],*txidstr; int32_t i,n,retval = -1; cJSON *json,*tx,*result,*result2;
|
||||
sprintf(params,"[%d]",height);
|
||||
if ( (retstr= komodo_issuemethod((char *)"getblockhash",params,port)) != 0 )
|
||||
{
|
||||
if ( (result= cJSON_Parse(retstr)) != 0 )
|
||||
{
|
||||
if ( (txidstr= jstr(result,(char *)"result")) != 0 && strlen(txidstr) == 64 )
|
||||
{
|
||||
sprintf(params,"[\"%s\"]",txidstr);
|
||||
if ( (retstr2= komodo_issuemethod((char *)"getblock",params,port)) != 0 )
|
||||
{
|
||||
//printf("getblock.(%s)\n",retstr2);
|
||||
if ( (json= cJSON_Parse(retstr2)) != 0 )
|
||||
{
|
||||
if ( (result2= jobj(json,(char *)"result")) != 0 && (tx= jarray(&n,result2,(char *)"tx")) != 0 )
|
||||
{
|
||||
for (i=0; i<n; i++)
|
||||
if ( komodo_gateway_tx(symbol,height,i,jstri(tx,i),port) < 0 )
|
||||
break;
|
||||
if ( i == n )
|
||||
retval = 0;
|
||||
else printf("error i.%d vs n.%d\n",i,n);
|
||||
}
|
||||
free_json(json);
|
||||
}
|
||||
free(retstr2);
|
||||
}
|
||||
} else printf("strlen.%ld (%s)\n",strlen(txidstr),txidstr);
|
||||
free_json(result);
|
||||
}
|
||||
free(retstr);
|
||||
}
|
||||
return(retval);
|
||||
}
|
||||
|
||||
void komodo_gateway_iteration(char *symbol)
|
||||
{
|
||||
char *retstr; int32_t i,kmdheight; cJSON *infoobj,*result; uint256 zero; uint16_t port = 7771;
|
||||
if ( KMDHEIGHT <= 0 )
|
||||
KMDHEIGHT = 1;
|
||||
if ( (retstr= komodo_issuemethod((char *)"getinfo",0,port)) != 0 )
|
||||
{
|
||||
if ( (infoobj= cJSON_Parse(retstr)) != 0 )
|
||||
{
|
||||
if ( (result= jobj(infoobj,(char *)"result")) != 0 && (kmdheight= jint(result,(char *)"blocks")) != 0 )
|
||||
{
|
||||
for (i=0; i<1000 && KMDHEIGHT<kmdheight; i++,KMDHEIGHT++)
|
||||
{
|
||||
//printf("KMDHEIGHT %d\n",KMDHEIGHT);
|
||||
if ( (KMDHEIGHT % 100) == 0 )
|
||||
{
|
||||
fprintf(stderr,"%s.%d ",symbol,KMDHEIGHT);
|
||||
memset(&zero,0,sizeof(zero));
|
||||
komodo_stateupdate(KMDHEIGHT,0,0,0,zero,0,0,0,0,KMDHEIGHT,0,0,0,0);
|
||||
}
|
||||
if ( komodo_gateway_block(symbol,KMDHEIGHT,port) < 0 )
|
||||
break;
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
free_json(infoobj);
|
||||
}
|
||||
free(retstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("error from %s\n",symbol);
|
||||
sleep(30);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KOMODO_ISSUER
|
||||
void komodo_gateway_issuer() // from "assetchain" connectblock()
|
||||
{
|
||||
// check for redeems
|
||||
}
|
||||
#else
|
||||
|
||||
void komodo_gateway_redeemer() // from "KMD" connectblock()
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -14,7 +14,6 @@
|
||||
******************************************************************************/
|
||||
|
||||
#define KOMODO_INTEREST ((uint64_t)(0.05 * COIN)) // 5%
|
||||
#define dstr(x) ((double)(x)/COIN)
|
||||
|
||||
uint64_t komodo_accrued_interest(int32_t height,int64_t paidinterest)
|
||||
{
|
||||
@@ -46,6 +45,7 @@ uint64_t komodo_accrued_interest(int32_t height,int64_t paidinterest)
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
uint64_t komodo_moneysupply(int32_t height)
|
||||
|
||||
@@ -85,8 +85,6 @@ void komodo_nutxoadd(int32_t height,int32_t notaryid,uint256 txhash,uint64_t vou
|
||||
np->notaryid = notaryid;
|
||||
HASH_ADD_KEYPTR(hh,NUTXOS,&np->txhash,sizeof(np->txhash),np);
|
||||
printf("Add NUTXO[%d] <- %s notaryid.%d t%u %s %llx\n",Num_nutxos,Notaries[notaryid][0],notaryid,komodo_txtime(txhash),txhash.ToString().c_str(),(long long)voutmask);
|
||||
//if ( addflag != 0 )
|
||||
// komodo_stateupdate(height,0,0,notaryid,txhash,voutmask,numvouts,0,0);
|
||||
Num_nutxos++;
|
||||
pthread_mutex_unlock(&komodo_mutex);
|
||||
}
|
||||
@@ -135,6 +133,8 @@ int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33)
|
||||
// -1 if not notary, 0 if notary, 1 if special notary
|
||||
struct knotary_entry *kp; int32_t numnotaries,modval = -1;
|
||||
*notaryidp = -1;
|
||||
if ( height < 0 || height/KOMODO_ELECTION_GAP >= sizeof(Pubkeys)/sizeof(*Pubkeys) )
|
||||
return(-1);
|
||||
pthread_mutex_lock(&komodo_mutex);
|
||||
HASH_FIND(hh,Pubkeys[height/KOMODO_ELECTION_GAP].Notaries,pubkey33,33,kp);
|
||||
pthread_mutex_unlock(&komodo_mutex);
|
||||
@@ -198,6 +198,8 @@ void komodo_init()
|
||||
if ( didinit == 0 )
|
||||
{
|
||||
didinit = 1;
|
||||
iguana_initQ(&DepositsQ,(char *)"Deposits");
|
||||
iguana_initQ(&PendingsQ,(char *)"Pendings");
|
||||
pthread_mutex_init(&komodo_mutex,NULL);
|
||||
decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str());
|
||||
n = (int32_t)(sizeof(Notaries)/sizeof(*Notaries));
|
||||
@@ -209,6 +211,6 @@ void komodo_init()
|
||||
}
|
||||
komodo_notarysinit(0,pubkeys,k);
|
||||
memset(&zero,0,sizeof(zero));
|
||||
komodo_stateupdate(0,0,0,0,zero,0,0,0,0);
|
||||
komodo_stateupdate(0,0,0,0,zero,0,0,0,0,0,0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
111
src/komodo_pax.h
111
src/komodo_pax.h
@@ -71,20 +71,36 @@ void pax_rank(uint64_t *ranked,uint32_t *pvals)
|
||||
|
||||
int32_t dpow_readprices(uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals)
|
||||
{
|
||||
uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,len = 0;
|
||||
uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,nonz,len = 0;
|
||||
if ( data[0] == 'P' && data[5] == 35 )
|
||||
data++;
|
||||
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp);
|
||||
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n);
|
||||
if ( n != 35 )
|
||||
{
|
||||
printf("dpow_readprices illegal n.%d\n",n);
|
||||
return(-1);
|
||||
}
|
||||
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000
|
||||
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000
|
||||
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd);
|
||||
*KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.));
|
||||
*BTCUSDp = ((double)btcusd / (1000000000. / 1000.));
|
||||
*CNYUSDp = ((double)cnyusd / 1000000000.);
|
||||
for (i=0; i<n-3; i++)
|
||||
for (i=nonz=0; i<n-3; i++)
|
||||
{
|
||||
if ( pvals[i] != 0 )
|
||||
nonz++;
|
||||
//else if ( nonz != 0 )
|
||||
// printf("pvals[%d] is zero\n",i);
|
||||
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&pvals[i]);
|
||||
//printf("%u ",pvals[i]);
|
||||
}
|
||||
/*if ( nonz < n-3 )
|
||||
{
|
||||
//printf("nonz.%d n.%d retval -1\n",nonz,n);
|
||||
return(-1);
|
||||
}*/
|
||||
pvals[i++] = kmdbtc;
|
||||
pvals[i++] = btcusd;
|
||||
pvals[i++] = cnyusd;
|
||||
@@ -95,7 +111,7 @@ int32_t dpow_readprices(uint8_t *data,uint32_t *timestampp,double *KMDBTCp,doubl
|
||||
int32_t komodo_pax_opreturn(uint8_t *opret,int32_t maxsize)
|
||||
{
|
||||
static uint32_t lastcrc;
|
||||
FILE *fp; char fname[512]; uint32_t crc32,check,timestamp; int32_t i,n,retval,fsize,len=0; uint8_t data[8192];
|
||||
FILE *fp; char fname[512]; uint32_t crc32,check,timestamp; int32_t i,n=0,retval,fsize,len=0; uint8_t data[8192];
|
||||
#ifdef WIN32
|
||||
sprintf(fname,"%s\\%s",GetDataDir(false).string().c_str(),(char *)"komodofeed");
|
||||
#else
|
||||
@@ -115,24 +131,26 @@ int32_t komodo_pax_opreturn(uint8_t *opret,int32_t maxsize)
|
||||
if ( check == crc32 )
|
||||
{
|
||||
double KMDBTC,BTCUSD,CNYUSD; uint32_t pvals[128];
|
||||
dpow_readprices(&data[len],×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals);
|
||||
if ( 0 && lastcrc != crc32 )
|
||||
if ( dpow_readprices(&data[len],×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals) > 0 )
|
||||
{
|
||||
for (i=0; i<32; i++)
|
||||
printf("%u ",pvals[i]);
|
||||
printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0);
|
||||
}
|
||||
if ( timestamp > time(NULL)-600 )
|
||||
{
|
||||
n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32)));
|
||||
if ( 0 && lastcrc != crc32 )
|
||||
{
|
||||
for (i=0; i<n; i++)
|
||||
printf("%02x",opret[i]);
|
||||
printf(" coinbase opret[%d] crc32.%u:%u\n",n,crc32,check);
|
||||
for (i=0; i<32; i++)
|
||||
printf("%u ",pvals[i]);
|
||||
printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0);
|
||||
}
|
||||
} //else printf("t%u too old for %u\n",timestamp,(uint32_t)time(NULL));
|
||||
lastcrc = crc32;
|
||||
if ( timestamp > time(NULL)-600 )
|
||||
{
|
||||
n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32)));
|
||||
if ( 0 && lastcrc != crc32 )
|
||||
{
|
||||
for (i=0; i<n; i++)
|
||||
printf("%02x",opret[i]);
|
||||
printf(" coinbase opret[%d] crc32.%u:%u\n",n,crc32,check);
|
||||
}
|
||||
} //else printf("t%u too old for %u\n",timestamp,(uint32_t)time(NULL));
|
||||
lastcrc = crc32;
|
||||
}
|
||||
} else printf("crc32 %u mismatch %u\n",crc32,check);
|
||||
} else printf("fread.%d error != fsize.%d\n",retval,fsize);
|
||||
} else printf("fsize.%d > maxsize.%d or data[%d]\n",fsize,maxsize,(int32_t)sizeof(data));
|
||||
@@ -153,14 +171,29 @@ int32_t komodo_pax_opreturn(uint8_t *opret,int32_t maxsize)
|
||||
return(val32);
|
||||
}*/
|
||||
|
||||
int32_t PAX_pubkey(uint8_t *pubkey33,uint8_t addrtype,uint8_t rmd160[20],char fiat[4],uint8_t shortflag,int32_t fiatoshis)
|
||||
int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp)
|
||||
{
|
||||
memset(pubkey33,0,33);
|
||||
pubkey33[0] = 0x02 | (shortflag != 0);
|
||||
memcpy(&pubkey33[1],fiat,3);
|
||||
iguana_rwnum(1,&pubkey33[4],sizeof(fiatoshis),(void *)&fiatoshis);
|
||||
pubkey33[12] = addrtype;
|
||||
memcpy(&pubkey33[13],rmd160,20);
|
||||
if ( rwflag != 0 )
|
||||
{
|
||||
memset(pubkey33,0,33);
|
||||
pubkey33[0] = 0x02 | (*shortflagp != 0);
|
||||
memcpy(&pubkey33[1],fiat,3);
|
||||
iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp);
|
||||
pubkey33[12] = *addrtypep;
|
||||
memcpy(&pubkey33[13],rmd160,20);
|
||||
}
|
||||
else
|
||||
{
|
||||
*shortflagp = (pubkey33[0] == 0x03);
|
||||
memcpy(fiat,&pubkey33[1],3);
|
||||
fiat[3] = 0;
|
||||
iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp);
|
||||
if ( *shortflagp != 0 )
|
||||
*fiatoshisp = -(*fiatoshisp);
|
||||
*addrtypep = pubkey33[12];
|
||||
memcpy(rmd160,&pubkey33[13],20);
|
||||
}
|
||||
return(33);
|
||||
}
|
||||
|
||||
double PAX_val(uint32_t pval,int32_t baseid)
|
||||
@@ -173,7 +206,7 @@ double PAX_val(uint32_t pval,int32_t baseid)
|
||||
|
||||
void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals)
|
||||
{
|
||||
int32_t i,nonz; double KMDBTC,BTCUSD,CNYUSD; uint32_t kmdbtc,btcusd,cnyusd;
|
||||
int32_t i,nonz; uint32_t kmdbtc,btcusd,cnyusd; double KMDBTC,BTCUSD,CNYUSD;
|
||||
if ( numpvals >= 35 )
|
||||
{
|
||||
for (nonz=i=0; i<32; i++)
|
||||
@@ -194,7 +227,8 @@ void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals)
|
||||
PVALS[36 * NUM_PRICES] = height;
|
||||
memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35);
|
||||
NUM_PRICES++;
|
||||
//printf("OP_RETURN.%d KMD %.8f BTC %.6f CNY %.6f NUM_PRICES.%d\n",height,KMDBTC,BTCUSD,CNYUSD,NUM_PRICES);
|
||||
if ( 0 )
|
||||
printf("OP_RETURN.%d KMD %.8f BTC %.6f CNY %.6f NUM_PRICES.%d (%llu %llu %llu)\n",height,KMDBTC,BTCUSD,CNYUSD,NUM_PRICES,(long long)kmdbtc,(long long)btcusd,(long long)cnyusd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,7 +248,7 @@ int32_t komodo_baseid(char *origbase)
|
||||
|
||||
uint64_t komodo_paxcalc(uint32_t *pvals,int32_t baseid,int32_t relid,uint64_t basevolume)
|
||||
{
|
||||
uint32_t pvalb,pvalr,kmdbtc,btcusd; uint64_t usdvol,baseusd,usdkmd,baserel,sum,ranked[32]; int32_t i;
|
||||
uint32_t pvalb,pvalr,kmdbtc,btcusd; uint64_t usdvol,baseusd,usdkmd,baserel,ranked[32];
|
||||
if ( basevolume > 1000000*COIN )
|
||||
return(0);
|
||||
if ( (pvalb= pvals[baseid]) != 0 )
|
||||
@@ -252,7 +286,7 @@ uint64_t komodo_paxcalc(uint32_t *pvals,int32_t baseid,int32_t relid,uint64_t ba
|
||||
|
||||
uint64_t komodo_paxprice(int32_t height,char *base,char *rel,uint64_t basevolume)
|
||||
{
|
||||
int32_t baseid=-1,relid=-1,i,ht; uint32_t *ptr;
|
||||
int32_t baseid=-1,relid=-1,i; uint32_t *ptr;
|
||||
if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 )
|
||||
{
|
||||
for (i=NUM_PRICES-1; i>=0; i--)
|
||||
@@ -267,7 +301,7 @@ uint64_t komodo_paxprice(int32_t height,char *base,char *rel,uint64_t basevolume
|
||||
|
||||
int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel)
|
||||
{
|
||||
int32_t baseid=-1,relid=-1,i,ht,num = 0; uint32_t *ptr;
|
||||
int32_t baseid=-1,relid=-1,i,num = 0; uint32_t *ptr;
|
||||
if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 )
|
||||
{
|
||||
for (i=NUM_PRICES-1; i>=0; i--)
|
||||
@@ -283,11 +317,19 @@ int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *bas
|
||||
return(num);
|
||||
}
|
||||
|
||||
uint64_t PAX_fiatdest(char *fiatbuf,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *origbase,int64_t fiatoshis)
|
||||
void komodo_paxpricefeed(int32_t height,uint8_t *pricefeed,int32_t opretlen)
|
||||
{
|
||||
uint8_t shortflag = 0; char base[4]; int32_t i,baseid,relid; uint8_t addrtype,rmd160[20]; uint64_t komodoshis = 0;
|
||||
fiatbuf[0] = 0;
|
||||
if ( strcmp(base,(char *)"KMD") == 0 || strcmp(base,(char *)"kmd") == 0 )
|
||||
double KMDBTC,BTCUSD,CNYUSD; uint32_t numpvals,timestamp,pvals[128]; uint256 zero;
|
||||
numpvals = dpow_readprices(pricefeed,×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals);
|
||||
memset(&zero,0,sizeof(zero));
|
||||
komodo_stateupdate(height,0,0,0,zero,0,0,pvals,numpvals,0,0,0,0,0);
|
||||
//printf("komodo_paxpricefeed vout OP_RETURN.%d prices numpvals.%d opretlen.%d\n",height,numpvals,opretlen);
|
||||
}
|
||||
|
||||
uint64_t PAX_fiatdest(int32_t tokomodo,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *origbase,int64_t fiatoshis)
|
||||
{
|
||||
uint8_t shortflag = 0; char base[4]; int32_t i,baseid; uint8_t addrtype,rmd160[20]; int64_t komodoshis = 0;
|
||||
if ( (baseid= komodo_baseid(origbase)) < 0 || baseid == MAX_CURRENCIES )
|
||||
return(0);
|
||||
for (i=0; i<3; i++)
|
||||
base[i] = toupper(origbase[i]);
|
||||
@@ -297,8 +339,7 @@ uint64_t PAX_fiatdest(char *fiatbuf,char *destaddr,uint8_t pubkey33[33],char *co
|
||||
komodoshis = komodo_paxprice(height,base,(char *)"KMD",(uint64_t)fiatoshis);
|
||||
if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 )
|
||||
{
|
||||
// put JSON into fiatbuf enough to replicate/validate
|
||||
PAX_pubkey(pubkey33,addrtype,rmd160,base,shortflag,fiatoshis);
|
||||
PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis);
|
||||
bitcoin_address(destaddr,KOMODO_PUBTYPE,pubkey33,33);
|
||||
}
|
||||
return(komodoshis);
|
||||
|
||||
@@ -13,14 +13,33 @@
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#define SATOSHIDEN ((uint64_t)100000000L)
|
||||
#define dstr(x) ((double)(x) / SATOSHIDEN)
|
||||
#define portable_mutex_t pthread_mutex_t
|
||||
#define portable_mutex_init(ptr) pthread_mutex_init(ptr,NULL)
|
||||
#define portable_mutex_lock pthread_mutex_lock
|
||||
#define portable_mutex_unlock pthread_mutex_unlock
|
||||
|
||||
struct allocitem { uint32_t allocsize,type; };
|
||||
struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; };
|
||||
|
||||
typedef struct queue
|
||||
{
|
||||
struct queueitem *list;
|
||||
pthread_mutex_t mutex;
|
||||
char name[64],initflag;
|
||||
} queue_t;
|
||||
|
||||
union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; };
|
||||
typedef union _bits256 bits256;
|
||||
|
||||
#include "mini-gmp.c"
|
||||
#include "uthash.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9"
|
||||
#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA"
|
||||
#define CRYPTO777_RMD160STR "f1dce4182fce875748c4986b240ff7d7bc3fffb0"
|
||||
|
||||
#define KOMODO_PUBTYPE 60
|
||||
|
||||
@@ -736,7 +755,7 @@ int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr
|
||||
}
|
||||
for (i=0; i<len; i++)
|
||||
printf("%02x ",buf[i]);
|
||||
char str[65]; printf("\nhex checkhash.(%s) len.%d mismatch %02x %02x %02x %02x vs %02x %02x %02x %02x\n",coinaddr,len,buf[len-1]&0xff,buf[len-2]&0xff,buf[len-3]&0xff,buf[len-4]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28]);
|
||||
printf("\nhex checkhash.(%s) len.%d mismatch %02x %02x %02x %02x vs %02x %02x %02x %02x\n",coinaddr,len,buf[len-1]&0xff,buf[len-2]&0xff,buf[len-3]&0xff,buf[len-4]&0xff,hash.bytes[31],hash.bytes[30],hash.bytes[29],hash.bytes[28]);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
@@ -832,6 +851,41 @@ int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex)
|
||||
return(n + adjust);
|
||||
}
|
||||
|
||||
char hexbyte(int32_t c)
|
||||
{
|
||||
c &= 0xf;
|
||||
if ( c < 10 )
|
||||
return('0'+c);
|
||||
else if ( c < 16 )
|
||||
return('a'+c-10);
|
||||
else return(0);
|
||||
}
|
||||
|
||||
int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len)
|
||||
{
|
||||
int32_t i;
|
||||
if ( len <= 0 )
|
||||
{
|
||||
hexbytes[0] = 0;
|
||||
return(1);
|
||||
}
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
hexbytes[i*2] = hexbyte((message[i]>>4) & 0xf);
|
||||
hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf);
|
||||
//printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]);
|
||||
}
|
||||
hexbytes[len*2] = 0;
|
||||
//printf("len.%ld\n",len*2+1);
|
||||
return((int32_t)len*2+1);
|
||||
}
|
||||
|
||||
char *bits256_str(char hexstr[65],bits256 x)
|
||||
{
|
||||
init_hexbytes_noT(hexstr,x.bytes,sizeof(x));
|
||||
return(hexstr);
|
||||
}
|
||||
|
||||
int32_t iguana_rwnum(int32_t rwflag,uint8_t *serialized,int32_t len,void *endianedp)
|
||||
{
|
||||
int32_t i; uint64_t x;
|
||||
@@ -883,6 +937,23 @@ int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *
|
||||
return(len);
|
||||
}
|
||||
|
||||
int32_t komodo_scriptitemlen(int32_t *opretlenp,uint8_t *script)
|
||||
{
|
||||
int32_t opretlen,len = 0;
|
||||
if ( (opretlen= script[len++]) >= 0x4c )
|
||||
{
|
||||
if ( opretlen == 0x4c )
|
||||
opretlen = script[len++];
|
||||
else if ( opretlen == 0x4d )
|
||||
{
|
||||
opretlen = script[len++];
|
||||
opretlen = (opretlen << 8) | script[len++];
|
||||
}
|
||||
}
|
||||
*opretlenp = opretlen;
|
||||
return(len);
|
||||
}
|
||||
|
||||
int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen)
|
||||
{
|
||||
int32_t offset = 0;
|
||||
@@ -902,7 +973,260 @@ int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_
|
||||
script[offset++] = opretlen;
|
||||
}
|
||||
} else script[offset++] = opretlen;
|
||||
script[offset] = type; // covered by opretlen
|
||||
memcpy(&script[offset],opret,opretlen);
|
||||
return(opretlen + offset);
|
||||
script[offset++] = type; // covered by opretlen
|
||||
memcpy(&script[offset],opret,opretlen-1);
|
||||
return(offset + opretlen - 1);
|
||||
}
|
||||
|
||||
long _stripwhite(char *buf,int accept)
|
||||
{
|
||||
int32_t i,j,c;
|
||||
if ( buf == 0 || buf[0] == 0 )
|
||||
return(0);
|
||||
for (i=j=0; buf[i]!=0; i++)
|
||||
{
|
||||
buf[j] = c = buf[i];
|
||||
if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') )
|
||||
j++;
|
||||
}
|
||||
buf[j] = 0;
|
||||
return(j);
|
||||
}
|
||||
|
||||
char *clonestr(char *str)
|
||||
{
|
||||
char *clone;
|
||||
if ( str == 0 || str[0] == 0 )
|
||||
{
|
||||
printf("warning cloning nullstr.%p\n",str);
|
||||
#ifdef __APPLE__
|
||||
while ( 1 ) sleep(1);
|
||||
#endif
|
||||
str = (char *)"<nullstr>";
|
||||
}
|
||||
clone = (char *)malloc(strlen(str)+16);
|
||||
strcpy(clone,str);
|
||||
return(clone);
|
||||
}
|
||||
|
||||
int32_t safecopy(char *dest,char *src,long len)
|
||||
{
|
||||
int32_t i = -1;
|
||||
if ( src != 0 && dest != 0 && src != dest )
|
||||
{
|
||||
if ( dest != 0 )
|
||||
memset(dest,0,len);
|
||||
for (i=0; i<len&&src[i]!=0; i++)
|
||||
dest[i] = src[i];
|
||||
if ( i == len )
|
||||
{
|
||||
printf("safecopy: %s too long %ld\n",src,len);
|
||||
#ifdef __APPLE__
|
||||
//getchar();
|
||||
#endif
|
||||
return(-1);
|
||||
}
|
||||
dest[i] = 0;
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
char *parse_conf_line(char *line,char *field)
|
||||
{
|
||||
line += strlen(field);
|
||||
for (; *line!='='&&*line!=0; line++)
|
||||
break;
|
||||
if ( *line == 0 )
|
||||
return(0);
|
||||
if ( *line == '=' )
|
||||
line++;
|
||||
while ( line[strlen(line)-1] == '\r' || line[strlen(line)-1] == '\n' || line[strlen(line)-1] == ' ' )
|
||||
line[strlen(line)-1] = 0;
|
||||
//printf("LINE.(%s)\n",line);
|
||||
_stripwhite(line,0);
|
||||
return(clonestr(line));
|
||||
}
|
||||
|
||||
void komodo_configfile(char *symbol,uint16_t port)
|
||||
{
|
||||
FILE *fp; char fname[512],buf[128],line[4096],*str,*rpcuser,*rpcpassword;
|
||||
srand((uint32_t)time(NULL));
|
||||
sprintf(buf,"%s.conf",symbol);
|
||||
BITCOIND_PORT = port;
|
||||
#ifdef WIN32
|
||||
sprintf(fname,"%s\\%s",GetDataDir(false).string().c_str(),buf);
|
||||
#else
|
||||
sprintf(fname,"%s/%s",GetDataDir(false).string().c_str(),buf);
|
||||
#endif
|
||||
if ( (fp= fopen(fname,"rb")) == 0 )
|
||||
{
|
||||
if ( (fp= fopen(fname,"wb")) != 0 )
|
||||
{
|
||||
fprintf(fp,"rpcuser=user%u\nrpcpassword=pass%u\nrpcport=%u\nserver=1\ntxindex=1\n",rand(),rand(),port);
|
||||
fclose(fp);
|
||||
printf("Created (%s)\n",fname);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(fp);
|
||||
strcpy(fname,GetDataDir(false).string().c_str());
|
||||
#ifdef WIN32
|
||||
while ( fname[strlen(fname)-1] != '\\' )
|
||||
fname[strlen(fname)-1] = 0;
|
||||
strcat(fname,".komodo/komodo.conf");
|
||||
#else
|
||||
while ( fname[strlen(fname)-1] != '/' )
|
||||
fname[strlen(fname)-1] = 0;
|
||||
strcat(fname,".komodo/komodo.conf");
|
||||
#endif
|
||||
printf("KOMODO.(%s)\n",fname);
|
||||
if ( (fp= fopen(fname,"rb")) != 0 )
|
||||
{
|
||||
rpcuser = rpcpassword = 0;
|
||||
while ( fgets(line,sizeof(line),fp) != 0 )
|
||||
{
|
||||
if ( line[0] == '#' )
|
||||
continue;
|
||||
//printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword"));
|
||||
if ( (str= strstr(line,(char *)"rpcuser")) != 0 )
|
||||
rpcuser = parse_conf_line(str,(char *)"rpcuser");
|
||||
else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 )
|
||||
rpcpassword = parse_conf_line(str,(char *)"rpcpassword");
|
||||
}
|
||||
if ( rpcuser != 0 && rpcpassword != 0 )
|
||||
{
|
||||
sprintf(KMDUSERPASS,"%s:%s",rpcuser,rpcpassword);
|
||||
}
|
||||
printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port);
|
||||
if ( rpcuser != 0 )
|
||||
free(rpcuser);
|
||||
if ( rpcpassword != 0 )
|
||||
free(rpcpassword);
|
||||
fclose(fp);
|
||||
} else printf("couldnt open.(%s)\n",fname);
|
||||
}
|
||||
}
|
||||
|
||||
double OS_milliseconds()
|
||||
{
|
||||
struct timeval tv; double millis;
|
||||
gettimeofday(&tv,NULL);
|
||||
millis = ((double)tv.tv_sec * 1000. + (double)tv.tv_usec / 1000.);
|
||||
//printf("tv_sec.%ld usec.%d %f\n",tv.tv_sec,tv.tv_usec,millis);
|
||||
return(millis);
|
||||
}
|
||||
|
||||
void lock_queue(queue_t *queue)
|
||||
{
|
||||
if ( queue->initflag == 0 )
|
||||
{
|
||||
portable_mutex_init(&queue->mutex);
|
||||
queue->initflag = 1;
|
||||
}
|
||||
portable_mutex_lock(&queue->mutex);
|
||||
}
|
||||
|
||||
void queue_enqueue(char *name,queue_t *queue,struct queueitem *item)
|
||||
{
|
||||
if ( queue->name[0] == 0 && name != 0 && name[0] != 0 )
|
||||
strcpy(queue->name,name);
|
||||
if ( item == 0 )
|
||||
{
|
||||
printf("FATAL type error: queueing empty value\n");
|
||||
return;
|
||||
}
|
||||
lock_queue(queue);
|
||||
DL_APPEND(queue->list,item);
|
||||
portable_mutex_unlock(&queue->mutex);
|
||||
}
|
||||
|
||||
struct queueitem *queue_dequeue(queue_t *queue)
|
||||
{
|
||||
struct queueitem *item = 0;
|
||||
lock_queue(queue);
|
||||
if ( queue->list != 0 )
|
||||
{
|
||||
item = queue->list;
|
||||
DL_DELETE(queue->list,item);
|
||||
}
|
||||
portable_mutex_unlock(&queue->mutex);
|
||||
return(item);
|
||||
}
|
||||
|
||||
void *queue_delete(queue_t *queue,struct queueitem *copy,int32_t copysize)
|
||||
{
|
||||
struct queueitem *item = 0;
|
||||
lock_queue(queue);
|
||||
if ( queue->list != 0 )
|
||||
{
|
||||
DL_FOREACH(queue->list,item)
|
||||
{
|
||||
if ( item == copy || (item->allocsize == copysize && memcmp((void *)((long)item + sizeof(struct queueitem)),(void *)((long)copy + sizeof(struct queueitem)),copysize) == 0) )
|
||||
{
|
||||
DL_DELETE(queue->list,item);
|
||||
portable_mutex_unlock(&queue->mutex);
|
||||
printf("name.(%s) deleted item.%p list.%p\n",queue->name,item,queue->list);
|
||||
return(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
portable_mutex_unlock(&queue->mutex);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void *queue_free(queue_t *queue)
|
||||
{
|
||||
struct queueitem *item = 0;
|
||||
lock_queue(queue);
|
||||
if ( queue->list != 0 )
|
||||
{
|
||||
DL_FOREACH(queue->list,item)
|
||||
{
|
||||
DL_DELETE(queue->list,item);
|
||||
free(item);
|
||||
}
|
||||
//printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list);
|
||||
}
|
||||
portable_mutex_unlock(&queue->mutex);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void *queue_clone(queue_t *clone,queue_t *queue,int32_t size)
|
||||
{
|
||||
struct queueitem *ptr,*item = 0;
|
||||
lock_queue(queue);
|
||||
if ( queue->list != 0 )
|
||||
{
|
||||
DL_FOREACH(queue->list,item)
|
||||
{
|
||||
ptr = (struct queueitem *)calloc(1,sizeof(*ptr));
|
||||
memcpy(ptr,item,size);
|
||||
queue_enqueue(queue->name,clone,ptr);
|
||||
}
|
||||
//printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list);
|
||||
}
|
||||
portable_mutex_unlock(&queue->mutex);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t queue_size(queue_t *queue)
|
||||
{
|
||||
int32_t count = 0;
|
||||
struct queueitem *tmp;
|
||||
lock_queue(queue);
|
||||
DL_COUNT(queue->list,tmp,count);
|
||||
portable_mutex_unlock(&queue->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
void iguana_initQ(queue_t *Q,char *name)
|
||||
{
|
||||
struct queueitem *item,*I;
|
||||
memset(Q,0,sizeof(*Q));
|
||||
I = (struct queueitem *)calloc(1,sizeof(*I));
|
||||
strcpy(Q->name,name);
|
||||
queue_enqueue(name,Q,I);
|
||||
if ( (item= queue_dequeue(Q)) != 0 )
|
||||
free(item);
|
||||
}
|
||||
|
||||
@@ -556,6 +556,7 @@ uint8_t NOTARY_PUBKEY33[33];
|
||||
//#define KOMODO_ENABLE_INTEREST enabling this is a hardfork
|
||||
#define KOMODO_SOURCE "KMD"
|
||||
#define KOMODO_PAX
|
||||
#define KOMODO_ZCASH
|
||||
#include "komodo.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -719,13 +720,13 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
|
||||
}
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||
{
|
||||
if ( txin.nSequence == 0xfffffffe && (int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime > nBlockTime )
|
||||
if ( txin.nSequence == 0xfffffffe && (((int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime > nBlockTime) || ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime > nBlockHeight)) )
|
||||
{
|
||||
|
||||
}
|
||||
else if (!txin.IsFinal())
|
||||
{
|
||||
printf("non-final txin seq.%x\n",txin.nSequence);
|
||||
printf("non-final txin seq.%x locktime.%u vs nTime.%u\n",txin.nSequence,(uint32_t)tx.nLockTime,(uint32_t)nBlockTime);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1151,7 +1152,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||
if (!view.HaveCoins(txin.prevout.hash)) {
|
||||
if (pfMissingInputs)
|
||||
*pfMissingInputs = true;
|
||||
fprintf(stderr,"missing inputs\n");
|
||||
//fprintf(stderr,"missing inputs\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
//txNew.nLockTime = (uint32_t)time(NULL) - 60;
|
||||
txNew.vin.resize(1);
|
||||
txNew.vin[0].prevout.SetNull();
|
||||
int32_t i,opretlen; uint8_t opret[8192],*ptr;
|
||||
int32_t i,opretlen; uint8_t opret[256],*ptr;
|
||||
if ( (opretlen= komodo_pax_opreturn(opret,sizeof(opret))) > 0 )
|
||||
{
|
||||
txNew.vout.resize(2);
|
||||
|
||||
@@ -70,8 +70,7 @@ see https://www.gnu.org/licenses/. */
|
||||
#define GMP_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define gmp_assert_nocarry(x) do { \
|
||||
mp_limb_t __cy = x; if ( __cy != 0 ) \
|
||||
; \
|
||||
mp_limb_t __cy = x; if ( __cy != 0 ) {} \
|
||||
assert (__cy == 0); \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
|
||||
if ( pindex != 0 && tx.nLockTime != 0 )
|
||||
{
|
||||
interest = komodo_interest(pindex->nHeight,txout.nValue,tx.nLockTime,pindex->nTime);
|
||||
fprintf(stderr,"TxtoJSON interest %llu %.8f\n",(long long)interest,(double)interest/COIN);
|
||||
//fprintf(stderr,"TxtoJSON interest %llu %.8f\n",(long long)interest,(double)interest/COIN);
|
||||
out.push_back(Pair("interest", ValueFromAmount(interest)));
|
||||
}
|
||||
out.push_back(Pair("n", (int64_t)i));
|
||||
|
||||
@@ -753,7 +753,8 @@ void StartRPCThreads()
|
||||
g_rpcSignals.Started();
|
||||
|
||||
// Launch one async rpc worker. The ability to launch multiple workers is not recommended at present and thus the option is disabled.
|
||||
getAsyncRPCQueue()->addWorker();
|
||||
//for (int i=0; i<32; i++)
|
||||
getAsyncRPCQueue()->addWorker();
|
||||
/*
|
||||
int n = GetArg("-rpcasyncthreads", 1);
|
||||
if (n<1) {
|
||||
|
||||
@@ -469,7 +469,7 @@ class FormatIterator
|
||||
void finish()
|
||||
{
|
||||
// It would be nice if we could do this from the destructor, but we
|
||||
// can't if TINFORMAT_ERROR is used to throw an exception!
|
||||
// can't if TINYFORMAT_ERROR is used to throw an exception!
|
||||
m_fmt = printFormatStringLiteral(m_out, m_fmt);
|
||||
if(*m_fmt != '\0')
|
||||
TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
|
||||
|
||||
753
src/utlist.h
Executable file
753
src/utlist.h
Executable file
@@ -0,0 +1,753 @@
|
||||
/*
|
||||
Copyright (c) 2007-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UTLIST_H
|
||||
#define UTLIST_H
|
||||
|
||||
#define UTLIST_VERSION 1.9.9
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* This file contains macros to manipulate singly and doubly-linked lists.
|
||||
*
|
||||
* 1. LL_ macros: singly-linked lists.
|
||||
* 2. DL_ macros: doubly-linked lists.
|
||||
* 3. CDL_ macros: circular doubly-linked lists.
|
||||
*
|
||||
* To use singly-linked lists, your structure must have a "next" pointer.
|
||||
* To use doubly-linked lists, your structure must "prev" and "next" pointers.
|
||||
* Either way, the pointer to the head of the list must be initialized to NULL.
|
||||
*
|
||||
* ----------------.EXAMPLE -------------------------
|
||||
* struct item {
|
||||
* int id;
|
||||
* struct item *prev, *next;
|
||||
* }
|
||||
*
|
||||
* struct item *list = NULL:
|
||||
*
|
||||
* int main() {
|
||||
* struct item *item;
|
||||
* ... allocate and populate item ...
|
||||
* DL_APPEND(list, item);
|
||||
* }
|
||||
* --------------------------------------------------
|
||||
*
|
||||
* For doubly-linked lists, the append and delete macros are O(1)
|
||||
* For singly-linked lists, append and delete are O(n) but prepend is O(1)
|
||||
* The sort macro is O(n log(n)) for all types of single/double/circular lists.
|
||||
*/
|
||||
|
||||
/* These macros use decltype or the earlier __typeof GNU extension.
|
||||
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
||||
when compiling c++ code), this code uses whatever method is needed
|
||||
or, for VS2008 where neither is available, uses casting workarounds. */
|
||||
#ifdef _MSC_VER /* MS compiler */
|
||||
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
|
||||
#define LDECLTYPE(x) decltype(x)
|
||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||
#define NO_DECLTYPE
|
||||
#define LDECLTYPE(x) char*
|
||||
#endif
|
||||
#elif defined(__ICCARM__)
|
||||
#define NO_DECLTYPE
|
||||
#define LDECLTYPE(x) char*
|
||||
#else /* GNU, Sun and other compilers */
|
||||
#define LDECLTYPE(x) __typeof(x)
|
||||
#endif
|
||||
|
||||
/* for VS2008 we use some workarounds to get around the lack of decltype,
|
||||
* namely, we always reassign our tmp variable to the list head if we need
|
||||
* to dereference its prev/next pointers, and save/restore the real head.*/
|
||||
#ifdef NO_DECLTYPE
|
||||
#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
|
||||
#define _NEXT(elt,list,next) ((char*)((list)->next))
|
||||
#define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
|
||||
/* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
|
||||
#define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
|
||||
#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
|
||||
#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
|
||||
#else
|
||||
#define _SV(elt,list)
|
||||
#define _NEXT(elt,list,next) ((elt)->next)
|
||||
#define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
|
||||
/* #define _PREV(elt,list,prev) ((elt)->prev) */
|
||||
#define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
|
||||
#define _RS(list)
|
||||
#define _CASTASGN(a,b) (a)=(b)
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
|
||||
* Unwieldy variable names used here to avoid shadowing passed-in variables. *
|
||||
*****************************************************************************/
|
||||
#define LL_SORT(list, cmp) \
|
||||
LL_SORT2(list, cmp, next)
|
||||
|
||||
#define LL_SORT2(list, cmp, next) \
|
||||
do { \
|
||||
LDECLTYPE(list) _ls_p; \
|
||||
LDECLTYPE(list) _ls_q; \
|
||||
LDECLTYPE(list) _ls_e; \
|
||||
LDECLTYPE(list) _ls_tail; \
|
||||
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
||||
if (list) { \
|
||||
_ls_insize = 1; \
|
||||
_ls_looping = 1; \
|
||||
while (_ls_looping) { \
|
||||
_CASTASGN(_ls_p,list); \
|
||||
list = NULL; \
|
||||
_ls_tail = NULL; \
|
||||
_ls_nmerges = 0; \
|
||||
while (_ls_p) { \
|
||||
_ls_nmerges++; \
|
||||
_ls_q = _ls_p; \
|
||||
_ls_psize = 0; \
|
||||
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
||||
_ls_psize++; \
|
||||
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
|
||||
if (!_ls_q) break; \
|
||||
} \
|
||||
_ls_qsize = _ls_insize; \
|
||||
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
||||
if (_ls_psize == 0) { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
} else if (_ls_qsize == 0 || !_ls_q) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
} else { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
|
||||
} else { \
|
||||
_CASTASGN(list,_ls_e); \
|
||||
} \
|
||||
_ls_tail = _ls_e; \
|
||||
} \
|
||||
_ls_p = _ls_q; \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
|
||||
} \
|
||||
if (_ls_nmerges <= 1) { \
|
||||
_ls_looping=0; \
|
||||
} \
|
||||
_ls_insize *= 2; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define DL_SORT(list, cmp) \
|
||||
DL_SORT2(list, cmp, prev, next)
|
||||
|
||||
#define DL_SORT2(list, cmp, prev, next) \
|
||||
do { \
|
||||
LDECLTYPE(list) _ls_p; \
|
||||
LDECLTYPE(list) _ls_q; \
|
||||
LDECLTYPE(list) _ls_e; \
|
||||
LDECLTYPE(list) _ls_tail; \
|
||||
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
||||
if (list) { \
|
||||
_ls_insize = 1; \
|
||||
_ls_looping = 1; \
|
||||
while (_ls_looping) { \
|
||||
_CASTASGN(_ls_p,list); \
|
||||
list = NULL; \
|
||||
_ls_tail = NULL; \
|
||||
_ls_nmerges = 0; \
|
||||
while (_ls_p) { \
|
||||
_ls_nmerges++; \
|
||||
_ls_q = _ls_p; \
|
||||
_ls_psize = 0; \
|
||||
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
||||
_ls_psize++; \
|
||||
_SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
|
||||
if (!_ls_q) break; \
|
||||
} \
|
||||
_ls_qsize = _ls_insize; \
|
||||
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
||||
if (_ls_psize == 0) { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
} else if (_ls_qsize == 0 || !_ls_q) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
} else { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
|
||||
} else { \
|
||||
_CASTASGN(list,_ls_e); \
|
||||
} \
|
||||
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
|
||||
_ls_tail = _ls_e; \
|
||||
} \
|
||||
_ls_p = _ls_q; \
|
||||
} \
|
||||
_CASTASGN(list->prev, _ls_tail); \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
|
||||
if (_ls_nmerges <= 1) { \
|
||||
_ls_looping=0; \
|
||||
} \
|
||||
_ls_insize *= 2; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CDL_SORT(list, cmp) \
|
||||
CDL_SORT2(list, cmp, prev, next)
|
||||
|
||||
#define CDL_SORT2(list, cmp, prev, next) \
|
||||
do { \
|
||||
LDECLTYPE(list) _ls_p; \
|
||||
LDECLTYPE(list) _ls_q; \
|
||||
LDECLTYPE(list) _ls_e; \
|
||||
LDECLTYPE(list) _ls_tail; \
|
||||
LDECLTYPE(list) _ls_oldhead; \
|
||||
LDECLTYPE(list) _tmp; \
|
||||
int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
|
||||
if (list) { \
|
||||
_ls_insize = 1; \
|
||||
_ls_looping = 1; \
|
||||
while (_ls_looping) { \
|
||||
_CASTASGN(_ls_p,list); \
|
||||
_CASTASGN(_ls_oldhead,list); \
|
||||
list = NULL; \
|
||||
_ls_tail = NULL; \
|
||||
_ls_nmerges = 0; \
|
||||
while (_ls_p) { \
|
||||
_ls_nmerges++; \
|
||||
_ls_q = _ls_p; \
|
||||
_ls_psize = 0; \
|
||||
for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
|
||||
_ls_psize++; \
|
||||
_SV(_ls_q,list); \
|
||||
if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \
|
||||
_ls_q = NULL; \
|
||||
} else { \
|
||||
_ls_q = _NEXT(_ls_q,list,next); \
|
||||
} \
|
||||
_RS(list); \
|
||||
if (!_ls_q) break; \
|
||||
} \
|
||||
_ls_qsize = _ls_insize; \
|
||||
while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
|
||||
if (_ls_psize == 0) { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
|
||||
} else if (_ls_qsize == 0 || !_ls_q) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
|
||||
} else if (cmp(_ls_p,_ls_q) <= 0) { \
|
||||
_ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
|
||||
_NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
|
||||
if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
|
||||
} else { \
|
||||
_ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
|
||||
_NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
|
||||
if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
|
||||
} \
|
||||
if (_ls_tail) { \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
|
||||
} else { \
|
||||
_CASTASGN(list,_ls_e); \
|
||||
} \
|
||||
_SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
|
||||
_ls_tail = _ls_e; \
|
||||
} \
|
||||
_ls_p = _ls_q; \
|
||||
} \
|
||||
_CASTASGN(list->prev,_ls_tail); \
|
||||
_CASTASGN(_tmp,list); \
|
||||
_SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \
|
||||
if (_ls_nmerges <= 1) { \
|
||||
_ls_looping=0; \
|
||||
} \
|
||||
_ls_insize *= 2; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/******************************************************************************
|
||||
* singly linked list macros (non-circular) *
|
||||
*****************************************************************************/
|
||||
#define LL_PREPEND(head,add) \
|
||||
LL_PREPEND2(head,add,next)
|
||||
|
||||
#define LL_PREPEND2(head,add,next) \
|
||||
do { \
|
||||
(add)->next = head; \
|
||||
head = add; \
|
||||
} while (0)
|
||||
|
||||
#define LL_CONCAT(head1,head2) \
|
||||
LL_CONCAT2(head1,head2,next)
|
||||
|
||||
#define LL_CONCAT2(head1,head2,next) \
|
||||
do { \
|
||||
LDECLTYPE(head1) _tmp; \
|
||||
if (head1) { \
|
||||
_tmp = head1; \
|
||||
while (_tmp->next) { _tmp = _tmp->next; } \
|
||||
_tmp->next=(head2); \
|
||||
} else { \
|
||||
(head1)=(head2); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LL_APPEND(head,add) \
|
||||
LL_APPEND2(head,add,next)
|
||||
|
||||
#define LL_APPEND2(head,add,next) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
(add)->next=NULL; \
|
||||
if (head) { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next) { _tmp = _tmp->next; } \
|
||||
_tmp->next=(add); \
|
||||
} else { \
|
||||
(head)=(add); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LL_DELETE(head,del) \
|
||||
LL_DELETE2(head,del,next)
|
||||
|
||||
#define LL_DELETE2(head,del,next) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
if ((head) == (del)) { \
|
||||
(head)=(head)->next; \
|
||||
} else { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next && (_tmp->next != (del))) { \
|
||||
_tmp = _tmp->next; \
|
||||
} \
|
||||
if (_tmp->next) { \
|
||||
_tmp->next = ((del)->next); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
|
||||
#define LL_APPEND_VS2008(head,add) \
|
||||
LL_APPEND2_VS2008(head,add,next)
|
||||
|
||||
#define LL_APPEND2_VS2008(head,add,next) \
|
||||
do { \
|
||||
if (head) { \
|
||||
(add)->next = head; /* use add->next as a temp variable */ \
|
||||
while ((add)->next->next) { (add)->next = (add)->next->next; } \
|
||||
(add)->next->next=(add); \
|
||||
} else { \
|
||||
(head)=(add); \
|
||||
} \
|
||||
(add)->next=NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LL_DELETE_VS2008(head,del) \
|
||||
LL_DELETE2_VS2008(head,del,next)
|
||||
|
||||
#define LL_DELETE2_VS2008(head,del,next) \
|
||||
do { \
|
||||
if ((head) == (del)) { \
|
||||
(head)=(head)->next; \
|
||||
} else { \
|
||||
char *_tmp = (char*)(head); \
|
||||
while ((head)->next && ((head)->next != (del))) { \
|
||||
head = (head)->next; \
|
||||
} \
|
||||
if ((head)->next) { \
|
||||
(head)->next = ((del)->next); \
|
||||
} \
|
||||
{ \
|
||||
char **_head_alias = (char**)&(head); \
|
||||
*_head_alias = _tmp; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#ifdef NO_DECLTYPE
|
||||
#undef LL_APPEND
|
||||
#define LL_APPEND LL_APPEND_VS2008
|
||||
#undef LL_DELETE
|
||||
#define LL_DELETE LL_DELETE_VS2008
|
||||
#undef LL_DELETE2
|
||||
#define LL_DELETE2 LL_DELETE2_VS2008
|
||||
#undef LL_APPEND2
|
||||
#define LL_APPEND2 LL_APPEND2_VS2008
|
||||
#undef LL_CONCAT /* no LL_CONCAT_VS2008 */
|
||||
#undef DL_CONCAT /* no DL_CONCAT_VS2008 */
|
||||
#endif
|
||||
/* end VS2008 replacements */
|
||||
|
||||
#define LL_COUNT(head,el,counter) \
|
||||
LL_COUNT2(head,el,counter,next) \
|
||||
|
||||
#define LL_COUNT2(head,el,counter,next) \
|
||||
{ \
|
||||
counter = 0; \
|
||||
LL_FOREACH2(head,el,next){ ++counter; } \
|
||||
}
|
||||
|
||||
#define LL_FOREACH(head,el) \
|
||||
LL_FOREACH2(head,el,next)
|
||||
|
||||
#define LL_FOREACH2(head,el,next) \
|
||||
for(el=head;el;el=(el)->next)
|
||||
|
||||
#define LL_FOREACH_SAFE(head,el,tmp) \
|
||||
LL_FOREACH_SAFE2(head,el,tmp,next)
|
||||
|
||||
#define LL_FOREACH_SAFE2(head,el,tmp,next) \
|
||||
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
|
||||
|
||||
#define LL_SEARCH_SCALAR(head,out,field,val) \
|
||||
LL_SEARCH_SCALAR2(head,out,field,val,next)
|
||||
|
||||
#define LL_SEARCH_SCALAR2(head,out,field,val,next) \
|
||||
do { \
|
||||
LL_FOREACH2(head,out,next) { \
|
||||
if ((out)->field == (val)) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_SEARCH(head,out,elt,cmp) \
|
||||
LL_SEARCH2(head,out,elt,cmp,next)
|
||||
|
||||
#define LL_SEARCH2(head,out,elt,cmp,next) \
|
||||
do { \
|
||||
LL_FOREACH2(head,out,next) { \
|
||||
if ((cmp(out,elt))==0) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_REPLACE_ELEM(head, el, add) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
(add)->next = (el)->next; \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} else { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next && (_tmp->next != (el))) { \
|
||||
_tmp = _tmp->next; \
|
||||
} \
|
||||
if (_tmp->next) { \
|
||||
_tmp->next = (add); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LL_PREPEND_ELEM(head, el, add) \
|
||||
do { \
|
||||
LDECLTYPE(head) _tmp; \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
(add)->next = (el); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} else { \
|
||||
_tmp = head; \
|
||||
while (_tmp->next && (_tmp->next != (el))) { \
|
||||
_tmp = _tmp->next; \
|
||||
} \
|
||||
if (_tmp->next) { \
|
||||
_tmp->next = (add); \
|
||||
} \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* doubly linked list macros (non-circular) *
|
||||
*****************************************************************************/
|
||||
#define DL_PREPEND(head,add) \
|
||||
DL_PREPEND2(head,add,prev,next)
|
||||
|
||||
#define DL_PREPEND2(head,add,prev,next) \
|
||||
do { \
|
||||
(add)->next = head; \
|
||||
if (head) { \
|
||||
(add)->prev = (head)->prev; \
|
||||
(head)->prev = (add); \
|
||||
} else { \
|
||||
(add)->prev = (add); \
|
||||
} \
|
||||
(head) = (add); \
|
||||
} while (0)
|
||||
|
||||
#define DL_APPEND(head,add) \
|
||||
DL_APPEND2(head,add,prev,next)
|
||||
|
||||
#define DL_APPEND2(head,add,prev,next) \
|
||||
do { \
|
||||
if (head) { \
|
||||
(add)->prev = (head)->prev; \
|
||||
(head)->prev->next = (add); \
|
||||
(head)->prev = (add); \
|
||||
(add)->next = NULL; \
|
||||
} else { \
|
||||
(head)=(add); \
|
||||
(head)->prev = (head); \
|
||||
(head)->next = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DL_CONCAT(head1,head2) \
|
||||
DL_CONCAT2(head1,head2,prev,next)
|
||||
|
||||
#define DL_CONCAT2(head1,head2,prev,next) \
|
||||
do { \
|
||||
LDECLTYPE(head1) _tmp; \
|
||||
if (head2) { \
|
||||
if (head1) { \
|
||||
_tmp = (head2)->prev; \
|
||||
(head2)->prev = (head1)->prev; \
|
||||
(head1)->prev->next = (head2); \
|
||||
(head1)->prev = _tmp; \
|
||||
} else { \
|
||||
(head1)=(head2); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DL_DELETE(head,del) \
|
||||
DL_DELETE2(head,del,prev,next)
|
||||
|
||||
#define DL_DELETE2(head,del,prev,next) \
|
||||
do { \
|
||||
assert((del)->prev != NULL); \
|
||||
if ((del)->prev == (del)) { \
|
||||
(head)=NULL; \
|
||||
} else if ((del)==(head)) { \
|
||||
(del)->next->prev = (del)->prev; \
|
||||
(head) = (del)->next; \
|
||||
} else { \
|
||||
(del)->prev->next = (del)->next; \
|
||||
if ((del)->next) { \
|
||||
(del)->next->prev = (del)->prev; \
|
||||
} else { \
|
||||
(head)->prev = (del)->prev; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DL_COUNT(head,el,counter) \
|
||||
DL_COUNT2(head,el,counter,next) \
|
||||
|
||||
#define DL_COUNT2(head,el,counter,next) \
|
||||
{ \
|
||||
counter = 0; \
|
||||
DL_FOREACH2(head,el,next){ ++counter; } \
|
||||
}
|
||||
|
||||
#define DL_FOREACH(head,el) \
|
||||
DL_FOREACH2(head,el,next)
|
||||
|
||||
#define DL_FOREACH2(head,el,next) \
|
||||
for(el=head;el;el=(el)->next)
|
||||
|
||||
/* this version is safe for deleting the elements during iteration */
|
||||
#define DL_FOREACH_SAFE(head,el,tmp) \
|
||||
DL_FOREACH_SAFE2(head,el,tmp,next)
|
||||
|
||||
#define DL_FOREACH_SAFE2(head,el,tmp,next) \
|
||||
for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
|
||||
|
||||
/* these are identical to their singly-linked list counterparts */
|
||||
#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
|
||||
#define DL_SEARCH LL_SEARCH
|
||||
#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
|
||||
#define DL_SEARCH2 LL_SEARCH2
|
||||
|
||||
#define DL_REPLACE_ELEM(head, el, add) \
|
||||
do { \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
(add)->next = (el)->next; \
|
||||
if ((el)->next == NULL) { \
|
||||
(add)->prev = (add); \
|
||||
} else { \
|
||||
(add)->prev = (el)->prev; \
|
||||
(add)->next->prev = (add); \
|
||||
} \
|
||||
} else { \
|
||||
(add)->next = (el)->next; \
|
||||
(add)->prev = (el)->prev; \
|
||||
(add)->prev->next = (add); \
|
||||
if ((el)->next == NULL) { \
|
||||
(head)->prev = (add); \
|
||||
} else { \
|
||||
(add)->next->prev = (add); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DL_PREPEND_ELEM(head, el, add) \
|
||||
do { \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
(add)->next = (el); \
|
||||
(add)->prev = (el)->prev; \
|
||||
(el)->prev = (add); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} else { \
|
||||
(add)->prev->next = (add); \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* circular doubly linked list macros *
|
||||
*****************************************************************************/
|
||||
#define CDL_PREPEND(head,add) \
|
||||
CDL_PREPEND2(head,add,prev,next)
|
||||
|
||||
#define CDL_PREPEND2(head,add,prev,next) \
|
||||
do { \
|
||||
if (head) { \
|
||||
(add)->prev = (head)->prev; \
|
||||
(add)->next = (head); \
|
||||
(head)->prev = (add); \
|
||||
(add)->prev->next = (add); \
|
||||
} else { \
|
||||
(add)->prev = (add); \
|
||||
(add)->next = (add); \
|
||||
} \
|
||||
(head)=(add); \
|
||||
} while (0)
|
||||
|
||||
#define CDL_DELETE(head,del) \
|
||||
CDL_DELETE2(head,del,prev,next)
|
||||
|
||||
#define CDL_DELETE2(head,del,prev,next) \
|
||||
do { \
|
||||
if ( ((head)==(del)) && ((head)->next == (head))) { \
|
||||
(head) = 0L; \
|
||||
} else { \
|
||||
(del)->next->prev = (del)->prev; \
|
||||
(del)->prev->next = (del)->next; \
|
||||
if ((del) == (head)) (head)=(del)->next; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CDL_COUNT(head,el,counter) \
|
||||
CDL_COUNT2(head,el,counter,next) \
|
||||
|
||||
#define CDL_COUNT2(head, el, counter,next) \
|
||||
{ \
|
||||
counter = 0; \
|
||||
CDL_FOREACH2(head,el,next){ ++counter; } \
|
||||
}
|
||||
|
||||
#define CDL_FOREACH(head,el) \
|
||||
CDL_FOREACH2(head,el,next)
|
||||
|
||||
#define CDL_FOREACH2(head,el,next) \
|
||||
for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
|
||||
|
||||
#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
|
||||
CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
|
||||
|
||||
#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \
|
||||
for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
|
||||
(el) && ((tmp2)=(el)->next, 1); \
|
||||
((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
|
||||
|
||||
#define CDL_SEARCH_SCALAR(head,out,field,val) \
|
||||
CDL_SEARCH_SCALAR2(head,out,field,val,next)
|
||||
|
||||
#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
|
||||
do { \
|
||||
CDL_FOREACH2(head,out,next) { \
|
||||
if ((out)->field == (val)) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define CDL_SEARCH(head,out,elt,cmp) \
|
||||
CDL_SEARCH2(head,out,elt,cmp,next)
|
||||
|
||||
#define CDL_SEARCH2(head,out,elt,cmp,next) \
|
||||
do { \
|
||||
CDL_FOREACH2(head,out,next) { \
|
||||
if ((cmp(out,elt))==0) break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define CDL_REPLACE_ELEM(head, el, add) \
|
||||
do { \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
if ((el)->next == (el)) { \
|
||||
(add)->next = (add); \
|
||||
(add)->prev = (add); \
|
||||
(head) = (add); \
|
||||
} else { \
|
||||
(add)->next = (el)->next; \
|
||||
(add)->prev = (el)->prev; \
|
||||
(add)->next->prev = (add); \
|
||||
(add)->prev->next = (add); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CDL_PREPEND_ELEM(head, el, add) \
|
||||
do { \
|
||||
assert(head != NULL); \
|
||||
assert(el != NULL); \
|
||||
assert(add != NULL); \
|
||||
(add)->next = (el); \
|
||||
(add)->prev = (el)->prev; \
|
||||
(el)->prev = (add); \
|
||||
(add)->prev->next = (add); \
|
||||
if ((head) == (el)) { \
|
||||
(head) = (add); \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
#endif /* UTLIST_H */
|
||||
@@ -466,7 +466,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||
return wtx.GetHash().GetHex();
|
||||
}
|
||||
|
||||
uint64_t PAX_fiatdest(char *fiatbuf,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *base,int64_t fiatoshis);
|
||||
uint64_t PAX_fiatdest(int32_t tokomodo,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *base,int64_t fiatoshis);
|
||||
int32_t komodo_opreturnscript(uint8_t *script,uint8_t type,uint8_t *opret,int32_t opretlen);
|
||||
#define CRYPTO777_KMDADDR "RXL3YXG2ceaB6C5hfJcN4fvmLH2C34knhA"
|
||||
|
||||
@@ -484,8 +484,8 @@ Value paxdeposit(const Array& params, bool fHelp)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
int64_t fiatoshis = atof(params[1].get_str().c_str()) * COIN;
|
||||
std::string base = params[2].get_str();
|
||||
std::string dest; char fiatbuf[1024];
|
||||
komodoshis = PAX_fiatdest(fiatbuf,destaddr,pubkey33,(char *)params[0].get_str().c_str(),chainActive.Tip()->nHeight,(char *)base.c_str(),fiatoshis);
|
||||
std::string dest;
|
||||
komodoshis = PAX_fiatdest(0,destaddr,pubkey33,(char *)params[0].get_str().c_str(),chainActive.Tip()->nHeight,(char *)base.c_str(),fiatoshis);
|
||||
dest.append(destaddr);
|
||||
CBitcoinAddress destaddress(CRYPTO777_KMDADDR);
|
||||
if (!destaddress.IsValid())
|
||||
@@ -496,17 +496,11 @@ Value paxdeposit(const Array& params, bool fHelp)
|
||||
printf(" ht.%d srcaddr.(%s) %s fiatoshis.%lld -> dest.(%s) komodoshis.%llu\n",chainActive.Tip()->nHeight,(char *)params[0].get_str().c_str(),(char *)base.c_str(),(long long)fiatoshis,destaddr,(long long)komodoshis);
|
||||
EnsureWalletIsUnlocked();
|
||||
CWalletTx wtx;
|
||||
/*std::string account,paxstr,tmp;
|
||||
account.append((char *)"account");
|
||||
paxstr.append(fiatbuf);
|
||||
tmp.append("PAX");
|
||||
wtx.mapValue["PAX"] = paxstr;
|
||||
pwalletMain->SetAddressBook(destaddress.Get(),account,tmp);*/
|
||||
uint8_t opretbuf[64]; int32_t opretlen; uint64_t fee = komodoshis / 1000;
|
||||
if ( fee < 10000 )
|
||||
fee = 10000;
|
||||
opretlen = komodo_opreturnscript(opretbuf,'D',pubkey33,33);
|
||||
SendMoney(destaddress.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,komodoshis);
|
||||
SendMoney(address.Get(),fee,fSubtractFeeFromAmount,wtx,opretbuf,opretlen,komodoshis);
|
||||
return wtx.GetHash().GetHex();
|
||||
}
|
||||
|
||||
|
||||
@@ -2592,14 +2592,11 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend,
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert change txn at random position:
|
||||
nChangePosRet = GetRandInt(txNew.vout.size()+1);
|
||||
nChangePosRet = txNew.vout.size() - 1; // dont change first or last
|
||||
vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosRet;
|
||||
txNew.vout.insert(position, newTxOut);
|
||||
}
|
||||
}
|
||||
else
|
||||
reservekey.ReturnKey();
|
||||
} else reservekey.ReturnKey();
|
||||
|
||||
// Fill vin
|
||||
//
|
||||
@@ -2935,7 +2932,7 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
|
||||
if (!HaveKey(keypool.vchPubKey.GetID()))
|
||||
throw runtime_error("ReserveKeyFromKeyPool(): unknown key in key pool");
|
||||
assert(keypool.vchPubKey.IsValid());
|
||||
LogPrintf("keypool reserve %d\n", nIndex);
|
||||
//LogPrintf("keypool reserve %d\n", nIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2957,7 +2954,7 @@ void CWallet::ReturnKey(int64_t nIndex)
|
||||
LOCK(cs_wallet);
|
||||
setKeyPool.insert(nIndex);
|
||||
}
|
||||
LogPrintf("keypool return %d\n", nIndex);
|
||||
//LogPrintf("keypool return %d\n", nIndex);
|
||||
}
|
||||
|
||||
bool CWallet::GetKeyFromPool(CPubKey& result)
|
||||
|
||||
Reference in New Issue
Block a user