Browse Source

Qsend rpc

pull/4/head
jl777 5 years ago
parent
commit
70486de20b
  1. 6
      src/cc/cclib.cpp
  2. 115
      src/cc/dilithium.c

6
src/cc/cclib.cpp

@ -87,6 +87,7 @@ CClib_methods[] =
{ (char *)"dilithium", (char *)"verify", (char *)"pubtxid msg sig", 3, 3, 'V', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"send", (char *)"handle pubtxid amount", 3, 3, 'x', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"spend", (char *)"sendtxid scriptPubKey [hexseed]", 2, 3, 'y', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"Qsend", (char *)"mypubtxid hexseed/'mypriv' destpubtxid,amount, ...", 4, 66, 'Q', EVAL_DILITHIUM },
#endif
};
@ -134,6 +135,7 @@ UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params
UniValue dilithium_keypair(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_sign(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_Qsend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
#endif
@ -261,7 +263,9 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr)
}
else if ( cp->evalcode == EVAL_DILITHIUM )
{
if ( strcmp(method,"send") == 0 )
if ( strcmp(method,"Qsend") == 0 )
return(dilithium_Qsend(txfee,cp,params));
else if ( strcmp(method,"send") == 0 )
return(dilithium_send(txfee,cp,params));
else if ( strcmp(method,"spend") == 0 )
return(dilithium_spend(txfee,cp,params));

115
src/cc/dilithium.c

@ -3209,16 +3209,6 @@ UniValue dilithium_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
} else return(cclib_error(result,"not enough parameters"));
}
/*
ultimately what is needed is to be able to scan all utxos to the CC address and be able to spend many vins in the same tx. to do this the opreturn would need to be able to have txid of special with the sigs. However, it is complicated by the need to create a specific message to sign that is the desired outputs and all the inputs. Also, to properly be able to do change and keep everything in dilithium outputs, there needs to be a second destpub.
so the proposed opreturn for spend would be:
destpubtxid0, destpubtxid1 (zeroid if only 1), vector of sigs/sigtxid where if it is len 32 it is a txid that just has the sig in the opreturn.
however, for now, to keep things simple we will only support spending a specific txid to normal output to avoid needing a combined opreturn and other complications.
*/
UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@ -3269,6 +3259,111 @@ UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params
} else return(cclib_error(result,"need to have exactly 2 params sendtxid, scriptPubKey"));
}
int64_t dilithium_inputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs,char *cmpaddr)
{
char coinaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 tmptxid,txid,hashBlock; std::vector<uint8_t> origpubkey,tmpsig; CTransaction vintx; int32_t vout,numvouts,n = 0; std::vector<uint256> voutpubtxids;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
threshold = total/(maxinputs+1);
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;
//char str[65]; fprintf(stderr,"%s check %s/v%d %.8f vs %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN,(double)threshold/COIN);
if ( it->second.satoshis < threshold || it->second.satoshis == DILITHIUM_TXFEE )
continue;
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 && (numvouts= vintx.vout.size()) > 1 )
{
if ( (nValue= IsCClibvout(cp,vintx,vout,cmpaddr)) > DILITHIUM_TXFEE && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
{
if ( dilithium_Qsendopretdecode(tmptxid,tmpsig,voutpubtxids,vintx.vout[numvouts-1].scriptPubKey) == 'Q' || dilithium_sendopretdecode(tmptxid,tmpsig,vintx.vout[numvouts-1].scriptPubKey) == 'x' )
{
if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
nValue = it->second.satoshis;
totalinputs += nValue;
n++;
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break;
}
} //else fprintf(stderr,"nValue %.8f too small or already spent in mempool\n",(double)nValue/COIN);
} else fprintf(stderr,"couldnt get tx\n");
}
return(totalinputs);
}
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<uint8_t> sig; std::vector<uint256> voutpubtxids;
if ( txfee == 0 )
txfee = DILITHIUM_TXFEE;
mypk = pubkey2pk(Mypubkey());
GetCCaddress(cp,myCCaddr,mypk);
if ( params != 0 && (n= cJSON_GetArraySize(params)) >= 4 && (n & 1) == 0 )
{
mypubtxid = juint256(jitem(params,0));
if ( cclib_parsehash(seed,jitem(params,1),32) < 0 )
{
Myprivkey(seed);
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!!"));
}
_dilithium_keypair(pk,sk,seed);
outputsum = 0;
for (i=2; i<n; i+=2)
{
amount = jdouble(jitem(params,i+1),0)*COIN + 0.0000000049;
scriptstr = jstr(jitem(params,i),0);
return(cclib_error(result,"illegal dest scriptPubKey"));
if ( is_hexstr(scriptstr,0) == 64 )
{
prevhash = juint256(jitem(params,i));
if ( dilithium_bigpubget(handle,destpub33,pk2,prevhash) < 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,destpub33));
voutpubtxids.push_back(prevhash); // binds destpub22 CC addr with dilithium bigpub
} else return(cclib_error(result,"couldnt find bigpub at txid"));
}
else
{
CScript scriptPubKey;
scriptPubKey.resize(strlen(scriptstr)/2);
decode_hex(&scriptPubKey[0],strlen(scriptstr)/2,scriptstr);
vout.nValue = amount;
vout.scriptPubKey = scriptPubKey;
mtx.vout.push_back(vout);
voutpubtxids.push_back(zeroid);
}
outputsum += amount;
}
if ( (inputsum= dilithium_inputs(cp,mtx,mypk,outputsum+txfee,64,myCCaddr)) >= outputsum+txfee )
{
change = (inputsum - outputsum - txfee)
if ( change >= txfee )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,change,mypk));
voutpubtxids.push_back(mypubtxid);
}
tx = mtx;
dilithium_Qmsghash(msg,tx,voutpubtxids);
sig.resize(32+CRYPTO_BYTES);
if ( dilithium_bigpubget(handle,destpub33,pk2,mypubtxid) < 0 )
return(cclib_error(result,"couldnt get bigpub"));
else if ( memcmp(pk,pk2,sizeof(pk)) != 0 )
return(cclib_error(result,"dilithium bigpub mismatch"));
else if ( destpub33 != mypk )
return(cclib_error(result,"destpub33 is not for this -pubkey"));
else if ( _dilithium_sign(&sig[0],&smlen,msg,32,sk) < 0 )
return(cclib_error(result,"dilithium signing error"));
else if ( smlen != 32+CRYPTO_BYTES )
return(cclib_error(result,"siglen error"));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_Qsendopret(destpubtxid,sig,voutpubtxids));
return(dilithium_rawtxresult(result,rawtx));
} else return(cclib_error(result,"couldnt find vin0"));
} else return(cclib_error(result,"need to have exactly 2 params sendtxid, scriptPubKey"));
}
bool dilithium_Qvalidate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
int32_t i,numvins,numvouts,mlen,smlen=CRYPTO_BYTES+32; CPubKey destpub33; std::string handle; uint256 tmptxid,hashBlock,destpubtxid,signerpubtxid; CTransaction vintx; std::vector<uint8_t> tmpsig,sig,vopret; uint8_t msg[32],msg2[CRYPTO_BYTES+32],pk[CRYPTO_PUBLICKEYBYTES],*script; std::vector<uint256> voutpubtxids;

Loading…
Cancel
Save