Merge branch 'FSM' of https://github.com/jl777/komodo into jl777-FSM

fix
This commit is contained in:
blackjok3r
2018-11-01 16:46:24 +08:00
13 changed files with 420 additions and 160 deletions

View File

@@ -24,10 +24,11 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys); std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys);
std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount); std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount);
std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount); std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount);
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector<uint8_t> withdrawpub,int64_t amount); std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount);
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin); UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin);
std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid,std::string refcoin,uint256 cointxid); std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid,std::string refcoin,uint256 cointxid);
std::string GatewaysMultisig(uint64_t txfee,std::string refcoin,uint256 bindtxid,uint256 withdrawtxid,char *txidaddr); UniValue GatewaysMultisig(char *txidaddr);
std::string GatewaysPartialSign(uint64_t txfee,uint256 txidaddr,std::string refcoin, std::string hex);
// CCcustom // CCcustom
UniValue GatewaysInfo(uint256 bindtxid); UniValue GatewaysInfo(uint256 bindtxid);

View File

@@ -276,10 +276,11 @@ int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *
abovei = belowi = -1; abovei = belowi = -1;
for (above=below=i=0; i<numunspents; i++) for (above=below=i=0; i<numunspents; i++)
{ {
if ( numunspents > 150 ) { // Filter to randomly pick utxo to avoid conflicts, and having multiple CC choose the same ones.
if ( (rand() % 100) < 80 ) //if ( numunspents > 500 ) {
continue; // if ( (rand() % 100) < 80 )
} // continue;
//}
if ( (atx_value= utxos[i].nValue) <= 0 ) if ( (atx_value= utxos[i].nValue) <= 0 )
continue; continue;
if ( atx_value == value ) if ( atx_value == value )

View File

@@ -193,7 +193,7 @@ bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)
strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str()); strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str());
return(true); return(true);
} }
fprintf(stderr,"ExtractDestination failed\n"); //fprintf(stderr,"ExtractDestination failed\n");
return(false); return(false);
} }

View File

