Browse Source

connect atomic to rpc

release/v0.1
jl777 9 years ago
parent
commit
0cbacc1d4f
  1. 4
      crypto777/bitcoind_RPC.c
  2. 2
      crypto777/iguana_utils.c
  3. 7
      iguana/SuperNET.h
  4. 673
      iguana/exchanges/bitcoin.c
  5. 7
      iguana/exchanges/bitcoin.h
  6. 7
      iguana/iguana777.h
  7. 24
      iguana/iguana_instantdex.c
  8. 4
      iguana/iguana_msg.c
  9. 4
      iguana/iguana_pubkeys.c
  10. 2
      iguana/iguana_ramchain.c
  11. 105
      iguana/iguana_tx.c
  12. 40
      iguana/swaps/iguana_BTCswap.c

4
crypto777/bitcoind_RPC.c

@ -49,7 +49,7 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
long i,j,len;
char *retstr = 0;
cJSON *json,*result,*error;
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
//printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
{
printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
@ -163,7 +163,7 @@ try_again:
databuf = (char *)malloc(256 + strlen(command) + strlen(params));
sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1);
printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
//printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf);
//
} //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params);
curl_easy_setopt(curl_handle,CURLOPT_POST,1L);

2
crypto777/iguana_utils.c

@ -342,7 +342,7 @@ int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex)
int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len)
{
int32_t i;
if ( len == 0 )
if ( len <= 0 )
{
hexbytes[0] = 0;
return(1);

7
iguana/SuperNET.h

@ -122,7 +122,12 @@ struct category_msg { struct queueitem DL; struct tai t; uint64_t remoteipbits;
struct exchange_quote { uint64_t satoshis,orderid,offerNXT,exchangebits; double price,volume; uint32_t timestamp,val; };
struct bitcoin_unspent { bits256 txid,privkeys[16]; uint64_t value; int32_t vout; uint8_t addrtype,rmd160[20],script[512]; };
struct bitcoin_unspent
{
bits256 txid,privkeys[16]; uint64_t value; int32_t vout,spendlen; uint32_t sequence;
uint8_t addrtype,rmd160[20],spendscript[2048];
};
struct bitcoin_spend
{
char changeaddr[64];

673
iguana/exchanges/bitcoin.c

@ -31,6 +31,290 @@ static const char base58_chars[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijk
#define IGUANA_SCRIPT_DATA 11
#define IGUANA_SCRIPT_STRANGE 15
enum opcodetype
{
// push value
OP_0 = 0x00,
OP_FALSE = OP_0,
OP_PUSHDATA1 = 0x4c,
OP_PUSHDATA2 = 0x4d,
OP_PUSHDATA4 = 0x4e,
OP_1NEGATE = 0x4f,
OP_RESERVED = 0x50,
OP_1 = 0x51,
OP_TRUE=OP_1,
OP_2 = 0x52,
OP_3 = 0x53,
OP_4 = 0x54,
OP_5 = 0x55,
OP_6 = 0x56,
OP_7 = 0x57,
OP_8 = 0x58,
OP_9 = 0x59,
OP_10 = 0x5a,
OP_11 = 0x5b,
OP_12 = 0x5c,
OP_13 = 0x5d,
OP_14 = 0x5e,
OP_15 = 0x5f,
OP_16 = 0x60,
// control
OP_NOP = 0x61,
OP_VER = 0x62,
OP_IF = 0x63,
OP_NOTIF = 0x64,
OP_VERIF = 0x65,
OP_VERNOTIF = 0x66,
OP_ELSE = 0x67,
OP_ENDIF = 0x68,
OP_VERIFY = 0x69,
OP_RETURN = 0x6a,
// stack ops
OP_TOALTSTACK = 0x6b,
OP_FROMALTSTACK = 0x6c,
OP_2DROP = 0x6d,
OP_2DUP = 0x6e,
OP_3DUP = 0x6f,
OP_2OVER = 0x70,
OP_2ROT = 0x71,
OP_2SWAP = 0x72,
OP_IFDUP = 0x73,
OP_DEPTH = 0x74,
OP_DROP = 0x75,
OP_DUP = 0x76,
OP_NIP = 0x77,
OP_OVER = 0x78,
OP_PICK = 0x79,
OP_ROLL = 0x7a,
OP_ROT = 0x7b,
OP_SWAP = 0x7c,
OP_TUCK = 0x7d,
// splice ops
OP_CAT = 0x7e,
OP_SUBSTR = 0x7f,
OP_LEFT = 0x80,
OP_RIGHT = 0x81,
OP_SIZE = 0x82,
// bit logic
OP_INVERT = 0x83,
OP_AND = 0x84,
OP_OR = 0x85,
OP_XOR = 0x86,
OP_EQUAL = 0x87,
OP_EQUALVERIFY = 0x88,
OP_RESERVED1 = 0x89,
OP_RESERVED2 = 0x8a,
// numeric
OP_1ADD = 0x8b,
OP_1SUB = 0x8c,
OP_2MUL = 0x8d,
OP_2DIV = 0x8e,
OP_NEGATE = 0x8f,
OP_ABS = 0x90,
OP_NOT = 0x91,
OP_0NOTEQUAL = 0x92,
OP_ADD = 0x93,
OP_SUB = 0x94,
OP_MUL = 0x95,
OP_DIV = 0x96,
OP_MOD = 0x97,
OP_LSHIFT = 0x98,
OP_RSHIFT = 0x99,
OP_BOOLAND = 0x9a,
OP_BOOLOR = 0x9b,
OP_NUMEQUAL = 0x9c,
OP_NUMEQUALVERIFY = 0x9d,
OP_NUMNOTEQUAL = 0x9e,
OP_LESSTHAN = 0x9f,
OP_GREATERTHAN = 0xa0,
OP_LESSTHANOREQUAL = 0xa1,
OP_GREATERTHANOREQUAL = 0xa2,
OP_MIN = 0xa3,
OP_MAX = 0xa4,
OP_WITHIN = 0xa5,
// crypto
OP_RIPEMD160 = 0xa6,
OP_SHA1 = 0xa7,
OP_SHA256 = 0xa8,
OP_HASH160 = 0xa9,
OP_HASH256 = 0xaa,
OP_CODESEPARATOR = 0xab,
OP_CHECKSIG = 0xac,
OP_CHECKSIGVERIFY = 0xad,
OP_CHECKMULTISIG = 0xae,
OP_CHECKMULTISIGVERIFY = 0xaf,
// expansion
OP_NOP1 = 0xb0,
OP_NOP2 = 0xb1,
OP_NOP3 = 0xb2,
OP_NOP4 = 0xb3,
OP_NOP5 = 0xb4,
OP_NOP6 = 0xb5,
OP_NOP7 = 0xb6,
OP_NOP8 = 0xb7,
OP_NOP9 = 0xb8,
OP_NOP10 = 0xb9,
// template matching params
OP_SMALLINTEGER = 0xfa,
OP_PUBKEYS = 0xfb,
OP_PUBKEYHASH = 0xfd,
OP_PUBKEY = 0xfe,
OP_INVALIDOPCODE = 0xff,
};
const char *get_opname(int32_t *extralenp,enum opcodetype opcode)
{
*extralenp = 0;
switch (opcode)
{
// push value
case OP_0 : return "0";
case OP_PUSHDATA1 : *extralenp = 1; return "OP_PUSHDATA1";
case OP_PUSHDATA2 : *extralenp = 2; return "OP_PUSHDATA2";
case OP_PUSHDATA4 : *extralenp = 4; return "OP_PUSHDATA4";
case OP_1NEGATE : return "-1";
case OP_RESERVED : return "OP_RESERVED";
case OP_1 : return "1";
case OP_2 : return "2";
case OP_3 : return "3";
case OP_4 : return "4";
case OP_5 : return "5";
case OP_6 : return "6";
case OP_7 : return "7";
case OP_8 : return "8";
case OP_9 : return "9";
case OP_10 : return "10";
case OP_11 : return "11";
case OP_12 : return "12";
case OP_13 : return "13";
case OP_14 : return "14";
case OP_15 : return "15";
case OP_16 : return "16";
// control
case OP_NOP : return "OP_NOP";
case OP_VER : return "OP_VER";
case OP_IF : return "OP_IF";
case OP_NOTIF : return "OP_NOTIF";
case OP_VERIF : return "OP_VERIF";
case OP_VERNOTIF : return "OP_VERNOTIF";
case OP_ELSE : return "OP_ELSE";
case OP_ENDIF : return "OP_ENDIF";
case OP_VERIFY : return "OP_VERIFY";
case OP_RETURN : return "OP_RETURN";
// stack ops
case OP_TOALTSTACK : return "OP_TOALTSTACK";
case OP_FROMALTSTACK : return "OP_FROMALTSTACK";
case OP_2DROP : return "OP_2DROP";
case OP_2DUP : return "OP_2DUP";
case OP_3DUP : return "OP_3DUP";
case OP_2OVER : return "OP_2OVER";
case OP_2ROT : return "OP_2ROT";
case OP_2SWAP : return "OP_2SWAP";
case OP_IFDUP : return "OP_IFDUP";
case OP_DEPTH : return "OP_DEPTH";
case OP_DROP : return "OP_DROP";
case OP_DUP : return "OP_DUP";
case OP_NIP : return "OP_NIP";
case OP_OVER : return "OP_OVER";
case OP_PICK : return "OP_PICK";
case OP_ROLL : return "OP_ROLL";
case OP_ROT : return "OP_ROT";
case OP_SWAP : return "OP_SWAP";
case OP_TUCK : return "OP_TUCK";
// splice ops
case OP_CAT : return "OP_CAT";
case OP_SUBSTR : return "OP_SUBSTR";
case OP_LEFT : return "OP_LEFT";
case OP_RIGHT : return "OP_RIGHT";
case OP_SIZE : return "OP_SIZE";
// bit logic
case OP_INVERT : return "OP_INVERT";
case OP_AND : return "OP_AND";
case OP_OR : return "OP_OR";
case OP_XOR : return "OP_XOR";
case OP_EQUAL : return "OP_EQUAL";
case OP_EQUALVERIFY : return "OP_EQUALVERIFY";
case OP_RESERVED1 : return "OP_RESERVED1";
case OP_RESERVED2 : return "OP_RESERVED2";
// numeric
case OP_1ADD : return "OP_1ADD";
case OP_1SUB : return "OP_1SUB";
case OP_2MUL : return "OP_2MUL";
case OP_2DIV : return "OP_2DIV";
case OP_NEGATE : return "OP_NEGATE";
case OP_ABS : return "OP_ABS";
case OP_NOT : return "OP_NOT";
case OP_0NOTEQUAL : return "OP_0NOTEQUAL";
case OP_ADD : return "OP_ADD";
case OP_SUB : return "OP_SUB";
case OP_MUL : return "OP_MUL";
case OP_DIV : return "OP_DIV";
case OP_MOD : return "OP_MOD";
case OP_LSHIFT : return "OP_LSHIFT";
case OP_RSHIFT : return "OP_RSHIFT";
case OP_BOOLAND : return "OP_BOOLAND";
case OP_BOOLOR : return "OP_BOOLOR";
case OP_NUMEQUAL : return "OP_NUMEQUAL";
case OP_NUMEQUALVERIFY : return "OP_NUMEQUALVERIFY";
case OP_NUMNOTEQUAL : return "OP_NUMNOTEQUAL";
case OP_LESSTHAN : return "OP_LESSTHAN";
case OP_GREATERTHAN : return "OP_GREATERTHAN";
case OP_LESSTHANOREQUAL : return "OP_LESSTHANOREQUAL";
case OP_GREATERTHANOREQUAL : return "OP_GREATERTHANOREQUAL";
case OP_MIN : return "OP_MIN";
case OP_MAX : return "OP_MAX";
case OP_WITHIN : return "OP_WITHIN";
// crypto
case OP_RIPEMD160 : return "OP_RIPEMD160";
case OP_SHA1 : return "OP_SHA1";
case OP_SHA256 : return "OP_SHA256";
case OP_HASH160 : return "OP_HASH160";
case OP_HASH256 : return "OP_HASH256";
case OP_CODESEPARATOR : return "OP_CODESEPARATOR";
case OP_CHECKSIG : return "OP_CHECKSIG";
case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY";
case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG";
case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY";
// expanson
case OP_NOP1 : return "OP_NOP1";
case OP_NOP2 : return "OP_NOP2";
case OP_NOP3 : return "OP_NOP3";
case OP_NOP4 : return "OP_NOP4";
case OP_NOP5 : return "OP_NOP5";
case OP_NOP6 : return "OP_NOP6";
case OP_NOP7 : return "OP_NOP7";
case OP_NOP8 : return "OP_NOP8";
case OP_NOP9 : return "OP_NOP9";
case OP_NOP10 : return "OP_NOP10";
case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
// Note:
// The template matching params OP_SMALLDATA/etc are defined in opcodetype enum
// as kind of implementation hack, they are *NOT* real opcodes. If found in real
// Script, just let the default: case deal with them.
default: return "OP_UNKNOWN";
}
}
char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params)
{
return(bitcoind_RPC(0,coinstr,serverport,userpass,method,params));
@ -326,6 +610,8 @@ int32_t bitcoin_sign(uint8_t *sig,int32_t maxlen,uint8_t *data,int32_t datalen,b
int32_t bitcoin_verify(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen,EC_KEY *KEY,uint8_t *pubkey,int32_t len)
{
ECDSA_SIG *esig; int32_t retval = -1; uint8_t tmp[33],*ptr,*sigptr = sig; EC_KEY *origkey = KEY;
if ( len < 0 )
return(-1);
if ( (esig= ECDSA_SIG_new()) != 0 )
{
if ( d2i_ECDSA_SIG(&esig,(const uint8_t **)&sigptr,siglen) != 0 )
@ -402,8 +688,8 @@ int32_t bitcoin_standardspend(uint8_t *script,int32_t n,uint8_t rmd160[20])
int32_t bitcoin_checklocktimeverify(uint8_t *script,int32_t n,uint32_t locktime)
{
script[n++] = (locktime >> 24), script[n++] = (locktime >> 16), script[n++] = (locktime >> 8), script[n++] = locktime;
script[n++] = OP_CHECKLOCKTIMEVERIFY;
script[n++] = OP_DROP;
script[n++] = SCRIPT_OP_CHECKLOCKTIMEVERIFY;
script[n++] = SCRIPT_OP_DROP;
return(n);
}
@ -510,8 +796,9 @@ int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd
int32_t iguana_scriptgen(struct iguana_info *coin,int32_t *Mp,int32_t *nump,char *coinaddr,uint8_t *script,char *asmstr,uint8_t rmd160[20],uint8_t type,const struct vin_info *vp,int32_t txi)
{
uint8_t addrtype; char rmd160str[41],pubkeystr[256]; int32_t i,m,n,flag = 0,scriptlen = 0;
uint8_t addrtype; char rmd160str[41],pubkeystr[256]; int32_t plen,i,m,n,flag = 0,scriptlen = 0;
m = n = 1;
asmstr[0] = 0;
if ( type == IGUANA_SCRIPT_76A988AC || type == IGUANA_SCRIPT_76AC || type == IGUANA_SCRIPT_P2SH )
{
if ( type == IGUANA_SCRIPT_P2SH )
@ -528,10 +815,12 @@ int32_t iguana_scriptgen(struct iguana_info *coin,int32_t *Mp,int32_t *nump,char
coinaddr[0] = 0;
break;
case IGUANA_SCRIPT_76AC:
init_hexbytes_noT(pubkeystr,(uint8_t *)vp->signers[0].pubkey,bitcoin_pubkeylen(vp->signers[0].pubkey));
if ( (plen= bitcoin_pubkeylen(vp->signers[0].pubkey)) < 0 )
return(0);
init_hexbytes_noT(pubkeystr,(uint8_t *)vp->signers[0].pubkey,plen);
sprintf(asmstr,"OP_DUP %s OP_CHECKSIG // %s",pubkeystr,coinaddr);
scriptlen = bitcoin_pubkeyspend(script,0,(uint8_t *)vp->signers[0].pubkey);
//printf("[%02x] scriptlen.%d (%s)\n",vp->signers[0].pubkey[0],scriptlen,asmstr);
printf("[%02x] scriptlen.%d (%s)\n",vp->signers[0].pubkey[0],scriptlen,asmstr);
break;
case IGUANA_SCRIPT_76A988AC:
sprintf(asmstr,"OP_DUP OP_HASH160 %s OP_EQUALVERIFY OP_CHECKSIG // %s",rmd160str,coinaddr);
@ -567,8 +856,11 @@ int32_t iguana_scriptgen(struct iguana_info *coin,int32_t *Mp,int32_t *nump,char
sprintf(asmstr,"%d ",m);
for (i=0; i<n; i++)
{
init_hexbytes_noT(asmstr + strlen(asmstr),(uint8_t *)vp->signers[i].pubkey,bitcoin_pubkeylen(vp->signers[i].pubkey));
strcat(asmstr," ");
if ( (plen= bitcoin_pubkeylen(vp->signers[i].pubkey)) > 0 )
{
init_hexbytes_noT(asmstr + strlen(asmstr),(uint8_t *)vp->signers[i].pubkey,plen);
strcat(asmstr," ");
} else strcat(asmstr,"NOPUBKEY ");
}
sprintf(asmstr + strlen(asmstr),"%d // M.%d of N.%d [",n,m,n);
for (i=0; i<n; i++)
@ -581,6 +873,12 @@ int32_t iguana_scriptgen(struct iguana_info *coin,int32_t *Mp,int32_t *nump,char
return(scriptlen);
}
int32_t iguana_expandscript(struct iguana_info *coin,char *asmstr,int32_t maxlen,uint8_t *script,int32_t scriptlen)
{
asmstr[0] = 0;
return(0);
}
int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp)
{
static uint8_t zero_rmd160[20];
@ -747,7 +1045,7 @@ int32_t iguana_parsevoutobj(struct iguana_info *coin,uint8_t *serialized,int32_t
int32_t iguana_parsevinobj(struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_msgvin *vin,cJSON *vinobj)
{
int32_t len = 0; char *hexstr; cJSON *sigjson;
int32_t n,len = 0; char *hexstr,*spendstr = 0; cJSON *scriptjson;
memset(vin,0,sizeof(*vin));
vin->prev_vout = -1;
vin->sequence = juint(vinobj,"sequence");
@ -755,20 +1053,26 @@ int32_t iguana_parsevinobj(struct iguana_info *coin,uint8_t *serialized,int32_t
{
vin->prev_hash = jbits256(vinobj,"txid");
vin->prev_vout = jint(vinobj,"vout");
if ( (sigjson= jobj(vinobj,"scriptSig")) != 0 )
hexstr = jstr(sigjson,"hex");
if ( (scriptjson= jobj(vinobj,"scriptSig")) != 0 )
hexstr = jstr(scriptjson,"hex");
if ( (scriptjson= jobj(vinobj,"scriptPub")) != 0 )
spendstr = jstr(scriptjson,"hex");
}
if ( hexstr != 0 )
{
len = (int32_t)strlen(hexstr) >> 1;
decode_hex(serialized,len,hexstr);
vin->script = serialized;
vin->sigscript = serialized;
vin->scriptlen = len;
}
else
serialized = &serialized[len];
} //else printf("iguana_parsevinobj: hex script missing (%s)\n",jprint(vinobj,0));
if ( spendstr != 0 )
{
printf("iguana_parsevinobj: hex script missing (%s)\n",jprint(vinobj,0));
return(0);
n = (int32_t)strlen(spendstr) >> 1;
decode_hex(serialized,n,spendstr);
vin->spendscript = serialized;
vin->spendlen = n;
len += n;
}
return(len);
}
@ -821,22 +1125,43 @@ cJSON *iguana_voutjson(struct iguana_info *coin,struct iguana_msgvout *vout,int3
return(json);
}
void iguana_addscript(struct iguana_info *coin,cJSON *dest,uint8_t *script,int32_t scriptlen,char *fieldname)
{
char *scriptstr,scriptbuf[8192+256]; int32_t len; cJSON *scriptobj;
if ( scriptlen > sizeof(scriptbuf) )
len = (scriptlen << 1) + 256, scriptstr = malloc(len);
else scriptstr = scriptbuf, len = sizeof(scriptbuf);
init_hexbytes_noT(scriptstr,script,scriptlen);
if ( strcmp(fieldname,"coinbase") == 0 )
jaddstr(dest,"coinbase",scriptstr);
else
{
scriptobj = cJSON_CreateObject();
jaddstr(scriptobj,"hex",scriptstr);
iguana_expandscript(coin,scriptstr,len,script,scriptlen);
if ( scriptstr[0] != 0 )
jaddstr(scriptobj,"asm",scriptstr);
if ( scriptstr != scriptbuf )
free(scriptstr);
jadd(dest,fieldname,scriptobj);
}
}
cJSON *iguana_vinjson(struct iguana_info *coin,struct iguana_msgvin *vin)
{
char scriptstr[8192+1],str[65]; int32_t vout; cJSON *sigjson,*json = cJSON_CreateObject();
char str[65]; int32_t vout; cJSON *json = cJSON_CreateObject();
vout = vin->prev_vout;
jaddnum(json,"sequence",vin->sequence);
if ( vin->script != 0 && vin->scriptlen*2+1 < sizeof(scriptstr) )
init_hexbytes_noT(scriptstr,vin->script,vin->scriptlen);
if ( vout < 0 && bits256_nonz(vin->prev_hash) == 0 )
jaddstr(json,"coinbase",scriptstr);
iguana_addscript(coin,json,vin->sigscript,vin->scriptlen,"coinbase");
else
{
jaddstr(json,"txid",bits256_str(str,vin->prev_hash));
jaddnum(json,"vout",vout);
sigjson = cJSON_CreateObject();
jaddstr(sigjson,"hex",scriptstr);
jadd(json,"scriptSig",sigjson);
if ( vin->scriptlen > 0 )
iguana_addscript(coin,json,vin->sigscript,vin->scriptlen,"scriptSig");
if ( vin->spendlen > 0 )
iguana_addscript(coin,json,vin->spendscript,vin->spendlen,"scriptPub");
}
return(json);
}
@ -848,16 +1173,16 @@ int32_t iguana_vinparse(struct iguana_info *coin,int32_t rwflag,uint8_t *seriali
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->prev_vout),&msg->prev_vout);
len += iguana_rwvarint32(rwflag,&serialized[len],&msg->scriptlen);
if ( rwflag == 0 )
msg->script = &serialized[len];
else memcpy(&serialized[len],msg->script,msg->scriptlen);
msg->sigscript = &serialized[len];
else memcpy(&serialized[len],msg->sigscript,msg->scriptlen);
len += msg->scriptlen;
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->sequence),&msg->sequence);
if ( 0 )
{
int32_t i; char str[65];
for (i=0; i<msg->scriptlen; i++)
printf("%02x",msg->script[i]);
printf(" prev_hash.(%s) vout.%d [%p] scriptlen.%d rwflag.%d\n",bits256_str(str,msg->prev_hash),msg->prev_vout,msg->script,msg->scriptlen,rwflag);
printf("%02x",msg->sigscript[i]);
printf(" prev_hash.(%s) vout.%d [%p] scriptlen.%d rwflag.%d\n",bits256_str(str,msg->prev_hash),msg->prev_vout,msg->sigscript,msg->scriptlen,rwflag);
}
return(len);
}
@ -907,6 +1232,7 @@ int32_t iguana_rwmsgtx(struct iguana_info *coin,int32_t rwflag,cJSON *json,uint8
return(-1);
maxsize -= (sizeof(struct iguana_msgvin) * msg->tx_in);
msg->vins = (struct iguana_msgvin *)&serialized[maxsize];
memset(msg->vins,0,sizeof(struct iguana_msgvin) * msg->tx_in);
}
//printf("tx_in.%08x\n",msg->tx_in);
if ( msg->tx_in > 0 && msg->tx_in*sizeof(struct iguana_msgvin) < maxsize )
@ -1097,11 +1423,12 @@ int32_t bitcoin_scriptget(struct iguana_info *coin,int32_t *hashtypep,struct vin
return(vp->spendlen);
}
int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,int32_t *scriptlens,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V,int32_t sighashsingle)
int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxsize,struct vin_info *V,int32_t sighashsingle)
{
bits256 txid,sigtxid,revsigtxid; char txidstr[128],bigstr[2560],coinaddr[64],vpnstr[64],str[65];
uint8_t *sig,*pubkey,*saveinput; struct vin_info *vp;
int32_t n2,i,j,k,plen,vini=0,flag,numvins,hashtype,retval,siglen,asmtype,numvouts = msgtx->tx_out;
bits256 txid,sigtxid,revsigtxid; uint8_t *sig,*pubkey; struct vin_info *vp;
char txidstr[128],bigstr[2560],coinaddr[64],vpnstr[64],str[65];
int32_t n2,i,j,k,plen,vini=0,flag,numvins,hashtype,retval,siglen,asmtype,numvouts;
numvouts = msgtx->tx_out;
vpnstr[0] = 0;
*signedtx = 0;
memset(signedtxidp,0,sizeof(*signedtxidp));
@ -1109,18 +1436,18 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
retval = -numvins;
for (vini=0; vini<numvins; vini++)
{
saveinput = msgtx->vins[vini].script;
//saveinput = msgtx->vins[vini].sigscript;
vp = &V[vini];
for (i=0; i<numvins; i++)
msgtx->vins[i].scriptlen = 0;
sig = &msgtx->vins[vini].script[1];
siglen = msgtx->vins[vini].script[0];
//for (i=0; i<numvins; i++)
// msgtx->vins[i].spendlen = 0;
sig = &msgtx->vins[vini].sigscript[1];
siglen = msgtx->vins[vini].sigscript[0];
vp->vin = msgtx->vins[vini];
flag = 0;
for (k=0; k<2; k++)
{
asmtype = (k == 0) ? IGUANA_SCRIPT_76A988AC : IGUANA_SCRIPT_76AC;
if ( bitcoin_scriptget(coin,&hashtype,vp,saveinput,scriptlens[vini],asmtype) < 0 )
if ( bitcoin_scriptget(coin,&hashtype,vp,msgtx->vins[vini].sigscript,msgtx->vins[vini].scriptlen,asmtype) < 0 )
{
printf("cant get script for (%s).v%d\n",bits256_str(str,vp->vin.prev_hash),vp->vin.prev_vout);
continue;
@ -1130,19 +1457,29 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
msgtx->tx_out = 1;
hashtype = SIGHASH_SINGLE;
} else msgtx->tx_out = numvouts;
msgtx->vins[vini].script = vp->spendscript;
msgtx->vins[vini].scriptlen = vp->spendlen;
msgtx->vins[vini].spendscript = vp->spendscript;
msgtx->vins[vini].spendlen = vp->spendlen;
msgtx->vins[vini].sequence = vp->sequence;
for (j=0; j<vp->N; j++)
{
pubkey = vp->signers[j].pubkey;
if ( (plen= bitcoin_pubkeylen(pubkey)) < 0 )
{
printf("illegal plen.%d [%02x]\n",plen,pubkey[0]);
break;
if ( bits256_nonz(vp->signers[j].privkey) > 0 )
{
pubkey = vp->signers[j].pubkey;
bitcoin_pubkey33(pubkey,vp->signers[j].privkey);
plen = bitcoin_pubkeylen(pubkey);
}
if ( plen < 0 )
{
printf("nopubkey for j.%d vini.%d plen.%d [%02x]\n",j,vini,plen,pubkey[0]);
continue;
}
}
bitcoin_address(coinaddr,coin->chain->pubtype,pubkey,plen);
n2 = iguana_rwmsgtx(coin,1,0,serialized,maxsize,msgtx,&txid,vpnstr);
msgtx->vins[vini].script = saveinput;
//msgtx->vins[vini].script = saveinput;
if ( n2 > 0 )
{
n2 += iguana_rwnum(1,&serialized[n2],sizeof(hashtype),&hashtype);
@ -1156,7 +1493,7 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
sig = vp->signers[j].sig;
sig[vp->signers[j].siglen++] = hashtype;
siglen = vp->signers[j].siglen;
msgtx->vins[vini].scriptlen = bitcoin_scriptsig(msgtx->vins[vini].script,0,(const struct vin_info *)vp);
msgtx->vins[vini].scriptlen = bitcoin_scriptsig(msgtx->vins[vini].sigscript,0,(const struct vin_info *)vp);
for (i=0; i<siglen; i++)
printf("%02x",sig[i]);
printf(" SIGNEDTX.[%02x] plen.%d siglen.%d\n",sig[siglen-1],plen,siglen);
@ -1188,29 +1525,13 @@ int32_t bitcoin_verifyvins(struct iguana_info *coin,bits256 *signedtxidp,char **
return(retval);
}
//printf("privkey.%s\n",bits256_str(str,privkey));
//EC_KEY *KEY = bitcoin_privkeyset(&pkey,privkey);
char *refstr = "01000000\
01\
eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2\
01000000\
8c\
4930460221009e0339f72c793a89e664a8a932df073962a3f84eda0bd9e02084a6a9567f75aa022100bd9cbaca2e5ec195751efdfac164b76250b1e21302e51ca86dd7ebd7020cdc0601410450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6\
ffffffff\
01\
605af40500000000\
19\
76a914097072524438d003d23a2f23edb65aae1bb3e46988ac\
00000000";
int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V)
{
int32_t i,len,maxsize,*scriptlens,numvins,retval = -1; uint8_t *serialized,*serialized2;
int32_t len,maxsize,numvins,retval = -1; uint8_t *serialized,*serialized2;
struct iguana_msgtx msgtx; bits256 txid; char vpnstr[64];
len = (int32_t)strlen(rawtxstr);
maxsize = len + 32768;
serialized = calloc(1,maxsize);
serialized2 = calloc(1,maxsize);
serialized = calloc(1,maxsize), serialized2 = calloc(1,maxsize);
len >>= 1;
vpnstr[0] = 0;
decode_hex(serialized,len,rawtxstr);
@ -1218,15 +1539,9 @@ int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **si
if ( iguana_rwmsgtx(coin,0,0,serialized,maxsize,&msgtx,&txid,vpnstr) > 0 )
{
numvins = msgtx.tx_in;
scriptlens = calloc(numvins,sizeof(*scriptlens));
for (i=0; i<numvins; i++)
scriptlens[i] = msgtx.vins[i].scriptlen;
if ( bitcoin_verifyvins(coin,signedtxidp,signedtx,scriptlens,&msgtx,serialized2,maxsize,V,0) == 0 )
if ( bitcoin_verifyvins(coin,signedtxidp,signedtx,&msgtx,serialized2,maxsize,V,0) == 0 )
retval = 0;
else printf("bitcoin_verifytx: bitcoin_verifyvins error\n");
for (i=0; i<numvins; i++)
msgtx.vins[i].scriptlen = scriptlens[i];
free(scriptlens);
} else printf("bitcoin_verifytx: error iguana_rwmsgtx\n");
free(serialized), free(serialized2);
return(retval);
@ -1237,11 +1552,11 @@ char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson)
int32_t txstart; uint8_t *serialized; struct iguana_msgtx msgtx; char *txbytes = 0;
serialized = malloc(IGUANA_MAXPACKETSIZE);
*txidp = iguana_parsetxobj(coin,&txstart,serialized,IGUANA_MAXPACKETSIZE,&msgtx,txjson);
if ( msgtx.allocsize != 0 )
if ( msgtx.allocsize > 0 )
{
txbytes = malloc(msgtx.allocsize*2 + 1);
init_hexbytes_noT(txbytes,&serialized[txstart],msgtx.allocsize);
} else printf("bitcoin_txtest: zero msgtx allocsize\n");
} else printf("bitcoin_txtest: zero msgtx allocsize.(%s)\n",jprint(txjson,0));
free(serialized);
return(txbytes);
}
@ -1293,6 +1608,7 @@ cJSON *bitcoin_createtx(struct iguana_info *coin,int32_t locktime)
cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis)
{
char *hexstr; cJSON *item,*skey,*vouts = jduplicate(jobj(txobj,"vout"));
jdelete(txobj,"vout");
item = cJSON_CreateObject();
jaddnum(item,"value",dstr(satoshis));
skey = cJSON_CreateObject();
@ -1301,23 +1617,152 @@ cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *payments
jaddstr(skey,"hex",hexstr);
free(hexstr);
jadd(item,"scriptPubkey",skey);
jdelete(vouts,"vout");
jadd(vouts,"vout",item);
jaddi(vouts,item);
jadd(txobj,"vout",vouts);
///printf("addoutput.(%s %s)\n",hexstr,jprint(skey,0));
return(txobj);
}
cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence)
cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence,uint8_t *script,int32_t scriptlen)
{
cJSON *item,*vins = jduplicate(jobj(txobj,"vin"));
cJSON *item,*vins;
vins = jduplicate(jobj(txobj,"vin"));
jdelete(txobj,"vin");
item = cJSON_CreateObject();
iguana_addscript(coin,item,script,scriptlen,"scriptPubKey");
jaddbits256(item,"txid",txid);
jaddnum(item,"vout",vout);
jaddnum(item,"sequence",sequence);
jdelete(vins,"vin");
jadd(vins,"vin",item);
jaddi(vins,item);
jadd(txobj,"vin",vins);
printf("addvin -> (%s)\n",jprint(txobj,0));
return(txobj);
}
struct bitcoin_unspent *iguana_bestfit(struct iguana_info *coin,struct bitcoin_unspent *unspents,int32_t numunspents,uint64_t value,int32_t mode)
{
int32_t i; uint64_t above,below,gap,atx_value; struct bitcoin_unspent *vin,*abovevin,*belowvin;
abovevin = belowvin = 0;
for (above=below=i=0; i<numunspents; i++)
{
vin = &unspents[i];
atx_value = vin->value;
//printf("(%.8f vs %.8f)\n",dstr(atx_value),dstr(value));
if ( atx_value == value )
return(vin);
else if ( atx_value > value )
{
gap = (atx_value - value);
if ( above == 0 || gap < above )
{
above = gap;
abovevin = vin;
}
}
else if ( mode == 0 )
{
gap = (value - atx_value);
if ( below == 0 || gap < below )
{
below = gap;
belowvin = vin;
}
}
}
if ( (vin= (abovevin != 0) ? abovevin : belowvin) == 0 && mode == 1 )
vin = unspents;
return(vin);
}
struct bitcoin_spend *iguana_spendset(struct supernet_info *myinfo,struct iguana_info *coin,int64_t amount,int64_t txfee,char *account)
{
int32_t i,mode,numunspents,maxinputs = 1024; struct bitcoin_unspent *ptr,*up;
struct bitcoin_unspent *ups; struct bitcoin_spend *spend; double balance; int64_t remains;
if ( (ups= iguana_unspentsget(myinfo,coin,0,&balance,&numunspents,coin->chain->minconfirms,account)) == 0 )
return(0);
spend = calloc(1,sizeof(*spend) + sizeof(*spend->inputs) * maxinputs);
spend->txfee = txfee;
remains = txfee + amount;
spend->satoshis = remains;
ptr = spend->inputs;
for (i=0; i<maxinputs; i++,ptr++)
{
for (mode=1; mode>=0; mode--)
if ( (up= iguana_bestfit(coin,ups,numunspents,remains,mode)) != 0 )
break;
if ( up != 0 )
{
spend->input_satoshis += up->value;
spend->inputs[spend->numinputs++] = *up;
if ( spend->input_satoshis >= spend->satoshis )
{
spend->netamount = (spend->input_satoshis - spend->satoshis);
spend->change = (spend->input_satoshis - spend->netamount) - txfee;
printf("numinputs %d -> (%.8f - spend %.8f) = net %.8f vs amount %.8f change %.8f -> txfee %.8f vs chainfee %.8f\n",spend->numinputs,dstr(spend->input_satoshis),dstr(spend->satoshis),dstr(spend->netamount),dstr(amount),dstr(spend->change),dstr(spend->input_satoshis - spend->change - spend->netamount),dstr(txfee));
break;
}
remains -= up->value;
} else break;
}
if ( spend->input_satoshis >= spend->satoshis )
{
spend = realloc(spend,sizeof(*spend) + sizeof(*spend->inputs) * spend->numinputs);
return(spend);
}
else
{
free(spend);
return(0);
}
}
void iguana_addinputs(struct iguana_info *coin,struct bitcoin_spend *spend,cJSON *txobj,uint32_t sequence)
{
int32_t i;
for (i=0; i<spend->numinputs; i++)
{
spend->inputs[i].sequence = sequence;
bitcoin_addinput(coin,txobj,spend->inputs[i].txid,spend->inputs[i].vout,spend->inputs[i].sequence,spend->inputs[i].spendscript,spend->inputs[i].spendlen);
}
}
cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj)
{
int32_t i,j; char *rawtxstr; struct vin_info V; bits256 txid;
for (i=0; i<spend->numinputs; i++) // N times less efficient, but for small number of inputs ok
{
if ( *signedtxp != 0 )
{
free_json(txobj);
txobj = bitcoin_hex2json(coin,&txid,0,*signedtxp);
free(*signedtxp);
}
if ( (rawtxstr= bitcoin_json2hex(coin,&txid,txobj)) != 0 )
{
memset(&V,0,sizeof(V));
for (j=0; j<sizeof(spend->inputs[i].privkeys)/sizeof(*spend->inputs[i].privkeys); j++)
{
if ( bits256_nonz(spend->inputs[i].privkeys[j]) > 0 )
V.signers[j].privkey = spend->inputs[i].privkeys[j];
}
if ( spend->inputs[i].spendlen > 0 )
{
memcpy(V.spendscript,spend->inputs[i].spendscript,spend->inputs[i].spendlen);
V.spendlen = spend->inputs[i].spendlen;
}
V.sequence = spend->inputs[i].sequence;
//printf("json2hex.(%s)\n",rawtxstr);
bitcoin_verifytx(coin,txidp,signedtxp,rawtxstr,&V);
//printf("json2hex.(%s)\n",rawtxstr);
free(rawtxstr);
} else break;
}
if ( *signedtxp != 0 && i != spend->numinputs )
free(*signedtxp), *signedtxp = 0;
return(txobj);
}
#ifdef testing
char *bitcoin_cltvtx(struct iguana_info *coin,char *changeaddr,char *senderaddr,char *senders_otheraddr,char *otheraddr,uint32_t locktime,uint64_t satoshis,bits256 txid,int32_t vout,uint64_t inputsatoshis,bits256 privkey)
{
uint64_t change; char *rawtxstr,*signedtx; struct vin_info V; bits256 cltxid,signedtxid;
@ -1365,6 +1810,20 @@ char *bitcoin_cltvtx(struct iguana_info *coin,char *changeaddr,char *senderaddr,
free_json(txobj);
return(signedtx);
}
#endif
char *refstr = "01000000\
01\
eccf7e3034189b851985d871f91384b8ee357cd47c3024736e5676eb2debb3f2\
01000000\
8c\
4930460221009e0339f72c793a89e664a8a932df073962a3f84eda0bd9e02084a6a9567f75aa022100bd9cbaca2e5ec195751efdfac164b76250b1e21302e51ca86dd7ebd7020cdc0601410450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b23522cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6\
ffffffff\
01\
605af40500000000\
19\
76a914097072524438d003d23a2f23edb65aae1bb3e46988ac\
00000000";
cJSON *bitcoin_txtest(struct iguana_info *coin,char *rawtxstr,bits256 txid)
{
@ -1445,22 +1904,37 @@ rawtxstr = refstr;
return(cJSON_Parse("{\"error\":\"testing bitcoin txbytes\"}"));
}
uint64_t bitcoin_parseunspent(struct bitcoin_unspent *unspent,double minconfirms,char *account,cJSON *item)
uint64_t bitcoin_parseunspent(struct iguana_info *coin,struct bitcoin_unspent *unspent,double minconfirms,char *account,cJSON *item)
{
uint64_t value = 0; char *hexstr;
// struct bitcoin_unspent { bits256 txid,privkey; uint64_t value; int32_t vout; };
uint8_t addrtype; char *hexstr,*wifstr,coinaddr[64],args[128];
memset(unspent,0,sizeof(*unspent));
if ( jstr(item,"address") != 0 )
bitcoin_addr2rmd160(&unspent->addrtype,unspent->rmd160,jstr(item,"address"));
if ( (account == 0 || jstr(item,"account") == 0 || strcmp(account,jstr(item,"account")) == 0) && (minconfirms < 0 || juint(item,"confirmations") >= minconfirms-SMALLVAL) )
{
if ( (hexstr= jstr(item,"scriptPubKey")) != 0 && strlen(hexstr) < sizeof(unspent->script)/2 )
decode_hex(unspent->script,(int32_t)strlen(hexstr),hexstr);
safecopy(coinaddr,jstr(item,"address"),sizeof(coinaddr));
bitcoin_addr2rmd160(&unspent->addrtype,unspent->rmd160,coinaddr);
sprintf(args,"[\"%s\"]",coinaddr);
wifstr = bitcoind_RPC(0,coin->symbol,coin->chain->serverport,coin->chain->userpass,"dumpprivkey",args);
if ( wifstr != 0 )
{
btc_wif2priv(&addrtype,unspent->privkeys[0].bytes,wifstr);
//printf("wifstr.(%s) -> %s\n",wifstr,bits256_str(str,unspent->privkeys[0]));
free(wifstr);
} else fprintf(stderr,"error (%s) cant find privkey\n",coinaddr);
}
if ( (account == 0 || jstr(item,"account") == 0 || strcmp(account,jstr(item,"account")) == 0) && (minconfirms <= 0 || juint(item,"confirmations") >= minconfirms-SMALLVAL) )
{
if ( (hexstr= jstr(item,"scriptPubKey")) != 0 )
{
unspent->spendlen = (int32_t)strlen(hexstr) >> 1;
if ( unspent->spendlen < sizeof(unspent->spendscript) )
decode_hex(unspent->spendscript,unspent->spendlen,hexstr);
}
unspent->txid = jbits256(item,"txid");
unspent->value = j64bits(item,"amount");
unspent->value = SATOSHIDEN * jdouble(item,"amount");
unspent->vout = jint(item,"vout");
}
return(value);
//char str[65]; printf("(%s) -> %s %.8f scriptlen.%d\n",jprint(item,0),bits256_str(str,unspent->txid),dstr(unspent->value),unspent->scriptlen);
} else printf("skip.(%s) minconfirms.%f\n",jprint(item,0),minconfirms);
return(unspent->value);
}
struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct iguana_info *coin,char **retstrp,double *balancep,int32_t *numunspentsp,double minconfirms,char *account)
@ -1474,18 +1948,28 @@ struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct i
sprintf(params,"%.0f, 99999999",minconfirms);
if ( (retstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",params)) != 0 )
{
printf("unspents.(%s)\n",retstr);
//printf("sss unspents.(%s)\n",retstr);
if ( (utxo= cJSON_Parse(retstr)) != 0 )
{
n = 0;
if ( (*numunspentsp= cJSON_GetArraySize(utxo)) > 0 )
{
unspents = calloc(*numunspentsp,sizeof(*unspents));
for (i=n=0; i<*numunspentsp; i++)
if ( (value= bitcoin_parseunspent(&unspents[n],minconfirms,account,jitem(utxo,i))) != 0 )
total += value, n++;
} else printf("numunspents.%d\n",*numunspentsp);
for (i=0; i<*numunspentsp; i++)
{
value = bitcoin_parseunspent(coin,&unspents[n],minconfirms,account,jitem(utxo,i));
//printf("i.%d n.%d value %.8f\n",i,n,dstr(value));
if ( value != 0 )
{
total += value;
n++;
}
}
}
printf("numunspents.%d -> %d total %.8f\n",*numunspentsp,n,dstr(total));
*numunspentsp = n;
free_json(utxo);
}
} else printf("error parsing.(%s)\n",retstr);
if ( retstrp != 0 )
*retstrp = retstr;
else free(retstr);
@ -1752,7 +2236,7 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount
{
struct vin_info V; uint8_t p2sh_rmd160[20],serialized[2096];
char msigaddr[64],*retstr; cJSON *retjson,*txobj; struct iguana_info *active;
bits256 signedtxid; char *signedtx; int scriptlens[1];
bits256 signedtxid; char *signedtx;
struct iguana_msgtx msgtx;
if ( (active= iguana_coinfind(activecoin)) == 0 )
return(clonestr("{\"error\":\"activecoin isnt active\"}"));
@ -1764,7 +2248,6 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount
bitcoin_txaddspend(active,txobj,destaddress,destamount);
if ( destaddress2[0] != 0 && destamount2 > 0. )
bitcoin_txaddspend(active,txobj,destaddress2,destamount2);
bitcoin_addinput(active,txobj,vintxid,vinvout,0xffffffff);
if ( pubA[0] != 0 && (retstr= _setVsigner(active,&V,0,pubA,wifA)) != 0 )
return(retstr);
if ( N >= 2 && pubB[0] != 0 && (retstr= _setVsigner(active,&V,1,pubB,wifC)) != 0 )
@ -1773,10 +2256,10 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount
return(retstr);
V.M = M, V.N = N, V.type = IGUANA_SCRIPT_P2SH;
V.p2shlen = bitcoin_MofNspendscript(p2sh_rmd160,V.p2shscript,0,&V);
bitcoin_addinput(active,txobj,vintxid,vinvout,0xffffffff,V.p2shscript,V.p2shlen);
bitcoin_address(msigaddr,active->chain->p2shtype,V.p2shscript,V.p2shlen);
scriptlens[0] = 0;
retjson = cJSON_CreateObject();
if ( bitcoin_verifyvins(active,&signedtxid,&signedtx,scriptlens,&msgtx,serialized,sizeof(serialized),&V,0) == 0 )
if ( bitcoin_verifyvins(active,&signedtxid,&signedtx,&msgtx,serialized,sizeof(serialized),&V,0) == 0 )
{
jaddstr(retjson,"result","msigtx");
if ( signedtx != 0 )

7
iguana/exchanges/bitcoin.h

@ -34,14 +34,15 @@
#define SCRIPT_OP_RETURN 0x6a
#define SCRIPT_OP_DUP 0x76
#define SCRIPT_OP_ENDIF 0x68
#define OP_DROP 0x75
#define SCRIPT_OP_DROP 0x75
#define SCRIPT_OP_EQUALVERIFY 0x88
#define SCRIPT_OP_HASH160 0xa9
#define SCRIPT_OP_EQUAL 0x87
#define SCRIPT_OP_CHECKSIG 0xac
#define SCRIPT_OP_CHECKMULTISIG 0xae
#define OP_CHECKSEQUENCEVERIFY 0xb2
#define OP_CHECKLOCKTIMEVERIFY 0xb1
#define SCRIPT_OP_CHECKSEQUENCEVERIFY 0xb2
#define SCRIPT_OP_CHECKLOCKTIMEVERIFY 0xb1
struct bp_key { EC_KEY *k; };

7
iguana/iguana777.h

@ -230,7 +230,7 @@ struct iguana_msgblock
uint32_t txn_count;
} __attribute__((packed));
struct iguana_msgvin { bits256 prev_hash; uint8_t *script; uint32_t prev_vout,scriptlen,sequence; } __attribute__((packed));
struct iguana_msgvin { bits256 prev_hash; uint8_t *sigscript,*spendscript; uint32_t prev_vout,scriptlen,spendlen,sequence; } __attribute__((packed));
struct iguana_msgvout { uint64_t value; uint32_t pk_scriptlen; uint8_t *pk_script; } __attribute__((packed));
@ -475,7 +475,7 @@ struct vin_signer { bits256 privkey; char coinaddr[64]; uint8_t siglen,sig[80],r
struct vin_info
{
struct iguana_msgvin vin;
int32_t M,N,validmask,spendlen,type,p2shlen;
int32_t M,N,validmask,spendlen,type,p2shlen; uint32_t sequence;
struct vin_signer signers[16];
char coinaddr[65];
uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE],p2shscript[IGUANA_MAXSCRIPTSIZE];
@ -755,13 +755,14 @@ cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,st
cJSON *bitcoin_createtx(struct iguana_info *coin,int32_t locktime);
cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis);
int32_t bitcoin_changescript(struct iguana_info *coin,uint8_t *changescript,int32_t n,uint64_t *changep,char *changeaddr,uint64_t inputsatoshis,uint64_t satoshis,uint64_t txfee);
cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence);
cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence,uint8_t *script,int32_t scriptlen);
int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V);
char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson);
int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr);
char *issue_startForging(struct supernet_info *myinfo,char *secret);
struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct iguana_info *coin,char **retstrp,double *balancep,int32_t *numunspentsp,double minconfirms,char *account);
void iguana_chainparms(struct iguana_chain *chain,cJSON *argjson);
void iguana_addinputs(struct iguana_info *coin,struct bitcoin_spend *spend,cJSON *txobj,uint32_t sequence);
extern queue_t bundlesQ;

