]> Git Repo - VerusCoin.git/commitdiff
Rpc and tx create
authorjl777 <[email protected]>
Sat, 21 Jul 2018 12:54:49 +0000 (01:54 -1100)
committerjl777 <[email protected]>
Sat, 21 Jul 2018 12:54:49 +0000 (01:54 -1100)
src/cc/assets.cpp
src/rpcserver.cpp
src/rpcserver.h

index dcc7f2228e5a86b6e0e990d4f11718b92712cded..efb1da4865483179112330a2e770cf43ab969713 100644 (file)
@@ -22,6 +22,9 @@
 #include "../core_io.h"
 #include "../script/sign.h"
 #include "../wallet/wallet.h"
+#include <univalue.h>
+
+extern uint8_t NOTARY_PUBKEY33[33];
 
 // code rpc
 
@@ -158,20 +161,23 @@ signEncodeTx "$transferTx"
 
 const char *Unspendableaddr = "RHTcNNYXEZhLGRcXspA2H4gw2v4u6w8MNp";
 char Unspendablehex[67] = { "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9" };
+uint256 Unspendablepriv;
 
-static uint256 zeroid;
-
-bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)
+CPubKey GetUnspendable(uint8_t evalcode,uint8_t *unspendablepriv)
 {
-    CTxDestination address;
-    if ( ExtractDestination(scriptPubKey,address) != 0 )
+    static CPubKey nullpk;
+    memset(unspendablepriv,0,32);
+    if ( evalcode == EVAL_ASSETS )
     {
-        strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str());
-        return(true);
-    }
-    return(false);
+        hexstr = Unspendablehex;
+        memset(unspendablepriv,&Unspendablepriv,32);
+    } else return(nullpk);
+    return(pubkey2pk(ParseHex(Unspendablehex));
 }
 
