Browse Source

createmultisig and addmultisigaddress

release/v0.1
jl777 9 years ago
parent
commit
989313c931
  1. 2
      crypto777/iguana_secp.c
  2. 16
      crypto777/inet.c
  3. 2
      iguana/SuperNET_keys.c
  4. 4
      iguana/iguana777.c
  5. 9
      iguana/iguana777.h
  6. 4
      iguana/iguana_json.c
  7. 3
      iguana/iguana_rpc.c
  8. 39
      iguana/iguana_unspents.c
  9. 298
      iguana/iguana_wallet.c
  10. 2
      iguana/tests/addmultisig
  11. 2
      iguana/tests/createmultisig
  12. 4
      iguana/tests/walletpassphrase
  13. 5
      includes/iguana_apideclares.h

2
crypto777/iguana_secp.c

@ -178,7 +178,7 @@ bits256 bitcoin_pubkey33(uint8_t *data,bits256 privkey)
data[0] = oddeven;
memcpy(data+1,pubkey.bytes,sizeof(pubkey));
EC_KEY_free(KEY);
}
} else memset(pubkey.bytes,0,sizeof(pubkey));
return(pubkey);
}

16
crypto777/inet.c

@ -389,13 +389,25 @@ void expand_ipbits(char *ipaddr,uint64_t ipbits)
uint64_t calc_ipbits(char *ip_port)
{
uint64_t ipbits = 0; char ipaddr[64];
uint64_t ipbits = 0; char ipaddr[64],ipaddr2[64]; int32_t i;
if ( ip_port != 0 )
{
ipbits = _calc_ipbits(ip_port);
expand_ipbits(ipaddr,ipbits);
if ( ipbits != 0 && strcmp(ipaddr,ip_port) != 0 )
printf("calc_ipbits error: (%s) -> %llx -> (%s)\n",ip_port,(long long)ipbits,ipaddr);//, getchar();
{
for (i=0; i<63; i++)
if ( (ipaddr[i]= ip_port[i]) == ':' || ipaddr[i] == 0 )
break;
ipaddr[i] = 0;
ipbits = _calc_ipbits(ipaddr);
expand_ipbits(ipaddr2,ipbits);
if ( ipbits != 0 && strcmp(ipaddr,ipaddr2) != 0 )
{
printf("calc_ipbits error: (%s) -> %llx -> (%s)\n",ip_port,(long long)ipbits,ipaddr);//, getchar();
ipbits = 0;
}
}
}
return(ipbits);
}

2
iguana/SuperNET_keys.c