24
iguana/iguana_instantdex.c

@ -137,8 +137,8 @@ struct instantdex_stateinfo *instantdex_statecreate(struct instantdex_stateinfo
state = &states[*numstatesp];
instantdex_stateinit(states,*numstatesp,state,name,errorstr,timeoutstr,process_func,timeout_func);
state->initialstate = initialstate;
state->ind = (*numstatesp)++;
printf("STATES[%d] %s %p %p %d %d\n",*numstatesp,state->name,state->process,state->timeout,state->timeoutind,state->errorind);
state->ind = (*numstatesp)++;
}
else
{
@ -187,7 +187,8 @@ struct instantdex_event *instantdex_addevent(struct instantdex_stateinfo *states
double instantdex_FSMtest(struct instantdex_stateinfo *states,int32_t numstates,int32_t maxiters)
{
int32_t i,most,r,n,m=0,initials[100]; struct instantdex_stateinfo *state; struct instantdex_event *event; double sum = 0.;
int32_t i,most,r,r2,n,m=0,initials[100],nextstate=-1;
struct instantdex_stateinfo *state; struct instantdex_event *event; double sum = 0.;
if ( maxiters < 1 )
maxiters = 1;
for (i=n=most=0; i<numstates; i++)
@ -202,14 +203,25 @@ double instantdex_FSMtest(struct instantdex_stateinfo *states,int32_t numstates,
{
r = rand() % n;
state = &states[initials[r]];
if ( state->name[0] == 0 || state->ind >= numstates )
{
printf("illegal state.(%s) %d? ind.%d >= numstates.%d\n",state->name,nextstate,state->ind,numstates);
break;
}
m = 0;
while ( m++ < 1000 && state->initialstate >= 0 && state->numevents )
while ( m++ < 1000 && state->initialstate >= 0 && state->numevents != 0 )
{
if ( (i % 1000000) == 0 )
fprintf(stderr,"%s ",state->name);
event = &state->events[rand() % state->numevents];
if ( event->nextstateind < 0 )
r2 = rand() % state->numevents;
event = &state->events[r2];
if ( (nextstate= event->nextstateind) < 0 )
break;
if ( event->nextstateind >= numstates )
{
printf("nextstateind overflow? %d vs %d\n",event->nextstateind,numstates);
break;
}
state = &states[event->nextstateind];
}
if ( m > most )
@ -911,6 +923,8 @@ char *instantdex_sendoffer(struct supernet_info *myinfo,struct exchange_info *ex
return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}"));
else if ( (retstr= instantdex_addfeetx(myinfo,newjson,ap,swap,"BOB_sentoffer","ALICE_sentoffer")) == 0 )
{
instantdex_bobtx(myinfo,iguana_coinfind("BTCD"),&swap->deposittxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->choosei],ap->offer.expiration-INSTANTDEX_LOCKTIME*2,swap->satoshis[1],1);
instantdex_alicetx(myinfo,iguana_coinfind("BTCD"),swap->altmsigaddr,&swap->altpaymenttxid,swap->pubAm,swap->pubBn,swap->satoshis[0]);
if ( 0 )
{
int32_t i;

4
iguana/iguana_msg.c

@ -320,8 +320,8 @@ int32_t iguana_rwvin(int32_t rwflag,struct OS_memspace *mem,uint8_t *serialized,
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->prev_vout),&msg->prev_vout);
len += iguana_rwvarint32(rwflag,&serialized[len],&msg->scriptlen);
if ( rwflag == 0 )
msg->script = iguana_memalloc(mem,msg->scriptlen,1);
len += iguana_rwmem(rwflag,&serialized[len],msg->scriptlen,msg->script);
msg->sigscript = iguana_memalloc(mem,msg->scriptlen,1);
len += iguana_rwmem(rwflag,&serialized[len],msg->scriptlen,msg->sigscript);
len += iguana_rwnum(rwflag,&serialized[len],sizeof(msg->sequence),&msg->sequence);
//char str[65]; printf("MSGvin.(%s/v%d) script[%d]\n",bits256_str(str,msg->prev_hash),msg->prev_vout,msg->scriptlen);
//int i; for (i=0; i<msg->scriptlen; i++)

4
iguana/iguana_pubkeys.c

@ -652,7 +652,7 @@ int32_t btc_priv2wif(char *wifstr,uint8_t privkey[32],uint8_t addrtype)
strcpy(wifstr,btc_addr->str);
cstr_free(btc_addr,true);
}
printf("-> (%s) -> wif.(%s) addrtype.%02x\n",hexstr,wifstr,addrtype);
//printf("-> (%s) -> wif.(%s) addrtype.%02x\n",hexstr,wifstr,addrtype);
return(0);
}
@ -668,7 +668,7 @@ int32_t btc_wif2priv(uint8_t *addrtypep,uint8_t privkey[32],char *wifstr)
len = (int32_t)cstr->len;
char tmp[138];
btc_priv2wif(tmp,privkey,*addrtypep);
printf("addrtype.%02x wifstr.(%llx) privlen.%d\n",*addrtypep,*(long long *)privkey,len);
//printf("addrtype.%02x wifstr.(%llx) privlen.%d\n",*addrtypep,*(long long *)privkey,len);
cstr_free(cstr,true);
}
return(len);

2
iguana/iguana_ramchain.c

@ -1482,7 +1482,7 @@ long iguana_ramchain_data(struct iguana_info *coin,struct iguana_peer *addr,stru
for (j=0; j<tx->tx_in; j++)
{
//char str[65]; printf("PT vin.%d %s vout.%d\n",j,bits256_str(str,tx->vins[j].prev_hash),tx->vins[j].prev_vout);
iguana_ramchain_addspend256(coin,RAMCHAIN_ARG,tx->vins[j].prev_hash,tx->vins[j].prev_vout,tx->vins[j].script,tx->vins[j].scriptlen,tx->vins[j].sequence);//,bp->hdrsi,bundlei);
iguana_ramchain_addspend256(coin,RAMCHAIN_ARG,tx->vins[j].prev_hash,tx->vins[j].prev_vout,tx->vins[j].sigscript,tx->vins[j].scriptlen,tx->vins[j].sequence);//,bp->hdrsi,bundlei);
}
}
//char str[65]; printf("before height.%d num.%d:%d T.%d U.%d S.%d P.%d X.%d %s\n",ramchain->height,ramchain->numblocks,ramchain->H.data->numblocks,ramchain->H.txidind,ramchain->H.unspentind,ramchain->H.spendind,ramchain->pkind,ramchain->externalind,bits256_str(str,ramchain->H.data->firsthash2));

105
iguana/iguana_tx.c

@ -335,108 +335,3 @@ cJSON *iguana_blockjson(struct iguana_info *coin,struct iguana_block *block,int3
jaddnum(retitem,"result",coin->blocks.hwmchain.height);
return(jprint(retitem,1));
}*/
struct bitcoin_unspent *iguana_bestfit(struct iguana_info *coin,struct bitcoin_unspent *unspents,int32_t numunspents,uint64_t value,int32_t mode)
{
int32_t i; uint64_t above,below,gap,atx_value; struct bitcoin_unspent *vin,*abovevin,*belowvin;
abovevin = belowvin = 0;
for (above=below=i=0; i<numunspents; i++)
{
vin = &unspents[i];
atx_value = vin->value;
//printf("(%.8f vs %.8f)\n",dstr(atx_value),dstr(value));
if ( atx_value == value )
return(vin);
else if ( atx_value > value )
{
gap = (atx_value - value);
if ( above == 0 || gap < above )
{
above = gap;
abovevin = vin;
}
}
else if ( mode == 0 )
{
gap = (value - atx_value);
if ( below == 0 || gap < below )
{
below = gap;
belowvin = vin;
}
}
}
if ( (vin= (abovevin != 0) ? abovevin : belowvin) == 0 && mode == 1 )
vin = unspents;
return(vin);
}
struct bitcoin_spend *iguana_spendset(struct supernet_info *myinfo,struct iguana_info *coin,int64_t amount,int64_t txfee,char *account)
{
int32_t i,mode,numunspents,maxinputs = 1024; int64_t remains; struct bitcoin_unspent *ptr,*up;
struct bitcoin_unspent *ups; struct bitcoin_spend *spend; double balance;
if ( (ups= iguana_unspentsget(myinfo,coin,0,&balance,&numunspents,coin->chain->minconfirms,account)) == 0 )
return(0);
spend = calloc(1,sizeof(*spend) + sizeof(*spend->inputs) * maxinputs);
spend->txfee = txfee;
remains = txfee + amount;
spend->satoshis = remains;
ptr = spend->inputs;
for (i=0; i<maxinputs; i++,ptr++)
{
for (mode=1; mode>=0; mode--)
if ( (up= iguana_bestfit(coin,ups,numunspents,remains,mode)) != 0 )
break;
if ( up != 0 )
{
spend->input_satoshis += up->value;
spend->inputs[spend->numinputs++] = *up;
if ( spend->input_satoshis >= spend->satoshis )
{
spend->netamount = (spend->input_satoshis - spend->satoshis);
spend->change = (spend->input_satoshis - spend->netamount);
printf("numinputs %d sum %.8f vs amount %.8f change %.8f -> txfee %.8f\n",spend->numinputs,dstr(spend->input_satoshis),dstr(amount),dstr(spend->change),dstr(spend->input_satoshis - spend->change - spend->netamount));
break;
}
remains -= up->value;
} else break;
}
if ( spend->input_satoshis >= spend->satoshis )
{
spend = realloc(spend,sizeof(*spend) + sizeof(*spend->inputs) * spend->numinputs);
return(spend);
}
else
{
free(spend);
return(0);
}
}
cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj)
{
int32_t i,j; char *rawtxstr; struct vin_info V; bits256 txid;
for (i=0; i<spend->numinputs; i++)
bitcoin_addinput(coin,txobj,spend->inputs[i].txid,spend->inputs[i].vout,0xffffffff);
for (i=0; i<spend->numinputs; i++) // N times less efficient, but for small number of inputs ok
{
if ( *signedtxp != 0 )
{
free_json(txobj);
txobj = bitcoin_hex2json(coin,&txid,0,*signedtxp);
free(*signedtxp);
}
if ( (rawtxstr= bitcoin_json2hex(coin,&txid,txobj)) != 0 )
{
memset(&V,0,sizeof(V));
for (j=0; j<sizeof(spend->inputs[i].privkeys)/sizeof(*spend->inputs[i].privkeys); j++)
if ( bits256_nonz(spend->inputs[i].privkeys[j]) > 0 )
V.signers[j].privkey = spend->inputs[i].privkeys[j];
bitcoin_verifytx(coin,txidp,signedtxp,rawtxstr,&V);
free(rawtxstr);
} else break;
}
if ( *signedtxp != 0 && i != spend->numinputs )
free(*signedtxp), *signedtxp = 0;
return(txobj);
}

40
iguana/swaps/iguana_BTCswap.c

@ -91,25 +91,36 @@ int32_t instantdex_outputinsurance(struct iguana_info *coin,cJSON *txobj,int64_t
decode_hex(rmd160,sizeof(rmd160),(orderid % 10) == 0 ? TIERNOLAN_RMD160 : INSTANTDEX_RMD160);
script[n++] = sizeof(uint64_t);
n += iguana_rwnum(1,&script[n],sizeof(orderid),&orderid);
script[n++] = OP_DROP;
script[n++] = SCRIPT_OP_DROP;
n = bitcoin_standardspend(script,n,rmd160);
bitcoin_addoutput(coin,txobj,script,n,insurance);
return(n);
}
void disp_tx(struct supernet_info *myinfo,struct iguana_info *coin,char *str,char *txbytes)
{
cJSON *txobj; bits256 txid;
txobj = bitcoin_hex2json(coin,&txid,0,txbytes);
printf("%s.(%s)\n",str,jprint(txobj,1));
}
char *instantdex_feetx(struct supernet_info *myinfo,bits256 *txidp,struct instantdex_accept *A)
{
int32_t n; char *feetx = 0; struct iguana_info *coinbtc; cJSON *txobj; struct bitcoin_spend *spend; int64_t insurance;
if ( (coinbtc= iguana_coinfind("BTC")) != 0 )
int32_t n; char *feetx = 0; struct iguana_info *coin; cJSON *txobj; struct bitcoin_spend *spend; int64_t insurance;
if ( (coin= iguana_coinfind("BTCD")) != 0 )
{
insurance = instantdex_insurance(coinbtc,instantdex_BTCsatoshis(A->offer.price64,A->offer.basevolume64));
if ( (spend= iguana_spendset(myinfo,coinbtc,insurance,coinbtc->chain->txfee,0)) != 0 )
insurance = 40 * instantdex_insurance(coin,instantdex_BTCsatoshis(A->offer.price64,A->offer.basevolume64));
if ( (spend= iguana_spendset(myinfo,coin,insurance,coin->chain->txfee,0)) != 0 )
{
txobj = bitcoin_createtx(coinbtc,0);
n = instantdex_outputinsurance(coinbtc,txobj,insurance,A->orderid);
txobj = iguana_signtx(coinbtc,txidp,&feetx,spend,txobj);
txobj = bitcoin_createtx(coin,0);
n = instantdex_outputinsurance(coin,txobj,insurance,A->orderid);
iguana_addinputs(coin,spend,txobj,0xffffffff);
txobj = iguana_signtx(coin,txidp,&feetx,spend,txobj);
if ( feetx != 0 )
{
printf("%s feetx.%s\n",A->offer.myside != 0 ? "BOB" : "ALICE",feetx);
disp_tx(myinfo,coin,"feetx",feetx);
}
else printf("error signing %s feetx numinputs.%d\n",A->offer.myside != 0 ? "BOB" : "ALICE",spend->numinputs);
free(spend);
}
@ -167,10 +178,13 @@ char *instantdex_bobtx(struct supernet_info *myinfo,struct iguana_info *coin,bit
calc_rmd160_sha256(secret,priv.bytes,sizeof(priv));
n = instantdex_bobscript(script,0,&secretstart,locktime,pub1,secret,pub2);
bitcoin_addoutput(coin,txobj,script,n,amount + depositflag*insurance*100);
iguana_addinputs(coin,spend,txobj,0xffffffff);
txobj = iguana_signtx(coin,txidp,&signedtx,spend,txobj);
if ( signedtx != 0 )
{
printf("bob deposit.%s\n",signedtx);
else printf("error signing bobdeposit numinputs.%d\n",spend->numinputs);
disp_tx(myinfo,coin,depositflag != 0 ? "deposit" : "payment",signedtx);
} else printf("error signing bobdeposit numinputs.%d\n",spend->numinputs);
free(spend);
}
free_json(txobj);
@ -260,9 +274,13 @@ char *instantdex_alicetx(struct supernet_info *myinfo,struct iguana_info *altcoi
txobj = bitcoin_createtx(altcoin,0);
n = instantdex_alicescript(script,0,msigaddr,altcoin->chain->p2shtype,pubAm,pubBn);
bitcoin_addoutput(altcoin,txobj,script,n,amount);
iguana_addinputs(altcoin,spend,txobj,0xffffffff);
txobj = iguana_signtx(altcoin,txidp,&signedtx,spend,txobj);
if ( signedtx != 0 )
{
printf("alice payment.%s\n",signedtx);
disp_tx(myinfo,altcoin,"altpayment",signedtx);
}
else printf("error signing alicetx numinputs.%d\n",spend->numinputs);
free(spend);
free_json(txobj);
@ -683,7 +701,6 @@ cJSON *BTC_cleanupfunc(struct supernet_info *myinfo,struct exchange_info *exchan
struct instantdex_stateinfo *BTC_initFSM(int32_t *n)
{
struct instantdex_stateinfo *s = 0;
*n = 2;
// Four initial states are BOB_sentoffer, ALICE_gotoffer, ALICE_sentoffer, BOB_gotoffer
// the initiator includes signed feetx and deck of INSTANTDEX_DECKSIZE keypairs
//
@ -694,8 +711,9 @@ struct instantdex_stateinfo *BTC_initFSM(int32_t *n)
// states instantdex_statecreate(s,n,<Name of State>,handlerfunc,errorhandler,<Timeout State>,<Error State>
// a given state has a couple of handlers and custom events, with timeouts and errors invoking a bypass
*n = 2;
s = instantdex_statecreate(s,n,"BTC_cleanup",BTC_cleanupfunc,0,0,0,-1); // from states without any commits
memset(s,0,sizeof(*s) * 2);
s = instantdex_statecreate(s,n,"BOB_reclaim",BOB_reclaimfunc,0,0,0,0); // Bob's gets his deposit back
instantdex_addevent(s,*n,"BOB_reclaim","brcfound","poll","BTC_cleanup");
instantdex_addevent(s,*n,"BOB_reclaim","poll","poll","BOB_reclaim");

Loading…
Cancel
Save