diff --git a/src/ac.json b/src/ac.json new file mode 100644 index 000000000..7f3f7ba03 --- /dev/null +++ b/src/ac.json @@ -0,0 +1,338 @@ +{ + "REVS": { + "ac_supply": "1300000" + } + , + + "SUPERNET": { + "ac_supply": "816061" + } + , + + "DEX": { + "ac_supply": "999999" + } + , + + "PANGEA": { + "ac_supply": "999999" + } + + , + "JUMBLR": { + "ac_supply": "999999" + } + , + + "BET": { + "ac_supply": "999999" + } + , + + "CRYPTO": { + "ac_supply": "999999" + } + , + + "HODL": { + "ac_supply": "9999999" + } + , + + "MSHARK": { + "ac_supply": "1400000" + } + , + + "BOTS": { + "ac_supply": "999999" + } + , + + "MGW": { + "ac_supply": "999999" + } + , + "COQUICASH": { + "ac_supply": "72000000", + "ac_reward": "7200000000", + "ac_staked": "50", + "ac_halving": "420000", + "ac_cc": "2", + "ac_ccenable": "227,235,236,241", + "addnode": [ + "78.47.108.168" + ] + } + , + + "WLC": { + "ac_supply": "210000000" + } + , + + "KV": { + "ac_supply": "1000000" + } + , + + "CEAL": { + "ac_supply": "366666666" + } + , + + "MESH": { + "ac_supply": "1000007" + } + , + + "AXO": { + "ac_supply": "200000000", + "ac_ccactivate": "130000" + } + , + + "ETOMIC": { + "ac_supply": "100000000" + } + , + + "BTCH": { + "ac_supply": "20998641" + } + , + + "PIZZA": { + "ac_supply": "100000000" + } + , + + "BEER": { + "ac_supply": "100000000" + } + , + + "NINJA": { + "ac_supply": "100000000" + } + , + + "OOT": { + "ac_supply": "216000000", + "ac_sapling": "5000000" + } + , + + "BNTN": { + "ac_supply": "500000000" + } + , + + "CHAIN": { + "ac_supply": "999999" + } + , + + "PRLPAY": { + "ac_supply": "500000000" + } + , + + "DSEC": { + "ac_supply": "7000000" + } + , + + "GLXT": { + "ac_supply": "10000000000" + } + , + + "EQL": { + "ac_supply": "500000000", + "ac_ccactivate": "205000" + } + , + + "ZILLA": { + "ac_supply": "11000000", + "ac_sapling": "5000000", + "addnode": [ + "51.68.215.104" + ] + } + , + + "RFOX": { + "ac_supply": "1000000000", + "ac_reward": "100000000" + } + , + + "SEC": { + "ac_supply": "1000000000", + "ac_cc": "333" + } + , + + "CCL": { + "ac_supply": "200000000", + "ac_end": "1", + "ac_cc": "2", + "addressindex": "1", + "spentindex": "1", + "addnode": [ + "142.93.136.89", + "195.201.22.89" + ] + } + , + + "PIRATE": { + "ac_supply": "0", + "ac_reward": "25600000000", + "ac_halving": "77777", + "ac_private": "1", + "addnode": [ + "136.243.102.225" + ] + } + , + + "PGT": { + "ac_supply": "10000000", + "ac_end": "1", + "addnode": [ + "190.114.254.104" + ] + } + , + + "DION": { + "ac_supply": "3900000000", + "ac_reward": "22260000000", + "ac_staked": "100", + "ac_cc": "1", + "ac_end": "4300000000", + "addnode": [ + "51.75.124.34" + ] + } + , + + "KMDICE": { + "ac_supply": "10500000", + "ac_reward": "2500000000", + "ac_halving": "210000", + "ac_cc": "2", + "addressindex": "1", + "spentindex": "1", + "addnode": [ + "144.76.217.232" + ] + } + , + + "KSB": { + "ac_supply": "1000000000", + "ac_end": "1", + "ac_public": "1", + "addnode": [ + "37.187.225.231" + ] + } + , + + "OUR": { + "ac_reward": "1478310502", + "ac_halving": "525600", + "ac_cc": "42", + "ac_supply": "100000000", + "ac_perc": "77700", + "ac_staked": "93", + "ac_pubkey": "02652a3f3e00b3a1875a918314f0bac838d6dd189a346fa623f5efe9541ac0b98c", + "ac_public": "1", + "addnode": [ + "51.255.195.65", + "217.182.129.38", + "37.187.225.231" + ] + } + , + + "ILN": { + "ac_supply": "10000000000", + "ac_cc": "2", + "addnode": ["51.75.122.83"] + } + , + + "RICK": { + "ac_supply": "90000000000", + "ac_reward": "100000000", + "ac_cc": "3", + "addnode": ["138.201.136.145"] + } + , + + "MORTY": { + "ac_supply": "90000000000", + "ac_reward": "100000000", + "ac_cc": "3", + "addnode": ["138.201.136.145"] + } + , + + "KOIN": { + "ac_supply": "125000000", + "addnode": ["3.0.32.10"] + } + , + + "ZEXO": { + "ac_reward": "1478310502", + "ac_halving": "525600", + "ac_cc": "42", + "ac_ccenable": "236", + "ac_supply": "100000000", + "ac_perc": "77700", + "ac_staked": "93", + "ac_pubkey": "02713bd85e054db923694b6b7a85306264edf4d6bd6d331814f2b40af444b3ebbc", + "ac_public": "1", + "addnode": [ + "195.201.20.230", + "80.240.17.222" + ] + } + , + + "K64": { + "ac_reward": "0", + "ac_supply": "64000777", + "ac_staked": "10", + "addnode": ["18.197.20.21"] + } + , + + "HUSH3": { + "ac_sapling": "1", + "ac_founders": "1", + "ac_reward": "0,1125000000,562500000", + "ac_end": "128,340000,5422111", + "ac_blocktime": "150", + "ac_supply": "6178674", + "ac_halving": "129,340000,840000", + "ac_cc": "2", + "ac_cclib": "hush3", + "ac_ccenable": "228,234,235,236,241", + "ac_perc": "11111111", + "ac_eras": "3", + "ac_script": "76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac", + "clientname": "GoldenSandtrout", + "addnode": [ + "188.165.212.101", + "136.243.227.142", + "5.9.224.250" + ] + } +} diff --git a/src/assetchains.json b/src/assetchains.json index 20dd04ee2..e68872d6b 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -44,9 +44,16 @@ "ac_supply": "999999" }, { - "ac_name": "COQUI", + "ac_name": "COQUICASH", "ac_supply": "72000000", - "ac_ccactivate": "200000" + "ac_reward": "7200000000", + "ac_staked": "50", + "ac_halving": "420000", + "ac_cc": "2", + "ac_ccenable": "227,235,236,241", + "addnode": [ + "78.47.108.168" + ] }, { "ac_name": "WLC", @@ -235,12 +242,6 @@ "ac_cc": "3", "addnode": ["138.201.136.145"] }, - { - "ac_name": "VOTE2019", - "ac_supply": "123651638", - "ac_public": "1", - "addnode": ["95.213.238.98"] - }, { "ac_name": "KOIN", "ac_supply": "125000000", diff --git a/src/cc/CCtx.cpp b/src/cc/CCtx.cpp index 5799f0b18..01cb02211 100644 --- a/src/cc/CCtx.cpp +++ b/src/cc/CCtx.cpp @@ -108,6 +108,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran else { fprintf(stderr,"vin.%d vout.%d is bigger than vintx.%d\n",i,mtx.vin[i].prevout.n,(int32_t)vintx.vout.size()); + memset(myprivkey,0,32); return(""); } } @@ -280,17 +281,21 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran if ( flag == 0 ) { fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); + memset(myprivkey,0,32); return(""); } } uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL,utxovalues[i],consensusBranchId, &txdata); - int32_t z; - for (z=0; z<32; z++) - fprintf(stderr,"%02x",privkey[z]); - fprintf(stderr," privkey, "); - for (z=0; z<32; z++) - fprintf(stderr,"%02x",((uint8_t *)sighash.begin())[z]); - fprintf(stderr," sighash [%d] %.8f %x\n",i,(double)utxovalues[i]/COIN,consensusBranchId); + if ( 0 ) + { + int32_t z; + for (z=0; z<32; z++) + fprintf(stderr,"%02x",privkey[z]); + fprintf(stderr," privkey, "); + for (z=0; z<32; z++) + fprintf(stderr,"%02x",((uint8_t *)sighash.begin())[z]); + fprintf(stderr," sighash [%d] %.8f %x\n",i,(double)utxovalues[i]/COIN,consensusBranchId); + } if ( cc_signTreeSecp256k1Msg32(cond,privkey,sighash.begin()) != 0 ) { mtx.vin[i].scriptSig = CCSig(cond); @@ -334,6 +339,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran } void NSPV_CCunspents(std::vector > &unspentOutputs,char *coinaddr,bool ccflag); +void NSPV_CCtxids(std::vector > &txids,char *coinaddr,bool ccflag); void SetCCunspents(std::vector > &unspentOutputs,char *coinaddr,bool ccflag) { @@ -362,6 +368,11 @@ void SetCCunspents(std::vector > &addressIndex,char *coinaddr,bool ccflag) { int32_t type=0,i,n; char *ptr; std::string addrstr; uint160 hashBytes; std::vector > addresses; + if ( KOMODO_NSPV != 0 ) + { + NSPV_CCtxids(addressIndex,coinaddr,ccflag); + return; + } n = (int32_t)strlen(coinaddr); addrstr.resize(n+1); ptr = (char *)addrstr.data(); diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index 0c456450f..dfb8aeff3 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -578,9 +578,13 @@ uint256 CCOraclesReverseScan(char const *logcategory,uint256 &txid,int32_t heigh return(zeroid); } +int32_t NSPV_coinaddr_inmempool(char const *logcategory,char *coinaddr,uint8_t CCflag); + int32_t myIs_coinaddr_inmempoolvout(char const *logcategory,char *coinaddr) { int32_t i,n; char destaddr[64]; + if ( KOMODO_NSPV != 0 ) + return(NSPV_coinaddr_inmempool(logcategory,coinaddr,1)); BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) { const CTransaction &tx = e.GetTx(); diff --git a/src/cc/channels.cpp b/src/cc/channels.cpp index f88546b6e..3a87b9fc2 100644 --- a/src/cc/channels.cpp +++ b/src/cc/channels.cpp @@ -453,6 +453,7 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C Myprivkey(myprivkey); if (tokenid!=zeroid) CCaddrTokens1of2set(cp,srcpub,destpub,myprivkey,coinaddr); else CCaddr1of2set(cp,srcpub,destpub,myprivkey,coinaddr); + memset(myprivkey,0,32); return totalinputs; } else return 0; diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index 20f7a0567..4d1453084 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -587,6 +587,7 @@ uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv,int32_t vout,int32_t fprintf(stderr,"%02x",ssecret2.bytes[i]); fprintf(stderr," ssecret2 dont match\n"); } + memset(tmp256.bytes,0,32); //char str[65],str2[65]; //fprintf(stderr,"generated house hentropy.%s <- entropy.%s\n",uint256_str(str,hentropy),uint256_str(str2,entropy)); return(hentropy); diff --git a/src/cc/dilithium.c b/src/cc/dilithium.c index 4a3813e61..d0f7aa16d 100644 --- a/src/cc/dilithium.c +++ b/src/cc/dilithium.c @@ -3148,6 +3148,8 @@ UniValue dilithium_keypair(uint64_t txfee,struct CCcontract_info *cp,cJSON *para if ( externalflag == 0 ) result.push_back(Pair("warning","test mode using privkey for -pubkey, only for testing. there is no point using quantum secure signing if you are using a privkey with a known secp256k1 pubkey!!")); result.push_back(Pair("result","success")); + memset(seed,0,32); + memset(sk,0,sizeof(sk)); return(result); } @@ -3194,9 +3196,23 @@ UniValue dilithium_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *par if ( CCchange != 0 ) mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,dilithiumpk)); rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_registeropret(handle,mypk,bigpub)); + memset(seed,0,32); + memset(sk,0,sizeof(sk)); return(musig_rawtxresult(result,rawtx)); - } else return(cclib_error(result,"couldnt find enough funds")); - } else return(cclib_error(result,"not enough parameters")); + } + else + { + memset(seed,0,32); + memset(sk,0,sizeof(sk)); + return(cclib_error(result,"couldnt find enough funds")); + } + } + else + { + memset(seed,0,32); + memset(sk,0,sizeof(sk)); + return(cclib_error(result,"not enough parameters")); + } } else return(cclib_error(result,"not dilithiumpk funds")); } @@ -3222,9 +3238,23 @@ UniValue dilithium_sign(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) result.push_back(Pair("signature",dilithium_hexstr(str,sm,smlen))); calc_rmd160_sha256(rmd160,sm,smlen); result.push_back(Pair("sighash",dilithium_hexstr(str,rmd160,20))); + memset(seed,0,32); + memset(sk,0,sizeof(sk)); return(result); - } else return(cclib_error(result,"unexpected signed message len")); - } else return(cclib_error(result,"not enough parameters")); + } + else + { + memset(seed,0,32); + memset(sk,0,sizeof(sk)); + return(cclib_error(result,"unexpected signed message len")); + } + } + else + { + memset(seed,0,32); + memset(sk,0,sizeof(sk)); + return(cclib_error(result,"not enough parameters")); + } } UniValue dilithium_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) @@ -3289,7 +3319,7 @@ UniValue dilithium_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,destpub33; CTransaction vintx; uint256 prevhash,hashBlock,destpubtxid; int32_t i,smlen,n,numvouts; char str[129],*scriptstr; CTxOut vout; std::string handle; uint8_t pk[CRYPTO_PUBLICKEYBYTES],pk2[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES],msg[32],seed[32]; std::vector sig; + UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,destpub33; CTransaction vintx; uint256 prevhash,hashBlock,destpubtxid; int32_t i,smlen,n,numvouts; char str[129],*scriptstr,*retstr=""; CTxOut vout; std::string handle; uint8_t pk[CRYPTO_PUBLICKEYBYTES],pk2[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES],msg[32],seed[32]; std::vector sig; if ( txfee == 0 ) txfee = DILITHIUM_TXFEE; mypk = pubkey2pk(Mypubkey()); @@ -3317,23 +3347,31 @@ UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params if ( dilithium_sendopretdecode(destpubtxid,vintx.vout[numvouts-1].scriptPubKey) == 'x' ) { if ( dilithium_bigpubget(handle,destpub33,pk2,destpubtxid) < 0 ) - return(cclib_error(result,"couldnt get bigpub")); + retstr = (char *)"couldnt get bigpub"; else if ( memcmp(pk,pk2,sizeof(pk)) != 0 ) - return(cclib_error(result,"dilithium bigpub mismatch")); + retstr = (char *)"dilithium bigpub mismatch"; else if ( destpub33 != mypk ) - return(cclib_error(result,"destpub33 is not for this -pubkey")); + retstr = (char *)"destpub33 is not for this -pubkey"; else if ( _dilithium_sign(&sig[0],&smlen,msg,32,sk) < 0 ) - return(cclib_error(result,"dilithium signing error")); + retstr = (char *)"dilithium signing error"; else if ( smlen != 32+CRYPTO_BYTES ) - return(cclib_error(result,"siglen error")); - mtx.vin.push_back(CTxIn(prevhash,0)); - mtx.vout.push_back(vout); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_spendopret(destpubtxid,sig)); - return(dilithium_rawtxresult(result,rawtx)); - } else return(cclib_error(result,"couldnt decode send opret")); - } else return(cclib_error(result,"couldnt find vin0")); - } else return(cclib_error(result,"script or bad destpubtxid is not hex")); - } else return(cclib_error(result,"need to have exactly 2 params sendtxid, scriptPubKey")); + retstr = (char *)"siglen error"; + else + { + mtx.vin.push_back(CTxIn(prevhash,0)); + mtx.vout.push_back(vout); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_spendopret(destpubtxid,sig)); + memset(seed,0,32); + memset(sk,0,sizeof(sk)); + return(dilithium_rawtxresult(result,rawtx)); + } + } else retstr = (char *)"couldnt decode send opret"; + } else retstr = (char *)"couldnt find vin0"; + } else retstr = (char *)"script or bad destpubtxid is not hex"; + } else retstr = (char *)"need to have exactly 2 params sendtxid, scriptPubKey"; + memset(seed,0,32); + memset(sk,0,sizeof(sk)); + return(cclib_error(result,retstr)); } int64_t dilithium_inputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 destpubtxid,int64_t total,int32_t maxinputs,char *cmpaddr) @@ -3377,7 +3415,7 @@ int64_t dilithium_inputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPu UniValue dilithium_Qsend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) { CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,destpub33; CTransaction tx,vintx; uint256 prevhash,mypubtxid,hashBlock,destpubtxid; int64_t amount,inputsum,outputsum,change; int32_t i,smlen,n,numvouts; char str[129],myCCaddr[64],*scriptstr; CTxOut vout; std::string handle; uint8_t pk[CRYPTO_PUBLICKEYBYTES],pk2[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES],msg[32],seed[32]; std::vector sig; std::vector voutpubtxids; + UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,destpub33; CTransaction tx,vintx; uint256 prevhash,mypubtxid,hashBlock,destpubtxid; int64_t amount,inputsum,outputsum,change; int32_t i,smlen,n,numvouts; char str[129],myCCaddr[64],*scriptstr,*retstr=""; CTxOut vout; std::string handle; uint8_t pk[CRYPTO_PUBLICKEYBYTES],pk2[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES],msg[32],seed[32]; std::vector sig; std::vector voutpubtxids; if ( txfee == 0 ) txfee = DILITHIUM_TXFEE; mypk = pubkey2pk(Mypubkey()); @@ -3402,6 +3440,8 @@ UniValue dilithium_Qsend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params if ( dilithium_bigpubget(handle,destpub33,pk2,prevhash) < 0 ) { result.push_back(Pair("destpubtxid",prevhash.GetHex().c_str())); + memset(seed,0,32); + memset(sk,0,sizeof(sk)); return(cclib_error(result,"couldnt find bigpub at destpubtxid")); } else @@ -3437,19 +3477,27 @@ UniValue dilithium_Qsend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params //fprintf(stderr," msg\n"); sig.resize(32+CRYPTO_BYTES); if ( dilithium_bigpubget(handle,destpub33,pk2,mypubtxid) < 0 ) - return(cclib_error(result,"couldnt get bigpub")); + retstr = (char *)"couldnt get bigpub"; else if ( memcmp(pk,pk2,sizeof(pk)) != 0 ) - return(cclib_error(result,"dilithium bigpub mismatch")); + retstr = (char *)"dilithium bigpub mismatch"; else if ( destpub33 != mypk ) - return(cclib_error(result,"destpub33 is not for this -pubkey")); + retstr = (char *)"destpub33 is not for this -pubkey"; else if ( _dilithium_sign(&sig[0],&smlen,msg,32,sk) < 0 ) - return(cclib_error(result,"dilithium signing error")); + retstr = (char *)"dilithium signing error"; else if ( smlen != 32+CRYPTO_BYTES ) - return(cclib_error(result,"siglen error")); - rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_Qsendopret(mypubtxid,sig,voutpubtxids)); - return(dilithium_rawtxresult(result,rawtx)); - } else return(cclib_error(result,"Q couldnt find enough Q or x inputs")); - } else return(cclib_error(result,"need to have exactly 2 params sendtxid, scriptPubKey")); + retstr = (char *)"siglen error"; + else + { + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_Qsendopret(mypubtxid,sig,voutpubtxids)); + memset(seed,0,32); + memset(sk,0,sizeof(sk)); + return(dilithium_rawtxresult(result,rawtx)); + } + } else retstr = (char *)"Q couldnt find enough Q or x inputs"; + } else retstr = (char *)"need to have exactly 2 params sendtxid, scriptPubKey"; + memset(seed,0,32); + memset(sk,0,sizeof(sk)); + return(cclib_error(result,retstr)); } bool dilithium_Qvalidate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx) diff --git a/src/cc/faucet.cpp b/src/cc/faucet.cpp index fd3a8f60f..e2fc360a8 100644 --- a/src/cc/faucet.cpp +++ b/src/cc/faucet.cpp @@ -35,6 +35,7 @@ int64_t IsFaucetvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v { if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 ) return(tx.vout[v].nValue); + //else fprintf(stderr,"dest.%s vs (%s)\n",destaddr,cp->unspendableCCaddr); } return(0); } @@ -170,7 +171,7 @@ int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub n++; if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) break; - } else fprintf(stderr,"nValue too small or already spent in mempool\n"); + } else fprintf(stderr,"vout.%d nValue %.8f too small or already spent in mempool\n",vout,(double)nValue/COIN); } else fprintf(stderr,"couldnt get tx\n"); } return(totalinputs); diff --git a/src/cc/gamescc.cpp b/src/cc/gamescc.cpp index 997013b0c..425ae473d 100644 --- a/src/cc/gamescc.cpp +++ b/src/cc/gamescc.cpp @@ -411,7 +411,7 @@ UniValue games_rng(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) int32_t games_eventsign(uint32_t ×tamp,std::vector &sig,std::vector payload,CPubKey pk) { static secp256k1_context *ctx; - size_t siglen = 74; secp256k1_pubkey pubkey; secp256k1_ecdsa_signature signature; int32_t len,verifyflag = 1; uint8_t privkey[32]; uint256 hash; uint32_t t; + size_t siglen = 74; secp256k1_pubkey pubkey; secp256k1_ecdsa_signature signature; int32_t len,verifyflag = 1,retval=-100; uint8_t privkey[32]; uint256 hash; uint32_t t; if ( ctx == 0 ) ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); if ( ctx != 0 ) @@ -439,10 +439,9 @@ int32_t games_eventsign(uint32_t ×tamp,std::vector &sig,std::vecto { if ( siglen != sig.size() ) sig.resize(siglen); - return(0); - } - else return(-3); - } else return(-2); + retval = 0; + } else retval = -3; + } else retval = -2; } else { @@ -451,12 +450,14 @@ int32_t games_eventsign(uint32_t ×tamp,std::vector &sig,std::vecto if ( secp256k1_ecdsa_signature_parse_der(ctx,&signature,&sig[0],sig.size()) > 0 ) { if ( secp256k1_ecdsa_verify(ctx,&signature,(uint8_t *)&hash,&pubkey) > 0 ) - return(0); - else return(-4); - } else return(-3); - } else return(-2); + retval = 0; + else retval = -4; + } else retval = -3; + } else retval = -2; } - } else return(-1); + } else retval = -1; + memset(privkey,0,sizeof(privkey)); + return(retval); } int32_t games_event(uint32_t timestamp,uint256 gametxid,int32_t eventid,std::vector payload) @@ -1339,6 +1340,7 @@ UniValue games_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *param CCaddr1of2set(cp,gamespk,mypk,mypriv,destaddr); rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,games_keystrokesopret(gametxid,batontxid,mypk,keystrokes)); //fprintf(stderr,"KEYSTROKES.(%s)\n",rawtx.c_str()); + memset(mypriv,0,sizeof(mypriv)); return(games_rawtxresult(result,rawtx,1)); } else return(cclib_error(result,"keystrokes tx was too late")); } else return(cclib_error(result,"couldnt find batontxid")); @@ -1612,6 +1614,7 @@ UniValue games_finish(uint64_t txfee,struct CCcontract_info *cp,cJSON *params,ch GetOpReturnData(opret, vopretNonfungible); rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeTokenCreateOpRet('c', Mypubkey(), std::string(seedstr), gametxid.GetHex(), vopretNonfungible)); } + memset(mypriv,0,sizeof(mypriv)); return(games_rawtxresult(result,rawtx,1)); } result.push_back(Pair("result","success")); diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index fc3a2f2fd..df3b0b7e8 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -967,6 +967,7 @@ template UniValue _HeirClaim(uint256 fundingtxid, int64_t txfee std::string rawhextx = FinalizeCCTx(0, cp, mtx, myPubkey, txfee, Helper::makeClaimOpRet(tokenid, voutTokenPubkeys, fundingtxid, (myPubkey == heirPubkey) ? 1 : hasHeirSpendingBegun)); // forward isHeirSpending to the next latest tx + memset(myprivkey,0,sizeof(myprivkey)); if (!rawhextx.empty()) { result.push_back(Pair("result", "success")); result.push_back(Pair("hex", rawhextx)); diff --git a/src/cc/heir_validate.h b/src/cc/heir_validate.h index c7424bc16..768390aa3 100644 --- a/src/cc/heir_validate.h +++ b/src/cc/heir_validate.h @@ -56,6 +56,7 @@ public: uint8_t mypriv[32]; Myprivkey(mypriv); CCaddr1of2set(cp, ownerPubkey, heirPubkey,mypriv, coinaddr); + memset(mypriv,0,sizeof(mypriv)); } }; @@ -101,6 +102,7 @@ public: uint8_t mypriv[32]; Myprivkey(mypriv); CCaddrTokens1of2set(cp, ownerPubkey, heirPubkey, mypriv, coinaddr); + memset(mypriv,0,sizeof(mypriv)); } }; diff --git a/src/cc/marmara.cpp b/src/cc/marmara.cpp index e28566079..68625c038 100644 --- a/src/cc/marmara.cpp +++ b/src/cc/marmara.cpp @@ -488,6 +488,7 @@ UniValue MarmaraLock(uint64_t txfee,int64_t amount,int32_t height) } } } + memset(mypriv,0,sizeof(mypriv)); } if ( inputsum >= amount+txfee ) { diff --git a/src/cc/musig.cpp b/src/cc/musig.cpp index bc113bc5c..e98937d71 100644 --- a/src/cc/musig.cpp +++ b/src/cc/musig.cpp @@ -482,10 +482,12 @@ UniValue musig_session(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) MUSIG[musiglocation]->numcommits = 1; result.push_back(Pair("commitment",str)); result.push_back(Pair("result","success")); + memset(privkey,0,sizeof(privkey)); return(result); } else { + memset(privkey,0,sizeof(privkey)); memset(session,0,sizeof(session)); return(cclib_error(result,"couldnt initialize session")); } diff --git a/src/cc/oracles.cpp b/src/cc/oracles.cpp index 5056ccade..0830ca6c1 100644 --- a/src/cc/oracles.cpp +++ b/src/cc/oracles.cpp @@ -193,6 +193,7 @@ CPubKey OracleBatonPk(char *batonaddr,struct CCcontract_info *cp) //fprintf(stderr,"batonpk.(%s) -> %s\n",(char *)HexStr(batonpk).c_str(),batonaddr); strcpy(cp->unspendableaddr2,batonaddr); } else fprintf(stderr,"error creating pubkey\n"); + memset(priv,0,sizeof(priv)); return(batonpk); } diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 17507a80e..e329ff5bf 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -75,6 +75,36 @@ */ +// payments cc fix +#if (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) + #undef mpz_set_si + #undef mpz_get_si + #define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1)) + #define GMP_NEG_CAST(T,x) (-(int64_t)((T)((x) + 1) - 1)) + + int64_t mpz_get_si (const mpz_t u) + { + mp_size_t us = u->_mp_size; + if (us > 0) + return (int64_t) (u->_mp_d[0] & ~GMP_LIMB_HIGHBIT); + else if (us < 0) + return (int64_t) (- u->_mp_d[0] | GMP_LIMB_HIGHBIT); + else + return 0; + } + + void mpz_set_si (mpz_t r, int64_t x) + { + if (x >= 0) + mpz_set_ui (r, x); + else /* (x < 0) */ + { + r->_mp_size = -1; + r->_mp_d[0] = GMP_NEG_CAST (uint64_t, x); + } + } +#endif + // start of consensus code CScript EncodePaymentsTxidOpRet(int64_t allocation,std::vector scriptPubKey,std::vector destopret) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 002b591c4..949417be5 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -439,7 +439,8 @@ int64_t AddPegsTokenInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,u uint8_t mypriv[32]; Myprivkey(mypriv); CCaddrTokens1of2set(cp,pk1,pk2,mypriv,coinaddr); - } + memset(mypriv,0,sizeof(mypriv)); + } } return(totalinputs); } @@ -753,6 +754,7 @@ std::string PegsFund(uint64_t txfee,uint256 pegstxid, uint256 tokenid,int64_t am mtx.vin.push_back(CTxIn(accounttxid,1,CScript())); GetCCaddress1of2(cp,coinaddr,mypk,pegspk); CCaddr1of2set(cp,mypk,pegspk,mypriv,coinaddr); + memset(mypriv,0,sizeof(mypriv)); } else funds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee+2*CC_MARKER_VALUE,3); if (funds>=txfee+2*CC_MARKER_VALUE) @@ -839,7 +841,9 @@ std::string PegsGet(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t am Myprivkey(mypriv); GetCCaddress1of2(cp,coinaddr,mypk,pegspk); CCaddr1of2set(cp,mypk,pegspk,mypriv,coinaddr); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret)); + std::string retstr = FinalizeCCTx(0,cp,mtx,mypk,txfee,opret); + memset(mypriv,0,sizeof(mypriv)); + return(retstr); } std::string PegsRedeem(uint64_t txfee,uint256 pegstxid, uint256 tokenid) @@ -929,28 +933,34 @@ std::string PegsRedeem(uint64_t txfee,uint256 pegstxid, uint256 tokenid) account.first=0; account.second=0; LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "new account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl); - return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePegsReedemOpRet(tokenid,pegstxid,mypk,amount,account))); + std::string retstr = FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePegsReedemOpRet(tokenid,pegstxid,mypk,amount,account)); + memset(mypriv,0,32); + return(retstr); } else { CCerror = strprintf("not enough balance in pegs global CC address"); LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl); - return(""); + memset(mypriv,0,32); + return(""); } } CCerror = strprintf("not enough tokens in pegs account (%lld) to redeem this amount of tokens %lld",tokenfunds,account.first); LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl); + memset(mypriv,0,32); return(""); } else { CCerror = strprintf("not enough balance in pegs global CC address"); LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl); - return(""); + memset(mypriv,0,32); + return(""); } } CCerror = strprintf("to redeem from account and close it you must redeem full debt ammount %lld instead of %lld",account.second,funds); LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl); + memset(mypriv,0,32); return(""); } diff --git a/src/cc/rogue_rpc.cpp b/src/cc/rogue_rpc.cpp index b0ed60ab2..a6168a206 100644 --- a/src/cc/rogue_rpc.cpp +++ b/src/cc/rogue_rpc.cpp @@ -963,6 +963,7 @@ UniValue rogue_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *param CCaddr1of2set(cp,roguepk,mypk,mypriv,destaddr); rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,rogue_keystrokesopret(gametxid,batontxid,mypk,keystrokes)); //fprintf(stderr,"KEYSTROKES.(%s)\n",rawtx.c_str()); + memset(mypriv,0,32); return(rogue_rawtxresult(result,rawtx,1)); } else return(cclib_error(result,"keystrokes tx was too late")); } else return(cclib_error(result,"couldnt find batontxid")); @@ -1330,6 +1331,7 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param GetOpReturnData(opret, vopretNonfungible); rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeTokenCreateOpRet('c', Mypubkey(), std::string(seedstr), gametxid.GetHex(), vopretNonfungible)); } + memset(mypriv,0,32); return(rogue_rawtxresult(result,rawtx,1)); } result.push_back(Pair("result","success")); diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 0093cd38a..b067a0b5e 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -654,6 +654,7 @@ const char *banned_txids[] = //"6cc1d0495170bc0e11fd3925297623562e529ea1336b66ea61f8a1159041aed2", //"250875424cece9bcd98cb226b09da7671625633d6958589e3a462bad89ad87cc", // missed //"ea8659011de52f4dac42cda12326064b7b5013b8492f88e33159884ca299aa05", // missed + //"ce567928b5490a17244167af161b1d8dd6ff753fef222fe6855d95b2278a35b3", // missed }; int32_t komodo_checkvout(int32_t vout,int32_t k,int32_t indallvouts) diff --git a/src/komodo_nSPV.h b/src/komodo_nSPV.h index 67bfd6bb0..27f03a5be 100644 --- a/src/komodo_nSPV.h +++ b/src/komodo_nSPV.h @@ -15,13 +15,10 @@ ******************************************************************************/ // todo: - -// myprivkey, scrub all destination buffers -// oversized tx +// spentinfo via CC // headers "sync" make sure it connects to prior blocks to notarization. use getinfo hdrht to get missing hdrs - // make sure to sanity check all vector lengths on receipt // make sure no files are updated (this is to allow nSPV=1 and later nSPV=0 without affecting database) // bug: under load, fullnode was returning all 0 nServices @@ -104,8 +101,9 @@ int32_t NSPV_rwutxosresp(int32_t rwflag,uint8_t *serialized,struct NSPV_utxosres len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->total),&ptr->total); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->interest),&ptr->interest); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad32),&ptr->pad32); len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad8),&ptr->pad8); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); if ( rwflag != 0 ) { memcpy(&serialized[len],ptr->coinaddr,sizeof(ptr->coinaddr)); @@ -139,6 +137,116 @@ void NSPV_utxosresp_copy(struct NSPV_utxosresp *dest,struct NSPV_utxosresp *ptr) } } +int32_t NSPV_rwtxidresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidresp *ptr) +{ + int32_t len = 0; + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->satoshis),&ptr->satoshis); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->height),&ptr->height); + return(len); +} + +int32_t NSPV_rwtxidsresp(int32_t rwflag,uint8_t *serialized,struct NSPV_txidsresp *ptr) +{ + int32_t i,len = 0; + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->numtxids),&ptr->numtxids); + if ( ptr->numtxids != 0 ) + { + if ( ptr->txids == 0 ) + ptr->txids = (struct NSPV_txidresp *)calloc(sizeof(*ptr->txids),ptr->numtxids); + for (i=0; inumtxids; i++) + len += NSPV_rwtxidresp(rwflag,&serialized[len],&ptr->txids[i]); + } + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->pad32),&ptr->pad32); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->skipcount),&ptr->skipcount); + if ( rwflag != 0 ) + { + memcpy(&serialized[len],ptr->coinaddr,sizeof(ptr->coinaddr)); + len += sizeof(ptr->coinaddr); + } + else + { + memcpy(ptr->coinaddr,&serialized[len],sizeof(ptr->coinaddr)); + len += sizeof(ptr->coinaddr); + } +//fprintf(stderr,"rwlen.%d\n",len); + return(len); +} + +void NSPV_txidsresp_purge(struct NSPV_txidsresp *ptr) +{ + if ( ptr != 0 ) + { + if ( ptr->txids != 0 ) + free(ptr->txids); + memset(ptr,0,sizeof(*ptr)); + } +} + +void NSPV_txidsresp_copy(struct NSPV_txidsresp *dest,struct NSPV_txidsresp *ptr) +{ + *dest = *ptr; + if ( ptr->txids != 0 ) + { + dest->txids = (struct NSPV_txidresp *)malloc(ptr->numtxids * sizeof(*ptr->txids)); + memcpy(dest->txids,ptr->txids,ptr->numtxids * sizeof(*ptr->txids)); + } +} + +int32_t NSPV_rwmempoolresp(int32_t rwflag,uint8_t *serialized,struct NSPV_mempoolresp *ptr) +{ + int32_t i,len = 0; + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->numtxids),&ptr->numtxids); + if ( ptr->numtxids != 0 ) + { + if ( ptr->txids == 0 ) + ptr->txids = (uint256 *)calloc(sizeof(*ptr->txids),ptr->numtxids); + for (i=0; inumtxids; i++) + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txids[i]),(uint8_t *)&ptr->txids[i]); + } + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(ptr->txid),(uint8_t *)&ptr->txid); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->nodeheight),&ptr->nodeheight); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vout),&ptr->vout); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->vindex),&ptr->vindex); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->CCflag),&ptr->CCflag); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(ptr->funcid),&ptr->funcid); + if ( rwflag != 0 ) + { + memcpy(&serialized[len],ptr->coinaddr,sizeof(ptr->coinaddr)); + len += sizeof(ptr->coinaddr); + } + else + { + memcpy(ptr->coinaddr,&serialized[len],sizeof(ptr->coinaddr)); + len += sizeof(ptr->coinaddr); + } + //fprintf(stderr,"NSPV_rwmempoolresp rwlen.%d\n",len); + return(len); +} + +void NSPV_mempoolresp_purge(struct NSPV_mempoolresp *ptr) +{ + if ( ptr != 0 ) + { + if ( ptr->txids != 0 ) + free(ptr->txids); + memset(ptr,0,sizeof(*ptr)); + } +} + +void NSPV_mempoolresp_copy(struct NSPV_mempoolresp *dest,struct NSPV_mempoolresp *ptr) +{ + *dest = *ptr; + if ( ptr->txids != 0 ) + { + dest->txids = (uint256 *)malloc(ptr->numtxids * sizeof(*ptr->txids)); + memcpy(dest->txids,ptr->txids,ptr->numtxids * sizeof(*ptr->txids)); + } +} + int32_t NSPV_rwntz(int32_t rwflag,uint8_t *serialized,struct NSPV_ntz *ptr) { int32_t len = 0; diff --git a/src/komodo_nSPV_defs.h b/src/komodo_nSPV_defs.h index 31c53fa22..4cf4d93eb 100644 --- a/src/komodo_nSPV_defs.h +++ b/src/komodo_nSPV_defs.h @@ -39,6 +39,15 @@ #define NSPV_SPENTINFORESP 0x0b #define NSPV_BROADCAST 0x0c #define NSPV_BROADCASTRESP 0x0d +#define NSPV_TXIDS 0x0e +#define NSPV_TXIDSRESP 0x0f +#define NSPV_MEMPOOL 0x10 +#define NSPV_MEMPOOLRESP 0x11 +#define NSPV_MEMPOOL_ALL 0 +#define NSPV_MEMPOOL_ADDRESS 1 +#define NSPV_MEMPOOL_ISSPENT 2 +#define NSPV_MEMPOOL_INMEMPOOL 3 +#define NSPV_MEMPOOL_CCEVALCODE 4 int32_t NSPV_gettransaction(int32_t skipvalidation,int32_t vout,uint256 txid,int32_t height,CTransaction &tx,int64_t extradata,uint32_t tiptime,int64_t &rewardsum); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); @@ -69,8 +78,32 @@ struct NSPV_utxosresp struct NSPV_utxoresp *utxos; char coinaddr[64]; int64_t total,interest; - int32_t nodeheight; - uint16_t numutxos; uint8_t CCflag,pad8; + int32_t nodeheight,skipcount,pad32; + uint16_t numutxos,CCflag; +}; + +struct NSPV_txidresp +{ + uint256 txid; + int64_t satoshis; + int32_t vout,height; +}; + +struct NSPV_txidsresp +{ + struct NSPV_txidresp *txids; + char coinaddr[64]; + int32_t nodeheight,skipcount,pad32; + uint16_t numtxids,CCflag; +}; + +struct NSPV_mempoolresp +{ + uint256 *txids; + char coinaddr[64]; + uint256 txid; + int32_t nodeheight,vout,vindex; + uint16_t numtxids; uint8_t CCflag,funcid; }; struct NSPV_ntz diff --git a/src/komodo_nSPV_fullnode.h b/src/komodo_nSPV_fullnode.h index 9e44df3a7..b5eba8ed3 100644 --- a/src/komodo_nSPV_fullnode.h +++ b/src/komodo_nSPV_fullnode.h @@ -139,44 +139,57 @@ int32_t NSPV_getinfo(struct NSPV_inforesp *ptr,int32_t reqheight) } else return(-1); } -int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC) // check mempool +int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC,int32_t skipcount) // check mempool { - int64_t total = 0,interest=0; uint32_t locktime; int32_t tipheight,maxlen,txheight,n = 0,len = 0; + int64_t total = 0,interest=0; uint32_t locktime; int32_t ind=0,tipheight,maxlen,txheight,n = 0,len = 0; std::vector > unspentOutputs; SetCCunspents(unspentOutputs,coinaddr,isCC); maxlen = MAX_BLOCK_SIZE(tipheight) - 512; maxlen /= sizeof(*ptr->utxos); strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); ptr->CCflag = isCC; + if ( skipcount < 0 ) + skipcount = 0; if ( (ptr->numutxos= (int32_t)unspentOutputs.size()) >= 0 && ptr->numutxos < maxlen ) { tipheight = chainActive.LastTip()->GetHeight(); ptr->nodeheight = tipheight; - ptr->utxos = (struct NSPV_utxoresp *)calloc(ptr->numutxos,sizeof(*ptr->utxos)); - for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) + if ( skipcount >= ptr->numutxos ) + skipcount = ptr->numutxos-1; + ptr->skipcount = skipcount; + if ( ptr->numutxos-skipcount > 0 ) { - ptr->utxos[n].txid = it->first.txhash; - ptr->utxos[n].vout = (int32_t)it->first.index; - ptr->utxos[n].satoshis = it->second.satoshis; - ptr->utxos[n].height = it->second.blockHeight; - if ( ASSETCHAINS_SYMBOL[0] == 0 && it->second.satoshis >= 10*COIN ) + ptr->utxos = (struct NSPV_utxoresp *)calloc(ptr->numutxos-skipcount,sizeof(*ptr->utxos)); + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { - ptr->utxos[n].extradata = komodo_accrued_interest(&txheight,&locktime,ptr->utxos[n].txid,ptr->utxos[n].vout,ptr->utxos[n].height,ptr->utxos[n].satoshis,tipheight); - interest += ptr->utxos[n].extradata; + // if gettxout is != null to handle mempool + { + if ( n >= skipcount ) + { + ptr->utxos[ind].txid = it->first.txhash; + ptr->utxos[ind].vout = (int32_t)it->first.index; + ptr->utxos[ind].satoshis = it->second.satoshis; + ptr->utxos[ind].height = it->second.blockHeight; + if ( ASSETCHAINS_SYMBOL[0] == 0 && it->second.satoshis >= 10*COIN ) + { + ptr->utxos[n].extradata = komodo_accrued_interest(&txheight,&locktime,ptr->utxos[ind].txid,ptr->utxos[ind].vout,ptr->utxos[ind].height,ptr->utxos[ind].satoshis,tipheight); + interest += ptr->utxos[ind].extradata; + } + ind++; + total += it->second.satoshis; + } + n++; + } } - total += it->second.satoshis; - n++; } + ptr->numutxos = ind; if ( len < maxlen ) { len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->utxos)*ptr->numutxos - sizeof(ptr->utxos)); //fprintf(stderr,"getaddressutxos for %s -> n.%d:%d total %.8f interest %.8f len.%d\n",coinaddr,n,ptr->numutxos,dstr(total),dstr(interest),len); - if ( n == ptr->numutxos ) - { - ptr->total = total; - ptr->interest = interest; - return(len); - } + ptr->total = total; + ptr->interest = interest; + return(len); } } if ( ptr->utxos != 0 ) @@ -185,6 +198,165 @@ int32_t NSPV_getaddressutxos(struct NSPV_utxosresp *ptr,char *coinaddr,bool isCC return(0); } +int32_t NSPV_getaddresstxids(struct NSPV_txidsresp *ptr,char *coinaddr,bool isCC,int32_t skipcount) +{ + int32_t maxlen,txheight,ind=0,n = 0,len = 0; + std::vector > txids; + SetCCtxids(txids,coinaddr,isCC); + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + maxlen = MAX_BLOCK_SIZE(ptr->nodeheight) - 512; + maxlen /= sizeof(*ptr->txids); + strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + ptr->CCflag = isCC; + if ( skipcount < 0 ) + skipcount = 0; + if ( (ptr->numtxids= (int32_t)txids.size()) >= 0 && ptr->numtxids < maxlen ) + { + if ( skipcount >= ptr->numtxids ) + skipcount = ptr->numtxids-1; + ptr->skipcount = skipcount; + if ( ptr->numtxids-skipcount > 0 ) + { + ptr->txids = (struct NSPV_txidresp *)calloc(ptr->numtxids-skipcount,sizeof(*ptr->txids)); + for (std::vector >::const_iterator it=txids.begin(); it!=txids.end(); it++) + { + if ( n >= skipcount ) + { + ptr->txids[ind].txid = it->first.txhash; + ptr->txids[ind].vout = (int32_t)it->first.index; + ptr->txids[ind].satoshis = (int64_t)it->second; + ptr->txids[ind].height = (int64_t)it->first.blockHeight; + ind++; + } + n++; + } + } + ptr->numtxids = ind; + len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); + return(len); + } + if ( ptr->txids != 0 ) + free(ptr->txids); + memset(ptr,0,sizeof(*ptr)); + return(0); +} + +int32_t NSPV_mempoolfuncs(int32_t *vindexp,std::vector &txids,char *coinaddr,bool isCC,uint8_t funcid,uint256 txid,int32_t vout) +{ + int32_t num = 0,vini = 0,vouti = 0; uint8_t evalcode=0,func=0; std::vector vopret; char destaddr[64]; + *vindexp = -1; + if ( mempool.size() == 0 ) + return(0); + if ( funcid == NSPV_MEMPOOL_CCEVALCODE ) + { + isCC = true; + evalcode = vout & 0xff; + func = (vout >> 8) & 0xff; + } + LOCK(mempool.cs); + BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) + { + const CTransaction &tx = e.GetTx(); + const uint256 &hash = tx.GetHash(); + if ( funcid == NSPV_MEMPOOL_ALL ) + { + txids.push_back(hash); + num++; + continue; + } + else if ( funcid == NSPV_MEMPOOL_INMEMPOOL ) + { + if ( hash == txid ) + { + txids.push_back(hash); + return(++num); + } + continue; + } + else if ( funcid == NSPV_MEMPOOL_CCEVALCODE ) + { + if ( tx.vout.size() > 1 ) + { + CScript scriptPubKey = tx.vout[tx.vout.size()-1].scriptPubKey; + if ( GetOpReturnData(scriptPubKey,vopret) != 0 ) + { + if ( vopret[0] == evalcode && vopret[1] == func ) + { + txids.push_back(hash); + num++; + } + } + } + continue; + } + if ( funcid == NSPV_MEMPOOL_ISSPENT ) + { + BOOST_FOREACH(const CTxIn &txin,tx.vin) + { + //fprintf(stderr,"%s/v%d ",uint256_str(str,txin.prevout.hash),txin.prevout.n); + if ( txin.prevout.n == vout && txin.prevout.hash == txid ) + { + txids.push_back(hash); + *vindexp = vini; + return(++num); + } + vini++; + } + } + else if ( funcid == NSPV_MEMPOOL_ADDRESS ) + { + BOOST_FOREACH(const CTxOut &txout,tx.vout) + { + if ( txout.scriptPubKey.IsPayToCryptoCondition() == isCC ) + { + Getscriptaddress(destaddr,txout.scriptPubKey); + if ( strcmp(destaddr,coinaddr) == 0 ) + { + txids.push_back(hash); + *vindexp = vouti; + num++; + } + } + vouti++; + } + } + //fprintf(stderr,"are vins for %s\n",uint256_str(str,hash)); + } + return(num); +} + +int32_t NSPV_mempooltxids(struct NSPV_mempoolresp *ptr,char *coinaddr,uint8_t isCC,uint8_t funcid,uint256 txid,int32_t vout) +{ + std::vector txids; uint256 tmp,tmpdest; int32_t i,len = 0; + ptr->nodeheight = chainActive.LastTip()->GetHeight(); + strncpy(ptr->coinaddr,coinaddr,sizeof(ptr->coinaddr)-1); + ptr->CCflag = isCC; + ptr->txid = txid; + ptr->vout = vout; + ptr->funcid = funcid; + if ( NSPV_mempoolfuncs(&ptr->vindex,txids,coinaddr,isCC,funcid,txid,vout) >= 0 ) + { + if ( (ptr->numtxids= (int32_t)txids.size()) >= 0 ) + { + if ( ptr->numtxids > 0 ) + { + ptr->txids = (uint256 *)calloc(ptr->numtxids,sizeof(*ptr->txids)); + for (i=0; inumtxids; i++) + { + tmp = txids[i]; + iguana_rwbignum(0,(uint8_t *)&tmp,sizeof(*ptr->txids),(uint8_t *)&ptr->txids[i]); + } + } + len = (int32_t)(sizeof(*ptr) + sizeof(*ptr->txids)*ptr->numtxids - sizeof(ptr->txids)); + return(len); + } + } + if ( ptr->txids != 0 ) + free(ptr->txids); + memset(ptr,0,sizeof(*ptr)); + return(0); +} + uint8_t *NSPV_getrawtx(CTransaction &tx,uint256 &hashBlock,int32_t *txlenp,uint256 txid) { uint8_t *rawtx = 0; @@ -332,7 +504,7 @@ int32_t NSPV_getspentinfo(struct NSPV_spentinfo *ptr,uint256 txid,int32_t vout) void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a request { - int32_t len,slen,ind,reqheight; std::vector response; uint32_t timestamp = (uint32_t)time(NULL); + int32_t len,slen,ind,reqheight,n; std::vector response; uint32_t timestamp = (uint32_t)time(NULL); if ( (len= request.size()) > 0 ) { if ( (ind= request[0]>>1) >= sizeof(pfrom->prevtimes)/sizeof(*pfrom->prevtimes) ) @@ -370,17 +542,22 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req if ( timestamp > pfrom->prevtimes[ind] ) { struct NSPV_utxosresp U; char coinaddr[64]; - if ( len < 64 && (request[1] == len-2 || request[1] == len-3) ) + if ( len < 64 && (request[1] == len-3 || request[1] == len-7) ) { - uint8_t isCC = 0; + int32_t skipcount = 0; uint8_t isCC = 0; memcpy(coinaddr,&request[2],request[1]); coinaddr[request[1]] = 0; if ( request[1] == len-3 ) isCC = (request[len-1] != 0); + else + { + isCC = (request[len-5] != 0); + iguana_rwnum(0,&request[len-4],sizeof(skipcount),&skipcount); + } if ( isCC != 0 ) - fprintf(stderr,"%s isCC.%d\n",coinaddr,isCC); + fprintf(stderr,"%s isCC.%d skipcount.%d\n",coinaddr,isCC,skipcount); memset(&U,0,sizeof(U)); - if ( (slen= NSPV_getaddressutxos(&U,coinaddr,isCC)) > 0 ) + if ( (slen= NSPV_getaddressutxos(&U,coinaddr,isCC,skipcount)) > 0 ) { response.resize(1 + slen); response[0] = NSPV_UTXOSRESP; @@ -394,6 +571,78 @@ void komodo_nSPVreq(CNode *pfrom,std::vector request) // received a req } } } + else if ( request[0] == NSPV_TXIDS ) + { + if ( timestamp > pfrom->prevtimes[ind] ) + { + struct NSPV_txidsresp T; char coinaddr[64]; + if ( len < 64+5 && (request[1] == len-3 || request[1] == len-7) ) + { + int32_t skipcount = 0; uint8_t isCC = 0; + memcpy(coinaddr,&request[2],request[1]); + coinaddr[request[1]] = 0; + if ( request[1] == len-3 ) + isCC = (request[len-1] != 0); + else + { + isCC = (request[len-5] != 0); + iguana_rwnum(0,&request[len-4],sizeof(skipcount),&skipcount); + } + //if ( isCC != 0 ) + fprintf(stderr,"%s isCC.%d skipcount.%d\n",coinaddr,isCC,skipcount); + memset(&T,0,sizeof(T)); + if ( (slen= NSPV_getaddresstxids(&T,coinaddr,isCC,skipcount)) > 0 ) + { +//fprintf(stderr,"slen.%d\n",slen); + response.resize(1 + slen); + response[0] = NSPV_TXIDSRESP; + if ( NSPV_rwtxidsresp(1,&response[1],&T) == slen ) + { + pfrom->PushMessage("nSPV",response); + pfrom->prevtimes[ind] = timestamp; + } + NSPV_txidsresp_purge(&T); + } + } else fprintf(stderr,"len.%d req1.%d\n",len,request[1]); + } + } + else if ( request[0] == NSPV_MEMPOOL ) + { + if ( timestamp > pfrom->prevtimes[ind] ) + { + struct NSPV_mempoolresp M; char coinaddr[64]; + if ( len < sizeof(M)+64 ) + { + int32_t vout; uint256 txid; uint8_t funcid,isCC = 0; + n = 1; + n += iguana_rwnum(0,&request[n],sizeof(isCC),&isCC); + n += iguana_rwnum(0,&request[n],sizeof(funcid),&funcid); + n += iguana_rwnum(0,&request[n],sizeof(vout),&vout); + n += iguana_rwbignum(0,&request[n],sizeof(txid),(uint8_t *)&txid); + slen = request[n++]; + if ( slen < 63 ) + { + memcpy(coinaddr,&request[n],slen), n += slen; + coinaddr[slen] = 0; + if ( isCC != 0 ) + fprintf(stderr,"(%s) isCC.%d funcid.%d %s/v%d len.%d slen.%d\n",coinaddr,isCC,funcid,txid.GetHex().c_str(),vout,len,slen); + memset(&M,0,sizeof(M)); + if ( (slen= NSPV_mempooltxids(&M,coinaddr,isCC,funcid,txid,vout)) > 0 ) + { + //fprintf(stderr,"NSPV_mempooltxids slen.%d\n",slen); + response.resize(1 + slen); + response[0] = NSPV_MEMPOOLRESP; + if ( NSPV_rwmempoolresp(1,&response[1],&M) == slen ) + { + pfrom->PushMessage("nSPV",response); + pfrom->prevtimes[ind] = timestamp; + } + NSPV_mempoolresp_purge(&M); + } + } + } else fprintf(stderr,"len.%d req1.%d\n",len,request[1]); + } + } else if ( request[0] == NSPV_NTZS ) { if ( timestamp > pfrom->prevtimes[ind] ) diff --git a/src/komodo_nSPV_superlite.h b/src/komodo_nSPV_superlite.h index 259f9cbc3..f8dae10bf 100644 --- a/src/komodo_nSPV_superlite.h +++ b/src/komodo_nSPV_superlite.h @@ -31,6 +31,8 @@ char NSPV_wifstr[64],NSPV_pubkeystr[67],NSPV_lastpeer[128]; std::string NSPV_address; struct NSPV_inforesp NSPV_inforesult; struct NSPV_utxosresp NSPV_utxosresult; +struct NSPV_txidsresp NSPV_txidsresult; +struct NSPV_mempoolresp NSPV_mempoolresult; struct NSPV_spentinfo NSPV_spentresult; struct NSPV_ntzsresp NSPV_ntzsresult; struct NSPV_ntzsproofresp NSPV_ntzsproofresult; @@ -158,9 +160,19 @@ void komodo_nSPVresp(CNode *pfrom,std::vector response) // received a r case NSPV_UTXOSRESP: NSPV_utxosresp_purge(&NSPV_utxosresult); NSPV_rwutxosresp(0,&response[1],&NSPV_utxosresult); - fprintf(stderr,"got utxos response %u size.%d\n",timestamp,(int32_t)response.size()); // update utxos list + fprintf(stderr,"got utxos response %u size.%d\n",timestamp,(int32_t)response.size()); break; - case NSPV_NTZSRESP: + case NSPV_TXIDSRESP: + NSPV_txidsresp_purge(&NSPV_txidsresult); + NSPV_rwtxidsresp(0,&response[1],&NSPV_txidsresult); + fprintf(stderr,"got txids response %u size.%d %s CC.%d num.%d\n",timestamp,(int32_t)response.size(),NSPV_txidsresult.coinaddr,NSPV_txidsresult.CCflag,NSPV_txidsresult.numtxids); + break; + case NSPV_MEMPOOLRESP: + NSPV_mempoolresp_purge(&NSPV_mempoolresult); + NSPV_rwmempoolresp(0,&response[1],&NSPV_mempoolresult); + fprintf(stderr,"got mempool response %u size.%d %s CC.%d num.%d funcid.%d %s/v%d\n",timestamp,(int32_t)response.size(),NSPV_mempoolresult.coinaddr,NSPV_mempoolresult.CCflag,NSPV_mempoolresult.numtxids,NSPV_mempoolresult.funcid,NSPV_mempoolresult.txid.GetHex().c_str(),NSPV_mempoolresult.vout); + break; + case NSPV_NTZSRESP: NSPV_ntzsresp_purge(&NSPV_ntzsresult); NSPV_rwntzsresp(0,&response[1],&NSPV_ntzsresult); if ( NSPV_ntzsresp_find(NSPV_ntzsresult.reqheight) == 0 ) @@ -395,6 +407,54 @@ UniValue NSPV_utxosresp_json(struct NSPV_utxosresp *ptr) return(result); } +UniValue NSPV_txidresp_json(struct NSPV_txidresp *utxos,int32_t numutxos) +{ + UniValue array(UniValue::VARR); int32_t i; + for (i=0; i 0 ) + item.push_back(Pair("vout",(int64_t)utxos[i].vout)); + else item.push_back(Pair("vin",(int64_t)utxos[i].vout)); + array.push_back(item); + } + return(array); +} + +UniValue NSPV_txidsresp_json(struct NSPV_txidsresp *ptr) +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("result","success")); + result.push_back(Pair("txids",NSPV_txidresp_json(ptr->txids,ptr->numtxids))); + result.push_back(Pair("address",ptr->coinaddr)); + result.push_back(Pair("isCC",ptr->CCflag)); + result.push_back(Pair("height",(int64_t)ptr->nodeheight)); + result.push_back(Pair("numtxids",(int64_t)ptr->numtxids)); + result.push_back(Pair("lastpeer",NSPV_lastpeer)); + return(result); +} + +UniValue NSPV_mempoolresp_json(struct NSPV_mempoolresp *ptr) +{ + UniValue result(UniValue::VOBJ),array(UniValue::VARR); int32_t i; + result.push_back(Pair("result","success")); + for (i=0; inumtxids; i++) + array.push_back(Pair("txid",ptr->txids[i].GetHex().c_str())); + result.push_back(Pair("txids",array)); + result.push_back(Pair("address",ptr->coinaddr)); + result.push_back(Pair("isCC",ptr->CCflag)); + result.push_back(Pair("height",(int64_t)ptr->nodeheight)); + result.push_back(Pair("numtxids",(int64_t)ptr->numtxids)); + result.push_back(Pair("txid",ptr->txid.GetHex().c_str())); + result.push_back(Pair("vout",(int64_t)ptr->vout)); + result.push_back(Pair("funcid",(int64_t)ptr->funcid)); + result.push_back(Pair("lastpeer",NSPV_lastpeer)); + return(result); +} + UniValue NSPV_ntzsresp_json(struct NSPV_ntzsresp *ptr) { UniValue result(UniValue::VOBJ); @@ -520,12 +580,14 @@ uint32_t NSPV_blocktime(int32_t hdrheight) return(0); } -UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag) +UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag,int32_t skipcount) { UniValue result(UniValue::VOBJ); uint8_t msg[64]; int32_t i,iter,slen,len = 0; //fprintf(stderr,"utxos %s NSPV addr %s\n",coinaddr,NSPV_address.c_str()); - if ( NSPV_utxosresult.nodeheight >= NSPV_inforesult.height && strcmp(coinaddr,NSPV_utxosresult.coinaddr) == 0 && CCflag == NSPV_utxosresult.CCflag ) + if ( NSPV_utxosresult.nodeheight >= NSPV_inforesult.height && strcmp(coinaddr,NSPV_utxosresult.coinaddr) == 0 && CCflag == NSPV_utxosresult.CCflag && skipcount == NSPV_utxosresult.skipcount ) return(NSPV_utxosresp_json(&NSPV_utxosresult)); + if ( skipcount < 0 ) + skipcount = 0; NSPV_utxosresp_purge(&NSPV_utxosresult); if ( bitcoin_base58decode(msg,coinaddr) != 25 ) { @@ -538,21 +600,134 @@ UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag) msg[len++] = slen; memcpy(&msg[len],coinaddr,slen), len += slen; msg[len++] = (CCflag != 0); + len += iguana_rwnum(1,&msg[len],sizeof(skipcount),&skipcount); for (iter=0; iter<3; iter++); if ( NSPV_req(0,msg,len,NODE_ADDRINDEX,msg[0]>>1) != 0 ) { for (i=0; i= NSPV_inforesult.height && strcmp(coinaddr,NSPV_utxosresult.coinaddr) == 0 && CCflag == NSPV_utxosresult.CCflag ) + if ( (NSPV_inforesult.height == 0 || NSPV_utxosresult.nodeheight >= NSPV_inforesult.height) && strcmp(coinaddr,NSPV_utxosresult.coinaddr) == 0 && CCflag == NSPV_utxosresult.CCflag ) return(NSPV_utxosresp_json(&NSPV_utxosresult)); } } else sleep(1); result.push_back(Pair("result","error")); result.push_back(Pair("error","no utxos result")); + result.push_back(Pair("lastpeer",NSPV_lastpeer)); return(result); } +UniValue NSPV_addresstxids(char *coinaddr,int32_t CCflag,int32_t skipcount) +{ + UniValue result(UniValue::VOBJ); uint8_t msg[64]; int32_t i,iter,slen,len = 0; + if ( NSPV_txidsresult.nodeheight >= NSPV_inforesult.height && strcmp(coinaddr,NSPV_txidsresult.coinaddr) == 0 && CCflag == NSPV_txidsresult.CCflag && skipcount == NSPV_txidsresult.skipcount ) + return(NSPV_txidsresp_json(&NSPV_txidsresult)); + if ( skipcount < 0 ) + skipcount = 0; + NSPV_txidsresp_purge(&NSPV_txidsresult); + if ( bitcoin_base58decode(msg,coinaddr) != 25 ) + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","invalid address")); + return(result); + } + slen = (int32_t)strlen(coinaddr); + msg[len++] = NSPV_TXIDS; + msg[len++] = slen; + memcpy(&msg[len],coinaddr,slen), len += slen; + msg[len++] = (CCflag != 0); + len += iguana_rwnum(1,&msg[len],sizeof(skipcount),&skipcount); + //fprintf(stderr,"skipcount.%d\n",skipcount); + for (iter=0; iter<3; iter++); + if ( NSPV_req(0,msg,len,NODE_ADDRINDEX,msg[0]>>1) != 0 ) + { + for (i=0; i= NSPV_inforesult.height) && strcmp(coinaddr,NSPV_txidsresult.coinaddr) == 0 && CCflag == NSPV_txidsresult.CCflag ) + return(NSPV_txidsresp_json(&NSPV_txidsresult)); + } + } else sleep(1); + result.push_back(Pair("result","error")); + result.push_back(Pair("error","no txid result")); + result.push_back(Pair("lastpeer",NSPV_lastpeer)); + return(result); +} + +UniValue NSPV_mempooltxids(char *coinaddr,int32_t CCflag,uint8_t funcid,uint256 txid,int32_t vout) +{ + UniValue result(UniValue::VOBJ); uint8_t msg[512]; int32_t i,iter,slen,len = 0; + NSPV_mempoolresp_purge(&NSPV_mempoolresult); + if ( coinaddr[0] != 0 && bitcoin_base58decode(msg,coinaddr) != 25 ) + { + result.push_back(Pair("result","error")); + result.push_back(Pair("error","invalid address")); + return(result); + } + msg[len++] = NSPV_MEMPOOL; + msg[len++] = (CCflag != 0); + len += iguana_rwnum(1,&msg[len],sizeof(funcid),&funcid); + len += iguana_rwnum(1,&msg[len],sizeof(vout),&vout); + len += iguana_rwbignum(1,&msg[len],sizeof(txid),(uint8_t *)&txid); + slen = (int32_t)strlen(coinaddr); + msg[len++] = slen; + memcpy(&msg[len],coinaddr,slen), len += slen; + fprintf(stderr,"(%s) func.%d CC.%d %s/v%d len.%d\n",coinaddr,funcid,CCflag,txid.GetHex().c_str(),vout,len); + for (iter=0; iter<3; iter++); + if ( NSPV_req(0,msg,len,NODE_NSPV,msg[0]>>1) != 0 ) + { + for (i=0; i= NSPV_inforesult.height && strcmp(coinaddr,NSPV_mempoolresult.coinaddr) == 0 && CCflag == NSPV_mempoolresult.CCflag && txid == NSPV_mempoolresult.txid && vout == NSPV_mempoolresult.vout && funcid == NSPV_mempoolresult.funcid ) + return(NSPV_mempoolresp_json(&NSPV_mempoolresult)); + } + } else sleep(1); + result.push_back(Pair("result","error")); + result.push_back(Pair("error","no txid result")); + result.push_back(Pair("lastpeer",NSPV_lastpeer)); + return(result); +} + +int32_t NSPV_coinaddr_inmempool(char const *logcategory,char *coinaddr,uint8_t CCflag) +{ + NSPV_mempooltxids(coinaddr,CCflag,NSPV_MEMPOOL_ADDRESS,zeroid,-1); + if ( NSPV_mempoolresult.txids != 0 && NSPV_mempoolresult.numtxids >= 1 && strcmp(NSPV_mempoolresult.coinaddr,coinaddr) == 0 && NSPV_mempoolresult.CCflag == CCflag ) + { + LogPrint(logcategory,"found (%s) vout in mempool\n",coinaddr); + return(true); + } else return(false); +} + +bool NSPV_spentinmempool(uint256 &spenttxid,int32_t &spentvini,uint256 txid,int32_t vout) +{ + NSPV_mempooltxids((char *)"",0,NSPV_MEMPOOL_ISSPENT,txid,vout); + if ( NSPV_mempoolresult.txids != 0 && NSPV_mempoolresult.numtxids == 1 && NSPV_mempoolresult.txid == txid ) + { + spenttxid = NSPV_mempoolresult.txids[0]; + spentvini = NSPV_mempoolresult.vindex; + return(true); + } else return(false); +} + +bool NSPV_inmempool(uint256 txid) +{ + NSPV_mempooltxids((char *)"",0,NSPV_MEMPOOL_INMEMPOOL,txid,0); + if ( NSPV_mempoolresult.txids != 0 && NSPV_mempoolresult.numtxids == 1 && NSPV_mempoolresult.txids[0] == txid ) + return(true); + else return(false); +} + +bool NSPV_evalcode_inmempool(uint8_t evalcode,uint8_t funcid) +{ + int32_t vout; + vout = ((uint32_t)funcid << 8) | evalcode; + NSPV_mempooltxids((char *)"",1,NSPV_MEMPOOL_CCEVALCODE,zeroid,vout); + if ( NSPV_mempoolresult.txids != 0 && NSPV_mempoolresult.numtxids >= 1 && NSPV_mempoolresult.vout == vout ) + return(true); + else return(false); +} + UniValue NSPV_notarizations(int32_t reqheight) { uint8_t msg[64]; int32_t i,iter,len = 0; struct NSPV_ntzsresp N,*ptr; diff --git a/src/komodo_nSPV_wallet.h b/src/komodo_nSPV_wallet.h index d7ff5e1a7..102cce534 100644 --- a/src/komodo_nSPV_wallet.h +++ b/src/komodo_nSPV_wallet.h @@ -343,7 +343,7 @@ UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis) // what its a return(result); } if ( NSPV_utxosresult.CCflag != 0 || strcmp(NSPV_utxosresult.coinaddr,srcaddr) != 0 || NSPV_utxosresult.nodeheight < NSPV_inforesult.height ) - NSPV_addressutxos(srcaddr,0); + NSPV_addressutxos(srcaddr,0,0); if ( NSPV_utxosresult.CCflag != 0 || strcmp(NSPV_utxosresult.coinaddr,srcaddr) != 0 || NSPV_utxosresult.nodeheight < NSPV_inforesult.height ) { result.push_back(Pair("result","error")); @@ -434,7 +434,7 @@ int64_t NSPV_AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG); if ( strcmp(ptr->U.coinaddr,coinaddr) != 0 ) { - NSPV_addressutxos(coinaddr,CCflag); + NSPV_addressutxos(coinaddr,CCflag,0); NSPV_utxosresp_purge(&ptr->U); NSPV_utxosresp_copy(&ptr->U,&NSPV_utxosresult); } @@ -468,10 +468,40 @@ void NSPV_utxos2CCunspents(struct NSPV_utxosresp *ptr,std::vector > &txids) +{ + CAddressIndexKey key; int64_t value; int32_t i,type; uint160 hashBytes; std::string addrstr(ptr->coinaddr); + if ( ptr->txids != NULL && ptr->numtxids > 0 ) + { + CBitcoinAddress address(addrstr); + if ( address.GetIndexKey(hashBytes, type, ptr->CCflag) == 0 ) + { + fprintf(stderr,"couldnt get indexkey\n"); + return; + } + for (i = 0; i < ptr->numtxids; i ++) + { + key.type = type; + key.hashBytes = hashBytes; + key.txhash = ptr->txids[i].txid; + key.index = ptr->txids[i].vout; + key.blockHeight = ptr->txids[i].height; + value = ptr->txids[i].satoshis; + txids.push_back(std::make_pair(key, value)); + } + } +} + void NSPV_CCunspents(std::vector > &outputs,char *coinaddr,bool ccflag) { - NSPV_addressutxos(coinaddr,ccflag); + NSPV_addressutxos(coinaddr,ccflag,0); NSPV_utxos2CCunspents(&NSPV_utxosresult,outputs); } +void NSPV_CCtxids(std::vector > &txids,char *coinaddr,bool ccflag) +{ + NSPV_addresstxids(coinaddr,ccflag,0); + NSPV_txids2CCtxids(&NSPV_txidsresult,txids); +} + #endif // KOMODO_NSPVWALLET_H diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 5d6f2722b..da293c242 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1772,6 +1772,8 @@ void komodo_args(char *argv0) { int32_t ecode = ccEnablesHeight[i]; int32_t ht = ccEnablesHeight[i+1]; + if ( i > 1 && ccEnablesHeight[i-2] == ecode ) + break; if ( ecode > 255 || ecode < 0 ) fprintf(stderr, "ac_ccactivateht: invalid evalcode.%i must be between 0 and 256.\n", ecode); else if ( ht > 0 ) @@ -1908,13 +1910,15 @@ void komodo_args(char *argv0) } if ( ASSETCHAINS_CC != 0 ) { + uint8_t prevCCi = 0; ASSETCHAINS_CCLIB = GetArg("-ac_cclib",""); Split(GetArg("-ac_ccenable",""), sizeof(ccenables)/sizeof(*ccenables), ccenables, 0); for (i=nonz=0; i<0x100; i++) { - if ( ccenables[i] != 0 ) + if ( ccenables[i] != prevCCi && ccenables[i] != 0 ) { nonz++; + prevCCi = ccenables[i]; fprintf(stderr,"%d ",(uint8_t)(ccenables[i] & 0xff)); } } @@ -1926,11 +1930,12 @@ void komodo_args(char *argv0) ASSETCHAINS_CCDISABLES[i] = 1; SETBIT(disablebits,i); } - for (i=0; i<256; i++) + for (i=0; i 0 ) { @@ -2144,6 +2149,7 @@ void komodo_args(char *argv0) extraptr[extralen++] = 'c'; if ( ASSETCHAINS_MARMARA != 0 ) extraptr[extralen++] = ASSETCHAINS_MARMARA; +fprintf(stderr,"extralen.%d before disable bits\n",extralen); if ( nonz > 0 ) { memcpy(&extraptr[extralen],disablebits,sizeof(disablebits)); diff --git a/src/net.h b/src/net.h index 0b8dcd901..2fa4e31b1 100644 --- a/src/net.h +++ b/src/net.h @@ -276,7 +276,7 @@ public: int64_t nLastRecv; int64_t nTimeConnected; int64_t nTimeOffset; - uint32_t prevtimes[8]; + uint32_t prevtimes[16]; CAddress addr; std::string addrName; CService addrLocal; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 9c55c807b..deb198aa6 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -390,11 +390,14 @@ UniValue getdifficulty(const UniValue& params, bool fHelp) return GetNetworkDifficulty(); } +bool NSPV_spentinmempool(uint256 &spenttxid,int32_t &spentvini,uint256 txid,int32_t vout); +bool NSPV_inmempool(uint256 txid); + bool myIsutxo_spentinmempool(uint256 &spenttxid,int32_t &spentvini,uint256 txid,int32_t vout) { - //char *uint256_str(char *str,uint256); char str[65]; - //LOCK(mempool.cs); int32_t vini = 0; + if ( KOMODO_NSPV != 0 ) + return(NSPV_spentinmempool(spenttxid,spentvini,txid,vout)); BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) { const CTransaction &tx = e.GetTx(); @@ -417,6 +420,10 @@ bool myIsutxo_spentinmempool(uint256 &spenttxid,int32_t &spentvini,uint256 txid, bool mytxid_inmempool(uint256 txid) { + if ( KOMODO_NSPV != 0 ) + { + + } BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) { const CTransaction &tx = e.GetTx(); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index b00f8c6c5..209126a5a 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -727,27 +727,31 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp) UniValue createrawtransaction(const UniValue& params, bool fHelp) { + string examplescriptPubKey = "21021ce1eac70455c3e6c52d67c133549b8aed4a588fba594372e8048e65c4f0fcb6ac"; + if (fHelp || params.size() < 2 || params.size() > 4) throw runtime_error( "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,...} ( locktime ) ( expiryheight )\n" - "\nCreate a transaction spending the given inputs and sending to the given addresses.\n" + "\nCreate a transaction spending the given inputs and creating new outputs.\n" + "Outputs can be addresses or standart scripts (in hex) or data.\n" "Returns hex-encoded raw transaction.\n" "Note that the transaction's inputs are not signed, and\n" "it is not stored in the wallet or transmitted to the network.\n" "\nArguments:\n" - "1. \"transactions\" (string, required) A json array of json objects\n" + "1. \"inputs\" (array, required) A json array of json objects\n" " [\n" " {\n" " \"txid\":\"id\", (string, required) The transaction id\n" - " \"vout\":n (numeric, required) The output number\n" - " \"sequence\":n (numeric, optional) The sequence number\n" - " }\n" + " \"vout\":n, (numeric, required) The output number\n" + " \"sequence\":n (numeric, optional) The sequence number\n" + " } \n" " ,...\n" " ]\n" - "2. \"addresses\" (string, required) a json object with addresses as keys and amounts as values\n" + "2. \"outputs\" (object, required) a json object with outputs\n" " {\n" - " \"address\": x.xxx (numeric, required) The key is the Komodo address, the value is the " + CURRENCY_UNIT + " amount\n" + " \"address\": x.xxx, (numeric or string, required) The key is the komodo address or script (in hex), the numeric value (can be string) is the " + CURRENCY_UNIT + " amount\n" + " \"data\": \"hex\" (string, required) The key is \"data\", the value is hex encoded data\n" " ,...\n" " }\n" "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n" @@ -757,7 +761,11 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) "\nExamples\n" + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"address\\\":0.01}\"") - + HelpExampleRpc("createrawtransaction", "[{\"txid\":\"myid\",\"vout\":0}], {\"address\":0.01}") + + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\""+examplescriptPubKey+"\\\":0.01}\"") + + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"{\\\"data\\\":\\\"00010203\\\"}\"") + + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"") + + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\""+examplescriptPubKey+"\\\":0.01}\"") + + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"data\\\":\\\"00010203\\\"}\"") ); LOCK(cs_main); @@ -817,22 +825,61 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) } std::set destinations; + //std::set destinations; + vector addrList = sendTo.getKeys(); - for (const std::string& name_ : addrList) { - CTxDestination destination = DecodeDestination(name_); - if (!IsValidDestination(destination)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Komodo address: ") + name_); + + if (addrList.size() != sendTo.size()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid outputs")); // for checking edge case, should never happened ... + } + + //for (const std::string& name_ : addrList) { + for (size_t idx = 0; idx < sendTo.size(); idx++) { + + const std::string& name_ = addrList[idx]; + + CScript scriptPubKey; + CTxDestination destination; + + if (name_ == "data") { + std::vector data = ParseHexV(sendTo[name_].getValStr(),"Data"); + CTxOut out(0, CScript() << OP_RETURN << data); + rawTx.vout.push_back(out); + } else { + destination = DecodeDestination(name_); + if (IsValidDestination(destination)) { + scriptPubKey = GetScriptForDestination(destination); + } else if (IsHex(name_)) { + std::vector data(ParseHex(name_)); + scriptPubKey = CScript(data.begin(), data.end()); + // destination is not valid, but we should convert it to valid anyway, to be able to check duplicates, + // so we need to get destination from existing scriptPubKey via ExtractDestination + if (!(ExtractDestination(scriptPubKey, destination) && + (scriptPubKey.IsPayToPublicKeyHash() || scriptPubKey.IsPayToPublicKey() || scriptPubKey.IsPayToScriptHash()) + )) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid script: ") + name_ + std::string(" (only P2PKH, P2PK and P2SH scripts are allowed)")); + } + } + else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Komodo address or script: ") + name_); + } + + if (!(fExperimentalMode && IS_KOMODO_NOTARY)) { + // support of sending duplicates in createrawtransaction requires experimental features enabled and + // notary flag, to prevent common users to get messed up with duplicates + + //if (!destinations.insert(EncodeDestination(destination)).second) { + if (!destinations.insert(destination).second) { + throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated destination: ") + name_); + } + } + + // CAmount nAmount = AmountFromValue(sendTo[name_]); // operator[](const std::string& key) const; + CAmount nAmount = AmountFromValue(sendTo[idx]); // operator[](size_t index) const; + + CTxOut out(nAmount, scriptPubKey); + rawTx.vout.push_back(out); } - - if (!destinations.insert(destination).second) { - throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_); - } - - CScript scriptPubKey = GetScriptForDestination(destination); - CAmount nAmount = AmountFromValue(sendTo[name_]); - - CTxOut out(nAmount, scriptPubKey); - rawTx.vout.push_back(out); } return EncodeHexTx(rawTx); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 1c8a65fe5..ebc1293e2 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -420,6 +420,8 @@ static const CRPCCommand vRPCCommands[] = { "nSPV", "nspv_getinfo", &nspv_getinfo, true }, { "nSPV", "nspv_login", &nspv_login, true }, { "nSPV", "nspv_listunspent", &nspv_listunspent, true }, + { "nSPV", "nspv_mempool", &nspv_mempool, true }, + { "nSPV", "nspv_listtransactions",&nspv_listtransactions, true }, { "nSPV", "nspv_spentinfo", &nspv_spentinfo, true }, { "nSPV", "nspv_notarizations", &nspv_notarizations, true }, { "nSPV", "nspv_hdrsproof", &nspv_hdrsproof, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 0e8c9db11..0865307c9 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -467,6 +467,8 @@ extern UniValue importgatewayprocessed(const UniValue& params, bool fHelp); extern UniValue nspv_getinfo(const UniValue& params, bool fHelp); extern UniValue nspv_login(const UniValue& params, bool fHelp); +extern UniValue nspv_listtransactions(const UniValue& params, bool fHelp); +extern UniValue nspv_mempool(const UniValue& params, bool fHelp); extern UniValue nspv_listunspent(const UniValue& params, bool fHelp); extern UniValue nspv_spentinfo(const UniValue& params, bool fHelp); extern UniValue nspv_notarizations(const UniValue& params, bool fHelp); diff --git a/src/script/script.cpp b/src/script/script.cpp index c821cd3bc..475acdfd5 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -385,9 +385,7 @@ bool CScript::IsPayToCryptoCondition(CScript *pCCSubScript, std::vector> vParams; - if ( pCCSubScript != 0 ) - return IsPayToCryptoCondition(pCCSubScript, vParams); - else return(false); + return IsPayToCryptoCondition(pCCSubScript, vParams); } bool CScript::IsPayToCryptoCondition() const diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 82e44190c..395612a3d 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -975,7 +975,9 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp) UniValue NSPV_getinfo_req(int32_t reqht); UniValue NSPV_login(char *wifstr); UniValue NSPV_logout(); -UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag); +UniValue NSPV_addresstxids(char *coinaddr,int32_t CCflag,int32_t skipcount); +UniValue NSPV_addressutxos(char *coinaddr,int32_t CCflag,int32_t skipcount); +UniValue NSPV_mempooltxids(char *coinaddr,int32_t CCflag,uint8_t funcid,uint256 txid,int32_t vout); UniValue NSPV_broadcast(char *hex); UniValue NSPV_spend(char *srcaddr,char *destaddr,int64_t satoshis); UniValue NSPV_spentinfo(uint256 txid,int32_t vout); @@ -1011,22 +1013,66 @@ UniValue nspv_login(const UniValue& params, bool fHelp) UniValue nspv_listunspent(const UniValue& params, bool fHelp) { - int32_t CCflag = 0; - if ( fHelp || params.size() > 2 ) - throw runtime_error("nspv_listunspent address [isCC]\n"); + int32_t skipcount = 0,CCflag = 0; + if ( fHelp || params.size() > 3 ) + throw runtime_error("nspv_listunspent [address [isCC [skipcount]]]\n"); if ( params.size() == 0 ) { if ( NSPV_address.size() != 0 ) - return(NSPV_addressutxos((char *)NSPV_address.c_str(),0)); - else throw runtime_error("nspv_listunspent address [isCC]\n"); + return(NSPV_addressutxos((char *)NSPV_address.c_str(),0,0)); + else throw runtime_error("nspv_listunspent [address [isCC [skipcount]]]\n"); } if ( params.size() >= 1 ) { - if ( params.size() == 2 ) + if ( params.size() >= 2 ) CCflag = atoi((char *)params[1].get_str().c_str()); - return(NSPV_addressutxos((char *)params[0].get_str().c_str(),CCflag)); + if ( params.size() == 3 ) + skipcount = atoi((char *)params[2].get_str().c_str()); + return(NSPV_addressutxos((char *)params[0].get_str().c_str(),CCflag,skipcount)); } - else throw runtime_error("nspv_listunspent address [isCC]\n"); + else throw runtime_error("nspv_listunspent [address [isCC [skipcount]]]\n"); +} + +UniValue nspv_mempool(const UniValue& params, bool fHelp) +{ + int32_t vout = 0,CCflag = 0; uint256 txid; uint8_t funcid; char *coinaddr; + memset(&txid,0,sizeof(txid)); + if ( fHelp || params.size() > 5 ) + throw runtime_error("nspv_mempool func(0 all, 1 address recv, 2 txid/vout spent, 3 txid inmempool) address isCC [txid vout]]]\n"); + funcid = atoi((char *)params[0].get_str().c_str()); + coinaddr = (char *)params[1].get_str().c_str(); + CCflag = atoi((char *)params[2].get_str().c_str()); + if ( params.size() > 3 ) + { + if ( params.size() != 5 ) + throw runtime_error("nspv_mempool func(0 all, 1 address recv, 2 txid/vout spent, 3 txid inmempool) address isCC [txid vout]]]\n"); + txid = Parseuint256((char *)params[3].get_str().c_str()); + vout = atoi((char *)params[4].get_str().c_str()); + } + return(NSPV_mempooltxids(coinaddr,CCflag,funcid,txid,vout)); +} + +UniValue nspv_listtransactions(const UniValue& params, bool fHelp) +{ + int32_t skipcount = 0,CCflag = 0; + if ( fHelp || params.size() > 3 ) + throw runtime_error("nspv_listtransactions [address [isCC [skipcount]]]\n"); + if ( params.size() == 0 ) + { + if ( NSPV_address.size() != 0 ) + return(NSPV_addresstxids((char *)NSPV_address.c_str(),0,0)); + else throw runtime_error("nspv_listtransactions [address [isCC [skipcount]]]\n"); + } + if ( params.size() >= 1 ) + { + if ( params.size() >= 2 ) + CCflag = atoi((char *)params[1].get_str().c_str()); + if ( params.size() == 3 ) + skipcount = atoi((char *)params[2].get_str().c_str()); + //fprintf(stderr,"call txids cc.%d skip.%d\n",CCflag,skipcount); + return(NSPV_addresstxids((char *)params[0].get_str().c_str(),CCflag,skipcount)); + } + else throw runtime_error("nspv_listtransactions [address [isCC [skipcount]]]\n"); } UniValue nspv_spentinfo(const UniValue& params, bool fHelp) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 426baa1f7..365399a7d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5399,6 +5399,7 @@ UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector %s\n",cp->unspendableCCaddr,destaddr); strcpy(cp->unspendableCCaddr,destaddr); + memset(priv,0,32); } result.push_back(Pair("result", "success")); sprintf(str,"%sCCAddress",name);