+static uint256 zeroid;
+
+
 /*
  vout.n-1: opreturn [EVAL_ASSETS] ['o']
  vout.n-1: opreturn [EVAL_ASSETS] ['c'] [{"<assetname>":"<description>"}]
@@ -213,203 +219,102 @@ CScript EncodeOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,uint64_t pri
             fprintf(stderr,"EncodeOpRet: illegal funcid.%02x\n",funcid);
             opret << OP_RETURN;
             break;
-   }
+    }
     return(opret);
 }
 
-CC *MakeAssetCond(CPubKey pk)
+bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)
 {
-    std::vector<CC*> pks; uint8_t evalcode = EVAL_ASSETS;
-    pks.push_back(CCNewSecp256k1(pk));
-    CC *assetCC = CCNewEval(E_MARSHAL(ss << evalcode));
-    CC *Sig = CCNewThreshold(1, pks);
-    return CCNewThreshold(2, {assetCC, Sig});
+    CTxDestination address;
+    if ( ExtractDestination(scriptPubKey,address) != 0 )
+    {
+        strcpy(destaddr,(char *)CBitcoinAddress(address).ToString().c_str());
+        return(true);
+    }
+    return(false);
 }
 
-CTxOut MakeAssetsVout(CAmount nValue,CPubKey pk)
+std::vector<uint8_t> Mypubkey()
 {
-    CTxOut vout;
-    CC *payoutCond = MakeAssetCond(pk);
-    CTxOut(nValue,CCPubKey(payoutCond));
-    cc_free(payoutCond);
-    return(vout);
+    std::vector<uint8_t> pubkey; int32_t i; uint8_t *dest,*pubkey33;
+    pubkey33 = NOTARY_PUBKEY33;
+    pubkey.resize(33);
+    dest = pubkey.data;
+    for (i=0; i<33; i++)
+        dest[i] = pubkey33[i];
+    return(pubkey);
 }
 
-#ifdef ENABLE_WALLET
-extern CWallet* pwalletMain;
-#endif
-
-std::string SignAssetTx(CMutableTransaction &mtx,uint64_t utxovalue,const CScript scriptPubKey)
+void Myprivkey(uint8_t myprivkey[])
 {
-#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,0,utxovalue,SIGHASH_ALL),scriptPubKey,sigdata,consensusBranchId) != 0 )
+    char coinaddr[64]; string strAddress; CBitcoinAddress address; CKeyID keyID; CKey vchSecret;
+    if ( Getscriptaddress(coinaddr,CScript() << Mypubkey() << OP_CHECKSIG) != 0 )
     {
-        UpdateTransaction(mtx,0,sigdata);
-        std::string strHex = EncodeHexTx(mtx);
-        if ( strHex.size() > 0 )
-            return(strHex);
-    } else fprintf(stderr,"signing error for CreateAsset\n");
-#else
-    return(0);
-#endif
+        if ( address.SetString(strAddress) != 0 && address.GetKeyID(keyID) != 0 )
+        {
+            if ( pwalletMain->GetKey(keyID,vchSecret) != 0 )
+            {
+                memcpy(myprivkey,vchSecret.begin(),32);
+                fprintf(stderr,"found privkey!\n");
+            }
+        }
+    }
 }
-
-uint64_t StartAssetTx(CPubKey &pk,CScript &scriptPubKey,uint64_t output,uint64_t txfee,std::vector<uint8_t> origpubkey,uint256 utxotxid,int32_t utxovout)
+           
+CPubKey pubkey2pk(std::vector<uint8_t> pubkey)
 {
-    CTransaction vintx; uint256 hashBlock; uint64_t nValue; int32_t i,n; uint8_t *pubkey33,*dest;
-    n = origpubkey.size();
+    CPubKey pk; int32_t i,n; uint8_t *dest,*pubkey33;
+    n = pubkey.size();
     dest = (uint8_t *)pk.begin();
-    pubkey33 = (uint8_t *)origpubkey.data();
+    pubkey33 = (uint8_t *)pubkey.data();
     for (i=0; i<n; i++)
         dest[i] = pubkey33[i];
-    if ( GetTransaction(utxotxid,vintx,hashBlock,false) != 0 )
-    {
-        nValue = vintx.vout[utxovout].nValue;
-        scriptPubKey = vintx.vout[utxovout].scriptPubKey;
-        if ( scriptPubKey.IsPayToCryptoCondition() == 0 && nValue >= output+txfee )
-            return(nValue);
-    }
-    return(0);
-}
-
-std::string FinalizeAssetTx(CMutableTransaction &mtx,CPubKey pk,uint64_t outvalue,uint64_t txfee,uint64_t utxovalue,CScript scriptPubKey,CScript opret)
-{
-    std::string hex; uint64_t change;
-    if ( utxovalue >= outvalue+2*txfee )
-    {
-        change = utxovalue - (outvalue+txfee);
-        mtx.vout.push_back(CTxOut(change,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG));
-    }
-    mtx.vout.push_back(CTxOut(0,opret));
-    return(SignAssetTx(mtx,utxovalue,scriptPubKey));
+    return(pk);
 }
 
-std::string CreateAsset(std::vector<uint8_t> origpubkey,uint256 utxotxid,int32_t utxovout,uint64_t assetsupply,std::string name,std::string description)
+CC *MakeAssetCond(CPubKey pk)
 {
-    CMutableTransaction mtx; CPubKey pk; CScript scriptPubKey; uint64_t utxovalue,txfee=10000;
-    if ( (utxovalue= StartAssetTx(pk,scriptPubKey,assetsupply,txfee,origpubkey,utxotxid,utxovout)) != 0 )
-    {
-        mtx.vin.push_back(CTxIn(utxotxid,utxovout,CScript()));
-        mtx.vout.push_back(MakeAssetsVout(assetsupply,pk));
-        return(FinalizeAssetTx(mtx,pk,assetsupply,txfee,utxovalue,scriptPubKey,EncodeCreateOpRet('c',name,description)));
-    }
-    return(0);
+    std::vector<CC*> pks; uint8_t evalcode = EVAL_ASSETS;
+    pks.push_back(CCNewSecp256k1(pk));
+    CC *assetCC = CCNewEval(E_MARSHAL(ss << evalcode));
+    CC *Sig = CCNewThreshold(1, pks);
+    return CCNewThreshold(2, {assetCC, Sig});
 }
 
-std::string CreateAssetTransfer(std::vector<uint8_t> origpubkey,uint256 utxotxid,int32_t utxovout,uint256 assetid,std::vector<CTxIn> CCinputs,std::vector<CTxOut> CCoutputs)
+CTxOut MakeAssetsVout(CAmount nValue,CPubKey pk)
 {
-    CMutableTransaction mtx; CPubKey pk; CScript scriptPubKey; int32_t i,n; uint64_t utxovalue,txfee=10000;
-    if ( (utxovalue= StartAssetTx(pk,scriptPubKey,0,txfee,origpubkey,utxotxid,utxovout)) != 0 )
-    {
-        mtx.vin.push_back(CTxIn(utxotxid,utxovout,CScript()));
-        n = CCinputs.size();
-        for (i=0; i<n; i++)
-            mtx.vin.push_back(CCinputs[i]); // CC
-        n = CCoutputs.size();
-        for (i=0; i<n; i++)
-            mtx.vout.push_back(CCoutputs[i]); // CC
-        return(FinalizeAssetTx(mtx,pk,0,txfee,utxovalue,scriptPubKey,EncodeOpRet('t',assetid,zeroid,0,origpubkey)));
-    }
-    return(0);
+    CTxOut vout;
+    CC *payoutCond = MakeAssetCond(pk);
+    CTxOut(nValue,CCPubKey(payoutCond));
+    cc_free(payoutCond);
+    return(vout);
 }
 
-std::string CreateBuyOffer(std::vector<uint8_t> origpubkey,uint256 utxotxid,int32_t utxovout,uint256 assetid,uint64_t bidamount,uint64_t required)
+CC *MakeCC(uint8_t evalcode,CPubKey pk)
 {
-    CMutableTransaction mtx; CPubKey pk; CScript scriptPubKey; int32_t i,n; uint64_t utxovalue,txfee=10000;
-    if ( (utxovalue= StartAssetTx(pk,scriptPubKey,bidamount,txfee,origpubkey,utxotxid,utxovout)) != 0 )
+    if ( evalcode == EVAL_ASSETS )
     {
-        mtx.vin.push_back(CTxIn(utxotxid,utxovout,CScript()));
-        mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(Unspendablehex) << OP_CHECKSIG));
-        return(FinalizeAssetTx(mtx,pk,bidamount,txfee,utxovalue,scriptPubKey,EncodeOpRet('b',assetid,zeroid,required,origpubkey)));
-    }
-    return(0);
+        std::vector<CC*> pks;
+        pks.push_back(CCNewSecp256k1(pk));
+        CC *assetCC = CCNewEval(E_MARSHAL(ss << evalcode));
+        CC *Sig = CCNewThreshold(1, pks);
+        return CCNewThreshold(2, {assetCC, Sig});
+    } else return(0);
 }
 
-std::string CancelBuyOffer(std::vector<uint8_t> origpubkey,uint256 utxotxid,int32_t utxovout,uint256 bidtxid,int32_t bidvout)
+bool GetCCaddress(uint8_t evalcode,char *destaddr,CPubKey pk)
 {
-    CTransaction vintx; uint256 hashBlock; CMutableTransaction mtx; CPubKey pk; CScript scriptPubKey; int32_t i,n; uint64_t bidamount,utxovalue,txfee=10000;
-    if ( (utxovalue= StartAssetTx(pk,scriptPubKey,0,txfee,origpubkey,utxotxid,utxovout)) != 0 )
+    CC *payoutCond;
+    if ( evalcode == EVAL_ASSETS )
     {
-        if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 )
-        {
-            bidamount = vintx.vout[bidvout].nValue;
-            mtx.vin.push_back(CTxIn(utxotxid,utxovout,CScript()));
-            mtx.vin.push_back(CTxIn(bidtxid,bidvout,CScript()));
-            mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG));
-            return(FinalizeAssetTx(mtx,pk,bidamount,txfee,utxovalue,scriptPubKey,EncodeOpRet('o',zeroid,zeroid,0,origpubkey)));
-        }
-    }
-    return(0);
+        payoutCond = MakeAssetCond(pk);
+        destaddr[0] = 0;
+        Getscriptaddress(destaddr,CCPubKey(payoutCond));
+        cc_free(payoutCond);
+        return(destaddr[0] != 0);
+    } else return false;
 }
-
-std::string FillBuyOffer(std::vector<uint8_t> mypubkey,uint256 utxotxid,int32_t utxovout,uint256 bidtxid,int32_t bidvout,uint256 assetid,uint256 filltxid,int32_t fillvout)
-{
-    CTransaction vintx,filltx; uint256 hashBlock; CMutableTransaction mtx; CPubKey pk; CScript scriptPubKey; int32_t i,n; uint64_t bidamount,paid_amount,fill_amount,remaining_required,utxovalue,txfee=10000; std::vector<uint8_t> origpubkey;
-    if ( (utxovalue= StartAssetTx(pk,scriptPubKey,0,txfee,mypubkey,utxotxid,utxovout)) != 0 )
-    {
-        if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 && GetTransaction(filltxid,filltx,hashBlock,false) != 0 )
-        {
-            bidamount = vintx.vout[bidvout].nValue;
-            fill_amount = filltx.vout[fillvout].nValue;
-            mtx.vin.push_back(CTxIn(utxotxid,utxovout,CScript()));
-            mtx.vin.push_back(CTxIn(bidtxid,bidvout,CScript()));
-            mtx.vin.push_back(CTxIn(filltxid,fillvout,CScript())); // CC
-            // set paid_amount and remaining_required and origpubkey, check filltxid is assetid;
-            mtx.vout.push_back(CTxOut(bidamount - paid_amount,CScript() << ParseHex(Unspendablehex) << OP_CHECKSIG));
-            mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(pk)) << OP_CHECKSIG));
-            mtx.vout.push_back(CTxOut(fill_amount,vintx.vout[bidvout].scriptPubKey));
-            return(FinalizeAssetTx(mtx,pk,0,txfee,utxovalue,scriptPubKey,EncodeOpRet('B',assetid,zeroid,remaining_required,origpubkey)));
-        }
-    }
-    return(0);
-}
-
-/*
-
-selloffer:
-vin.0: normal input
-vin.1: valid CC output for sale
-vout.0: vin.1 assetoshis output to CC to unspendable
-vout.1: normal output for change (if any)
-vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey]
-
-exchange:
-vin.0: normal input
-vin.1: valid CC output
-vout.0: vin.1 assetoshis output to CC to unspendable
-vout.1: normal output for change (if any)
-vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey]
-
-cancel:
-vin.0: normal input
-vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx
-vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey]
-vout.1: normal output for change (if any)
-vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid]
-
-fillsell:
-vin.0: normal input
-vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0]
-vin.2: normal output that satisfies selloffer (*tx.vin[2])->nValue
-vout.0: remaining assetoshis -> unspendable
-vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any
-vout.2: vin.2 value to original pubkey [origpubkey]
-vout.3: normal output for change (if any)
-vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey]
-
-fillexchange:
-vin.0: normal input
-vin.1: unspendable.(vout.0 assetoshis from exchange) exchangeTx.vout[0]
-vin.2: valid CC assetid2 output that satisfies exchange (*tx.vin[2])->nValue
-vout.0: remaining assetoshis -> unspendable
-vout.1: vin.1 assetoshis to signer of vin.2 exchangeTx.vout[0].nValue -> any
-vout.2: vin.2 assetoshis2 to original pubkey [origpubkey]
-vout.3: normal output for change (if any)
-vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
-*/
-
+           
 uint8_t DecodeOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,uint64_t &price,std::vector<uint8_t> &origpubkey)
 {
     std::vector<uint8_t> vopret; uint8_t funcid=0,*script;
@@ -447,6 +352,14 @@ uint8_t DecodeOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &asseti
     return(funcid);
 }
 
