This commit is contained in:
jl777
2017-07-12 12:15:20 +02:00
parent b35ca43347
commit eeaaf55488
6 changed files with 571 additions and 1 deletions

View File

@@ -46,6 +46,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block);
int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char *dest);
#include "komodo_kv.h"
#include "komodo_jumblr.h"
#include "komodo_gateway.h"
#include "komodo_events.h"

View File

@@ -1363,7 +1363,10 @@ void komodo_passport_iteration()
}
refsp = komodo_stateptr(symbol,dest);
if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
refid = 33;
jumblr_iteration();
}
else
{
refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0

525
src/komodo_jumblr.h Executable file
View File

@@ -0,0 +1,525 @@
/******************************************************************************
* Copyright © 2014-2017 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
/*
z_exportkey "zaddr"
z_exportwallet "filename"
z_getoperationstatus (["operationid", ... ])
z_gettotalbalance ( minconf )
z_importkey "zkey" ( rescan )
z_importwallet "filename"
z_listaddresses
z_sendmany "fromaddress" [{"address":... ,"amount":..., "memo":"<hex>"},...] ( minconf ) ( fee )
*/
#define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t"
#define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6"
#define JUMBLR_MAXSECRETADDRS 777
#define JUMBLR_SYNCHRONIZED_BLOCKS 2 // 60
#define JUMBLR_INCR (99.65 / 100)
#define JUMBLR_FEE 0.001
#define JUMBLR_TXFEE 0.01
struct jumblr_item
{
UT_hash_handle hh;
int64_t amount,fee,txfee;
uint32_t spent,pad;
char opid[64],src[128],dest[128],status;
} *Jumblrs;
char Jumblr_secretaddrs[JUMBLR_MAXSECRETADDRS][64],Jumblr_deposit[64];
int32_t Jumblr_numsecretaddrs; // if 0 -> run silent mode
char *jumblr_importaddress(char *addr)
{
char params[1024];
sprintf(params,"[\"%s\", \"%s\", false]",address,address);
return(komodo_issuemethod(KMDUSERPASS,(char *)"importaddress",params,7771));
}
int32_t Jumblr_secretaddrfind(char *searchaddr)
{
int32_t i;
for (i=0; i<Jumblr_numsecretaddrs; i++)
{
if ( strcmp(searchaddr,Jumblr_secretaddrs[i]) == 0 )
return(i);
}
return(-1);
}
int32_t Jumblr_secretaddradd(char *secretaddr) // external
{
int32_t ind;
if ( secretaddr != 0 && secretaddr[0] != 0 && Jumblr_numsecretaddrs < JUMBLR_MAXSECRETADDRS )
{
if ( (ind= Jumblr_secretaddrfind(secretaddr)) < 0 )
{
safecopy(Jumblr_secretaddrs[Jumblr_numsecretaddrs],secretaddr,64);
Jumblr_numsecretaddrs++;
} else return(ind);
}
return(Jumblr_numsecretaddrs);
}
char *Jumblr_depositaddradd(char *depositaddr) // external
{
if ( depositaddr == 0 )
depositaddr = "";
if ( (ind= Jumblr_secretaddrfind(secretaddr)) < 0 )
{
safecopy(Jumblr_deposit,depositaddr,sizeof(Jumblr_deposit));
return(jumblr_importaddress(depositaddr));
} else return(clonestr("{\"error\":\"cant make a secret address a depositaddress\"}"));
}
int32_t Jumblr_secretaddr(char *secretaddr)
{
uint32_t r;
if ( Jumblr_numsecretaddrs > 0 )
{
OS_randombytes((void *)&r,sizeof(r));
r %= Jumblr_numsecretaddrs;
safecopy(secretaddr,Jumblr_secretaddrs[r],64);
}
return(r);
}
int32_t jumblr_addresstype(char *addr)
{
if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 )
return('z');
else if ( strlen(addr) < 40 )
return('t');
else return(-1);
}
struct jumblr_item *jumblr_opidfind(char *opid)
{
struct jumblr_item *ptr;
HASH_FIND(hh,Jumblrs,opid,(int32_t)strlen(opid),ptr);
return(ptr);
}
struct jumblr_item *jumblr_opidadd(char *opid)
{
struct jumblr_item *ptr;
if ( (ptr= jumblr_opidfind(opid)) == 0 )
{
ptr = calloc(1,sizeof(*ptr));
safecopy(ptr->opid,opid,sizeof(ptr->opid));
HASH_ADD_KEYPTR(hh,Jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr);
if ( ptr != jumblr_opidfind(opid) )
printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid);
}
return(ptr);
}
char *jumblr_validateaddress(char *addr)
{
char params[1024];
sprintf(params,"[\"%s\"]",addr);
return(komodo_issuemethod(KMDUSERPASS,(char *)"validateaddress",params,7771));
}
char *jumblr_zgetnewaddress()
{
char params[1024];
sprintf(params,"[]",);
return(komodo_issuemethod(KMDUSERPASS,(char *)"z_getnewaddress",params,7771));
}
char *jumblr_zlistoperationids()
{
char params[1024];
sprintf(params,"[]",);
return(komodo_issuemethod(KMDUSERPASS,(char *)"z_listoperationids",params,7771));
}
char *jumblr_zgetoperationresult(char *opid)
{
char params[1024];
sprintf(params,"[[\"%s\"]]",opid);
return(komodo_issuemethod(KMDUSERPASS,(char *)"z_getoperationresult",params,7771));
}
char *jumblr_zgetoperationstatus(char *opid)
{
char params[1024];
sprintf(params,"[[\"%s\"]]",opid);
return(komodo_issuemethod(KMDUSERPASS,(char *)"z_getoperationstatus",params,7771));
}
char *jumblr_sendt_to_z(char *taddr,char *zaddr,double amount)
{
char params[1024]; double fee = (amount-3*JUMBLR_TXFEE) * JUMBLR_FEE;
if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' )
return(clonestr("{\"error\":\"illegal address in t to z\"}"));
sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE);
return(komodo_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,7771));
}
char *jumblr_sendz_to_z(char *zaddrS,char *zaddrD,double amount)
{
char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE;
if ( jumblr_addresstype(zaddrS) != 'z' || jumblr_addresstype(zaddrD) != 'z' )
return(clonestr("{\"error\":\"illegal address in z to z\"}"));
sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE);
return(komodo_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,7771));
}
char *jumblr_sendz_to_t(char *zaddr,char *taddr,double amount)
{
char params[1024]; double fee = (amount-JUMBLR_TXFEE) * JUMBLR_FEE;
if ( jumblr_addresstype(zaddr) != 'z' || jumblr_addresstype(taddr) != 't' )
return(clonestr("{\"error\":\"illegal address in z to t\"}"));
sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE);
return(komodo_issuemethod(KMDUSERPASS,(char *)"z_sendmany",params,7771));
}
char *jumblr_zlistreceivedbyaddress(char *addr)
{
char params[1024];
sprintf(params,"[\"%s\", 1]",addr);
return(komodo_issuemethod(KMDUSERPASS,(char *)"z_listreceivedbyaddress",params,7771));
}
char *jumblr_getreceivedbyaddress(char *addr)
{
char params[1024];
sprintf(params,"[\"%s\", 1]",addr);
return(komodo_issuemethod(KMDUSERPASS,(char *)"getreceivedbyaddress",params,7771));
}
char *jumblr_importprivkey(char *wifstr)
{
char params[1024];
sprintf(params,"[\"%s\", \"\", false]",wifstr);
return(komodo_issuemethod(KMDUSERPASS,(char *)"importprivkey",params,7771));
}
char *jumblr_zgetbalance(char *addr)
{
char params[1024];
sprintf(params,"[\"%s\", 1]",addr);
return(komodo_issuemethod(KMDUSERPASS,(char *)"z_getbalance",params,7771));
}
char *jumblr_listunspent(char *coinaddr)
{
char params[1024];
sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr);
return(komodo_issuemethod(KMDUSERPASS,(char *)"listunspent",params,7771));
}
int64_t jumblr_receivedby(char *addr)
{
char *retstr; int64_t total = 0;
if ( (retstr= jumblr_getreceivedbyaddress(addr)) != 0 )
{
total = atof(retstr) * SATOSHIDEN;
free(retstr);
}
return(total);
}
int64_t jumblr_balance(char *addr)
{
char *retstr; double val; cJSON *retjson; int32_t i,n; int64_t balance = 0;
if ( jumblr_addresstype(addr) == 't' )
{
if ( (retstr= jumblr_listunspent(addr)) != 0 )
{
printf("jumblr.[%s].(%s)\n","KMD",retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (n= cJSON_GetArraySize(retjson)) > 0 )
for (i=0; i<n; i++)
balance += SATOSHIDEN * jdouble(jitem(retjson,i),"amount");
free_json(retjson);
}
free(retstr);
}
}
else if ( (retstr= jumblr_zgetbalance(addr)) != 0 )
{
if ( (val= atof(retstr)) > SMALLVAL )
balance = val * SATOSHIDEN;
free(retstr);
}
return(balance);
}
int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status)
{
cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount;
/*"params" : {
"fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5",
"amounts" : [
{
"address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft",
"amount" : 3.00000000
}
],
"minconf" : 1,
"fee" : 0.00010000
}*/
if ( (params= jobj(item,"params")) != 0 )
{
//printf("params.(%s)\n",jprint(params,0));
if ( (from= jstr(params,"fromaddress")) != 0 )
{
safecopy(ptr->src,from,sizeof(ptr->src));
}
if ( (amounts= jarray(&n,params,"amounts")) != 0 )
{
for (i=0; i<n; i++)
{
dest = jitem(amounts,i);
//printf("%s ",jprint(dest,0));
if ( (addr= jstr(dest,"address")) != 0 && (amount= jdouble(dest,"amount")*SATOSHIDEN) > 0 )
{
if ( strcmp(addr,JUMBLR_ADDR) == 0 )
ptr->fee = amount;
else
{
ptr->amount = amount;
safecopy(ptr->dest,addr,sizeof(ptr->dest));
}
}
}
}
ptr->txfee = jdouble(params,"fee") * SATOSHIDEN;
}
return(1);
}
void jumblr_opidupdate(struct jumblr_item *ptr)
{
char *retstr,*status; cJSON *retjson,*item;
if ( ptr->status == 0 )
{
if ( (retstr= jumblr_zgetoperationstatus(ptr->opid)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( cJSON_GetArraySize(retjson) == 1 )
{
item = jitem(retjson,0);
//printf("%s\n",jprint(item,0));
if ( (status= jstr(item,"status")) != 0 )
{
if ( strcmp(status,"success") == 0 )
{
ptr->status = jumblr_itemset(ptr,item,status);
if ( (jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->src) == 'z' && strcmp(ptr->src,Jumblr_deposit) != 0) || (jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->src) == 't' && Jumblr_secretaddrfind(ptr->dest) < 0) )
{
printf("a non-jumblr t->z pruned\n");
free(jumblr_zgetoperationresult(ptr->opid));
ptr->status = -1;
}
}
else if ( strcmp(status,"failed") == 0 )
{
printf("jumblr_opidupdate %s failed\n",ptr->opid);
free(jumblr_zgetoperationresult(ptr->opid));
ptr->status = -1;
}
}
}
free_json(retjson);
}
free(retstr);
}
}
}
void jumblr_prune(struct jumblr_item *ptr)
{
struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1;
printf("jumblr_prune %s\n",ptr->opid);
strcpy(oldsrc,ptr->src);
free(jumblr_zgetoperationresult(ptr->opid));
while ( flag != 0 )
{
flag = 0;
HASH_ITER(hh,Jumblrs,ptr,tmp)
{
if ( strcmp(oldsrc,ptr->dest) == 0 )
{
printf("jumblr_prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest);
free(jumblr_zgetoperationresult(ptr->opid));
strcpy(oldsrc,ptr->src);
flag = 1;
break;
}
}
}
}
void jumblr_opidsupdate()
{
char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr;
if ( (retstr= jumblr_zlistoperationids()) != 0 )
{
if ( (array= cJSON_Parse(retstr)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
if ( (ptr= jumblr_opidadd(jstri(array,i))) != 0 )
{
if ( ptr->status == 0 )
jumblr_opidupdate(ptr);
//printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount));
if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 't' )
jumblr_prune(ptr);
}
}
}
free_json(array);
}
free(retstr);
}
}
void jumblr_iteration()
{
static int32_t lastheight;
char *zaddr,*retstr; int32_t iter,height,counter,chosen_one,n; uint64_t amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint8_t r,s;
height = (int32_t)chainActive.Tip()->nHeight;
if ( lastheight == height )
return;
if ( (height % JUMBLR_SYNCHRONIZED_BLOCKS) != 0 )
return;
fee = JUMBLR_INCR * JUMBLR_FEE;
OS_randombytes(&r,sizeof(r));
s = ((r >> 2) % 3);
switch ( s )
{
case 0: // public -> z, need to importprivkey
if ( Jumblr_deposit[0] != 0 && (total= jumblr_balance(Jumblr_deposit)) >= (JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))*SATOSHIDEN )
{
if ( (zaddr= jumblr_zgetnewaddress()) != 0 )
{
amount = 0;
if ( (height % (JUMBLR_SYNCHRONIZED_BLOCKS*JUMBLR_SYNCHRONIZED_BLOCKS)) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) )
amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE);
else if ( (r & 3) == 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) )
amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE);
else amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE);
if ( amount > 0 && (retstr= jumblr_sendt_to_z(Jumblr_deposit,zaddr,dstr(amount))) != 0 )
{
printf("sendt_to_z.(%s)\n",retstr);
free(retstr);
}
free(zaddr);
} else printf("no zaddr from jumblr_zgetnewaddress\n");
}
else if ( Jumblr_deposit[0] != 0 )
printf("%s total %.8f vs %.8f\n",Jumblr_deposit,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE)));
break;
case 1: // z -> z
jumblr_opidsupdate();
chosen_one = -1;
for (iter=counter=0; iter<2; iter++)
{
counter = n = 0;
HASH_ITER(hh,Jumblrs,ptr,tmp)
{
if ( jumblr_addresstype(ptr->src) == 't' && jumblr_addresstype(ptr->dest) == 'z' )
{
if ( ptr->spent == 0 && (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
{
if ( iter == 1 && counter == chosen_one )
{
if ( (zaddr= jumblr_zgetnewaddress()) != 0 )
{
if ( (retstr= jumblr_sendz_to_z(ptr->dest,zaddr,dstr(total))) != 0 )
{
printf("n.%d counter.%d chosen_one.%d sendz_to_z.(%s)\n",n,counter,chosen_one,retstr);
free(retstr);
}
ptr->spent = (uint32_t)time(NULL);
free(zaddr);
break;
}
}
counter++;
}
}
n++;
}
if ( counter == 0 )
break;
if ( iter == 0 )
{
OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one));
if ( chosen_one < 0 )
chosen_one = -chosen_one;
chosen_one %= counter;
printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n);
}
}
break;
case 2: // z -> public
if ( Jumblr_numsecretaddrs > 0 )
{
jumblr_opidsupdate();
chosen_one = -1;
for (iter=0; iter<2; iter++)
{
counter = n = 0;
HASH_ITER(hh,Jumblrs,ptr,tmp)
{
if ( jumblr_addresstype(ptr->src) == 'z' && jumblr_addresstype(ptr->dest) == 'z' )
{
if ( ptr->spent == 0 && (total= jumblr_balance(ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN )
{
if ( iter == 1 && n == chosen_one )
{
Jumblr_secretaddr(secretaddr);
if ( (retstr= jumblr_sendz_to_t(ptr->dest,secretaddr,dstr(total))) != 0 )
{
printf("sendz_to_t.(%s)\n",retstr);
free(retstr);
}
ptr->spent = (uint32_t)time(NULL);
break;
}
counter++;
}
}
n++;
}
if ( counter == 0 )
break;
if ( iter == 0 )
{
OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one));
if ( chosen_one < 0 )
chosen_one = -chosen_one;
chosen_one %= counter;
printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n);
}
}
}
break;
}
}