@ -151,7 +151,7 @@ int32_t SuperNET_savejsonfile(char *finalfname,bits256 privkey,bits256 destpubke
else
{
//sprintf(fname,"confs/iguana.conf");
printf("save (%s) <- (%s)\n",destfname,confstr);
//printf("save (%s) <- (%s)\n",destfname,confstr);
if ( (fp= fopen(destfname,"wb")) != 0 )
{
if ( fwrite(confstr,1,strlen(confstr)+1,fp) == strlen(confstr)+1 )

4
iguana/iguana777.c

@ -839,7 +839,7 @@ struct iguana_info *iguana_setcoin(char *symbol,void *launched,int32_t maxpeers,
return(coin);
}
int32_t iguana_launchcoin(char *symbol,cJSON *json)
int32_t iguana_launchcoin(struct supernet_info *myinfo,char *symbol,cJSON *json)
{
int32_t maxpeers,maphash,initialheight,minconfirms,maxrequests,maxbundles;
int64_t maxrecvcache; uint64_t services; struct iguana_info **coins,*coin;
@ -848,6 +848,8 @@ int32_t iguana_launchcoin(char *symbol,cJSON *json)
printf("launchcoin.%s\n",symbol);
if ( (coin= iguana_coinadd(symbol,json)) == 0 )
return(-1);
if ( myinfo->rpcsymbol[0] == 0 || iguana_coinfind(myinfo->rpcsymbol) == 0 )
strcpy(myinfo->rpcsymbol,symbol);
if ( coin->launched == 0 )
{
if ( juint(json,"GBavail") < 8 )

9
iguana/iguana777.h

@ -474,7 +474,7 @@ struct iguana_bundlereq
struct iguana_bitmap { int32_t width,height,amplitude; char name[52]; uint8_t data[IGUANA_WIDTH*IGUANA_HEIGHT*3]; };
struct iguana_waddress { UT_hash_handle hh; uint8_t rmd160[20],type,pubkey[33],wiftype; bits256 privkey; char symbol[8],coinaddr[36],wifstr[54]; };
struct iguana_waddress { UT_hash_handle hh; uint16_t scriptlen; uint8_t rmd160[20],type,pubkey[33],wiftype; bits256 privkey; char symbol[8],coinaddr[36],wifstr[54]; uint8_t redeemScript[]; };
struct iguana_waccount { UT_hash_handle hh; char account[128]; struct iguana_waddress *waddr,*current; };
struct iguana_wallet { UT_hash_handle hh; struct iguana_waccount *wacct; };
@ -511,7 +511,7 @@ struct iguana_info
double bandwidth,maxbandwidth,backstopmillis; bits256 backstophash2; int64_t spaceused;
int32_t initialheight,mapflags,minconfirms,numrecv,bindsock,isRT,backstop,blocksrecv,merging,polltimeout,numreqtxids,allhashes,balanceflush; bits256 reqtxids[64];
void *launched,*started,*rpcloop;
uint64_t bloomsearches,bloomhits,bloomfalse,collisions;
uint64_t bloomsearches,bloomhits,bloomfalse,collisions,txfee_perkb;
uint8_t blockspace[IGUANA_MAXPACKETSIZE + 8192]; struct OS_memspace blockMEM;
struct iguana_blocks blocks; bits256 APIblockhash,APItxid; char *APIblockstr;
struct iguana_hhutxo *utxotable; struct iguana_hhaccount *accountstable; char lastdispstr[2048];
@ -771,14 +771,14 @@ int32_t iguana_send_supernet(struct iguana_info *coin,struct iguana_peer *addr,c
struct iguana_waccount *iguana_waccountfind(struct supernet_info *myinfo,struct iguana_info *coin,char *account);
struct iguana_waddress *iguana_waccountadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount **wacctp,char *walletaccount,char *coinaddr);
struct iguana_waddress *iguana_waccountswitch(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr);
struct iguana_waddress *iguana_waccountswitch(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr,char *redeemScript);
struct iguana_waddress *iguana_waddresscalc(uint8_t pubval,uint8_t wiftype,struct iguana_waddress *addr,bits256 privkey);
struct iguana_waddress *iguana_waddressfind(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,char *coinaddr);
char *iguana_coinjson(struct iguana_info *coin,char *method,cJSON *json);
cJSON *iguana_peersjson(struct iguana_info *coin,int32_t addronly);
//int32_t btc_priv2wif(char *wifstr,uint8_t privkey[32],uint8_t addrtype);
//int32_t btc_pub2rmd(uint8_t rmd160[20],uint8_t pubkey[33]);
int32_t iguana_launchcoin(char *symbol,cJSON *json);
int32_t iguana_launchcoin(struct supernet_info *myinfo,char *symbol,cJSON *json);
int32_t iguana_bundleinitmap(struct iguana_info *coin,struct iguana_bundle *bp,int32_t height,bits256 hash2,bits256 hash1);
int32_t iguana_jsonQ();
int32_t is_bitcoinrpc(struct supernet_info *myinfo,char *method,char *remoteaddr);
@ -927,6 +927,7 @@ struct iguana_waddress *iguana_waddresssearch(struct supernet_info *myinfo,struc
int64_t iguana_addressreceived(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,cJSON *txids,cJSON *vouts,char *coinaddr,int32_t minconf);
cJSON *iguana_walletjson(struct supernet_info *myinfo);
int32_t iguana_payloadupdate(struct supernet_info *myinfo,struct iguana_info *coin,char *retstr,struct iguana_waddress *waddr,char *account);
int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp);
extern int32_t HDRnet,netBLOCKS;

4
iguana/iguana_json.c

@ -613,7 +613,7 @@ STRING_ARG(iguana,addcoin,newcoin)
// if ( strcmp(symbol,"BTC") == 0 )
// return(clonestr("{\"result\":\"BTC for chrome app is not yet\"}"));
#endif
if ( (retval= iguana_launchcoin(symbol,json)) > 0 )
if ( (retval= iguana_launchcoin(myinfo,symbol,json)) > 0 )
{
if ( myinfo->rpcsymbol[0] == 0 )
safecopy(myinfo->rpcsymbol,symbol,sizeof(myinfo->rpcsymbol));
@ -841,7 +841,7 @@ STRING_ARG(SuperNET,bitcoinrpc,setcoin)
strcpy(myinfo->rpcsymbol,setcoin);
touppercase(myinfo->rpcsymbol);
printf("bitcoinrpc.%s\n",myinfo->rpcsymbol);
if ( iguana_launchcoin(myinfo->rpcsymbol,json) < 0 )
if ( iguana_launchcoin(myinfo,myinfo->rpcsymbol,json) < 0 )
return(clonestr("{\"error\":\"error creating coin\"}"));
else
{

3
iguana/iguana_rpc.c

@ -234,7 +234,7 @@ static char *createmultisig(RPCARGS)
static char *addmultisigaddress(RPCARGS)
{
return(sglue3(0,CALLGLUE,"bitcoinrpc","createmultisig","M",params[0],"pubkeys",params[1],"account",params[2]));
return(sglue3(0,CALLGLUE,"bitcoinrpc","addmultisigaddress","M",params[0],"pubkeys",params[1],"account",params[2]));
}
// blockchain
@ -553,6 +553,7 @@ struct RPC_info { char *name; char *(*rpcfunc)(RPCARGS); int32_t flag0,remotefla
{ "move", &movecmd, false, false },
{ "sendfrom", &sendfrom, false, false },
{ "sendmany", &sendmany, false, false },
{ "addmultisig", &addmultisigaddress, false, false },
{ "addmultisigaddress", &addmultisigaddress, false, false },
{ "getblock", &getblock, false, true },
{ "gettransaction", &gettransaction, false, true },

39
iguana/iguana_unspents.c

@ -2216,24 +2216,27 @@ int32_t iguana_convert(struct iguana_info *coin,int32_t helperid,struct iguana_b
void iguana_RTramchainfree(struct iguana_info *coin,struct iguana_bundle *bp)
{
int32_t hdrsi;
printf("free RTramchain\n");
iguana_utxoupdate(coin,-1,0,0,0,0,-1); // free hashtables
coin->RTheight = coin->balanceswritten * coin->chain->bundlesize;
coin->RTgenesis = 0;
iguana_ramchain_free(coin,&coin->RTramchain,1);
if ( bp != 0 )
bp->ramchain = coin->RTramchain;
iguana_mempurge(&coin->RTmem);
iguana_mempurge(&coin->RThashmem);
coin->RTdatabad = 0;
for (hdrsi=coin->bundlescount-1; hdrsi>0; hdrsi--)
if ( (bp= coin->bundles[hdrsi]) == 0 && bp != coin->current )
{
iguana_volatilespurge(coin,&bp->ramchain);
if ( iguana_volatilesmap(coin,&bp->ramchain) != 0 )
printf("error mapping bundle.[%d]\n",hdrsi);
}
printf("done RTramchain\n");
if ( coin->utxotable != 0 )
{
printf("free RTramchain\n");
iguana_utxoupdate(coin,-1,0,0,0,0,-1); // free hashtables
coin->RTheight = coin->balanceswritten * coin->chain->bundlesize;
coin->RTgenesis = 0;
iguana_ramchain_free(coin,&coin->RTramchain,1);
if ( bp != 0 )
bp->ramchain = coin->RTramchain;
iguana_mempurge(&coin->RTmem);
iguana_mempurge(&coin->RThashmem);
coin->RTdatabad = 0;
for (hdrsi=coin->bundlescount-1; hdrsi>0; hdrsi--)
if ( (bp= coin->bundles[hdrsi]) == 0 && bp != coin->current )
{
iguana_volatilespurge(coin,&bp->ramchain);
if ( iguana_volatilesmap(coin,&bp->ramchain) != 0 )
printf("error mapping bundle.[%d]\n",hdrsi);
}
printf("done RTramchain\n");
}
}
void *iguana_ramchainfile(struct iguana_info *coin,struct iguana_ramchain *dest,struct iguana_ramchain *R,struct iguana_bundle *bp,int32_t bundlei,struct iguana_block *block)

298
iguana/iguana_wallet.c

@ -57,19 +57,23 @@ void iguana_walletdelete(struct supernet_info *myinfo,int32_t deleteflag)
cJSON *iguana_walletjson(struct supernet_info *myinfo)
{
struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; cJSON *wallet,*account;
struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; cJSON *wallet,*account; char scriptstr[4096];
HASH_ITER(hh,myinfo->wallet,wacct,tmp)
{
account = cJSON_CreateObject();
HASH_ITER(hh,wacct->waddr,waddr,tmp2)
{
if ( bits256_nonz(waddr->privkey) == 0 )
if ( bits256_nonz(waddr->privkey) == 0 && waddr->scriptlen == 0 )
{
free_json(account);
printf("found a null privkey in wallet, abort saving\n");
return(0);
}
jaddbits256(account,waddr->coinaddr,waddr->privkey);
if ( waddr->scriptlen != 0 )
{
init_hexbytes_noT(scriptstr,waddr->redeemScript,waddr->scriptlen);
jaddstr(account,waddr->coinaddr,scriptstr);
} else jaddbits256(account,waddr->coinaddr,waddr->privkey);
}
wallet = cJSON_CreateObject();
jadd(wallet,wacct->account,account);
@ -85,46 +89,72 @@ struct iguana_waddress *iguana_waddressfind(struct supernet_info *myinfo,struct
return(waddr);
}
struct iguana_waddress *iguana_waddresscreate(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,char *coinaddr)
struct iguana_waddress *iguana_waddressalloc(char *symbol,char *coinaddr,char *redeemScript)
{
struct iguana_waddress *waddr; int32_t scriptlen;
scriptlen = (redeemScript != 0) ? ((int32_t)strlen(redeemScript) >> 1) : 0;
waddr = mycalloc('w',1,sizeof(*waddr) + scriptlen);
strcpy(waddr->coinaddr,coinaddr);
strcpy(waddr->symbol,symbol);
if ( (waddr->scriptlen= scriptlen) != 0 )
decode_hex(waddr->redeemScript,scriptlen,redeemScript);
return(waddr);
}
struct iguana_waddress *iguana_waddresscreate(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,char *coinaddr,char *redeemScript)
{
struct iguana_waddress *waddr,*ptr; int32_t len = (int32_t)strlen(coinaddr)+1;
HASH_FIND(hh,wacct->waddr,coinaddr,len,waddr);
if ( waddr == 0 )
{
waddr = mycalloc('w',1,sizeof(*waddr));
strcpy(waddr->coinaddr,coinaddr);
strcpy(waddr->symbol,coin->symbol);
HASH_ADD_KEYPTR(hh,wacct->waddr,waddr->coinaddr,len,waddr);
myinfo->dirty = (uint32_t)time(NULL);
printf("create (%s).%d -> (%s)\n",coinaddr,len,wacct->account);
if ( (waddr= iguana_waddressalloc(coin->symbol,coinaddr,redeemScript)) != 0 )
{
HASH_ADD_KEYPTR(hh,wacct->waddr,waddr->coinaddr,len,waddr);
myinfo->dirty = (uint32_t)time(NULL);
printf("create (%s).%d scriptlen.%d -> (%s)\n",coinaddr,len,waddr->scriptlen,wacct->account);
} else printf("error iguana_waddressalloc null waddr\n");
} //else printf("have (%s) in (%s)\n",coinaddr,wacct->account);
if ( (ptr= iguana_waddressfind(myinfo,coin,wacct,coinaddr)) != waddr )
printf("iguana_waddresscreate verify error %p vs %p\n",ptr,waddr);
return(waddr);
}
struct iguana_waddress *iguana_waddressadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,struct iguana_waddress *addwaddr)
struct iguana_waddress *iguana_waddressadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,struct iguana_waddress *addwaddr,char *redeemScript)
{
struct iguana_waddress *waddr,*ptr; int32_t len = (int32_t)strlen(addwaddr->coinaddr)+1;
HASH_FIND(hh,wacct->waddr,addwaddr->coinaddr,len,waddr);
if ( waddr == 0 )
{
waddr = mycalloc('w',1,sizeof(*waddr));
memcpy(waddr,addwaddr,sizeof(*waddr));
addwaddr = waddr;
HASH_ADD_KEYPTR(hh,wacct->waddr,waddr->coinaddr,len,waddr);
myinfo->dirty = (uint32_t)time(NULL);
printf("add (%s).%d -> (%s)\n",waddr->coinaddr,len,wacct->account);
if ( (waddr= iguana_waddressalloc(coin->symbol,addwaddr->coinaddr,redeemScript)) != 0 )
{
HASH_ADD_KEYPTR(hh,wacct->waddr,waddr->coinaddr,len,waddr);
myinfo->dirty = (uint32_t)time(NULL);
printf("add (%s).%d scriptlen.%d -> (%s)\n",waddr->coinaddr,len,waddr->scriptlen,wacct->account);
} else printf("error iguana_waddressalloc null waddr\n");
} //else printf("have (%s) in (%s)\n",waddr->coinaddr,wacct->account);
if ( (ptr= iguana_waddressfind(myinfo,coin,wacct,waddr->coinaddr)) != waddr )
printf("iguana_waddressadd verify error %p vs %p\n",ptr,waddr);
if ( waddr != 0 && waddr != addwaddr )
{
waddr->privkey = addwaddr->privkey;
if ( redeemScript != 0 && (addwaddr->scriptlen= (int32_t)strlen(redeemScript) >> 1) != 0 )
{
if ( waddr->scriptlen != addwaddr->scriptlen )
{
if ( waddr->scriptlen < addwaddr->scriptlen )
{
printf("unexpected waddr->scriptlen mismatch\n");
}
waddr->scriptlen = addwaddr->scriptlen;
decode_hex(waddr->redeemScript,waddr->scriptlen,redeemScript);
}
}
if ( bits256_nonz(waddr->privkey) == 0 )
waddr->privkey = addwaddr->privkey;
memcpy(waddr->pubkey,addwaddr->pubkey,sizeof(waddr->pubkey));
memcpy(waddr->rmd160,addwaddr->rmd160,sizeof(waddr->rmd160));
strcpy(waddr->coinaddr,addwaddr->coinaddr);
strcpy(waddr->wifstr,addwaddr->wifstr);
if ( waddr->wifstr[0] == 0 )
strcpy(waddr->wifstr,addwaddr->wifstr);
waddr->wiftype = addwaddr->wiftype;
waddr->type = addwaddr->type;
myinfo->dirty = (uint32_t)time(NULL);
@ -200,7 +230,7 @@ struct iguana_waddress *iguana_waddresscalc(uint8_t pubtype,uint8_t wiftype,stru
return(0);
}
struct iguana_waddress *iguana_waccountswitch(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr)
struct iguana_waddress *iguana_waccountswitch(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr,char *redeemScript)
{
struct iguana_waccount *wacct = 0; struct iguana_waddress addr,*waddr = 0; int32_t flag = 0;
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,coinaddr)) != 0 )
@ -211,8 +241,8 @@ struct iguana_waddress *iguana_waccountswitch(struct supernet_info *myinfo,struc
}
if ( (wacct= iguana_waccountcreate(myinfo,coin,account)) != 0 )
{
waddr = iguana_waddresscreate(myinfo,coin,wacct,coinaddr);
if ( flag != 0 )
waddr = iguana_waddresscreate(myinfo,coin,wacct,coinaddr,redeemScript);
if ( flag != 0 && redeemScript == 0 )
iguana_waddresscalc(coin->chain->pubtype,coin->chain->wiftype,waddr,addr.privkey);
}
return(waddr);
@ -263,15 +293,15 @@ cJSON *getaddressesbyaccount(struct supernet_info *myinfo,struct iguana_info *co
return(array);
}
struct iguana_waddress *iguana_waccountadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount **wacctp,char *walletaccount,char *coinaddr)
/*struct iguana_waddress *iguana_waccountadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount **wacctp,char *walletaccount,char *coinaddr,char *redeemScript)
{
struct iguana_waccount *wacct; struct iguana_waddress *waddr = 0;
if ( (wacct= iguana_waccountfind(myinfo,coin,walletaccount)) == 0 )
wacct = iguana_waccountcreate(myinfo,coin,walletaccount);
if ( wacct != 0 )
waddr = iguana_waddresscreate(myinfo,coin,wacct,coinaddr);
waddr = iguana_waddresscreate(myinfo,coin,wacct,coinaddr,redeemScript);
return(waddr);
}
}*/
void iguana_walletlock(struct supernet_info *myinfo)
{
@ -328,7 +358,7 @@ int32_t iguana_addressvalidate(struct iguana_info *coin,uint8_t *addrtypep,uint8
cJSON *iguana_waddressjson(cJSON *item,struct iguana_waddress *waddr)
{
char str[256];
char str[256],redeemScript[4096];
if ( item == 0 )
item = cJSON_CreateObject();
jaddstr(item,"address",waddr->coinaddr);
@ -339,17 +369,22 @@ cJSON *iguana_waddressjson(cJSON *item,struct iguana_waddress *waddr)
init_hexbytes_noT(str,waddr->rmd160,20);
jaddstr(item,"rmd160",str);
jaddstr(item,"coin",waddr->symbol);
if ( waddr->scriptlen > 0 )
{
init_hexbytes_noT(redeemScript,waddr->redeemScript,waddr->scriptlen);
jaddstr(item,"redeemScript",redeemScript);
}
return(item);
}
char *setaccount(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr)
char *setaccount(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr,char *redeemScript)
{
uint8_t addrtype,rmd160[20]; struct iguana_waddress *waddr=0;
if ( coinaddr != 0 && coinaddr[0] != 0 && account != 0 && account[0] != 0 )
{
if ( iguana_addressvalidate(coin,&addrtype,rmd160,coinaddr) < 0 )
return(clonestr("{\"error\":\"invalid coin address\"}"));
if ( (waddr= iguana_waccountswitch(myinfo,coin,account,coinaddr)) != 0 )
if ( (waddr= iguana_waccountswitch(myinfo,coin,account,coinaddr,redeemScript)) != 0 )
return(clonestr("{\"result\":\"success\"}"));
else return(clonestr("{\"error\":\"couldnt set account\"}"));
}
@ -407,11 +442,31 @@ bits256 iguana_str2priv(struct supernet_info *myinfo,struct iguana_info *coin,ch
{
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,str)) != 0 )
privkey = waddr->privkey;
else memset(privkey.bytes,0,sizeof(privkey));
}
}
return(privkey);
}
int32_t iguana_pubkeyget(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *pubkey33,char *pkstr)
{
bits256 privkey,pubkey;
decode_hex(pubkey33,(int32_t)strlen(pkstr) >> 1,pkstr);
if ( bitcoin_pubkeylen(pubkey33) <= 0 )
{
privkey = iguana_str2priv(myinfo,coin,pkstr);
if ( bits256_nonz(privkey) == 0 )
return(-1);
else
{
pubkey = bitcoin_pubkey33(pubkey33,privkey);
if ( bits256_nonz(pubkey) == 0 )
return(-1);
}
}
return(0);
}
char *iguana_addressconv(struct iguana_info *coin,char *destaddr,struct iguana_info *other,int32_t isp2sh,uint8_t rmd160[20])
{
if ( bitcoin_address(destaddr,isp2sh != 0 ? other->chain->pubtype : other->chain->p2shtype,rmd160,20) == destaddr )
@ -469,7 +524,7 @@ int32_t iguana_payloadupdate(struct supernet_info *myinfo,struct iguana_info *co
return(retval);
}
cJSON *iguana_walletadd(struct supernet_info *myinfo,struct iguana_waddress **waddrp,struct iguana_info *coin,char *retstr,char *account,struct iguana_waddress *refwaddr,int32_t setcurrent)
cJSON *iguana_walletadd(struct supernet_info *myinfo,struct iguana_waddress **waddrp,struct iguana_info *coin,char *retstr,char *account,struct iguana_waddress *refwaddr,int32_t setcurrent,char *redeemScript)
{
cJSON *retjson=0; struct iguana_waccount *wacct; struct iguana_waddress *waddr;
if ( (wacct= iguana_waccountfind(myinfo,coin,account)) == 0 )
@ -477,7 +532,7 @@ cJSON *iguana_walletadd(struct supernet_info *myinfo,struct iguana_waddress **wa
if ( wacct != 0 )
{
//waddr = iguana_waddressfind(myinfo,coin,wacct,refwaddr->coinaddr);
waddr = iguana_waddressadd(myinfo,coin,wacct,refwaddr);
waddr = iguana_waddressadd(myinfo,coin,wacct,refwaddr,redeemScript);
if ( setcurrent != 0 )
wacct->current = waddr;
if ( iguana_payloadupdate(myinfo,coin,retstr,waddr,account) < 0 )
@ -505,11 +560,12 @@ char *getnewaddress(struct supernet_info *myinfo,struct iguana_waddress **waddrp
struct iguana_waddress addr; cJSON *retjson;
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
if ( retstr != 0 )
{
memset(&addr,0,sizeof(addr));
if ( iguana_waddresscalc(coin->chain->pubtype,coin->chain->wiftype,&addr,rand256(1)) != 0 )
retjson = iguana_walletadd(myinfo,waddrp,coin,retstr,account,&addr,1);
retjson = iguana_walletadd(myinfo,waddrp,coin,retstr,account,&addr,1,0);
else return(clonestr("{\"error\":\"couldnt calculate waddr\"}"));
} else return(clonestr("{\"error\":\"no wallet data\"}"));
return(jprint(retjson,1));
@ -555,6 +611,7 @@ ZERO_ARGS(bitcoinrpc,getinfo)
{
jaddstr(retjson,"result","success");
jaddnum(retjson,"protocolversion",PROTOCOL_VERSION);
jaddnum(retjson,"kbfee",dstr(coin->txfee_perkb));
jaddnum(retjson,"blocks",coin->blocks.hwmchain.height);
jaddnum(retjson,"longestchain",coin->longestchain);
jaddnum(retjson,"port",coin->chain->portp2p);
@ -570,7 +627,10 @@ TWO_STRINGS(bitcoinrpc,setaccount,address,account)
{
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
return(setaccount(myinfo,coin,account,address));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
return(setaccount(myinfo,coin,account,address,0));
}
STRING_ARG(bitcoinrpc,getaccount,address)
@ -587,6 +647,7 @@ STRING_ARG(bitcoinrpc,getnewaddress,account)
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
{
free(retstr);
@ -606,6 +667,7 @@ STRING_ARG(bitcoinrpc,getaccountaddress,account)
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
if ( account != 0 && account[0] != 0 )
{
if ( (wacct= iguana_waccountfind(myinfo,coin,account)) == 0 )
@ -647,7 +709,7 @@ ZERO_ARGS(bitcoinrpc,walletlock)
void iguana_walletinitcheck(struct supernet_info *myinfo,struct iguana_info *coin)
{
// "wallet":{"test":{"R9S7zZzzvgb4CkiBH1i7gnFcwJuL1MYbxN":"18ab9c89ce83929db720cf26b663bf762532276146cd9d3e1f89086fcdf00053"}}
cJSON *payload,*item,*array,*child; char *account,*coinaddr,*privkeystr; int32_t i,j,n,len; struct iguana_waccount *wacct,*tmp; struct iguana_waddress waddr; bits256 privkey;
cJSON *payload,*item,*array,*child; char *account,*coinaddr,*privkeystr; int32_t i,j,n,len; struct iguana_waccount *wacct,*tmp; struct iguana_waddress waddr; bits256 privkey; uint8_t addrtype,rmd160[20];
if ( myinfo->wallet == 0 && myinfo->decryptstr != 0 && (payload= cJSON_Parse(myinfo->decryptstr)) != 0 )
{
if ( (array= jobj(payload,"wallet")) != 0 )
@ -670,21 +732,24 @@ void iguana_walletinitcheck(struct supernet_info *myinfo,struct iguana_info *coi
{
if ( iguana_waddresssearch(myinfo,coin,&tmp,coinaddr) == 0 )
{
privkey = bits256_conv(privkeystr);
if ( iguana_waddresscalc(coin->chain->pubtype,coin->chain->wiftype,&waddr,privkey) != 0 )
memset(&waddr,0,sizeof(waddr));
strcpy(waddr.coinaddr,coinaddr);
if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == sizeof(rmd160) && addrtype == coin->chain->p2shtype )
iguana_waddressadd(myinfo,coin,wacct,&waddr,privkeystr);
else
{
strcpy(waddr.coinaddr,coinaddr);
iguana_waddressadd(myinfo,coin,wacct,&waddr);
//iguana_waccountswitch(myinfo,coin,account,coinaddr);
privkey = bits256_conv(privkeystr);
if ( iguana_waddresscalc(coin->chain->pubtype,coin->chain->wiftype,&waddr,privkey) != 0 )
iguana_waddressadd(myinfo,coin,wacct,&waddr,0);
}
} else printf("dup.(%s) ",coinaddr);
len = (int32_t)strlen(privkeystr);
for (j=0; j<len; j++)
privkeystr[j] = 0;
for (j=0; j<len; j++)
privkeystr[j] = 0x20 + (rand() % 64);
privkey = rand256(0);
}
len = (int32_t)strlen(privkeystr);
for (j=0; j<len; j++)
privkeystr[j] = 0;
for (j=0; j<len; j++)
privkeystr[j] = 0x20 + (rand() % 64);
privkey = rand256(0);
}
child = child->next;
}
@ -702,7 +767,7 @@ void iguana_walletinitcheck(struct supernet_info *myinfo,struct iguana_info *coi
int32_t iguana_walletemit(struct supernet_info *myinfo,char *fname,struct iguana_info *coin,cJSON *array)
{
cJSON *item,*child; uint8_t addrtype,wiftype,rmd160[20]; char str[64],wifstr[128],*account,*coinaddr,*privkeystr; int32_t i,j,n; FILE *fp; bits256 privkey;
cJSON *item,*child; uint8_t addrtype,wiftype,rmd160[20]; char p2shaddr[128],str[64],wifstr[128],*account,*coinaddr,*privkeystr; int32_t i,j,n; FILE *fp; bits256 privkey;
if ( (fp= fopen(fname,"wb")) == 0 )
return(-1);
n = cJSON_GetArraySize(array);
@ -718,19 +783,28 @@ int32_t iguana_walletemit(struct supernet_info *myinfo,char *fname,struct iguana
privkeystr = child->valuestring;
if ( coinaddr != 0 && privkeystr != 0 )
{
// RZXuGgmzABFpXRmGJet8AbJoqVGEs27WgdvkSSXUMg7en8jjBW2m 2016-03-26T18:40:06Z reserve=1 # addr=GRVaqhY6XVWGeEabEEx5gE7mAQ7EYQi5JV
privkey = bits256_conv(privkeystr);
bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr);
wiftype = 188;
for (j=0; j<IGUANA_MAXCOINS; j++)
if ( (coin= Coins[j]) != 0 && coin->chain != 0 && coin->chain->pubtype == addrtype )
{
if ( (coin= Coins[j]) != 0 && coin->chain != 0 )
{
wiftype = coin->chain->wiftype;
break;
if ( addrtype == coin->chain->pubtype )
{
wiftype = coin->chain->wiftype;
privkey = bits256_conv(privkeystr);
if ( bitcoin_priv2wif(wifstr,privkey,wiftype) > 0 )
{
fprintf(fp,"%s %s %32s=%d # addr=%s\n",wifstr,utc_str(str,(uint32_t)time(NULL)),account,i+1,coinaddr);
}
break;
}
else if ( addrtype == coin->chain->p2shtype )
{
fprintf(fp,"%s %s %32s=%d # addr=%s # p2sh\n",privkeystr,utc_str(str,(uint32_t)time(NULL)),account,i+1,p2shaddr);
break;
}
}
if ( bitcoin_priv2wif(wifstr,privkey,wiftype) > 0 )
{
fprintf(fp,"%s %s %32s=%d # addr=%s\n",wifstr,utc_str(str,(uint32_t)time(NULL)),account,i+1,coinaddr);
}
}
child = child->next;
@ -808,6 +882,9 @@ TWOSTRINGS_AND_INT(bitcoinrpc,importprivkey,wif,account,rescan)
bits256 privkey; char *retstr; cJSON *retjson; struct iguana_waddress addr,*waddr; struct iguana_waccount *wacct = 0;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
if ( account == 0 || account[0] == 0 )
account = "default";
privkey = iguana_str2priv(myinfo,coin,wif);
@ -818,11 +895,12 @@ TWOSTRINGS_AND_INT(bitcoinrpc,importprivkey,wif,account,rescan)
{
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,addr.coinaddr)) != 0 )
{
waddr = iguana_waccountswitch(myinfo,coin,account,addr.coinaddr);
waddr = iguana_waccountswitch(myinfo,coin,account,addr.coinaddr,0);
return(clonestr("{\"result\":\"privkey already in wallet\"}"));
}
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
{
free(retstr);
@ -830,7 +908,7 @@ TWOSTRINGS_AND_INT(bitcoinrpc,importprivkey,wif,account,rescan)
if ( waddr == 0 )
waddr = &addr;
iguana_waddresscalc(coin->chain->pubtype,coin->chain->wiftype,waddr,privkey);
retjson = iguana_walletadd(myinfo,0,coin,retstr,account,waddr,0);
retjson = iguana_walletadd(myinfo,0,coin,retstr,account,waddr,0,0);
if ( retstr != 0 )
scrubfree(retstr);
return(jprint(retjson,1));
@ -844,6 +922,9 @@ STRING_ARG(bitcoinrpc,dumpprivkey,address)
cJSON *retjson; struct iguana_waddress *waddr; struct iguana_waccount *wacct;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,address)) != 0 && waddr->wifstr[0] != 0 )
{
retjson = cJSON_CreateObject();
@ -857,6 +938,9 @@ ZERO_ARGS(bitcoinrpc,checkwallet)
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
return(jprint(retjson,1));
@ -867,6 +951,9 @@ ZERO_ARGS(bitcoinrpc,repairwallet)
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
return(jprint(retjson,1));
@ -879,6 +966,7 @@ STRING_ARG(bitcoinrpc,dumpwallet,filename)
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration != 0 )
{
myinfo->expiration++;
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
@ -908,6 +996,7 @@ STRING_ARG(bitcoinrpc,backupwallet,filename)
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration != 0 )
{
myinfo->expiration++;
if ( (loginstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
{
retstr = clonestr("{\"error\":\"couldnt backup wallet\"}");
@ -940,7 +1029,11 @@ cJSON *iguana_payloadmerge(cJSON *loginjson,cJSON *importjson)
if ( (field= jfieldname(item)) != 0 )
{
if ( (obj= jobj(retjson,field)) == 0 )
jaddbits256(retjson,field,jbits256(item,0));
{
if ( strlen(field) == 20*2 )
jaddstr(retjson,field,jstr(item,0));
else jaddbits256(retjson,field,jbits256(item,0));
}
}
item = item->next;
}
@ -954,6 +1047,7 @@ STRING_ARG(bitcoinrpc,importwallet,filename)
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration != 0 )
{
myinfo->expiration++;
if ( (importstr= OS_filestr(&filesize,filename)) != 0 )
{
if ( (importjson= cJSON_Parse(importstr)) != 0 )
@ -1175,22 +1269,85 @@ STRING_AND_INT(bitcoinrpc,getreceivedbyaddress,address,minconf)
return(jprint(retjson,1));
}
INT_ARRAY_STRING(bitcoinrpc,createmultisig,M,array,ignore)
INT_ARRAY_STRING(bitcoinrpc,createmultisig,M,pubkeys,ignore)
{
cJSON *retjson;
cJSON *retjson,*pkjson; uint8_t script[2048],p2sh_rmd160[20]; char msigaddr[64],*pkstr,scriptstr[sizeof(script)*2+1]; struct vin_info V; int32_t i,len,n = cJSON_GetArraySize(pubkeys);
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( n < 0 || n > 16 || M < 0 || M > n )
return(clonestr("{\"error\":\"illegal number of pubkeys\"}"));
memset(&V,0,sizeof(V));
V.M = M, V.N = n;
pkjson = cJSON_CreateArray();
for (i=0; i<n; i++)
{
if ( (pkstr= jstr(jitem(pubkeys,i),0)) != 0 )
{
if ( iguana_pubkeyget(myinfo,coin,V.signers[i].pubkey,pkstr) < 0 )
break;
if ( bitcoin_pubkeylen(V.signers[i].pubkey) <= 0 )
break;
jaddistr(pkjson,pkstr);
} else break;
}
retjson = cJSON_CreateObject();
if ( i == n )
{
len = bitcoin_MofNspendscript(p2sh_rmd160,script,0,&V);
bitcoin_address(msigaddr,coin->chain->p2shtype,p2sh_rmd160,sizeof(p2sh_rmd160));
jaddstr(retjson,"result","success");
jaddstr(retjson,"address",msigaddr);
init_hexbytes_noT(scriptstr,script,len);
jaddstr(retjson,"redeemScript",scriptstr);
jaddnum(retjson,"M",M);
jaddnum(retjson,"N",n);
jadd(retjson,"pubkeys",pkjson);
}
else
{
jaddstr(retjson,"error","couldnt get all pubkeys");
free_json(pkjson);
}
return(jprint(retjson,1));
}
INT_ARRAY_STRING(bitcoinrpc,addmultisig,M,array,account) //
INT_ARRAY_STRING(bitcoinrpc,addmultisigaddress,M,pubkeys,account) //
{
cJSON *retjson;
cJSON *retjson,*tmpjson,*setjson=0; char *retstr,*str=0,*msigaddr,*redeemScript;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
retjson = cJSON_CreateObject();
return(jprint(retjson,1));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
if ( (retstr= bitcoinrpc_createmultisig(IGUANA_CALLARGS,M,pubkeys,account)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (msigaddr= jstr(retjson,"address")) != 0 )
{
if ( (redeemScript= jstr(retjson,"redeemScript")) == 0 || (str= setaccount(myinfo,coin,account,msigaddr,redeemScript)) == 0 || (setjson= cJSON_Parse(str)) == 0 || jobj(setjson,"error") != 0 )
{
if ( jobj(retjson,"result") != 0 )
jdelete(retjson,"result");
if ( jobj(retjson,"error") == 0 )
jaddstr(retjson,"error","couldnt add multisig address to account");
}
else
{
tmpjson = cJSON_CreateObject();
jaddstr(tmpjson,"result",msigaddr);
free_json(retjson);
free(retstr);
retjson = tmpjson;
}
}
if ( setjson != 0 )
free_json(setjson);
if ( str != 0 )
free(str);
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"couldnt parse retstr from createmultisig\"}"));
} else return(clonestr("{\"error\":\"no retstr from createmultisig\"}"));
}
STRING_AND_INT(bitcoinrpc,sendrawtransaction,rawtx,allowhighfees)
@ -1204,7 +1361,12 @@ DOUBLE_ARG(bitcoinrpc,settxfee,amount)
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
coin->txfee_perkb = amount * SATOSHIDEN;
retjson = cJSON_CreateObject();
jadd(retjson,"result",jtrue());
return(jprint(retjson,1));
}
@ -1213,6 +1375,9 @@ S_D_SS(bitcoinrpc,sendtoaddress,address,amount,comment,comment2)
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
retjson = cJSON_CreateObject();
return(jsuccess());
}
@ -1222,6 +1387,9 @@ SS_D_I_SS(bitcoinrpc,sendfrom,fromaccount,toaddress,amount,minconf,comment,comme
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
retjson = cJSON_CreateObject();
return(jsuccess());
}
@ -1231,6 +1399,9 @@ SS_D_I_S(bitcoinrpc,move,fromaccount,toaccount,amount,minconf,comment)
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
retjson = cJSON_CreateObject();
return(jprint(retjson,1));
}
@ -1240,6 +1411,9 @@ S_A_I_S(bitcoinrpc,sendmany,fromaccount,array,minconf,comment)
cJSON *retjson;
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
if ( myinfo->expiration == 0 )
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
myinfo->expiration++;
retjson = cJSON_CreateObject();
return(jprint(retjson,1));
}

2
iguana/tests/addmultisig

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"addmultisig\",\"params\":[2, [\"002629c77b81a4d338a339488aaff796a93aeec8c734b22dee865d0ff58ff64c\", \"d0296ed1364639c696c374730320480301f3194c86231f62f0409cd76467f87c\", \"d045925b3e6f648bca6ed0c65149ee445137f0ab14e88cf60013d88419bcdd60\"], \"msigs\"]}"

2
iguana/tests/createmultisig

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"createmultisig\",\"params\":[2, [\"002629c77b81a4d338a339488aaff796a93aeec8c734b22dee865d0ff58ff64c\", \"d0296ed1364639c696c374730320480301f3194c86231f62f0409cd76467f87c\", \"d045925b3e6f648bca6ed0c65149ee445137f0ab14e88cf60013d88419bcdd60\"]]}"

4
iguana/tests/walletpassphrase

@ -1,2 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"method\":\"walletpassphrase\",\"params\":[\"test\", 600]}"
#curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"bitcoinrpc\",\"method\":\"walletpassphrase\",\"password\":\"test\",\"timeout\":300}"
#curl --url "http://127.0.0.1:7778" --data "{\"method\":\"walletpassphrase\",\"params\":[\"test\", 600]}"
curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"bitcoinrpc\",\"method\":\"walletpassphrase\",\"password\":\"test\",\"timeout\":300}"

5
includes/iguana_apideclares.h

@ -57,8 +57,9 @@ STRING_ARG(bitcoinrpc,getaccount,address);
STRING_ARG(bitcoinrpc,getaccountaddress,account);
TWO_STRINGS(bitcoinrpc,setaccount,address,account);
INT_ARRAY_STRING(bitcoinrpc,createmultisig,M,array,ignore); //
INT_ARRAY_STRING(bitcoinrpc,addmultisig,M,array,account); //
INT_ARRAY_STRING(bitcoinrpc,createmultisig,M,pubkeys,ignore);
INT_ARRAY_STRING(bitcoinrpc,addmultisigaddress,M,pubkeys,account);
STRING_ARRAY_OBJ_STRING(bitcoinrpc,signrawtransaction,rawtx,vins,privkeys,sighash); //
STRING_AND_INT(bitcoinrpc,sendrawtransaction,rawtx,allowhighfees); //

Loading…
Cancel
Save