+bool SetOrigpubkey(std::vector<uint8_t> &origpubkey,uint64_t &price,CTransaction &tx)
+{
+    uint256 assetid,assetid2;
+    if ( DecodeOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,assetid,assetid2,price,origpubkey) != 0 )
+        return(true);
+    else return(false);
+}
+           
 bool Getorigaddr(char *destaddr,CTransaction& tx)
 {
     uint256 assetid,assetid2; uint64_t price,nValue=0; int32_t n; uint8_t funcid; std::vector<uint8_t> origpubkey; CScript script;
@@ -456,7 +369,7 @@ bool Getorigaddr(char *destaddr,CTransaction& tx)
     script = CScript() << origpubkey << OP_CHECKSIG;
     return(Getscriptaddress(destaddr,script));
 }
-
+       
 CC* GetCryptoCondition(CScript const& scriptSig)
 {
     auto pc = scriptSig.begin();
@@ -465,7 +378,16 @@ CC* GetCryptoCondition(CScript const& scriptSig)
     if (scriptSig.GetOp(pc, opcode, ffbin))
         return cc_readFulfillmentBinary((uint8_t*)ffbin.data(), ffbin.size()-1);
 }
-
+       
+bool IsCCInput(CScript const& scriptSig)
+{
+    CC *cond;
+    if ( (cond= GetCryptoCondition(scriptSig)) == 0 )
+        return false;
+    cc_free(cond);
+    return true;
+}
+       
 bool IsAssetInput(CScript const& scriptSig)
 {
     CC *cond;
@@ -482,7 +404,7 @@ bool IsAssetInput(CScript const& scriptSig)
     cc_free(cond);
     return out;
 }
