Duke
4 months ago
2 changed files with 0 additions and 858 deletions
@ -1,856 +0,0 @@ |
|||||
// Copyright (c) 2016-2023 The Hush developers
|
|
||||
// Distributed under the GPLv3 software license, see the accompanying
|
|
||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
||||
/******************************************************************************
|
|
||||
* Copyright © 2014-2019 The SuperNET Developers. * |
|
||||
* * |
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * |
|
||||
* the top-level directory of this distribution for the individual copyright * |
|
||||
* holder information and the developer policies on copyright and licensing. * |
|
||||
* * |
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the * |
|
||||
* SuperNET software, including this file may be copied, modified, propagated * |
|
||||
* or distributed except according to the terms contained in the LICENSE file * |
|
||||
* * |
|
||||
* Removal or modification of this copyright notice is prohibited. * |
|
||||
* * |
|
||||
******************************************************************************/ |
|
||||
|
|
||||
#include "CCinclude.h" |
|
||||
#include "key_io.h" |
|
||||
|
|
||||
std::vector<CPubKey> NULL_pubkeys; |
|
||||
struct NSPV_CCmtxinfo NSPV_U; |
|
||||
|
|
||||
/* see description to function definition in CCinclude.h */ |
|
||||
bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey) |
|
||||
{ |
|
||||
#ifdef ENABLE_WALLET |
|
||||
CTransaction txNewConst(mtx); SignatureData sigdata; const CKeyStore& keystore = *pwalletMain; |
|
||||
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); |
|
||||
if ( ProduceSignature(TransactionSignatureCreator(&keystore,&txNewConst,vini,utxovalue,SIGHASH_ALL),scriptPubKey,sigdata,consensusBranchId) != 0 ) |
|
||||
{ |
|
||||
UpdateTransaction(mtx,vini,sigdata); |
|
||||
return(true); |
|
||||
} else fprintf(stderr,"signing error for SignTx vini.%d %.8f\n",vini,(double)utxovalue/COIN); |
|
||||
#endif |
|
||||
return(false); |
|
||||
} |
|
||||
|
|
||||
/*
|
|
||||
FinalizeCCTx is a very useful function that will properly sign both CC and normal inputs, adds normal change and the opreturn. |
|
||||
|
|
||||
This allows the contract transaction functions to create the appropriate vins and vouts and have FinalizeCCTx create a properly signed transaction. |
|
||||
|
|
||||
By using -addressindex=1, it allows tracking of all the CC addresses |
|
||||
*/ |
|
||||
std::string FinalizeCCTx(uint64_t CCmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector<CPubKey> pubkeys) |
|
||||
{ |
|
||||
UniValue sigData = FinalizeCCTxExt(false, CCmask, cp, mtx, mypk, txfee, opret, pubkeys); |
|
||||
return sigData[JSON_HEXTX].getValStr(); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// extended version that supports signInfo object with conds to vins map for remote cc calls
|
|
||||
UniValue FinalizeCCTxExt(bool remote, uint64_t CCmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector<CPubKey> pubkeys) |
|
||||
{ |
|
||||
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); |
|
||||
CTransaction vintx; std::string hex; CPubKey globalpk; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0; |
|
||||
int64_t utxovalues[CC_MAXVINS],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0; |
|
||||
int32_t i,flag,mgret,utxovout,n,err = 0; |
|
||||
char myaddr[64], destaddr[64], unspendable[64], mytokensaddr[64], mysingletokensaddr[64], unspendabletokensaddr[64],CC1of2CCaddr[64]; |
|
||||
uint8_t *privkey = NULL, myprivkey[32] = { '\0' }, unspendablepriv[32] = { '\0' }, /*tokensunspendablepriv[32],*/ *msg32 = 0; |
|
||||
CC *mycond=0, *othercond=0, *othercond2=0,*othercond4=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond=0, *condCC2=0,*mytokenscond = NULL, *mysingletokenscond = NULL, *othertokenscond = NULL; |
|
||||
CPubKey unspendablepk /*, tokensunspendablepk*/; |
|
||||
struct CCcontract_info *cpTokens, tokensC; |
|
||||
UniValue sigData(UniValue::VARR),result(UniValue::VOBJ); |
|
||||
const UniValue sigDataNull = NullUniValue; |
|
||||
|
|
||||
globalpk = GetUnspendable(cp,0); |
|
||||
n = mtx.vout.size(); |
|
||||
for (i=0; i<n; i++) |
|
||||
{ |
|
||||
if ( mtx.vout[i].scriptPubKey.IsPayToCryptoCondition() == 0 ) |
|
||||
normaloutputs += mtx.vout[i].nValue; |
|
||||
totaloutputs += mtx.vout[i].nValue; |
|
||||
} |
|
||||
if ( (n= mtx.vin.size()) > CC_MAXVINS ) |
|
||||
{ |
|
||||
fprintf(stderr,"FinalizeCCTx: %d is too many vins\n",n); |
|
||||
result.push_back(Pair(JSON_HEXTX, "0")); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
//Myprivkey(myprivkey); // for NSPV mode we need to add myprivkey for the explicitly defined mypk param
|
|
||||
#ifdef ENABLE_WALLET |
|
||||
// get privkey for mypk
|
|
||||
CKeyID keyID = mypk.GetID(); |
|
||||
CKey vchSecret; |
|
||||
if (pwalletMain->GetKey(keyID, vchSecret)) |
|
||||
memcpy(myprivkey, vchSecret.begin(), sizeof(myprivkey)); |
|
||||
#endif |
|
||||
|
|
||||
GetCCaddress(cp,myaddr,mypk); |
|
||||
mycond = MakeCCcond1(cp->evalcode,mypk); |
|
||||
|
|
||||
// to spend from single-eval evalcode 'unspendable' cc addr
|
|
||||
unspendablepk = GetUnspendable(cp, unspendablepriv); |
|
||||
GetCCaddress(cp, unspendable, unspendablepk); |
|
||||
othercond = MakeCCcond1(cp->evalcode, unspendablepk); |
|
||||
GetCCaddress1of2(cp,CC1of2CCaddr,unspendablepk,unspendablepk); |
|
||||
|
|
||||
//fprintf(stderr,"evalcode.%d (%s)\n",cp->evalcode,unspendable);
|
|
||||
|
|
||||
// tokens support:
|
|
||||
// to spend from dual/three-eval mypk vout
|
|
||||
GetTokensCCaddress(cp, mytokensaddr, mypk); |
|
||||
// NOTE: if additionalEvalcode2 is not set it is a dual-eval (not three-eval) cc cond:
|
|
||||
mytokenscond = MakeTokensCCcond1(cp->evalcode, cp->additionalTokensEvalcode2, mypk); |
|
||||
|
|
||||
// to spend from single-eval EVAL_TOKENS mypk
|
|
||||
cpTokens = CCinit(&tokensC, EVAL_TOKENS); |
|
||||
GetCCaddress(cpTokens, mysingletokensaddr, mypk); |
|
||||
mysingletokenscond = MakeCCcond1(EVAL_TOKENS, mypk); |
|
||||
|
|
||||
// to spend from dual/three-eval EVAL_TOKEN+evalcode 'unspendable' pk:
|
|
||||
GetTokensCCaddress(cp, unspendabletokensaddr, unspendablepk); // it may be a three-eval cc, if cp->additionalEvalcode2 is set
|
|
||||
othertokenscond = MakeTokensCCcond1(cp->evalcode, cp->additionalTokensEvalcode2, unspendablepk); |
|
||||
|
|
||||
//Reorder vins so that for multiple normal vins all other except vin0 goes to the end
|
|
||||
//This is a must to avoid hardfork change of validation in every CC, because there could be maximum one normal vin at the begining with current validation.
|
|
||||
for (i=0; i<n; i++) |
|
||||
{ |
|
||||
if (i==0 && mtx.vin[i].prevout.n==10e8) |
|
||||
continue; |
|
||||
if ( myGetTransaction(mtx.vin[i].prevout.hash,vintx,hashBlock) != 0 && mtx.vin[i].prevout.n < vintx.vout.size() ) |
|
||||
{ |
|
||||
if ( vintx.vout[mtx.vin[i].prevout.n].scriptPubKey.IsPayToCryptoCondition() == 0 && ccvins==0) |
|
||||
normalvins++; |
|
||||
else ccvins++; |
|
||||
} |
|
||||
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 UniValue(UniValue::VOBJ); |
|
||||
} |
|
||||
} |
|
||||
if (normalvins>1 && ccvins) |
|
||||
{ |
|
||||
for(i=1;i<normalvins;i++) |
|
||||
{ |
|
||||
mtx.vin.push_back(mtx.vin[1]); |
|
||||
mtx.vin.erase(mtx.vin.begin() + 1); |
|
||||
} |
|
||||
} |
|
||||
memset(utxovalues,0,sizeof(utxovalues)); |
|
||||
for (i=0; i<n; i++) |
|
||||
{ |
|
||||
if (i==0 && mtx.vin[i].prevout.n==10e8) continue; |
|
||||
if ( (mgret= myGetTransaction(mtx.vin[i].prevout.hash,vintx,hashBlock)) != 0 ) |
|
||||
{ |
|
||||
utxovout = mtx.vin[i].prevout.n; |
|
||||
utxovalues[i] = vintx.vout[utxovout].nValue; |
|
||||
totalinputs += utxovalues[i]; |
|
||||
if ( vintx.vout[utxovout].scriptPubKey.IsPayToCryptoCondition() == 0 ) |
|
||||
{ |
|
||||
//fprintf(stderr,"vin.%d is normal %.8f\n",i,(double)utxovalues[i]/COIN);
|
|
||||
normalinputs += utxovalues[i]; |
|
||||
vinimask |= (1LL << i); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
mask |= (1LL << i); |
|
||||
} |
|
||||
} else fprintf(stderr,"FinalizeCCTx couldnt find %s mgret.%d\n",mtx.vin[i].prevout.hash.ToString().c_str(),mgret); |
|
||||
} |
|
||||
nmask = (1LL << n) - 1; |
|
||||
if ( 0 && (mask & nmask) != (CCmask & nmask) ) |
|
||||
fprintf(stderr,"mask.%llx vs CCmask.%llx %llx %llx %llx\n",(long long)(mask & nmask),(long long)(CCmask & nmask),(long long)mask,(long long)CCmask,(long long)nmask); |
|
||||
if ( totalinputs >= totaloutputs+2*txfee ) |
|
||||
{ |
|
||||
change = totalinputs - (totaloutputs+txfee); |
|
||||
mtx.vout.push_back(CTxOut(change,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); |
|
||||
} |
|
||||
if ( opret.size() > 0 ) |
|
||||
mtx.vout.push_back(CTxOut(0,opret)); |
|
||||
PrecomputedTransactionData txdata(mtx); |
|
||||
n = mtx.vin.size(); |
|
||||
for (i=0; i<n; i++) |
|
||||
{ |
|
||||
if (i==0 && mtx.vin[i].prevout.n==10e8) |
|
||||
continue; |
|
||||
if ( (mgret= myGetTransaction(mtx.vin[i].prevout.hash,vintx,hashBlock)) != 0 ) |
|
||||
{ |
|
||||
utxovout = mtx.vin[i].prevout.n; |
|
||||
if ( vintx.vout[utxovout].scriptPubKey.IsPayToCryptoCondition() == 0 ) |
|
||||
{ |
|
||||
if ( HUSH_NSPV_FULLNODE ) |
|
||||
{ |
|
||||
if (!remote) |
|
||||
{ |
|
||||
if (SignTx(mtx, i, vintx.vout[utxovout].nValue, vintx.vout[utxovout].scriptPubKey) == 0) |
|
||||
fprintf(stderr, "signing error for vini.%d of %llx\n", i, (long long)vinimask); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
// if no myprivkey for mypk it means remote call from nspv superlite client
|
|
||||
// add sigData for superlite client
|
|
||||
UniValue cc(UniValue::VNULL); |
|
||||
AddSigData2UniValue(sigData, i, cc, HexStr(vintx.vout[utxovout].scriptPubKey), vintx.vout[utxovout].nValue ); // store vin i with scriptPubKey
|
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
{ |
|
||||
char addr[64]; |
|
||||
Getscriptaddress(addr,vintx.vout[utxovout].scriptPubKey); |
|
||||
fprintf(stderr,"vout[%d] %.8f -> %s\n",utxovout,dstr(vintx.vout[utxovout].nValue),addr); |
|
||||
} |
|
||||
if ( NSPV_SignTx(mtx,i,vintx.vout[utxovout].nValue,vintx.vout[utxovout].scriptPubKey,0) == 0 ) |
|
||||
fprintf(stderr,"NSPV signing error for vini.%d of %llx\n",i,(long long)vinimask); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
Getscriptaddress(destaddr,vintx.vout[utxovout].scriptPubKey); |
|
||||
//fprintf(stderr,"FinalizeCCTx() vin.%d is CC %.8f -> (%s) vs %s\n",i,(double)utxovalues[i]/COIN,destaddr,mysingletokensaddr);
|
|
||||
//std::cerr << "FinalizeCCtx() searching destaddr=" << destaddr << " for vin[" << i << "] satoshis=" << utxovalues[i] << std::endl;
|
|
||||
if( strcmp(destaddr, myaddr) == 0 ) |
|
||||
{ |
|
||||
//fprintf(stderr, "FinalizeCCTx() matched cc myaddr (%s)\n", myaddr);
|
|
||||
privkey = myprivkey; |
|
||||
cond = mycond; |
|
||||
} |
|
||||
else if (strcmp(destaddr, mytokensaddr) == 0) // if this is TokensCC1vout
|
|
||||
{ |
|
||||
privkey = myprivkey; |
|
||||
cond = mytokenscond; |
|
||||
//fprintf(stderr,"FinalizeCCTx() matched dual-eval TokensCC1vout my token addr.(%s)\n",mytokensaddr);
|
|
||||
} |
|
||||
else if (strcmp(destaddr, mysingletokensaddr) == 0) // if this is TokensCC1vout
|
|
||||
{ |
|
||||
privkey = myprivkey; |
|
||||
cond = mysingletokenscond; |
|
||||
//fprintf(stderr, "FinalizeCCTx() matched single-eval token CC1vout my token addr.(%s)\n", mytokensaddr);
|
|
||||
} |
|
||||
else if ( strcmp(destaddr,unspendable) == 0 ) |
|
||||
{ |
|
||||
privkey = unspendablepriv; |
|
||||
cond = othercond; |
|
||||
//fprintf(stderr,"FinalizeCCTx evalcode(%d) matched unspendable CC addr.(%s)\n",cp->evalcode,unspendable);
|
|
||||
} |
|
||||
else if (strcmp(destaddr, unspendabletokensaddr) == 0) |
|
||||
{ |
|
||||
privkey = unspendablepriv; |
|
||||
cond = othertokenscond; |
|
||||
//fprintf(stderr,"FinalizeCCTx() matched unspendabletokensaddr dual/three-eval CC addr.(%s)\n",unspendabletokensaddr);
|
|
||||
} |
|
||||
// check if this is the 2nd additional evalcode + 'unspendable' cc addr:
|
|
||||
else if ( strcmp(destaddr, cp->unspendableaddr2) == 0) |
|
||||
{ |
|
||||
//fprintf(stderr,"FinalizeCCTx() matched %s unspendable2!\n",cp->unspendableaddr2);
|
|
||||
privkey = cp->unspendablepriv2; |
|
||||
if( othercond2 == 0 ) |
|
||||
othercond2 = MakeCCcond1(cp->unspendableEvalcode2, cp->unspendablepk2); |
|
||||
cond = othercond2; |
|
||||
} |
|
||||
// check if this is 3rd additional evalcode + 'unspendable' cc addr:
|
|
||||
else if ( strcmp(destaddr,cp->unspendableaddr3) == 0 ) |
|
||||
{ |
|
||||
//fprintf(stderr,"FinalizeCCTx() matched %s unspendable3!\n",cp->unspendableaddr3);
|
|
||||
privkey = cp->unspendablepriv3; |
|
||||
if( othercond3 == 0 ) |
|
||||
othercond3 = MakeCCcond1(cp->unspendableEvalcode3, cp->unspendablepk3); |
|
||||
cond = othercond3; |
|
||||
} |
|
||||
// check if this is spending from 1of2 cc coins addr:
|
|
||||
else if (strcmp(cp->coins1of2addr, destaddr) == 0) |
|
||||
{ |
|
||||
//fprintf(stderr,"FinalizeCCTx() matched %s unspendable1of2!\n",cp->coins1of2addr);
|
|
||||
privkey = cp->coins1of2priv;//myprivkey;
|
|
||||
if (othercond1of2 == 0) |
|
||||
othercond1of2 = MakeCCcond1of2(cp->evalcode, cp->coins1of2pk[0], cp->coins1of2pk[1]); |
|
||||
cond = othercond1of2; |
|
||||
} |
|
||||
else if ( strcmp(CC1of2CCaddr,destaddr) == 0 ) |
|
||||
{ |
|
||||
//fprintf(stderr,"FinalizeCCTx() matched %s CC1of2CCaddr!\n",CC1of2CCaddr);
|
|
||||
privkey = unspendablepriv; |
|
||||
if (condCC2 == 0) |
|
||||
condCC2 = MakeCCcond1of2(cp->evalcode,unspendablepk,unspendablepk); |
|
||||
cond = condCC2; |
|
||||
} |
|
||||
// check if this is spending from 1of2 cc tokens addr:
|
|
||||
else if (strcmp(cp->tokens1of2addr, destaddr) == 0) |
|
||||
{ |
|
||||
//fprintf(stderr,"FinalizeCCTx() matched %s cp->tokens1of2addr!\n", cp->tokens1of2addr);
|
|
||||
privkey = cp->tokens1of2priv;//myprivkey;
|
|
||||
if (othercond1of2tokens == 0) |
|
||||
// NOTE: if additionalEvalcode2 is not set then it is dual-eval cc else three-eval cc
|
|
||||
// TODO: verify evalcodes order if additionalEvalcode2 is not 0
|
|
||||
othercond1of2tokens = MakeTokensCCcond1of2(cp->evalcode, cp->additionalTokensEvalcode2, cp->tokens1of2pk[0], cp->tokens1of2pk[1]); |
|
||||
cond = othercond1of2tokens; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
flag = 0; |
|
||||
if ( pubkeys != NULL_pubkeys ) |
|
||||
{ |
|
||||
char coinaddr[64]; |
|
||||
GetCCaddress1of2(cp,coinaddr,globalpk,pubkeys[i]); |
|
||||
//fprintf(stderr,"%s + %s -> %s vs %s\n",HexStr(globalpk).c_str(),HexStr(pubkeys[i]).c_str(),coinaddr,destaddr);
|
|
||||
if ( strcmp(destaddr,coinaddr) == 0 ) |
|
||||
{ |
|
||||
privkey = cp->CCpriv; |
|
||||
if ( othercond4 != 0 ) |
|
||||
cc_free(othercond4); |
|
||||
othercond4 = MakeCCcond1of2(cp->evalcode,globalpk,pubkeys[i]); |
|
||||
cond = othercond4; |
|
||||
flag = 1; |
|
||||
} |
|
||||
} //else privkey = myprivkey;
|
|
||||
|
|
||||
if ( flag == 0 ) |
|
||||
{ |
|
||||
fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr); |
|
||||
memset(myprivkey,0,32); |
|
||||
return sigDataNull; |
|
||||
} |
|
||||
} |
|
||||
uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL,utxovalues[i],consensusBranchId, &txdata); |
|
||||
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 (!remote) // we have privkey in the wallet
|
|
||||
{ |
|
||||
if (cc_signTreeSecp256k1Msg32(cond, privkey, sighash.begin()) != 0) |
|
||||
{ |
|
||||
mtx.vin[i].scriptSig = CCSig(cond); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
fprintf(stderr, "vini.%d has CC signing error address.(%s) %s\n", i, destaddr, EncodeHexTx(mtx).c_str()); |
|
||||
memset(myprivkey, 0, sizeof(myprivkey)); |
|
||||
return sigDataNull; |
|
||||
} |
|
||||
} |
|
||||
else // no privkey locally - remote call
|
|
||||
{ |
|
||||
// serialize cc:
|
|
||||
UniValue ccjson; |
|
||||
ccjson.read(cc_conditionToJSONString(cond)); |
|
||||
if (ccjson.empty()) |
|
||||
{ |
|
||||
fprintf(stderr, "vini.%d can't serialize CC.(%s) %s\n", i, destaddr, EncodeHexTx(mtx).c_str()); |
|
||||
memset(myprivkey, 0, sizeof(myprivkey)); |
|
||||
return sigDataNull; |
|
||||
} |
|
||||
|
|
||||
AddSigData2UniValue(sigData, i, ccjson, std::string(), vintx.vout[utxovout].nValue); // store vin i with scriptPubKey
|
|
||||
} |
|
||||
} |
|
||||
} else fprintf(stderr,"FinalizeCCTx2 couldnt find %s mgret.%d\n",mtx.vin[i].prevout.hash.ToString().c_str(),mgret); |
|
||||
} |
|
||||
if ( mycond != 0 ) |
|
||||
cc_free(mycond); |
|
||||
if ( condCC2 != 0 ) |
|
||||
cc_free(condCC2); |
|
||||
if ( othercond != 0 ) |
|
||||
cc_free(othercond); |
|
||||
if ( othercond2 != 0 ) |
|
||||
cc_free(othercond2); |
|
||||
if ( othercond3 != 0 ) |
|
||||
cc_free(othercond3); |
|
||||
if ( othercond4 != 0 ) |
|
||||
cc_free(othercond4); |
|
||||
if ( othercond1of2 != 0 ) |
|
||||
cc_free(othercond1of2); |
|
||||
if ( othercond1of2tokens != 0 ) |
|
||||
cc_free(othercond1of2tokens); |
|
||||
if ( mytokenscond != 0 ) |
|
||||
cc_free(mytokenscond); |
|
||||
if ( mysingletokenscond != 0 ) |
|
||||
cc_free(mysingletokenscond); |
|
||||
if ( othertokenscond != 0 ) |
|
||||
cc_free(othertokenscond); |
|
||||
memset(myprivkey,0,sizeof(myprivkey)); |
|
||||
std::string strHex = EncodeHexTx(mtx); |
|
||||
if ( strHex.size() > 0 ) |
|
||||
result.push_back(Pair(JSON_HEXTX, strHex)); |
|
||||
else { |
|
||||
result.push_back(Pair(JSON_HEXTX, "0")); |
|
||||
} |
|
||||
if (sigData.size() > 0) result.push_back(Pair(JSON_SIGDATA,sigData)); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
void NSPV_CCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr,bool ccflag); |
|
||||
void NSPV_CCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &txids,char *coinaddr,bool ccflag); |
|
||||
void NSPV_CCtxids(std::vector<uint256> &txids,char *coinaddr,bool ccflag, uint8_t evalcode,uint256 filtertxid, uint8_t func); |
|
||||
|
|
||||
void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr,bool ccflag) |
|
||||
{ |
|
||||
int32_t type=0,i,n; char *ptr; std::string addrstr; uint160 hashBytes; std::vector<std::pair<uint160, int> > addresses; |
|
||||
if ( HUSH_NSPV_SUPERLITE ) |
|
||||
{ |
|
||||
NSPV_CCunspents(unspentOutputs,coinaddr,ccflag); |
|
||||
return; |
|
||||
} |
|
||||
n = (int32_t)strlen(coinaddr); |
|
||||
addrstr.resize(n+1); |
|
||||
ptr = (char *)addrstr.data(); |
|
||||
for (i=0; i<=n; i++) |
|
||||
ptr[i] = coinaddr[i]; |
|
||||
CBitcoinAddress address(addrstr); |
|
||||
if ( address.GetIndexKey(hashBytes, type, ccflag) == 0 ) |
|
||||
return; |
|
||||
addresses.push_back(std::make_pair(hashBytes,type)); |
|
||||
for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) |
|
||||
{ |
|
||||
if ( GetAddressUnspent((*it).first, (*it).second, unspentOutputs) == 0 ) |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr,bool ccflag) |
|
||||
{ |
|
||||
int32_t type=0,i,n; char *ptr; std::string addrstr; uint160 hashBytes; std::vector<std::pair<uint160, int> > addresses; |
|
||||
if ( HUSH_NSPV_SUPERLITE ) |
|
||||
{ |
|
||||
NSPV_CCtxids(addressIndex,coinaddr,ccflag); |
|
||||
return; |
|
||||
} |
|
||||
n = (int32_t)strlen(coinaddr); |
|
||||
addrstr.resize(n+1); |
|
||||
ptr = (char *)addrstr.data(); |
|
||||
for (i=0; i<=n; i++) |
|
||||
ptr[i] = coinaddr[i]; |
|
||||
CBitcoinAddress address(addrstr); |
|
||||
if ( address.GetIndexKey(hashBytes, type, ccflag) == 0 ) |
|
||||
return; |
|
||||
addresses.push_back(std::make_pair(hashBytes,type)); |
|
||||
for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) |
|
||||
{ |
|
||||
if ( GetAddressIndex((*it).first, (*it).second, addressIndex) == 0 ) |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void SetCCtxids(std::vector<uint256> &txids,char *coinaddr,bool ccflag, uint8_t evalcode, uint256 filtertxid, uint8_t func) |
|
||||
{ |
|
||||
int32_t type=0,i,n; char *ptr; std::string addrstr; uint160 hashBytes; std::vector<std::pair<uint160, int> > addresses; |
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; |
|
||||
if ( HUSH_NSPV_SUPERLITE ) |
|
||||
{ |
|
||||
NSPV_CCtxids(txids,coinaddr,ccflag,evalcode,filtertxid,func); |
|
||||
return; |
|
||||
} |
|
||||
n = (int32_t)strlen(coinaddr); |
|
||||
addrstr.resize(n+1); |
|
||||
ptr = (char *)addrstr.data(); |
|
||||
for (i=0; i<=n; i++) |
|
||||
ptr[i] = coinaddr[i]; |
|
||||
CBitcoinAddress address(addrstr); |
|
||||
if ( address.GetIndexKey(hashBytes, type, ccflag) == 0 ) |
|
||||
return; |
|
||||
addresses.push_back(std::make_pair(hashBytes,type)); |
|
||||
for (std::vector<std::pair<uint160, int> >::iterator it = addresses.begin(); it != addresses.end(); it++) |
|
||||
{ |
|
||||
if ( GetAddressIndex((*it).first, (*it).second, addressIndex) == 0 ) |
|
||||
return; |
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it1=addressIndex.begin(); it1!=addressIndex.end(); it1++) |
|
||||
{ |
|
||||
if (it1->second>=0) txids.push_back(it1->first.txhash); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout,int32_t CCflag) |
|
||||
{ |
|
||||
uint256 txid; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; |
|
||||
SetCCunspents(unspentOutputs,coinaddr,CCflag!=0?true:false); |
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) |
|
||||
{ |
|
||||
txid = it->first.txhash; |
|
||||
if ( txid == utxotxid && utxovout == it->first.index ) |
|
||||
return(it->second.satoshis); |
|
||||
} |
|
||||
return(0); |
|
||||
} |
|
||||
|
|
||||
int64_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag,int32_t lockflag) |
|
||||
{ |
|
||||
CCoins coins; |
|
||||
//fprintf(stderr,"CCgettxoud %s/v%d\n",txid.GetHex().c_str(),vout);
|
|
||||
if ( mempoolflag != 0 ) |
|
||||
{ |
|
||||
if ( lockflag != 0 ) |
|
||||
{ |
|
||||
LOCK(mempool.cs); |
|
||||
CCoinsViewMemPool view(pcoinsTip, mempool); |
|
||||
if (!view.GetCoins(txid, coins)) |
|
||||
return(-1); |
|
||||
else if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) != 0 ) |
|
||||
return(-1); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
CCoinsViewMemPool view(pcoinsTip, mempool); |
|
||||
if (!view.GetCoins(txid, coins)) |
|
||||
return(-1); |
|
||||
else if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) != 0 ) |
|
||||
return(-1); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
if (!pcoinsTip->GetCoins(txid, coins)) |
|
||||
return(-1); |
|
||||
} |
|
||||
if ( vout < coins.vout.size() ) |
|
||||
return(coins.vout[vout].nValue); |
|
||||
else return(-1); |
|
||||
} |
|
||||
|
|
||||
int32_t CCgetspenttxid(uint256 &spenttxid,int32_t &vini,int32_t &height,uint256 txid,int32_t vout) |
|
||||
{ |
|
||||
CSpentIndexKey key(txid, vout); |
|
||||
CSpentIndexValue value; |
|
||||
if ( !GetSpentIndex(key, value) ) |
|
||||
return(-1); |
|
||||
spenttxid = value.txid; |
|
||||
vini = (int32_t)value.inputIndex; |
|
||||
height = value.blockHeight; |
|
||||
return(0); |
|
||||
} |
|
||||
|
|
||||
int64_t CCaddress_balance(char *coinaddr,int32_t CCflag) |
|
||||
{ |
|
||||
int64_t sum = 0; std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; |
|
||||
SetCCunspents(unspentOutputs,coinaddr,CCflag!=0?true:false); |
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) |
|
||||
{ |
|
||||
sum += it->second.satoshis; |
|
||||
} |
|
||||
return(sum); |
|
||||
} |
|
||||
|
|
||||
int64_t CCfullsupply(uint256 tokenid) |
|
||||
{ |
|
||||
uint256 hashBlock; int32_t numvouts; CTransaction tx; std::vector<uint8_t> origpubkey; std::string name,description; |
|
||||
if ( myGetTransaction(tokenid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 ) |
|
||||
{ |
|
||||
if (DecodeTokenCreateOpRet(tx.vout[numvouts-1].scriptPubKey,origpubkey,name,description)) |
|
||||
{ |
|
||||
return(tx.vout[1].nValue); |
|
||||
} |
|
||||
} |
|
||||
return(0); |
|
||||
} |
|
||||
|
|
||||
int64_t CCtoken_balance(char *coinaddr,uint256 reftokenid) |
|
||||
{ |
|
||||
int64_t price,sum = 0; int32_t numvouts; CTransaction tx; uint256 tokenid,txid,hashBlock; |
|
||||
std::vector<uint8_t> vopretExtra; |
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; |
|
||||
uint8_t evalCode; |
|
||||
|
|
||||
SetCCunspents(unspentOutputs,coinaddr,true); |
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) |
|
||||
{ |
|
||||
txid = it->first.txhash; |
|
||||
if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size()) > 0 ) |
|
||||
{ |
|
||||
char str[65]; |
|
||||
std::vector<CPubKey> voutTokenPubkeys; |
|
||||
std::vector<std::pair<uint8_t, vscript_t>> oprets; |
|
||||
if ( reftokenid==txid || (DecodeTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCode, tokenid, voutTokenPubkeys, oprets) != 0 && reftokenid == tokenid)) |
|
||||
{ |
|
||||
sum += it->second.satoshis; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
return(sum); |
|
||||
} |
|
||||
|
|
||||
int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *belowp,struct CC_utxo utxos[],int32_t numunspents,int64_t value) |
|
||||
{ |
|
||||
int32_t i,abovei,belowi; int64_t above,below,gap,atx_value; |
|
||||
abovei = belowi = -1; |
|
||||
for (above=below=i=0; i<numunspents; i++) |
|
||||
{ |
|
||||
// Filter to randomly pick utxo to avoid conflicts, and having multiple CC choose the same ones.
|
|
||||
//if ( numunspents > 200 ) {
|
|
||||
// if ( (rand() % 100) < 90 )
|
|
||||
// continue;
|
|
||||
//}
|
|
||||
if ( (atx_value= utxos[i].nValue) <= 0 ) |
|
||||
continue; |
|
||||
if ( atx_value == value ) |
|
||||
{ |
|
||||
*aboveip = *belowip = i; |
|
||||
*abovep = *belowp = 0; |
|
||||
return(i); |
|
||||
} |
|
||||
else if ( atx_value > value ) |
|
||||
{ |
|
||||
gap = (atx_value - value); |
|
||||
if ( above == 0 || gap < above ) |
|
||||
{ |
|
||||
above = gap; |
|
||||
abovei = i; |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
gap = (value - atx_value); |
|
||||
if ( below == 0 || gap < below ) |
|
||||
{ |
|
||||
below = gap; |
|
||||
belowi = i; |
|
||||
} |
|
||||
} |
|
||||
//printf("value %.8f gap %.8f abovei.%d %.8f belowi.%d %.8f\n",dstr(value),dstr(gap),abovei,dstr(above),belowi,dstr(below));
|
|
||||
} |
|
||||
*aboveip = abovei; |
|
||||
*abovep = above; |
|
||||
*belowip = belowi; |
|
||||
*belowp = below; |
|
||||
//printf("above.%d below.%d\n",abovei,belowi);
|
|
||||
if ( abovei >= 0 && belowi >= 0 ) |
|
||||
{ |
|
||||
if ( above < (below >> 1) ) |
|
||||
return(abovei); |
|
||||
else return(belowi); |
|
||||
} |
|
||||
else if ( abovei >= 0 ) |
|
||||
return(abovei); |
|
||||
else return(belowi); |
|
||||
} |
|
||||
|
|
||||
int64_t AddNormalinputsLocal(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs) |
|
||||
{ |
|
||||
int32_t abovei,belowi,ind,vout,i,n = 0; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector<COutput> vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up; |
|
||||
if ( HUSH_NSPV_SUPERLITE ) |
|
||||
return(NSPV_AddNormalinputs(mtx,mypk,total,maxinputs,&NSPV_U)); |
|
||||
|
|
||||
// if (mypk != pubkey2pk(Mypubkey())) //remote superlite mypk, do not use wallet since it is not locked for non-equal pks (see rpcs with nspv support)!
|
|
||||
// return(AddNormalinputs3(mtx, mypk, total, maxinputs));
|
|
||||
|
|
||||
#ifdef ENABLE_WALLET |
|
||||
assert(pwalletMain != NULL); |
|
||||
const CKeyStore& keystore = *pwalletMain; |
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet); |
|
||||
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); |
|
||||
utxos = (struct CC_utxo *)calloc(CC_MAXVINS,sizeof(*utxos)); |
|
||||
if ( maxinputs > CC_MAXVINS ) |
|
||||
maxinputs = CC_MAXVINS; |
|
||||
if ( maxinputs > 0 ) |
|
||||
threshold = total/maxinputs; |
|
||||
else threshold = total; |
|
||||
sum = 0; |
|
||||
BOOST_FOREACH(const COutput& out, vecOutputs) |
|
||||
{ |
|
||||
if ( out.fSpendable != 0 && out.tx->vout[out.i].nValue >= threshold ) |
|
||||
{ |
|
||||
txid = out.tx->GetHash(); |
|
||||
vout = out.i; |
|
||||
if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0 ) |
|
||||
{ |
|
||||
//fprintf(stderr,"check %.8f to vins array.%d of %d %s/v%d\n",(double)out.tx->vout[out.i].nValue/COIN,n,maxutxos,txid.GetHex().c_str(),(int32_t)vout);
|
|
||||
if ( mtx.vin.size() > 0 ) |
|
||||
{ |
|
||||
for (i=0; i<mtx.vin.size(); i++) |
|
||||
if ( txid == mtx.vin[i].prevout.hash && vout == mtx.vin[i].prevout.n ) |
|
||||
break; |
|
||||
if ( i != mtx.vin.size() ) |
|
||||
continue; |
|
||||
} |
|
||||
if ( n > 0 ) |
|
||||
{ |
|
||||
for (i=0; i<n; i++) |
|
||||
if ( txid == utxos[i].txid && vout == utxos[i].vout ) |
|
||||
break; |
|
||||
if ( i != n ) |
|
||||
continue; |
|
||||
} |
|
||||
if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) |
|
||||
{ |
|
||||
up = &utxos[n++]; |
|
||||
up->txid = txid; |
|
||||
up->nValue = out.tx->vout[out.i].nValue; |
|
||||
up->vout = vout; |
|
||||
sum += up->nValue; |
|
||||
//fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxutxos);
|
|
||||
if ( n >= maxinputs || sum >= total ) |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
remains = total; |
|
||||
for (i=0; i<maxinputs && n>0; i++) |
|
||||
{ |
|
||||
below = above = 0; |
|
||||
abovei = belowi = -1; |
|
||||
if ( CC_vinselect(&abovei,&above,&belowi,&below,utxos,n,remains) < 0 ) |
|
||||
{ |
|
||||
printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,n,(double)remains/COIN,(double)total/COIN); |
|
||||
free(utxos); |
|
||||
return(0); |
|
||||
} |
|
||||
if ( belowi < 0 || abovei >= 0 ) |
|
||||
ind = abovei; |
|
||||
else ind = belowi; |
|
||||
if ( ind < 0 ) |
|
||||
{ |
|
||||
printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,n,(double)remains/COIN,(double)total/COIN,abovei,belowi,ind); |
|
||||
free(utxos); |
|
||||
return(0); |
|
||||
} |
|
||||
up = &utxos[ind]; |
|
||||
mtx.vin.push_back(CTxIn(up->txid,up->vout,CScript())); |
|
||||
totalinputs += up->nValue; |
|
||||
remains -= up->nValue; |
|
||||
utxos[ind] = utxos[--n]; |
|
||||
memset(&utxos[n],0,sizeof(utxos[n])); |
|
||||
//fprintf(stderr,"totalinputs %.8f vs total %.8f i.%d vs max.%d\n",(double)totalinputs/COIN,(double)total/COIN,i,maxinputs);
|
|
||||
if ( totalinputs >= total || (i+1) >= maxinputs ) |
|
||||
break; |
|
||||
} |
|
||||
free(utxos); |
|
||||
if ( totalinputs >= total ) |
|
||||
{ |
|
||||
//fprintf(stderr,"return totalinputs %.8f\n",(double)totalinputs/COIN);
|
|
||||
return(totalinputs); |
|
||||
} |
|
||||
#endif |
|
||||
return(0); |
|
||||
} |
|
||||
|
|
||||
// always uses -pubkey param as mypk
|
|
||||
int64_t AddNormalinputs2(CMutableTransaction &mtx, int64_t total, int32_t maxinputs) |
|
||||
{ |
|
||||
CPubKey mypk = pubkey2pk(Mypubkey()); |
|
||||
return AddNormalinputsRemote(mtx, mypk, total, maxinputs); |
|
||||
} |
|
||||
|
|
||||
// has additional mypk param for nspv calls
|
|
||||
int64_t AddNormalinputsRemote(CMutableTransaction &mtx, CPubKey mypk, int64_t total, int32_t maxinputs) |
|
||||
{ |
|
||||
int32_t abovei,belowi,ind,vout,i,n = 0; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; char coinaddr[64]; uint256 txid,hashBlock; CTransaction tx; struct CC_utxo *utxos,*up; |
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; |
|
||||
if ( HUSH_NSPV_SUPERLITE ) |
|
||||
return(NSPV_AddNormalinputs(mtx,mypk,total,maxinputs,&NSPV_U)); |
|
||||
utxos = (struct CC_utxo *)calloc(CC_MAXVINS,sizeof(*utxos)); |
|
||||
if ( maxinputs > CC_MAXVINS ) |
|
||||
maxinputs = CC_MAXVINS; |
|
||||
if ( maxinputs > 0 ) |
|
||||
threshold = total/maxinputs; |
|
||||
else threshold = total; |
|
||||
sum = 0; |
|
||||
Getscriptaddress(coinaddr,CScript() << vscript_t(mypk.begin(), mypk.end()) << OP_CHECKSIG); |
|
||||
SetCCunspents(unspentOutputs,coinaddr,false); |
|
||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) |
|
||||
{ |
|
||||
txid = it->first.txhash; |
|
||||
vout = (int32_t)it->first.index; |
|
||||
if ( it->second.satoshis < threshold ) |
|
||||
continue; |
|
||||
if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0 ) |
|
||||
{ |
|
||||
//fprintf(stderr,"check %.8f to vins array.%d of %d %s/v%d\n",(double)out.tx->vout[out.i].nValue/COIN,n,maxutxos,txid.GetHex().c_str(),(int32_t)vout);
|
|
||||
if ( mtx.vin.size() > 0 ) |
|
||||
{ |
|
||||
for (i=0; i<mtx.vin.size(); i++) |
|
||||
if ( txid == mtx.vin[i].prevout.hash && vout == mtx.vin[i].prevout.n ) |
|
||||
break; |
|
||||
if ( i != mtx.vin.size() ) |
|
||||
continue; |
|
||||
} |
|
||||
if ( n > 0 ) |
|
||||
{ |
|
||||
for (i=0; i<n; i++) |
|
||||
if ( txid == utxos[i].txid && vout == utxos[i].vout ) |
|
||||
break; |
|
||||
if ( i != n ) |
|
||||
continue; |
|
||||
} |
|
||||
if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 ) |
|
||||
{ |
|
||||
up = &utxos[n++]; |
|
||||
up->txid = txid; |
|
||||
up->nValue = it->second.satoshis; |
|
||||
up->vout = vout; |
|
||||
sum += up->nValue; |
|
||||
//fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxutxos);
|
|
||||
if ( n >= maxinputs || sum >= total ) |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
remains = total; |
|
||||
for (i=0; i<maxinputs && n>0; i++) |
|
||||
{ |
|
||||
below = above = 0; |
|
||||
abovei = belowi = -1; |
|
||||
if ( CC_vinselect(&abovei,&above,&belowi,&below,utxos,n,remains) < 0 ) |
|
||||
{ |
|
||||
printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,n,(double)remains/COIN,(double)total/COIN); |
|
||||
free(utxos); |
|
||||
return(0); |
|
||||
} |
|
||||
if ( belowi < 0 || abovei >= 0 ) |
|
||||
ind = abovei; |
|
||||
else ind = belowi; |
|
||||
if ( ind < 0 ) |
|
||||
{ |
|
||||
printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,n,(double)remains/COIN,(double)total/COIN,abovei,belowi,ind); |
|
||||
free(utxos); |
|
||||
return(0); |
|
||||
} |
|
||||
up = &utxos[ind]; |
|
||||
mtx.vin.push_back(CTxIn(up->txid,up->vout,CScript())); |
|
||||
totalinputs += up->nValue; |
|
||||
remains -= up->nValue; |
|
||||
utxos[ind] = utxos[--n]; |
|
||||
memset(&utxos[n],0,sizeof(utxos[n])); |
|
||||
//fprintf(stderr,"totalinputs %.8f vs total %.8f i.%d vs max.%d\n",(double)totalinputs/COIN,(double)total/COIN,i,maxinputs);
|
|
||||
if ( totalinputs >= total || (i+1) >= maxinputs ) |
|
||||
break; |
|
||||
} |
|
||||
free(utxos); |
|
||||
if ( totalinputs >= total ) |
|
||||
{ |
|
||||
//fprintf(stderr,"return totalinputs %.8f\n",(double)totalinputs/COIN);
|
|
||||
return(totalinputs); |
|
||||
} |
|
||||
return(0); |
|
||||
} |
|
||||
|
|
||||
int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs,bool remote) |
|
||||
{ |
|
||||
if (!remote) return (AddNormalinputsLocal(mtx,mypk,total,maxinputs)); |
|
||||
else return (AddNormalinputsRemote(mtx,mypk,total,maxinputs)); |
|
||||
} |
|
||||
|
|
||||
void AddSigData2UniValue(UniValue &sigdata, int32_t vini, UniValue& ccjson, std::string sscriptpubkey, int64_t amount) |
|
||||
{ |
|
||||
UniValue elem(UniValue::VOBJ); |
|
||||
elem.push_back(Pair("vin", vini)); |
|
||||
if (!ccjson.empty()) |
|
||||
elem.push_back(Pair("cc", ccjson)); |
|
||||
if (!sscriptpubkey.empty()) |
|
||||
elem.push_back(Pair("scriptPubKey", sscriptpubkey)); |
|
||||
elem.push_back(Pair("amount", amount)); |
|
||||
sigdata.push_back(elem); |
|
||||
} |
|
Loading…
Reference in new issue