|
|
@ -2929,6 +2929,29 @@ int32_t main(void) |
|
|
|
void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen); |
|
|
|
char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); |
|
|
|
|
|
|
|
struct dilithium_handle |
|
|
|
{ |
|
|
|
UT_hash_handle hh; |
|
|
|
uint256 destpubtxid; |
|
|
|
char handle[32]; |
|
|
|
} *Dilithium_handles; |
|
|
|
|
|
|
|
struct dilithium_handle *dilithium_handlenew(std::string handle) |
|
|
|
{ |
|
|
|
struct dilithium_handle *hashstr = 0; |
|
|
|
if ( handle.size() < sizeof(Dilithium_handles[0].handle)-1 ) |
|
|
|
{ |
|
|
|
HASH_FIND(hh,Dilithium_handles,handle,(int32_t)handle.size(),hashstr); |
|
|
|
if ( hashstr == 0 ) |
|
|
|
{ |
|
|
|
hashstr = calloc(1,sizeof(*hashstr)); |
|
|
|
strncpy(hashstr->handle,handle.c_str(),sizeof(hashstr->handle)); |
|
|
|
HASH_ADD_KEYPTR(hh,Dilithium_handles,hashstr->handle,(int32_t)handle.size(),hashstr); |
|
|
|
} |
|
|
|
} |
|
|
|
return(hashstr); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t dilithium_Qmsghash(uint8_t *msg,CTransaction tx,int32_t numvouts,std::vector<uint256> voutpubtxids) |
|
|
|
{ |
|
|
|
CScript data; uint256 hash; int32_t i,numvins,len = 0; std::vector<uint256> vintxids; std::vector<int32_t> vinprevns; std::vector<CTxOut> vouts; |
|
|
@ -3110,12 +3133,20 @@ UniValue dilithium_keypair(uint64_t txfee,struct CCcontract_info *cp,cJSON *para |
|
|
|
return(result); |
|
|
|
} |
|
|
|
|
|
|
|
CPubKey Faucet_pubkeyget() |
|
|
|
{ |
|
|
|
struct CCcontract_info *cp,C; |
|
|
|
cp = CCinit(&C,EVAL_FAUCET); |
|
|
|
return(GetUnspendable(cp,0)); |
|
|
|
} |
|
|
|
|
|
|
|
UniValue dilithium_register(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,dilithiumpk; uint8_t seed[SEEDBYTES],pk[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES]; char coinaddr[64],str[CRYPTO_SECRETKEYBYTES*2+1]; std::vector<uint8_t> bigpub; int32_t i,n,warningflag = 0; |
|
|
|
UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey faucetpk,mypk,dilithiumpk; uint8_t seed[SEEDBYTES],pk[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES]; char coinaddr[64],str[CRYPTO_SECRETKEYBYTES*2+1]; int64_t CCchange,inputs; std::vector<uint8_t> bigpub; int32_t i,n,warningflag = 0; |
|
|
|
if ( txfee == 0 ) |
|
|
|
txfee = DILITHIUM_TXFEE; |
|
|
|
faucetpk = Faucet_pubkeyget(); |
|
|
|
mypk = pubkey2pk(Mypubkey()); |
|
|
|
dilithiumpk = GetUnspendable(cp,0); |
|
|
|
if ( params != 0 && ((n= cJSON_GetArraySize(params)) == 1 || n == 2) ) |
|
|
@ -3132,14 +3163,23 @@ UniValue dilithium_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *par |
|
|
|
result.push_back(Pair("skaddr",dilithium_addr(coinaddr,sk,CRYPTO_SECRETKEYBYTES))); |
|
|
|
for (i=0; i<CRYPTO_PUBLICKEYBYTES; i++) |
|
|
|
bigpub.push_back(pk[i]); |
|
|
|
if ( AddNormalinputs(mtx,mypk,3*txfee,64) >= 3*txfee ) |
|
|
|
if ( (inputs= AddCClibtxfee(cp,mtx,dilithiumpk)) > 0 ) |
|
|
|
{ |
|
|
|
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,dilithiumpk)); |
|
|
|
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk)); |
|
|
|
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_registeropret(handle,mypk,bigpub)); |
|
|
|
return(musig_rawtxresult(result,rawtx)); |
|
|
|
} else return(cclib_error(result,"couldnt find enough funds")); |
|
|
|
} else return(cclib_error(result,"not enough parameters")); |
|
|
|
if ( inputs > txfee ) |
|
|
|
CCchange = (inputs - txfee); |
|
|
|
else CCchange = 0; |
|
|
|
if ( AddNormalinputs(mtx,mypk,COIN+3*txfee,64) >= 3*txfee ) |
|
|
|
{ |
|
|
|
mtx.vout.push_back(MakeCC1vout(cp->evalcode,2*txfee,dilithiumpk)); |
|
|
|
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk)); |
|
|
|
mtx.vout.push_back(MakeCC1vout(EVAL_FAUCET,COIN,faucetpk)); |
|
|
|
if ( CCchange != 0 ) |
|
|
|
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,dilithiumpk)); |
|
|
|
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_registeropret(handle,mypk,bigpub)); |
|
|
|
return(musig_rawtxresult(result,rawtx)); |
|
|
|
} else return(cclib_error(result,"couldnt find enough funds")); |
|
|
|
} else return(cclib_error(result,"not enough parameters")); |
|
|
|
} else return(cclib_error(result,"not dilithiumpk funds")); |
|
|
|
} |
|
|
|
|
|
|
|
UniValue dilithium_sign(uint64_t txfee,struct CCcontract_info *cp,cJSON *params) |
|
|
@ -3452,6 +3492,65 @@ bool dilithium_Qvalidate(struct CCcontract_info *cp,int32_t height,Eval *eval,co |
|
|
|
} else return eval->Invalid("unexpected zero signerpubtxid"); |
|
|
|
} |
|
|
|
|
|
|
|
bool dilithium_Rvalidate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx) |
|
|
|
{ |
|
|
|
static int32_t didinit; |
|
|
|
std::vector<std::pair<CAddressIndexKey, CAmount> > txids; |
|
|
|
uint256 txid,hashBlock; int32_t numvouts; struct dilithium_handle *hashstr; std::string handle; std::vector<uint8_t> bigpub; CTransaction txi; CPubKey pub33,dilithiumpk; CTxOut vout,vout0; char CCaddr[64]; |
|
|
|
dilithiumpk = GetUnspendable(cp,0); |
|
|
|
if ( didinit == 0 ) |
|
|
|
{ |
|
|
|
GetCCaddress(cp,CCaddr,dilithiumpk); |
|
|
|
SetCCtxids(txids,CCaddr); |
|
|
|
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=txids.begin(); it!=txids.end(); it++) |
|
|
|
{ |
|
|
|
txid = it->first.txhash; |
|
|
|
if ( myGetTransaction(txid,txi,hashBlock) != 0 && (numvouts= txi.vout.size()) > 1 ) |
|
|
|
{ |
|
|
|
if ( dilithium_registeropretdecode(handle,pub33,bigpub,txi.vout[numvouts-1].scriptPubKey) == 'R' ) |
|
|
|
{ |
|
|
|
if ( (hashstr= dilithium_handlenew(handle)) != 0 ) |
|
|
|
{ |
|
|
|
if ( hashstr->destpubtxid != txid ) |
|
|
|
{ |
|
|
|
if ( hashstr->destpubtxid != zeroid ) |
|
|
|
fprintf(stderr,"overwriting %s %s with %s\n",handle.c_str(),hashstr->destpubtxid.GetHex().c_str(),txid.GetHex().c_str()); |
|
|
|
fprintf(stderr,"%s <- %s\n",handle.c_str(),txid.GetHex().c_str()); |
|
|
|
hashstr->destpubtxid = txid; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
didinit = 1; |
|
|
|
} |
|
|
|
if ( (numvouts= tx.vout.size()) <= 1 ) |
|
|
|
return eval->Invalid("not enough vouts for registration tx"); |
|
|
|
else if ( dilithium_registeropretdecode(handle,pub33,bigpub,tx.vout[numvouts-1].scriptPubKey) == 'R' ) |
|
|
|
{ |
|
|
|
// relies on all current block tx to be put into mempool
|
|
|
|
txid = tx.GetHash(); |
|
|
|
vout0 = MakeCC1vout(cp->evalcode,2*DILITHIUM_TXFEE,dilithiumpk); |
|
|
|
vout = MakeCC1vout(EVAL_FAUCET,COIN,Faucet_pubkeyget()); |
|
|
|
if ( tx.vout[0] != vout0 ) |
|
|
|
return eval->Invalid("mismatched vout0 for register"); |
|
|
|
else if ( tx.vout[1].nValue != DILITHIUM_TXFEE ) |
|
|
|
return eval->Invalid("vout1 for register not txfee"); |
|
|
|
else if ( tx.vout[2] != vout ) |
|
|
|
return eval->Invalid("register not sending to faucet"); |
|
|
|
else if ( (hashstr= dilithium_handlenew(handle)) == 0 ) |
|
|
|
return eval->Invalid("error creating dilithium handle"); |
|
|
|
else if ( hashstr->destpubtxid == zeroid ) |
|
|
|
{ |
|
|
|
hashstr->destpubtxid = txid; |
|
|
|
return(true); |
|
|
|
} |
|
|
|
else if ( hashstr->destpubtxid == txid ) |
|
|
|
return(true); |
|
|
|
else return eval->Invalid("duplicate dilithium handle rejected"); |
|
|
|
} else return eval->Invalid("couldnt decode register opret"); |
|
|
|
} |
|
|
|
|
|
|
|
bool dilithium_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx) |
|
|
|
{ |
|
|
|
CPubKey destpub33; std::string handle; uint256 hashBlock,destpubtxid,checktxid; CTransaction vintx; int32_t numvouts,mlen,smlen=CRYPTO_BYTES+32; std::vector<uint8_t> sig,vopret; uint8_t msg[32],msg2[CRYPTO_BYTES+32],pk[CRYPTO_PUBLICKEYBYTES],*script; |
|
|
@ -3459,7 +3558,9 @@ bool dilithium_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,con |
|
|
|
numvouts = tx.vout.size(); |
|
|
|
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret); |
|
|
|
script = (uint8_t *)vopret.data(); |
|
|
|
if ( script[1] == 'Q' ) |
|
|
|
if ( script[1] == 'R' ) |
|
|
|
return(dilithium_Rvalidate(cp,height,eval,tx)); |
|
|
|
else if ( script[1] == 'Q' ) |
|
|
|
return(dilithium_Qvalidate(cp,height,eval,tx)); |
|
|
|
else if ( tx.vout.size() != 2 ) |
|
|
|
return eval->Invalid("numvouts != 2"); |
|
|
|