-
+       
 uint64_t IsAssetvout(uint64_t &price,std::vector<uint8_t> &origpubkey,CTransaction& tx,int32_t v,uint256 refassetid)
 {
     uint256 assetid,assetid2; uint64_t nValue=0; int32_t n; uint8_t funcid;
@@ -514,6 +436,392 @@ uint64_t IsAssetvout(uint64_t &price,std::vector<uint8_t> &origpubkey,CTransacti
     }
     return(0);
 }
+           
+#ifdef ENABLE_WALLET
+extern CWallet* pwalletMain;
+#endif
+
+std::string SignTx(CMutableTransaction &mtx,int32_t vini,uint64_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(1);
+    } else fprintf(stderr,"signing error for CreateAsset\n");
+#else
+    return(0);
+#endif
+}
+
+std::string FinalizeCCTx(uint8_t evalcode,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret)
+{
+    CTransaction vintx; std::string hex; uint256 hashBlock; uint64_t vinimask=0,utxovalues[64],change,totaloutputs=0,totalinputs=0; int32_t i,n,err = 0; char myaddr[64],destaddr[64],unspendable[64]; uint8_t *privkey,myprivkey[32],unspendablepriv[32],*msg32 = 0; CC *mycond=0,*othercond=0,*cond; CPubKey unspendablepk;
+    n = mtx.vout.size();
+    for (i=0; i<n; i++)
+    {
+        if ( mtx.vout[i].scriptPubKey.IsPayToCryptoCondition() == 0 )
+            totaloutputs += mtx.vout[i].nValue;
+    }
+    if ( (n= mtx.vin.size()) > 64 )
+    {
+        fprintf(stderr,"FinalizeAssetTx: %d is too many vins\n",n);
+        return(0);
+    }
+    Myprivkey(myprivkey);
+    unspendablepk = GetUnspendable(evalcode,unspendablepriv)
+    GetCCaddress(evalcode,myaddr,mypk);
+    mycond = MakeCC(evalcode,mypk);
+    GetCCaddress(evalcode,unspendable,unspendablepk);
+    othercond = MakeCC(evalcode,unspendablepk);
+    fprintf(stderr,"myCCaddr.(%s) %p vs unspendable.(%s) %p\n",myaddr,mycond,unspendable,othercond);
+    memset(utxovalues,0,sizeof(utxovalues));
+    for (i=0; i<n; i++)
+    {
+        if ( GetTransaction(mtx.vin[i].prevout.hash,vintx,hashBlock,false) != 0 )
+        {
+            if ( IsCCInput(mtx.vin[i].scriptSig) == 0 )
+            {
+                vinimask |= (1LL << i);
+                utxovalues[i] = vintx.vout[mtx.vin[i].prevout.n].nValue;
+                totalinputs += utxovalues[i];
+            }
+            else
+            {
+                Getscriptaddress(destaddr,vintx.vout[mtx.vin[i].prevout.n].scriptPubKey);
+                if ( strcmp(destaddr,myaddr) == 0 )
+                {
+                    privkey = myprivkey;
+                    cond = mycond;
+                }
+                else if ( strcmp(destaddr,unspendable) == 0 )
+                {
+                    privkey = Unspendablepriv;
+                    cond = othercond;
+                }
+                else
+                {
+                    fprintf(stderr,"vini.%d has unknown CC address.(%s)\n",i,destaddr);
+                    continue;
+                }
+                if ( cc_signTreeSecp256k1Msg32(cond,privkey,msg32) != 0 )
+                    mtx.vin[i].scriptSig = CCSig(cond);
+                else fprintf(stderr,"vini.%d has CC signing error address.(%s)\n",i,destaddr);
+            }
+        } else fprintf(stderr,"FinalizeCCTx couldnt find %s\n",mtx.vin[i].prevout.hash.ToString());
+    }
+    if ( mycond != 0 )
+        cc_free(mycond);
+    if ( othercond != 0 )
+        cc_free(othercond);
+    if ( totalinputs >= totalout+2*txfee )
+    {
+        change = totalinputs - (totalout+txfee);
+        mtx.vout.push_back(CTxOut(change,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
+    }
+    mtx.vout.push_back(CTxOut(0,opret));
+    n = mtx.vin.size();
+    for (i=0; i<n; i++)
+    {
+        if ( ((1LL << i) & vinimask) != 0 )
+        {
+            if ( GetTransaction(mtx.vin[i].prevout.hash,vintx,hashBlock,false) != 0 )
+            {
+                if ( SignTx(mtx,i,vintx.vout[utxovout].nValue,vintx.vout[utxovout].scriptPubKey) == 0 )
+                    fprintf(stderr,"signing error for vini.%d of %llx\n",vini,(long long)vinimask);
+            } else fprintf(stderr,"FinalizeAssetTx couldnt find %s\n",mtx.vin[i].prevout.hash.ToString());
+        }
+    }
+    std::string strHex = EncodeHexTx(mtx);
+    if ( strHex.size() > 0 )
+        return(strHex);
+    else return(0);
+}
+
+           
+bool ValidateRemainder(uint64_t remaining_price,uint64_t remaining_nValue,uint64_t orig_nValue,uint64_t received,uint64_t paid,uint64_t totalprice)
+{
+    uint64_t price,recvprice;
+    if ( orig_nValue == 0 || received == 0 || paid == 0 || totalprice == 0 )
+    {
+        fprintf(stderr,"ValidateRemainder: orig_nValue == %llu || received == %llu || paid == %llu || totalprice == %llu\n",(long long)orig_nValue,(long long)received,(long long)paid,(long long)totalprice);
+        return(false);
+    }
+    else if ( remaining_price < (totalprice - received) )
+    {
+        fprintf(stderr,"ValidateRemainder: remaining_price %llu < %llu (totalprice %llu - %llu received)\n",(long long)remaining_price,(long long)(totalprice - received),(long long)totalprice,(long long)received);
+        return(false);
+    }
+    else if ( remaining_nValue < (orig_nValue - paid) )
+    {
+        fprintf(stderr,"ValidateRemainder: remaining_nValue %llu < %llu (totalprice %llu - %llu received)\n",(long long)remaining_nValue,(long long)(orig_nValue - paid),(long long)orig_nValue,(long long)paid);
+        return(false);
+    }
+    else if ( remaining_nValue > 0 )
+    {
+        price = (totalprice * COIN) / orig_nValue;
+        recvprice = (received * COIN) / paid;
+        if ( recvprice < price )
+        {
+            fprintf(stderr,"recvprice %llu < %llu price\n",(long long)recvprice,(long long)price);
+            return(false);
+        }
+    }
+    return(true);
+}
+
+bool SetFillamounts(uint64_t &paid,uint64_t &remaining_price,uint64_t orig_nValue,uint64_t received,uint64_t totalprice)
+{
+    uint64_t remaining_nValue,price,mult;
+    remaining_price = (totalprice - received);
+    price = (totalprice * COIN) / orig_nValue;
+    mult = (received * COIN);
+    if ( price > 0 && (paid= mult / price) > 0 )
+    {
+        if ( (mult % price) != 0 )
+            paid--;
+        remaining_nValue = (orig_nValue - paid);
+        return(ValidateRemainder(remaining_price,remaining_nValue,orig_nValue,received,paid,totalprice));
+    } else return(false);
+}
+           
+/*uint64_t IsNormalUtxo(uint64_t output,uint64_t txfee,uint256 feetxid,int32_t feevout)
+{
+    CTransaction vintx; uint256 hashBlock; uint64_t nValue;
+    if ( GetTransaction(feetxid,vintx,hashBlock,false) != 0 )
+    {
+        nValue = vintx.vout[feevout].nValue;
+        if ( vintx.vout[feevout].scriptPubKey.IsPayToCryptoCondition() == 0 && nValue >= output+txfee )
+            return(nValue);
+    }
+    return(0);
+}*/
+
+uint64_t AddCCinputs(CMutableTransaction &mtx,CPubKey mypk,uint256 assetid,uint64_t total)
+{
+    uint64_t totalinputs = 0;
+    //for (i=0; i<n; i++)
+    //   mtx.vin.push_back(CCinputs[i]); // CC
+    return(totalinputs);
+}
+       
+uint64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,uint64_t total,int32_t maxinputs)
+{
+    int32_t n = 0; uint64_t totalinputs = 0;
+    const CKeyStore& keystore = *pwalletMain;
+    assert(pwalletMain != NULL);
+    LOCK2(cs_main, pwalletMain->cs_wallet);
+    pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
+    BOOST_FOREACH(const COutput& out, vecOutputs)
+    {
+        if ( out.fSpendable != 0 )
+        {
+            mtx.vin.push_back(CTxIn(out.tx->GetHash(),out.i,CScript()));
+            nValue = out.tx->vout[out.i].nValue;
+            totalinputs += nValue;
+            if ( totalinputs >= total || n >= maxinputs )
+                break;
+        }
+    }
+    if ( totalinputs >= total )
+        return(totalinputs);
+    else return(0);
+}
+
+std::string CreateAsset(std::vector<uint8_t> mypubkey,uint64_t txfee,uint64_t assetsupply,std::string name,std::string description)
+{
+    CMutableTransaction mtx; CPubKey mypk;
+    if ( name.size() > 32 || description.size() > 4096 )
+    {
+        fprintf(stderr,"name.%d or description.%d is too big\n",name.size(),description.size());
+        return(0);
+    }
+    if ( txfee == 0 )
+        txfee = 10000;
+    mypk = pubkey2pk(mypubkey);
+    if ( AddNormalinputs(mtx,mypk,assetsupply+txfee,64) > 0 )
+    {
+        mtx.vout.push_back(MakeAssetsVout(assetsupply,mypk));
+        return(FinalizeCCTx(EVAL_ASSETS,mtx,mypk,txfee,EncodeCreateOpRet('c',name,description)));
+    }
+    return(0);
+}
+    
+UniValue tokencreate(const UniValue& params, bool fHelp)
+{
+    UniValue result(UniValue::VOBJ); std::string name,description,hex; uint64_t supply;
+    if ( fHelp || params.size() > 3 || params.size() < 2 )
+        throw runtime_error("tokencreate name supply description\n")
+    name = params[0].get_str();
+    supply = atof(params[1].get_str()) * COIN;
+    if ( params.size() == 3 )
+        description = params[2].get_str();
+    hex = CreateAsset(Mypubkey(),0,supply,name,description);
+    if ( hex.size() > 0 )
+    {
+        result.push_back(Pair("result", "success"));
+        result.push_back(Pair("hex", hex));
+    } else result.push_back(Pair("error", "could create transaction"));
+}
+    
+UniValue tokentransfer(const UniValue& params, bool fHelp)
+{
+    UniValue result(UniValue::VOBJ);
+    return(result);
+}
+           
+UniValue tokenbid(const UniValue& params, bool fHelp)
+{
+    UniValue result(UniValue::VOBJ);
+    return(result);
+}
+           
+UniValue tokencancelbid(const UniValue& params, bool fHelp)
+{
+    UniValue result(UniValue::VOBJ);
+    return(result);
+}
+           
+UniValue tokenfillbid(const UniValue& params, bool fHelp)
+{
+    UniValue result(UniValue::VOBJ);
+    return(result);
+}
+           
+std::string CreateAssetTransfer(std::vector<uint8_t> mypubkey,uint64_t txfee,uint256 assetid,std::vector<CPubKey>outputs,std::vector<uint64_t>amounts)
+{
+    CMutableTransaction mtx; CPubKey mypk; int32_t i,n; uint64_t CCchange=0,inputs=0,total=0;
+    if ( txfee == 0 )
+        txfee = 10000;
+    mypk = pubkey2pk(mypubkey);
+    if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
+    {
+        n = outputs.size();
+        if ( n == amounts.size() )
+        {
+            for (i=0; i<n; i++)
+                total += amounts[i];
+            if ( (inputs= AddCCinputs(mtx,mypk,assetid,total)) > 0 )
+            {
+                if ( inputs > total )
+                    CCchange = (inputs - total);
+                for (i=0; i<n; i++)
+                    mtx.vout.push_back(MakeAssetsVout(amounts[i],outputs[i]));
+                if ( CCchange != 0 )
+                    mtx.vout.push_back(MakeAssetsVout(CCchange,mypk));
+                return(FinalizeCCTx(EVAL_ASSETS,mtx,mypk,txfee,EncodeOpRet('t',assetid,zeroid,0,mypubkey)));
+            } else fprintf(stderr,"not enough CC asset inputs for %.8f\n",(double)total/COIN);
+        } else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,amounts.size());
+    }
+    return(0);
+}
+
+std::string CreateBuyOffer(std::vector<uint8_t> mypubkey,uint64_t txfee,uint64_t bidamount,uint256 assetid,uint64_t pricetotal)
+{
+    CMutableTransaction mtx; CPubKey mypk;
+    if ( txfee == 0 )
+        txfee = 10000;
+    mypk = pubkey2pk(mypubkey);
+    if ( AddNormalinputs(mtx,mypk,bidamount+txfee,64) > 0 )
+    {
+        mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(Unspendablehex) << OP_CHECKSIG));
+        return(FinalizeCCTx(EVAL_ASSETS,mtx,mypk,txfee,EncodeOpRet('b',assetid,zeroid,pricetotal,mypubkey)));
+    }
+    return(0);
+}
+
+std::string CancelBuyOffer(std::vector<uint8_t> mypubkey,uint64_t txfee,uint256 bidtxid)
+{
+    CMutableTransaction mtx; CTransaction vintx; uint256 hashBlock; uint64_t bidamount; CPubKey mypk;
+    if ( txfee == 0 )
+        txfee = 10000;
+    mypk = pubkey2pk(mypubkey);
+    if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
+    {
+        if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 )
+        {
+            bidamount = vintx.vout[0].nValue;
+            mtx.vin.push_back(CTxIn(bidtxid,0,CScript()));
+            mtx.vout.push_back(CTxOut(bidamount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
+            return(FinalizeCCTx(EVAL_ASSETS,mtx,mypk,txfee,EncodeOpRet('o',zeroid,zeroid,0,mypubkey)));
+        }
+    }
+    return(0);
+}
+
+std::string FillBuyOffer(std::vector<uint8_t> mypubkey,uint64_t txfee,uint256 assetid,uint256 bidtxid,uint256 filltxid,int32_t fillvout)
+{
+    CTransaction vintx,filltx; uint256 hashBlock; CMutableTransaction mtx; CPubKey mypk; std::vector<uint8_t> origpubkey,tmppubkey; int32_t bidvout=0; uint64_t tmpprice,origprice,bidamount,paid_amount,fill_amount,remaining_required;
+    if ( txfee == 0 )
+        txfee = 10000;
+    mypk = pubkey2pk(mypubkey);
+    if ( AddNormalinputs(mtx,mypk,txfee,1) > 0 )
+    {
+        if ( GetTransaction(bidtxid,vintx,hashBlock,false) != 0 && GetTransaction(filltxid,filltx,hashBlock,false) != 0 )
+        {
+            bidamount = vintx.vout[bidvout].nValue;
+            SetOrigpubkey(origpubkey,origprice,vintx);
+            fill_amount = filltx.vout[fillvout].nValue;
+            mtx.vin.push_back(CTxIn(bidtxid,bidvout,CScript()));
+            if ( IsAssetvout(tmpprice,tmppubkey,filltx,fillvout,assetid) == fill_amount )
+            {
+                mtx.vin.push_back(CTxIn(filltxid,fillvout,CScript())); // CC
+                SetFillamounts(paid_amount,remaining_required,bidamount,fillamount,origprice);
+                mtx.vout.push_back(CTxOut(bidamount - paid_amount,CScript() << ParseHex(Unspendablehex) << OP_CHECKSIG));
+                mtx.vout.push_back(CTxOut(paid_amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
+                mtx.vout.push_back(MakeAssetsVout(fill_amount,pubkey2pk(origpubkey)));
+                return(FinalizeCCTx(EVAL_ASSETS,mtx,mypk,txfee,EncodeOpRet('B',assetid,zeroid,remaining_required,origpubkey)));
+            } else fprintf(stderr,"filltx wasnt for assetid\n");
+        }
+    }
+    return(0);
+}
+
+/*
+
+selloffer:
+vin.0: normal input
+vin.1: valid CC output for sale
+vout.0: vin.1 assetoshis output to CC to unspendable
+vout.1: normal output for change (if any)
+vout.n-1: opreturn [EVAL_ASSETS] ['s'] [assetid] [amount of native coin required] [origpubkey]
+
+exchange:
+vin.0: normal input
+vin.1: valid CC output
+vout.0: vin.1 assetoshis output to CC to unspendable
+vout.1: normal output for change (if any)
+vout.n-1: opreturn [EVAL_ASSETS] ['e'] [assetid] [assetid2] [amount of asset2 required] [origpubkey]
+
+cancel:
+vin.0: normal input
+vin.1: unspendable.(vout.0 from exchange or selloffer) sellTx/exchangeTx.vout[0] inputTx
+vout.0: vin.1 assetoshis to original pubkey CC sellTx/exchangeTx.vout[0].nValue -> [origpubkey]
+vout.1: normal output for change (if any)
+vout.n-1: opreturn [EVAL_ASSETS] ['x'] [assetid]
+
+fillsell:
+vin.0: normal input
+vin.1: unspendable.(vout.0 assetoshis from selloffer) sellTx.vout[0]
+vin.2: normal output that satisfies selloffer (*tx.vin[2])->nValue
+vout.0: remaining assetoshis -> unspendable
+vout.1: vin.1 assetoshis to signer of vin.2 sellTx.vout[0].nValue -> any
+vout.2: vin.2 value to original pubkey [origpubkey]
+vout.3: normal output for change (if any)
+vout.n-1: opreturn [EVAL_ASSETS] ['S'] [assetid] [amount of coin still required] [origpubkey]
+
+fillexchange:
+vin.0: normal input
+vin.1: unspendable.(vout.0 assetoshis from exchange) exchangeTx.vout[0]
+vin.2: valid CC assetid2 output that satisfies exchange (*tx.vin[2])->nValue
+vout.0: remaining assetoshis -> unspendable
+vout.1: vin.1 assetoshis to signer of vin.2 exchangeTx.vout[0].nValue -> any
+vout.2: vin.2 assetoshis2 to original pubkey [origpubkey]
+vout.3: normal output for change (if any)
+vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
+*/
 
 uint64_t AssetValidatevin(Eval* eval,char *origaddr,CTransaction &tx,CTransaction &vinTx)
 {
@@ -554,32 +862,13 @@ uint64_t AssetValidateSellvin(Eval* eval,uint64_t &tmpprice,std::vector<uint8_t>
     else return(assetoshis);
 }
 
-bool ValidateRemainder(uint64_t remaining_price,uint64_t remaining_nValue,uint64_t orig_nValue,uint64_t received,uint64_t paid,uint64_t totalprice)
-{
-    uint64_t price,recvprice;
-    if ( orig_nValue == 0 || received == 0 || paid == 0 || totalprice == 0 )
-        return(false);
-    else if ( remaining_price < (totalprice - received) )
-        return(false);
-    else if ( remaining_nValue < (orig_nValue - paid) )
-        return(false);
-    else if ( remaining_nValue > 0 )
-    {
-        price = (totalprice * COIN) / orig_nValue;
-        recvprice = (received * COIN) / paid;
-        if ( recvprice < price )
-            return(false);
-    }
-    return(true);
-}
-
 bool AssetValidate(Eval* eval,CTransaction &tx,int32_t numvouts,uint8_t funcid,uint256 assetid,uint256 assetid2,uint64_t remaining_price,std::vector<uint8_t> origpubkey)
 {
     static uint256 zero;
     CTxDestination address; CTransaction vinTx; uint256 hashBlock; int32_t i,numvins; uint64_t nValue,assetoshis,outputs,inputs,tmpprice,ignore; std::vector<uint8_t> tmporigpubkey,ignorepubkey; char destaddr[64],origaddr[64];
     numvins = tx.vin.size();
     outputs = inputs = 0;
-    if ( IsAssetInput(tx.vin[0].scriptSig) != 0 )
+    if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
         return eval->Invalid("illegal asset vin0");
     if ( funcid != 'c' && assetid == zero )
         return eval->Invalid("illegal assetid");
@@ -629,7 +918,7 @@ bool AssetValidate(Eval* eval,CTransaction &tx,int32_t numvouts,uint8_t funcid,u
                 return eval->Invalid("illegal null amount for buyoffer");
             for (i=1; i<numvins; i++)
             {
-                if ( IsAssetInput(tx.vin[i].scriptSig) != 0 )
+                if ( IsCCInput(tx.vin[i].scriptSig) != 0 )
                     return eval->Invalid("invalid CC vin for buyoffer");
             }
             for (i=0; i<numvouts-1; i++)
index f37124d0c0057518d74f2d127aad03f167b15dd6..48c6f23867f490fdbef9037a3a726a1e6a64e1fc 100644 (file)
@@ -345,6 +345,13 @@ static const CRPCCommand vRPCCommands[] =
     { "rawtransactions",    "fundrawtransaction",     &fundrawtransaction,     false },
 #endif
 
+/* tokens */
+    { "tokens",       "tokencreate",      &tokencreate,      true  },
+    { "tokens",       "tokentransfer",    &tokentransfer,        true },
+    { "tokens",       "tokenbid",         &tokenbid,       true },
+    { "tokens",       "tokencancelbid",   &tokencancelbid,        true },
+    { "tokens",       "tokenfillbid",     &tokenfillbid,      true },
+
 /* Address index */
     { "addressindex",       "getaddressmempool",      &getaddressmempool,      true  },
     { "addressindex",       "getaddressutxos",        &getaddressutxos,        false },
index 586d79a886faae8fb0be18a76555a3c9f8519bcc..1bf5298c49a736ed7fd52ee514f78df69cfd7a4e 100644 (file)
@@ -208,6 +208,11 @@ extern UniValue submitblock(const UniValue& params, bool fHelp);
 extern UniValue estimatefee(const UniValue& params, bool fHelp);
 extern UniValue estimatepriority(const UniValue& params, bool fHelp);
 extern UniValue coinsupply(const UniValue& params, bool fHelp);
+extern UniValue tokencreate(const UniValue& params, bool fHelp);
+extern UniValue tokentransfer(const UniValue& params, bool fHelp);
+extern UniValue tokenbid(const UniValue& params, bool fHelp);
+extern UniValue tokencancelbid(const UniValue& params, bool fHelp);
+extern UniValue tokenfillbid(const UniValue& params, bool fHelp);
 
 extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp
 //extern UniValue getnewaddress64(const UniValue& params, bool fHelp); // in rpcwallet.cpp
This page took 0.048456 seconds and 4 git commands to generate.