@@ -64,7 +64,7 @@ Possible third iteration:
int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub, CPubKey destpub,int32_t v) int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub, CPubKey destpub,int32_t v)
{ {
char destaddr[64],channeladdr[64]; char destaddr[65],channeladdr[65];
GetCCaddress1of2(cp,channeladdr,srcpub,destpub); GetCCaddress1of2(cp,channeladdr,srcpub,destpub);
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
@@ -77,7 +77,7 @@ int64_t IsChannelsvout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey
int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub,int32_t v) int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,CPubKey srcpub,int32_t v)
{ {
char destaddr[64],ccaddr[64]; char destaddr[65],ccaddr[65];
GetCCaddress(cp,ccaddr,srcpub); GetCCaddress(cp,ccaddr,srcpub);
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
@@ -364,7 +364,7 @@ bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, CTransaction openTx, uint256 &prevtxid) int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, CTransaction openTx, uint256 &prevtxid)
{ {
char coinaddr[64]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t param1; char coinaddr[65]; int64_t param2,totalinputs = 0,numvouts; uint256 txid=zeroid,tmp_txid,hashBlock,param3; CTransaction tx; int32_t param1;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
CPubKey srcpub,destpub; CPubKey srcpub,destpub;
uint8_t myprivkey[32]; uint8_t myprivkey[32];
@@ -692,7 +692,7 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
UniValue ChannelsInfo(uint256 channeltxid) UniValue ChannelsInfo(uint256 channeltxid)
{ {
UniValue result(UniValue::VOBJ); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,prevtxid; UniValue result(UniValue::VOBJ); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,prevtxid;
struct CCcontract_info *cp,C; char myCCaddr[64],addr[64],str1[256],str2[64]; int32_t vout,numvouts,param1,numpayments; struct CCcontract_info *cp,C; char myCCaddr[65],addr[65],str1[256],str2[256]; int32_t vout,numvouts,param1,numpayments;
int64_t nValue,param2,payment; CPubKey srcpub,destpub,mypk; int64_t nValue,param2,payment; CPubKey srcpub,destpub,mypk;
std::vector<std::pair<CAddressIndexKey, CAmount> > txids; std::vector<std::pair<CAddressIndexKey, CAmount> > txids;

View File

@@ -19,6 +19,8 @@
#include <memory.h> #include <memory.h>
#include "cJSON.c" #include "cJSON.c"
bits256 zeroid;
char hexbyte(int32_t c) char hexbyte(int32_t c)
{ {
c &= 0xf; c &= 0xf;
@@ -139,7 +141,7 @@ long _stripwhite(char *buf,int accept)
char *clonestr(char *str) char *clonestr(char *str)
{ {
char *clone; char *clone;
if ( str == 0 || str[0] == 0 ) if ( str == 0 || str[0]==0)
{ {
printf("warning cloning nullstr.%p\n",str); printf("warning cloning nullstr.%p\n",str);
//#ifdef __APPLE__ //#ifdef __APPLE__
@@ -331,6 +333,7 @@ cJSON *get_komodocli(char *refcoin,char **retstrp,char *acname,char *method,char
*retstrp = 0; *retstrp = 0;
if ( (jsonstr= filestr(&fsize,fname)) != 0 ) if ( (jsonstr= filestr(&fsize,fname)) != 0 )
{ {
jsonstr[strlen(jsonstr)-1]='\0';
//fprintf(stderr,"%s -> jsonstr.(%s)\n",cmdstr,jsonstr); //fprintf(stderr,"%s -> jsonstr.(%s)\n",cmdstr,jsonstr);
if ( (jsonstr[0] != '{' && jsonstr[0] != '[') || (retjson= cJSON_Parse(jsonstr)) == 0 ) if ( (jsonstr[0] != '{' && jsonstr[0] != '[') || (retjson= cJSON_Parse(jsonstr)) == 0 )
*retstrp = jsonstr; *retstrp = jsonstr;
@@ -357,7 +360,7 @@ bits256 komodobroadcast(char *refcoin,char *acname,cJSON *hexjson)
retstr[64] = 0; retstr[64] = 0;
decode_hex(txid.bytes,32,retstr); decode_hex(txid.bytes,32,retstr);
} }
fprintf(stderr,"broadcast %s txid.(%s)\n",acname,bits256_str(str,txid)); fprintf(stderr,"broadcast %s txid.(%s)\n",strlen(acname)>0?acname:refcoin,bits256_str(str,txid));
free(retstr); free(retstr);
} }
} }
@@ -530,6 +533,23 @@ cJSON *get_rawtransaction(char *refcoin,char *acname,bits256 txid)
return(0); return(0);
} }
int32_t validateaddress(char *refcoin,char *acname,char *depositaddr, char* compare)
{
cJSON *retjson; char *retstr; int32_t res=0;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"validateaddress",depositaddr,"","","")) != 0 )
{
if (is_cJSON_True(jobj(retjson,compare)) != 0 ) res=1;
free_json(retjson);
}
else if ( retstr != 0 )
{
fprintf(stderr,"validateaddress.(%s) %s error.(%s)\n",refcoin,acname,retstr);
free(retstr);
}
return (res);
}
void importaddress(char *refcoin,char *acname,char *depositaddr) void importaddress(char *refcoin,char *acname,char *depositaddr)
{ {
cJSON *retjson; char *retstr; cJSON *retjson; char *retstr;
@@ -545,6 +565,24 @@ void importaddress(char *refcoin,char *acname,char *depositaddr)
} }
} }
void addmultisigaddress(char *refcoin,char *acname,int32_t M, char *pubkeys,char *bindtxidstr)
{
cJSON *retjson; char *retstr,Mstr[10],tmp[128];
sprintf(Mstr,"%d",M);
sprintf(tmp,"\"%s\"",bindtxidstr);
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"addmultisigaddress",Mstr,pubkeys,tmp,"")) != 0 )
{
fprintf(stderr,"unexpected addmultisigaddress json.(%s)\n",jprint(retjson,0));
free(retstr);
}
else if ( retstr != 0 )
{
printf("addmultisigaddress.(%s)\n",retstr);
free_json(retjson);
}
}
cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required) cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required)
{ {
cJSON *vin,*item,*vins = cJSON_CreateArray(); int32_t i,n,v; int64_t satoshis; bits256 txid; cJSON *vin,*item,*vins = cJSON_CreateArray(); int32_t i,n,v; int64_t satoshis; bits256 txid;
@@ -584,7 +622,7 @@ char *createmultisig(char *refcoin,char *acname,char *depositaddr,char *signerad
return(0); return(0);
} }
satoshis -= txfee; satoshis -= txfee;
sprintf(array,"[\"%s\"]",depositaddr); sprintf(array,"\'[\"%s\"]\'",depositaddr);
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"listunspent","1","99999999",array,"")) != 0 ) if ( (retjson= get_komodocli(refcoin,&retstr,acname,"listunspent","1","99999999",array,"")) != 0 )
{ {
//createrawtransaction [{"txid":"id","vout":n},...] {"address":amount,...} //createrawtransaction [{"txid":"id","vout":n},...] {"address":amount,...}
@@ -599,9 +637,12 @@ char *createmultisig(char *refcoin,char *acname,char *depositaddr,char *signerad
change = (total - satoshis); change = (total - satoshis);
jaddnum(vouts,depositaddr,(double)change/SATOSHIDEN); jaddnum(vouts,depositaddr,(double)change/SATOSHIDEN);
} }
char *argA,*argB; char *tmpA=jprint(vins,1);
argA = jprint(vins,1); char *tmpB=jprint(vouts,1);
argB = jprint(vouts,1); char *argA=malloc(sizeof(char) * (strlen(tmpA)+3));
char *argB=malloc(sizeof(char) * (strlen(tmpB)+3));
sprintf(argA,"\'%s\'",tmpA);
sprintf(argB,"\'%s\'",tmpB);
if ( (retjson2= get_komodocli(refcoin,&txstr,acname,"createrawtransaction",argA,argB,"","")) != 0 ) if ( (retjson2= get_komodocli(refcoin,&txstr,acname,"createrawtransaction",argA,argB,"","")) != 0 )
{ {
printf("createmultisig: unexpected JSON2.(%s)\n",jprint(retjson2,0)); printf("createmultisig: unexpected JSON2.(%s)\n",jprint(retjson2,0));
@@ -609,10 +650,13 @@ char *createmultisig(char *refcoin,char *acname,char *depositaddr,char *signerad
} }
else if ( txstr == 0 ) else if ( txstr == 0 )
printf("createmultisig: null txstr and JSON2\n"); printf("createmultisig: null txstr and JSON2\n");
free(tmpA);
free(tmpB);
free(argA); free(argA);
free(argB); free(argB);
} }
} }
free_json(retjson);
} }
else if ( retstr != 0 ) else if ( retstr != 0 )
{ {
@@ -628,7 +672,7 @@ cJSON *addmultisignature(char *refcoin,char *acname,char *signeraddr,char *rawtx
char *retstr,*hexstr; cJSON *retjson; char *retstr,*hexstr; cJSON *retjson;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"signrawtransaction",rawtx,"","","")) != 0 ) if ( (retjson= get_komodocli(refcoin,&retstr,acname,"signrawtransaction",rawtx,"","","")) != 0 )
{ {
if ( jint(retjson,"complete") != 0 ) if ( is_cJSON_True(jobj(retjson,"complete")) != 0 )
return(retjson); return(retjson);
else if ( (hexstr= jstr(retjson,"hex")) != 0 && strlen(hexstr) > strlen(rawtx) ) else if ( (hexstr= jstr(retjson,"hex")) != 0 && strlen(hexstr) > strlen(rawtx) )
{ {
@@ -640,18 +684,36 @@ cJSON *addmultisignature(char *refcoin,char *acname,char *signeraddr,char *rawtx
return(0); return(0);
} }
char *get_gatewaysmultisig(char *refcoin,char *acname,char *bindtxidstr,char *withtxidstr,char *txidaddr) char *get_gatewaysmultisig(char *refcoin,char *acname,char *txidaddr,int32_t *K)
{ {
char *retstr,*hexstr,*hex=0; cJSON *retjson; char *retstr,*hexstr,*hex=0; cJSON *retjson;
if ( (retjson= get_komodocli("KMD",&retstr,acname,"gatewaysmultisig",bindtxidstr,refcoin,withtxidstr,txidaddr)) != 0 ) if ( (retjson= get_komodocli("KMD",&retstr,acname,"gatewaysmultisig",txidaddr,"","","")) != 0 )
{ {
if ( (hexstr= jstr(retjson,"hex")) != 0 ) if ((hexstr=jstr(retjson,"hex")) != 0 )
hex = clonestr(hexstr); {
if (strlen(hexstr)>0) hex = clonestr(hexstr);
}
*K=jint(retjson,"number_of_signs");
free_json(retjson); free_json(retjson);
} }
return(hex); return(hex);
} }
bits256 gatewayspartialsign(char *refcoin,char *acname,bits256 txid,char *hex)
{
char str[65],*retstr; cJSON *retjson;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewayspartialsign",bits256_str(str,txid),refcoin,hex,"")) != 0 )
{
return(komodobroadcast(refcoin,acname,retjson));
}
else if ( retstr != 0 )
{
printf("error parsing gatewayspartialsing.(%s)\n",retstr);
free(retstr);
}
return (zeroid);
}
void gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid,char *coin,bits256 cointxid) void gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid,char *coin,bits256 cointxid)
{ {
char str[65],str2[65],*retstr; cJSON *retjson; char str[65],str2[65],*retstr; cJSON *retjson;
@@ -668,9 +730,9 @@ void gatewaysmarkdone(char *refcoin,char *acname,bits256 withtxid,char *coin,bit
} }
} }
int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *Mp,int32_t *Np,char *bindtxidstr,char *coin,char *oraclestr) int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *Mp,int32_t *Np,char *bindtxidstr,char *coin,char *oraclestr, char **pubkeys)
{ {
char *oracle,*retstr,*name,*deposit; cJSON *retjson; char *oracle,*retstr,*name,*deposit,temp[128]; cJSON *retjson,*pubarray; int32_t n;
if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewaysinfo",bindtxidstr,"","","")) != 0 ) if ( (retjson= get_komodocli(refcoin,&retstr,acname,"gatewaysinfo",bindtxidstr,"","","")) != 0 )
{ {
if ( (oracle= jstr(retjson,"oracletxid")) != 0 && strcmp(oracle,oraclestr) == 0 && (deposit= jstr(retjson,"deposit")) != 0 ) if ( (oracle= jstr(retjson,"oracletxid")) != 0 && strcmp(oracle,oraclestr) == 0 && (deposit= jstr(retjson,"deposit")) != 0 )
@@ -680,9 +742,23 @@ int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *M
{ {
*Mp = jint(retjson,"M"); *Mp = jint(retjson,"M");
*Np = jint(retjson,"N"); *Np = jint(retjson,"N");
//printf("(%s)\n",jprint(retjson,0)); }
} else printf("coin.%s vs %s\n",jstr(retjson,"coin"),coin); else printf("coin.%s vs %s\n",jstr(retjson,"coin"),coin);
} else printf("%s != %s\n",oracle,oraclestr); if ((pubarray=jarray(&n,retjson,"pubkeys"))!=0)
{
*pubkeys=malloc((sizeof(char)*70*n)+64);
sprintf(*pubkeys,"\"[");
for (int i=0;i<n;i++)
{
sprintf(temp,"\\\"%s\\\"",jstri(pubarray,i));
if (i<n-1) strcat(temp,",");
strcat(*pubkeys,temp);
}
sprintf(temp,"]\"");
strcat(*pubkeys,temp);
}
}
else printf("%s != %s\n",oracle,oraclestr);
free_json(retjson); free_json(retjson);
} }
else if ( retstr != 0 ) else if ( retstr != 0 )
@@ -697,15 +773,14 @@ int32_t get_gatewaysinfo(char *refcoin,char *acname,char *depositaddr,int32_t *M
int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinaddr) int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinaddr)
{ {
cJSON *txobj,*vouts,*vout,*sobj,*addresses; char *addr,str[65]; int32_t i,j,n,numvouts,retval = 0; cJSON *txobj,*vouts,*vout,*vins,*vin,*sobj,*addresses; char *addr,str[65]; int32_t i,j,n,numarray,retval = 0, hasvout=0;
if ( (txobj= get_rawtransaction(refcoin,acname,txid)) != 0 ) if ( (txobj= get_rawtransaction(refcoin,acname,txid)) != 0 )
{ {
if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 ) if ( (vouts= jarray(&numarray,txobj,"vout")) != 0 )
{ {
for (i=0; i<numvouts; i++) for (i=0; i<numarray; i++)
{ {
vout = jitem(vouts,i); if ((vout = jitem(vouts,i)) !=0 && (sobj= jobj(vout,"scriptPubKey")) != 0 )
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 )
{ {
if ( (addresses= jarray(&n,sobj,"addresses")) != 0 ) if ( (addresses= jarray(&n,sobj,"addresses")) != 0 )
{ {
@@ -715,26 +790,55 @@ int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinadd
if ( strcmp(addr,coinaddr) == 0 ) if ( strcmp(addr,coinaddr) == 0 )
{ {
//fprintf(stderr,"found %s in %s v%d\n",coinaddr,bits256_str(str,txid),i); //fprintf(stderr,"found %s in %s v%d\n",coinaddr,bits256_str(str,txid),i);
retval = 1; hasvout = 1;
break;
} }
} }
} }
} }
if (hasvout==1) break;
} }
} }
// if (hasvout==1 && (vins=jarray(&numarray,txobj,"vin"))!=0)
// {
// for (int i=0;i<numarray;i++)
// {
// if ((vin=jitem(vins,i))!=0 && validateaddress(refcoin,acname,jstr(vin,"address"),"ismine")!=0)
// {
// retval=1;
// break;
// }
// }
// }
free_json(txobj); free_json(txobj);
} }
return(retval); return(hasvout);
} }
int32_t coinaddrexists(char *refcoin,char *acname,char *coinaddr) int32_t markerfromthisnodeorunconfirmed(char *refcoin,char *acname,char *coinaddr)
{ {
cJSON *array; bits256 txid; int32_t i,n,num=0; cJSON *array,*item,*rawtx,*vins,*vin; bits256 txid,tmptxid; int32_t i,n,m,num=0; char *retstr;
if ( (array= get_addressutxos(refcoin,acname,coinaddr)) != 0 ) if ( (array= get_addressutxos(refcoin,acname,coinaddr)) != 0 )
{ {
num = cJSON_GetArraySize(array); n=cJSON_GetArraySize(array);
for (i=0; i<n; i++)
{
if ((item=jitem(array,i))!=0 && (bits256_nonz(tmptxid=jbits256(item,"txid")))!=0 && (rawtx=get_rawtransaction(refcoin,acname,tmptxid))!=0 && (vins=jarray(&m,rawtx,"vin"))!=0)
{
for (int j=0;j<m;j++)
{
if ((vin=jitem(vins,j))!=0 && validateaddress(refcoin,acname,jstr(vin,"address"),"ismine")!=0)
{
num=1;
break;
}
}
}
if (num==1) break;
}
free_json(array); free_json(array);
} else return(-1); }
else return(-1);
if ( num == 0 ) if ( num == 0 )
{ {
if ( (array= get_rawmempool(refcoin,acname)) != 0 ) if ( (array= get_rawmempool(refcoin,acname)) != 0 )
@@ -766,7 +870,7 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
/// if enough sigs, sendrawtransaction and when it confirms spend marker (txid.2) /// if enough sigs, sendrawtransaction and when it confirms spend marker (txid.2)
/// if not enough sigs, post partially signed to acname with marker2 /// if not enough sigs, post partially signed to acname with marker2
// monitor marker2, for the partially signed withdraws // monitor marker2, for the partially signed withdraws
cJSON *retjson,*pending,*item,*clijson; char str[65],*rawtx,*coinstr,*txidaddr,*signeraddr,*depositaddr,*withdrawaddr; int32_t i,j,n,retval,processed = 0; bits256 txid,cointxid,origtxid,zeroid; int64_t satoshis; cJSON *retjson,*pending,*item,*clijson; char str[65],*rawtx,*coinstr,*txidaddr,*signeraddr,*depositaddr,*withdrawaddr; int32_t i,j,n,K,retval,processed = 0; bits256 txid,cointxid,origtxid; int64_t satoshis;
memset(&zeroid,0,sizeof(zeroid)); memset(&zeroid,0,sizeof(zeroid));
if ( (retjson= get_gatewayspending("KMD",acname,bindtxidstr)) != 0 ) if ( (retjson= get_gatewayspending("KMD",acname,bindtxidstr)) != 0 )
{ {
@@ -783,17 +887,16 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
//process item.0 {"txid":"10ec8f4dad6903df6b249b361b879ac77b0617caad7629b97e10f29fa7e99a9b","txidaddr":"RMbite4TGugVmkGmu76ytPHDEQZQGSUjxz","withdrawaddr":"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc","amount":"1.00000000","depositaddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj","signeraddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj"} //process item.0 {"txid":"10ec8f4dad6903df6b249b361b879ac77b0617caad7629b97e10f29fa7e99a9b","txidaddr":"RMbite4TGugVmkGmu76ytPHDEQZQGSUjxz","withdrawaddr":"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc","amount":"1.00000000","depositaddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj","signeraddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj"}
if ( (txidaddr= jstr(item,"txidaddr")) != 0 && (withdrawaddr= jstr(item,"withdrawaddr")) != 0 && (depositaddr= jstr(item,"depositaddr")) != 0 && (signeraddr= jstr(item,"signeraddr")) != 0 ) if ( (txidaddr= jstr(item,"txidaddr")) != 0 && (withdrawaddr= jstr(item,"withdrawaddr")) != 0 && (depositaddr= jstr(item,"depositaddr")) != 0 && (signeraddr= jstr(item,"signeraddr")) != 0 )
{ {
if ( (satoshis= jdouble(item,"amount")*SATOSHIDEN) != 0 && (retval= coinaddrexists("KMD",acname,txidaddr)) == 0 ) if ( (satoshis= jdouble(item,"amount")*SATOSHIDEN) != 0 && markerfromthisnodeorunconfirmed("KMD",acname,txidaddr) == 0)
{ {
// this is less errors but more expensive: ./komodo-cli z_sendmany "signeraddr" '[{"address":"<txidaddr>","amount":0.0001},{"address":"<withdrawaddr>","amount":<withamount>}]' // the actual withdraw
txid = sendtoaddress("KMD",acname,txidaddr,10000); if ( strcmp(depositaddr,signeraddr) == 0 )
if ( bits256_nonz(txid) != 0 && coinaddrexists("KMD",acname,txidaddr) > 0 )
{ {
// the actual withdraw txid= sendtoaddress("KMD",acname,txidaddr,10000);
if ( strcmp(depositaddr,signeraddr) == 0 ) if (bits256_nonz(txid) != 0)
{ {
cointxid = sendtoaddress(refcoin,"",withdrawaddr,satoshis); cointxid = sendtoaddress(refcoin,"",withdrawaddr,satoshis);
if ( bits256_nonz(cointxid) != 0 ) if ( bits256_nonz(cointxid) != 0)
{ {
fprintf(stderr,"withdraw %s %s %s %.8f processed\n",refcoin,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN); fprintf(stderr,"withdraw %s %s %s %.8f processed\n",refcoin,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
gatewaysmarkdone("KMD",acname,origtxid,refcoin,cointxid); gatewaysmarkdone("KMD",acname,origtxid,refcoin,cointxid);
@@ -806,41 +909,39 @@ void update_gatewayspending(char *refcoin,char *acname,char *bindtxidstr,int32_t
} }
else else
{ {
if ( (rawtx= get_gatewaysmultisig(refcoin,acname,bindtxidstr,bits256_str(str,origtxid),txidaddr)) == 0 ) fprintf(stderr,"ERROR sending withdraw marker %s %s to %s %.8f processed\n",refcoin,bits256_str(str,cointxid),txidaddr,(double)10000/SATOSHIDEN);
{
rawtx = createmultisig(refcoin,"",depositaddr,signeraddr,withdrawaddr,satoshis);
}
if ( rawtx != 0 )
{
if ( (clijson= addmultisignature(refcoin,"",signeraddr,rawtx)) != 0 )
{
if ( jint(clijson,"complete") != 0 )
{
cointxid = komodobroadcast(refcoin,"",clijson);
if ( bits256_nonz(cointxid) != 0 )
{
fprintf(stderr,"withdraw %s M.%d N.%d %s %s %.8f processed\n",refcoin,M,N,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
gatewaysmarkdone("KMD",acname,origtxid,refcoin,cointxid);
}
}
else if ( jint(clijson,"partialtx") != 0 )
{
// 10000 + ith -> txidaddr
txid = komodobroadcast("KMD",acname,clijson);
fprintf(stderr,"%s M.%d of N.%d partialtx %s sent\n",refcoin,M,N,bits256_str(str,txid));
}
free_json(clijson);
}
processed++;
free(rawtx);
} else fprintf(stderr,"couldnt create msig rawtx\n");
} }
} }
} else
else if ( retval > 0 ) {
{ if ( (rawtx= get_gatewaysmultisig(refcoin,acname,txidaddr,&K)) == 0)
fprintf(stderr,"already did withdraw %s %s %.8f processed\n",refcoin,withdrawaddr,(double)satoshis/SATOSHIDEN); {
gatewaysmarkdone("KMD",acname,origtxid,refcoin,zeroid); rawtx = createmultisig(refcoin,"",depositaddr,signeraddr,withdrawaddr,satoshis);
}
if ( rawtx != 0 )
{
if ( (clijson= addmultisignature(refcoin,"",signeraddr,rawtx)) != 0 )
{
if ( is_cJSON_True(jobj(clijson,"complete")) != 0 )
{
cointxid = komodobroadcast(refcoin,"",clijson);
if ( bits256_nonz(cointxid) != 0 )
{
fprintf(stderr,"withdraw %s M.%d N.%d %s %s %.8f processed\n",refcoin,M,N,bits256_str(str,cointxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
gatewaysmarkdone("KMD",acname,origtxid,refcoin,cointxid);
}
}
else if ( jint(clijson,"partialtx") != 0 )
{
txid=gatewayspartialsign(refcoin,acname,origtxid,jstr(clijson,"hex"));
fprintf(stderr,"%d of %d partialtx %s sent\n",K+1,N,bits256_str(str,txid));
}
free_json(clijson);
}
processed++;
free(rawtx);
} else fprintf(stderr,"couldnt create msig rawtx\n");
}
} }
} }
} }
@@ -907,7 +1008,7 @@ oraclesdata 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 034
int32_t main(int32_t argc,char **argv) int32_t main(int32_t argc,char **argv)
{ {
cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,retval,M,N,n,height,prevheight = 0; char *format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid; cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,retval,M,N,n,height,prevheight = 0; char *pubkeys,*format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid;
if ( argc < 6 ) if ( argc < 6 )
{ {
printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli]\n"); printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli]\n");
@@ -943,12 +1044,18 @@ int32_t main(int32_t argc,char **argv)
printf("need to specify path to refcoin's cli as last argv\n"); printf("need to specify path to refcoin's cli as last argv\n");
exit(0); exit(0);
} }
if ( get_gatewaysinfo("KMD",acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr) < 0 ) pubkeys=0;
if ( get_gatewaysinfo("KMD",acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) < 0 )
{ {
printf("cant find bindtxid.(%s)\n",bindtxidstr); printf("cant find bindtxid.(%s)\n",bindtxidstr);
exit(0); exit(0);
} }
importaddress(refcoin,"",depositaddr); if (validateaddress(refcoin,"",depositaddr,"iswatchonly")==0)
{
if (M==N==1) importaddress(refcoin,"",depositaddr);
else addmultisigaddress(refcoin,"",M,pubkeys,bindtxidstr);
}
if (pubkeys!=0) free(pubkeys);
printf("set refcoin %s <- %s [%s] M.%d of N.%d\n",depositaddr,refcoin,REFCOIN_CLI,M,N); printf("set refcoin %s <- %s [%s] M.%d of N.%d\n",depositaddr,refcoin,REFCOIN_CLI,M,N);
} }
if ( (regjson= jarray(&n,clijson,"registered")) != 0 ) if ( (regjson= jarray(&n,clijson,"registered")) != 0 )

View File

@@ -85,6 +85,11 @@ WARNING: there is an attack vector that precludes betting any large amounts, it
3. reorg the chain and make a big bet using the winning entropy calculated in 2. 3. reorg the chain and make a big bet using the winning entropy calculated in 2.
In order to mitigate this, the disclosure of the house entropy needs to be delayed beyond a reasonable reorg depth (notarization). It is recommended for production dice game with significant amounts of money to use such a delayed disclosure method. In order to mitigate this, the disclosure of the house entropy needs to be delayed beyond a reasonable reorg depth (notarization). It is recommended for production dice game with significant amounts of money to use such a delayed disclosure method.
Actually a much better solution to this is possible, which allows to retain the realtime response aspect of dice CC, which is critical to its usage.
*/ */
#include "../compat/endian.h" #include "../compat/endian.h"
@@ -279,7 +284,7 @@ uint64_t DiceCalc(int64_t bet,int64_t odds,int64_t minbet,int64_t maxbet,int64_t
break; break;
} }
} }
fprintf(stderr,"modval %d vs %d\n",modval,(int32_t)(10000/(odds+1))); //fprintf(stderr,"modval %d vs %d\n",modval,(int32_t)(10000/(odds+1)));
if ( modval < 10000/(odds+1) ) if ( modval < 10000/(odds+1) )
winnings = bet * (odds+1); winnings = bet * (odds+1);
} }
@@ -413,10 +418,8 @@ int32_t DiceIsWinner(uint256 &entropy,uint256 txid,CTransaction tx,CTransaction
hentropy2 = DiceHashEntropy(entropy,vinTx.vin[0].prevout.hash); hentropy2 = DiceHashEntropy(entropy,vinTx.vin[0].prevout.hash);
if ( hentropy == hentropy2 ) if ( hentropy == hentropy2 )
{ {
char str[65];
fprintf(stderr, "%s something \n",uint256_str(str,entropy));
winnings = DiceCalc(tx.vout[1].nValue,tx.vout[2].nValue,minbet,maxbet,maxodds,timeoutblocks,entropy,bettorentropy); winnings = DiceCalc(tx.vout[1].nValue,tx.vout[2].nValue,minbet,maxbet,maxodds,timeoutblocks,entropy,bettorentropy);
fprintf(stderr,"%s winnings %.8f bet %.8f at odds %d:1\n",uint256_str(str,tx.GetHash()),(double)winnings/COIN,(double)tx.vout[1].nValue/COIN,(int32_t)(tx.vout[2].nValue-10000)); char str[65]; fprintf(stderr,"%s winnings %.8f bet %.8f at odds %d:1\n",uint256_str(str,tx.GetHash()),(double)winnings/COIN,(double)tx.vout[1].nValue/COIN,(int32_t)(tx.vout[2].nValue-10000));
//fprintf(stderr,"I am house entropy %.8f entropy.(%s) vs %s -> winnings %.8f\n",(double)vinTx.vout[0].nValue/COIN,uint256_str(str,entropy),uint256_str(str2,hash),(double)winnings/COIN); //fprintf(stderr,"I am house entropy %.8f entropy.(%s) vs %s -> winnings %.8f\n",(double)vinTx.vout[0].nValue/COIN,uint256_str(str,entropy),uint256_str(str2,hash),(double)winnings/COIN);
if ( winnings == 0 ) if ( winnings == 0 )
{ {
@@ -445,7 +448,6 @@ bool DiceVerifyTimeout(CTransaction &betTx,int32_t timeoutblocks)
bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx) bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx)
{ {
uint256 txid,fundingtxid,vinfundingtxid,vinhentropy,vinproof,hashBlock,hash,proof,entropy; int64_t minbet,maxbet,maxodds,timeoutblocks,odds,winnings; uint64_t vinsbits,sbits,amount,inputs,outputs,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,iswin; uint8_t funcid; CScript fundingPubKey; CTransaction fundingTx,vinTx,vinofvinTx; char CCaddr[64]; uint256 txid,fundingtxid,vinfundingtxid,vinhentropy,vinproof,hashBlock,hash,proof,entropy; int64_t minbet,maxbet,maxodds,timeoutblocks,odds,winnings; uint64_t vinsbits,sbits,amount,inputs,outputs,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,iswin; uint8_t funcid; CScript fundingPubKey; CTransaction fundingTx,vinTx,vinofvinTx; char CCaddr[64];
CBlockIndex block;
numvins = tx.vin.size(); numvins = tx.vin.size();
numvouts = tx.vout.size(); numvouts = tx.vout.size();
preventCCvins = preventCCvouts = -1; preventCCvins = preventCCvouts = -1;
@@ -544,18 +546,22 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx)
//vin.3+: funding CC vout.0 from 'F', 'E', 'W', 'L' or 'T' //vin.3+: funding CC vout.0 from 'F', 'E', 'W', 'L' or 'T'
//vout.1: tag to owner address for entropy funds //vout.1: tag to owner address for entropy funds
preventCCvouts = 1; preventCCvouts = 1;
CBlockIndex block;
DiceAmounts(inputs,outputs,cp,eval,tx,sbits,fundingtxid); DiceAmounts(inputs,outputs,cp,eval,tx,sbits,fundingtxid);
if ( IsCCInput(tx.vin[1].scriptSig) == 0 || IsCCInput(tx.vin[2].scriptSig) == 0 ) if ( IsCCInput(tx.vin[1].scriptSig) == 0 || IsCCInput(tx.vin[2].scriptSig) == 0 )
return eval->Invalid("vin0 or vin1 normal vin for bet"); return eval->Invalid("vin0 or vin1 normal vin for bet");
else if ( tx.vin[1].prevout.hash != tx.vin[2].prevout.hash ) else if ( tx.vin[1].prevout.hash != tx.vin[2].prevout.hash )
return eval->Invalid("vin0 != vin1 prevout.hash for bet"); return eval->Invalid("vin0 != vin1 prevout.hash for bet");
<<<<<<< HEAD
else if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 ) { else if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 ) {
char str[65],str2[65],str3[65]; char str[65],str2[65],str3[65];
fprintf(stderr, "txid.%s tx.%s hashBlock.%s\n",uint256_str(str,txid),uint256_str(str2,tx.vin[1].prevout.hash),uint256_str(str3,hashBlock)); fprintf(stderr, "txid.%s tx.%s hashBlock.%s\n",uint256_str(str,txid),uint256_str(str2,tx.vin[1].prevout.hash),uint256_str(str3,hashBlock));
return eval->Invalid("always should find looking vin.0, but didnt for wlt"); return eval->Invalid("always should find looking vin.0, but didnt for wlt");
} else if (hashBlock.IsNull() || !eval->GetBlock(hashBlock, block)) } else if (hashBlock.IsNull() || !eval->GetBlock(hashBlock, block))
return eval->Invalid(" TX not confirmed! always should find vin.0, but didnt for wlt"); return eval->Invalid(" TX not confirmed! always should find vin.0, but didnt for wlt");
=======
else if ( eval->GetTxUnconfirmed(tx.vin[1].prevout.hash,vinTx,hashBlock) == 0 )
return eval->Invalid("always should find looking vin.0, but didnt for wlt");
>>>>>>> 19d614c8344b70a0d4a7da8620a2dd1168016abc
else if ( vinTx.vout.size() < 3 || DecodeDiceOpRet(tx.vin[1].prevout.hash,vinTx.vout[vinTx.vout.size()-1].scriptPubKey,vinsbits,vinfundingtxid,vinhentropy,vinproof) != 'B' ) else if ( vinTx.vout.size() < 3 || DecodeDiceOpRet(tx.vin[1].prevout.hash,vinTx.vout[vinTx.vout.size()-1].scriptPubKey,vinsbits,vinfundingtxid,vinhentropy,vinproof) != 'B' )
return eval->Invalid("not betTx for vin0/1 for wlt"); return eval->Invalid("not betTx for vin0/1 for wlt");
else if ( sbits != vinsbits || fundingtxid != vinfundingtxid ) else if ( sbits != vinsbits || fundingtxid != vinfundingtxid )
@@ -591,12 +597,21 @@ bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx)
{ {
fprintf(stderr,"inputs %.8f != outputs %.8f + %.8f\n",(double)inputs/COIN,(double)outputs/COIN,(double)tx.vout[2].nValue/COIN); fprintf(stderr,"inputs %.8f != outputs %.8f + %.8f\n",(double)inputs/COIN,(double)outputs/COIN,(double)tx.vout[2].nValue/COIN);
return eval->Invalid("CC funds mismatch for win/timeout"); return eval->Invalid("CC funds mismatch for win/timeout");
<<<<<<< HEAD
} }
else if ( tx.vout[3].scriptPubKey != fundingPubKey ) else if ( tx.vout[3].scriptPubKey != fundingPubKey )
{ {
if ( tx.vout[3].scriptPubKey.size() == 0 || ((uint8_t *)tx.vout[3].scriptPubKey.data())[0] != 0x6a ) if ( tx.vout[3].scriptPubKey.size() == 0 || ((uint8_t *)tx.vout[3].scriptPubKey.data())[0] != 0x6a )
return eval->Invalid("vout[3] not send to fundingPubKey for win/timeout"); return eval->Invalid("vout[3] not send to fundingPubKey for win/timeout");
} }
=======
}
else if ( tx.vout[3].scriptPubKey != fundingPubKey )
{
if ( tx.vout[3].scriptPubKey.size() == 0 || ((uint8_t *)tx.vout[3].scriptPubKey.data())[0] != 0x6a )
return eval->Invalid("vout[3] not send to fundingPubKey for win/timeout");
}
>>>>>>> 19d614c8344b70a0d4a7da8620a2dd1168016abc
iswin = (funcid == 'W'); iswin = (funcid == 'W');
} }
if ( iswin != 0 ) if ( iswin != 0 )
@@ -732,7 +747,9 @@ int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbit
entropytxid = txid; entropytxid = txid;
entropyval = tx.vout[0].nValue; entropyval = tx.vout[0].nValue;
first = 1; first = 1;
fprintf(stderr, "chosen entropy on loop: %d\n",loops); if (random) {
fprintf(stderr, "chosen entropy on loop: %d\n",loops);
}
} }
else else
{ {
@@ -1198,7 +1215,7 @@ double DiceStatus(uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettx
} else return(0.); } else return(0.);
} }
error = "didnt find dicefinish tx"; error = "didnt find dicefinish tx";
} } else error = res;
return(-1.); return(-1.);
} }
return(0.); return(0.);