View File

@@ -41,6 +41,8 @@ using namespace std;
* Or alternatively, create a specific query method for the information.
**/
char *Jumblr_depositaddradd(char *depositaddr);
int32_t Jumblr_secretaddradd(char *secretaddr);
uint64_t komodo_interestsum();
int32_t komodo_longestchain();
int32_t komodo_notarized_height(uint256 *hashp,uint256 *txidp);
@@ -48,7 +50,7 @@ int32_t komodo_whoami(char *pubkeystr,int32_t height);
extern int32_t KOMODO_LASTMINED;
extern char ASSETCHAINS_SYMBOL[];
int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp);
#define KOMODO_VERSION "0.1.0"
#define KOMODO_VERSION "0.1.1"
UniValue getinfo(const UniValue& params, bool fHelp)
{
@@ -188,6 +190,40 @@ public:
};
#endif
UniValue jumblr_deposit(const UniValue& params, bool fHelp)
{
char *retstr; UniValue result(UniValue::VOBJ);
if (fHelp || params.size() != 1)
throw runtime_error("jumblr_deposit \"depositaddress\"\n");
CBitcoinAddress address(params[0].get_str());
bool isValid = address.IsValid();
if ( isValid != 0 )
{
string addr = params[0].get_str();
if ( (retstr= Jumblr_depositaddradd(addr.c_str())) == 0 )
result.push_back(Pair("result", (char *)"null return from Jumblr_depositaddradd"));
else result.push_back(Pair("result", retstr));
} else result.push_back(Pair("error", "invalid address"));
return(result);
}
UniValue jumblr_secret(const UniValue& params, bool fHelp)
{
int32_t retval; UniValue result(UniValue::VOBJ);
if (fHelp || params.size() != 1)
throw runtime_error("jumblr_secret \"secretaddress\"\n");
CBitcoinAddress address(params[0].get_str());
bool isValid = address.IsValid();
if ( isValid != 0 )
{
string addr = params[0].get_str();
retval = Jumblr_secretaddradd(addr.c_str());
result.push_back(Pair("result", "success"));
result.push_back(Pair("num", retval));
} else result.push_back(Pair("error", "invalid address"));
return(result);
}
UniValue validateaddress(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)

View File

@@ -336,6 +336,8 @@ static const CRPCCommand vRPCCommands[] =
{ "util", "estimatefee", &estimatefee, true },
{ "util", "estimatepriority", &estimatepriority, true },
{ "util", "z_validateaddress", &z_validateaddress, true }, /* uses wallet if enabled */
{ "util", "jumblr_deposit", &jumblr_depositaddr, true },
{ "util", "jumblr_secret", &jumblr_secretaddr, true },
/* Not shown in help */
{ "hidden", "invalidateblock", &invalidateblock, true },

View File

@@ -246,6 +246,9 @@ extern UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp);
extern UniValue zc_raw_receive(const UniValue& params, bool fHelp);
extern UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp);
extern UniValue jumblr_deposit(const UniValue& params, bool fHelp);
extern UniValue jumblr_secret(const UniValue& params, bool fHelp);
extern UniValue getrawtransaction(const UniValue& params, bool fHelp); // in rcprawtransaction.cpp
extern UniValue listunspent(const UniValue& params, bool fHelp);
extern UniValue lockunspent(const UniValue& params, bool fHelp);