View File

@@ -178,6 +178,41 @@ uint8_t DecodeGatewaysOpRet(const CScript &scriptPubKey,std::string &coin,uint25
return(0); return(0);
} }
uint8_t DecodeGatewaysPartialOpRet(const CScript &scriptPubKey,int32_t &K, CPubKey &signerpk, std::string &coin,std::string &hex)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> K; ss >> signerpk; ss >> coin; ss >> hex) != 0 )
{
return(f);
}
return(0);
}
uint8_t DecodeGatewaysWithdrawOpRet(const CScript &scriptPubKey, uint256 &assetid, std::string &refcoin, CPubKey &withdrawpub, int64_t &amount)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> assetid; ss >> refcoin; ss >> withdrawpub; ss >> amount) != 0 )
{
return(f);
}
return(0);
}
uint8_t DecodeGatewaysMarkdoneOpRet(const CScript &scriptPubKey, std::string &refcoin, uint256 &cointxid)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> refcoin; ss >> cointxid) != 0 )
{
return(f);
}
return(0);
}
uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,std::string &coin,uint256 &tokenid,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &pubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2) uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,std::string &coin,uint256 &tokenid,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &pubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2)
{ {
std::vector<uint8_t> vopret; uint8_t *script,e,f; std::vector<uint8_t> vopret; uint8_t *script,e,f;
@@ -763,9 +798,11 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
return(""); return("");
} }
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector<uint8_t> withdrawpub,int64_t amount) std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount)
{ {
CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C; uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin; std::vector<CPubKey> msigpubkeys; char depositaddr[64],str[65],coinaddr[64]; CMutableTransaction mtx; CTransaction tx; CPubKey mypk,gatewayspk; struct CCcontract_info *cp,C;
uint256 assetid,hashBlock,oracletxid; int32_t numvouts; int64_t totalsupply,inputs,CCchange=0; uint8_t M,N,taddr,prefix,prefix2; std::string coin;
std::vector<CPubKey> msigpubkeys; char depositaddr[64],str[65],coinaddr[64]; CScript opret;
cp = CCinit(&C,EVAL_GATEWAYS); cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 10000; txfee = 10000;
@@ -788,11 +825,12 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
if ( inputs > amount ) if ( inputs > amount )
CCchange = (inputs - amount); CCchange = (inputs - amount);
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,amount,gatewayspk)); mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,amount,gatewayspk));
mtx.vout.push_back(CTxOut(txfee,CScript() << withdrawpub << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(withdrawpub)) << OP_CHECKSIG));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(gatewayspk)) << OP_CHECKSIG)); mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,txfee,gatewayspk));
if ( CCchange != 0 ) if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CCchange,mypk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeAssetOpRet('t',assetid,zeroid,0,Mypubkey()))); opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'W' << assetid << refcoin << withdrawpub << amount);
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
} }
} }
fprintf(stderr,"cant find enough inputs or mismatched total\n"); fprintf(stderr,"cant find enough inputs or mismatched total\n");
@@ -806,6 +844,7 @@ std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid,std::string ref
if ( txfee == 0 ) if ( txfee == 0 )
txfee = 5000; txfee = 5000;
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
mtx.vin.push_back(CTxIn(withdrawtxid,2,CScript())); mtx.vin.push_back(CTxIn(withdrawtxid,2,CScript()));
mtx.vout.push_back(CTxOut(5000,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); mtx.vout.push_back(CTxOut(5000,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'M' << cointxid << refcoin); opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'M' << cointxid << refcoin);
@@ -814,8 +853,12 @@ std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid,std::string ref
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin) UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
{ {
UniValue result(UniValue::VOBJ),pending(UniValue::VARR),obj(UniValue::VOBJ); CTransaction tx; std::string coin; CPubKey mypk,gatewayspk; std::vector<CPubKey> msigpubkeys; uint256 hashBlock,assetid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2; char depositaddr[64],withmarker[64],coinaddr[64],destaddr[64],str[65],withaddr[64],numstr[32],txidaddr[64],signeraddr[64]; int32_t i,n,numvouts,vout,numqueued,queueflag; int64_t totalsupply; struct CCcontract_info *cp,C; UniValue result(UniValue::VOBJ),pending(UniValue::VARR); CTransaction tx; std::string coin,tmprefcoin; CPubKey mypk,gatewayspk,withdrawpub; std::vector<CPubKey> msigpubkeys;
uint256 cointxid,hashBlock,assetid,txid,oracletxid; uint8_t M,N,taddr,prefix,prefix2;
char depositaddr[64],withmarker[64],coinaddr[64],destaddr[64],str[65],withaddr[64],numstr[32],txidaddr[64],signeraddr[64];
int32_t i,n,numvouts,vout,numqueued,queueflag; int64_t totalsupply,amount,nValue; struct CCcontract_info *cp,C;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
cp = CCinit(&C,EVAL_GATEWAYS); cp = CCinit(&C,EVAL_GATEWAYS);
mypk = pubkey2pk(Mypubkey()); mypk = pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0); gatewayspk = GetUnspendable(cp,0);
@@ -838,19 +881,22 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
queueflag = 1; queueflag = 1;
break; break;
} }
Getscriptaddress(withmarker,CScript() << ParseHex(HexStr(gatewayspk)) << OP_CHECKSIG); SetCCunspents(unspentOutputs,coinaddr);
SetCCunspents(unspentOutputs,withmarker);
numqueued = 0; numqueued = 0;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{ {
txid = it->first.txhash; txid = it->first.txhash;
vout = (int32_t)it->first.index; vout = (int32_t)it->first.index;
if ( GetTransaction(txid,tx,hashBlock,false) != 0 ) nValue = (int64_t)it->second.satoshis;
fprintf(stderr,"%s %d %ld\n",txid.ToString().c_str(),vout,(long)nValue);
if ( vout == 2 && nValue == 10000 && GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) &&
DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,assetid,tmprefcoin,withdrawpub,amount) == 'W' && myIsutxo_spentinmempool(txid,vout) == 0)
{ {
Getscriptaddress(destaddr,tx.vout[0].scriptPubKey); Getscriptaddress(destaddr,tx.vout[0].scriptPubKey);
Getscriptaddress(withaddr,tx.vout[1].scriptPubKey); Getscriptaddress(withaddr,tx.vout[1].scriptPubKey);
if ( strcmp(destaddr,coinaddr) == 0 ) if ( strcmp(destaddr,coinaddr) == 0 )
{ {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("txid",uint256_str(str,txid))); obj.push_back(Pair("txid",uint256_str(str,txid)));
CCtxidaddr(txidaddr,txid); CCtxidaddr(txidaddr,txid);
obj.push_back(Pair("txidaddr",txidaddr)); obj.push_back(Pair("txidaddr",txidaddr));
@@ -873,31 +919,72 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
return(result); return(result);
} }
std::string GatewaysMultisig(uint64_t txfee,std::string refcoin,uint256 bindtxid,uint256 withdrawtxid,char *txidaddr) UniValue GatewaysMultisig(char *txidaddr)
{ {
UniValue result(UniValue::VOBJ); std::string coin,hex; char str[67],numstr[65],depositaddr[64],gatewaysassets[64]; uint8_t M,N; std::vector<CPubKey> pubkeys; uint8_t taddr,prefix,prefix2; uint256 tokenid,oracletxid,hashBlock; CTransaction tx; CPubKey Gatewayspk,mypk; struct CCcontract_info *cp,C; int32_t i,n,complete,partialtx; int64_t totalsupply; std::string parthex,hex,refcoin; uint256 txid,hashBlock; CTransaction tx; int32_t i,maxK,K,numvouts; CPubKey signerpk;
cp = CCinit(&C,EVAL_GATEWAYS); std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; UniValue result(UniValue::VOBJ);
if ( txfee == 0 )
txfee = 10000; SetCCunspents(unspentOutputs,txidaddr);
complete = partialtx = 0; maxK=0;
mypk = pubkey2pk(Mypubkey()); for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
Gatewayspk = GetUnspendable(cp,0);
_GetCCaddress(gatewaysassets,EVAL_GATEWAYS,Gatewayspk);
if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 )
{ {
depositaddr[0] = 0; txid = it->first.txhash;
if ( tx.vout.size() > 0 && DecodeGatewaysBindOpRet(depositaddr,tx.vout[tx.vout.size()-1].scriptPubKey,coin,tokenid,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2) != 0 && M <= N && N > 1 && coin == refcoin ) if (GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts=tx.vout.size()) > 0 && DecodeGatewaysPartialOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,K,signerpk,refcoin,hex) == 'P' && K>maxK )
{ {
// need a decentralized way to add signatures to msig tx maxK=K;
n = pubkeys.size(); parthex=hex;
for (i=0; i<n; i++)
if ( mypk == pubkeys[i] )
break;
if ( i != n )
{
hex = "";
} else fprintf(stderr,"not one of the multisig signers\n");
} }
} }
return(hex);
BOOST_FOREACH(const CTxMemPoolEntry &e, mempool.mapTx)
{
const CTransaction &txmempool = e.GetTx();
const uint256 &hash = txmempool.GetHash();
if ((numvouts=txmempool.vout.size()) > 0 && DecodeGatewaysPartialOpRet(txmempool.vout[numvouts-1].scriptPubKey,K,signerpk,refcoin,hex) == 'P' && K>maxK)
{
maxK=K;
parthex=hex;
}
}
result.push_back(Pair("hex",parthex));
result.push_back(Pair("number_of_signs",maxK));
return (result);
}
std::string GatewaysPartialSign(uint64_t txfee,uint256 txid,std::string refcoin, std::string hex)
{
CMutableTransaction mtx; CScript opret; CPubKey mypk,txidaddrpk,signerpk; struct CCcontract_info *cp,C; CTransaction tx;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; char txidaddr[65];
int32_t maxK,K=0; uint256 tmptxid,parttxid,hashBlock;
cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 )
txfee = 5000;
mypk = pubkey2pk(Mypubkey());
txidaddrpk=CCtxidaddr(txidaddr,txid);
SetCCunspents(unspentOutputs,txidaddr);
maxK=0;
if (unspentOutputs.size()==0)
{
if (AddNormalinputs(mtx,mypk,2*txfee,2)==0) fprintf(stderr,"error adding funds for partialsign\n");
}
else
{
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
tmptxid = it->first.txhash;
if (GetTransaction(tmptxid,tx,hashBlock,false) != 0 && tx.vout.size() > 0 && DecodeGatewaysPartialOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,K,signerpk,refcoin,hex) == 'P' && K>maxK )
{
maxK=K;
parttxid=tmptxid;
}
}
if (maxK>0) mtx.vin.push_back(CTxIn(parttxid,0,CScript()));
else fprintf(stderr,"Error finding previous partial tx\n");
}
mtx.vout.push_back(CTxOut(5000,CScript() << ParseHex(HexStr(txidaddrpk)) << OP_CHECKSIG));
opret << OP_RETURN << E_MARSHAL(ss << cp->evalcode << 'P' << maxK+1 << mypk << refcoin << hex);
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
} }

View File

@@ -92,6 +92,7 @@ unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA;
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
CTxMemPool mempool(::minRelayTxFee); CTxMemPool mempool(::minRelayTxFee);
CTxMemPool tmpmempool(::minRelayTxFee);
struct COrphanTx { struct COrphanTx {
CTransaction tx; CTransaction tx;
@@ -1309,7 +1310,7 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
} }
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee) bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, bool fNullifiers)
{ {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
if (pfMissingInputs) if (pfMissingInputs)
@@ -1390,14 +1391,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return false; return false;
} }
} }
BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) if (fNullifiers == false)
{ {
BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit)
{ {
if (pool.mapNullifiers.count(nf)) BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers)
{ {
fprintf(stderr,"pool.mapNullifiers.count\n"); if (pool.mapNullifiers.count(nf))
return false; {
fprintf(stderr,"pool.mapNullifiers.count\n");
return false;
}
} }
} }
} }
@@ -1450,12 +1454,14 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
} }
} }
// are the joinsplit's requirements met? // are the joinsplit's requirements met?
if (!view.HaveJoinSplitRequirements(tx)) if ( fNullifiers == true )
{ {
//fprintf(stderr,"accept failure.2\n"); if (!view.HaveJoinSplitRequirements(tx))
return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); {
//fprintf(stderr,"accept failure.2\n");
return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met");
}
} }
// Bring the best block into scope // Bring the best block into scope
view.GetBestBlock(); view.GetBestBlock();
@@ -4247,6 +4253,17 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
{ {
CValidationState stateDummy; int32_t i,j,rejects=0,lastrejects=0; CValidationState stateDummy; int32_t i,j,rejects=0,lastrejects=0;
//fprintf(stderr,"put block's tx into mempool\n"); //fprintf(stderr,"put block's tx into mempool\n");
// Copy the mempool to temporary mempool because there can be tx in local mempool that make the block invalid.
LOCK(mempool.cs);
BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) {
const CTransaction &tx = e.GetTx();
const uint256 &hash = tx.GetHash();
tmpmempool.addUnchecked(hash,e,!IsInitialBlockDownload());
//fprintf(stderr, "added mempool tx to temp mempool\n");
}
// clear the mempool before importing all block txs to mempool.
mempool.clear();
// add all the txs in the block to the empty mempool.
while ( 1 ) while ( 1 )
{ {
for (i=0; i<block.vtx.size(); i++) for (i=0; i<block.vtx.size(); i++)
@@ -4295,6 +4312,21 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
LogPrintf("CheckBlockHeader komodo_check_deposit error"); LogPrintf("CheckBlockHeader komodo_check_deposit error");
return(false); return(false);
} }
if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order
{
int invalidtxs = 0;
BOOST_FOREACH(const CTxMemPoolEntry& e, tmpmempool.mapTx) {
CTransaction tx = e.GetTx();
CValidationState state; bool fMissingInputs,fOverrideFees = false;
if (AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees,true) == false )
invalidtxs++;
//else fprintf(stderr, "added mempool tx back to mempool\n");
}
if ( 0 && invalidtxs > 0 )
fprintf(stderr, "number of invalid txs: %d\n",invalidtxs );
// empty the temp mempool for next time.
tmpmempool.clear();
}
return true; return true;
} }

View File

@@ -267,7 +267,7 @@ void PruneAndFlush();
/** (try to) add transaction to memory pool **/ /** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
bool* pfMissingInputs, bool fRejectAbsurdFee=false); bool* pfMissingInputs, bool fRejectAbsurdFee=false, bool fNullifiers=false);
struct CNodeStateStats { struct CNodeStateStats {

View File

@@ -426,6 +426,7 @@ static const CRPCCommand vRPCCommands[] =
{ "gateways", "gatewayspending", &gatewayspending, true }, { "gateways", "gatewayspending", &gatewayspending, true },
{ "gateways", "gatewaysmultisig", &gatewaysmultisig, true }, { "gateways", "gatewaysmultisig", &gatewaysmultisig, true },
{ "gateways", "gatewaysmarkdone", &gatewaysmarkdone, true }, { "gateways", "gatewaysmarkdone", &gatewaysmarkdone, true },
{ "gateways", "gatewayspartialsign", &gatewayspartialsign, true },
/* dice */ /* dice */
{ "dice", "dicelist", &dicelist, true }, { "dice", "dicelist", &dicelist, true },

View File

@@ -253,6 +253,7 @@ extern UniValue gatewayswithdraw(const UniValue& params, bool fHelp);
extern UniValue gatewayspending(const UniValue& params, bool fHelp); extern UniValue gatewayspending(const UniValue& params, bool fHelp);
extern UniValue gatewaysmarkdone(const UniValue& params, bool fHelp); extern UniValue gatewaysmarkdone(const UniValue& params, bool fHelp);
extern UniValue gatewaysmultisig(const UniValue& params, bool fHelp); extern UniValue gatewaysmultisig(const UniValue& params, bool fHelp);
extern UniValue gatewayspartialsign(const UniValue& params, bool fHelp);
extern UniValue channelsinfo(const UniValue& params, bool fHelp); extern UniValue channelsinfo(const UniValue& params, bool fHelp);
extern UniValue channelsopen(const UniValue& params, bool fHelp); extern UniValue channelsopen(const UniValue& params, bool fHelp);
extern UniValue channelspayment(const UniValue& params, bool fHelp); extern UniValue channelspayment(const UniValue& params, bool fHelp);

View File

@@ -246,7 +246,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
CPubKey pubKey(vSolutions[0]); CPubKey pubKey(vSolutions[0]);
if (!pubKey.IsValid()) if (!pubKey.IsValid())
{ {
fprintf(stderr,"TX_PUBKEY invalid pubkey\n"); //fprintf(stderr,"TX_PUBKEY invalid pubkey\n");
return false; return false;
} }

View File

@@ -5621,7 +5621,7 @@ UniValue gatewayswithdraw(const UniValue& params, bool fHelp)
coin = params[1].get_str(); coin = params[1].get_str();
withdrawpub = ParseHex(params[2].get_str()); withdrawpub = ParseHex(params[2].get_str());
amount = atof((char *)params[3].get_str().c_str()) * COIN; amount = atof((char *)params[3].get_str().c_str()) * COIN;
hex = GatewaysWithdraw(0,bindtxid,coin,withdrawpub,amount); hex = GatewaysWithdraw(0,bindtxid,coin,pubkey2pk(withdrawpub),amount);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
@@ -5665,18 +5665,30 @@ UniValue gatewayspending(const UniValue& params, bool fHelp)
UniValue gatewaysmultisig(const UniValue& params, bool fHelp) UniValue gatewaysmultisig(const UniValue& params, bool fHelp)
{ {
UniValue result(UniValue::VOBJ); uint256 bindtxid,withtxid; std::string coin,hex; char *txidaddr; UniValue result(UniValue::VOBJ); std::string hex; char *txidaddr;
if ( fHelp || params.size() != 2 ) if ( fHelp || params.size() != 1 )
throw runtime_error("gatewaysmultisig bindtxid coin withtxid txidaddr\n"); throw runtime_error("gatewaysmultisig txidaddr\n");
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
bindtxid = Parseuint256((char *)params[0].get_str().c_str()); txidaddr = (char *)params[0].get_str().c_str();
return(GatewaysMultisig(txidaddr));
}
UniValue gatewayspartialsign(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ); std::string coin,parthex,hex; uint256 txid;
if ( fHelp || params.size() != 3 )
throw runtime_error("gatewayspartialsign txidaddr refcoin hex\n");
if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet);
txid = Parseuint256((char *)params[0].get_str().c_str());
coin = params[1].get_str(); coin = params[1].get_str();
withtxid = Parseuint256((char *)params[2].get_str().c_str()); parthex = params[2].get_str();
txidaddr = (char *)params[3].get_str().c_str(); hex = GatewaysPartialSign(0,txid,coin,parthex);
hex = GatewaysMultisig(0,coin,bindtxid,withtxid,txidaddr);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {
result.push_back(Pair("result", "success")); result.push_back(Pair("result", "success"));
@@ -5715,7 +5727,8 @@ UniValue oraclesregister(const UniValue& params, bool fHelp)
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
txid = Parseuint256((char *)params[0].get_str().c_str()); txid = Parseuint256((char *)params[0].get_str().c_str());
datafee = atol((char *)params[1].get_str().c_str()); if ( (datafee= atol((char *)params[1].get_str().c_str())) == 0 )
datafee = atof((char *)params[1].get_str().c_str()) * COIN;
hex = OracleRegister(0,txid,datafee); hex = OracleRegister(0,txid,datafee);
if ( hex.size() > 0 ) if ( hex.size() > 0 )
{ {