]> Git Repo - VerusCoin.git/blob - src/cc/prices.cpp
Merge branch 'dev' into jl777
[VerusCoin.git] / src / cc / prices.cpp
1 /******************************************************************************
2  * Copyright © 2014-2018 The SuperNET Developers.                             *
3  *                                                                            *
4  * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at                  *
5  * the top-level directory of this distribution for the individual copyright  *
6  * holder information and the developer policies on copyright and licensing.  *
7  *                                                                            *
8  * Unless otherwise agreed in a custom licensing agreement, no part of the    *
9  * SuperNET software, including this file may be copied, modified, propagated *
10  * or distributed except according to the terms contained in the LICENSE file *
11  *                                                                            *
12  * Removal or modification of this copyright notice is prohibited.            *
13  *                                                                            *
14  ******************************************************************************/
15
16 #include "CCPrices.h"
17
18 /*
19  Prices CC would best build on top of the oracles CC, ie. to combine payments for multiple oracles and to calculate a 51% protected price feed.
20  
21  We need to assume there is an oracle for a specific price. In the event there are more than one provider, the majority need to be within correlation distance to update a pricepoint.
22
23  int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format);
24
25  Using the above function, a consensus price can be obtained for a datasource.
26  
27  given an oracletxid, the marketaddr and format can be extracted to be used for future calls to OraclePrice. This allows to set a starting price and that in turn allows cash settled leveraged trading!
28  
29  Funds work like with dice, ie. there is a Prices plan that traders bet against.
30  
31  PricesOpen -> oracletxid start with 'L' price, leverage, amount
32  funds are locked into global CC address
33     it can be closed at anytime by the trader for cash settlement
34     the house account can close it if rekt
35  
36  
37 */
38
39 // start of consensus code
40
41 int64_t IsPricesvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
42 {
43     char destaddr[64];
44     if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
45     {
46         if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 )
47             return(tx.vout[v].nValue);
48     }
49     return(0);
50 }
51
52 bool PricesExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee)
53 {
54     static uint256 zerohash;
55     CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis;
56     numvins = tx.vin.size();
57     numvouts = tx.vout.size();
58     for (i=0; i<numvins; i++)
59     {
60         //fprintf(stderr,"vini.%d\n",i);
61         if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
62         {
63             //fprintf(stderr,"vini.%d check mempool\n",i);
64             if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
65                 return eval->Invalid("cant find vinTx");
66             else
67             {
68                 //fprintf(stderr,"vini.%d check hash and vout\n",i);
69                 if ( hashBlock == zerohash )
70                     return eval->Invalid("cant Prices from mempool");
71                 if ( (assetoshis= IsPricesvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 )
72                     inputs += assetoshis;
73             }
74         }
75     }
76     for (i=0; i<numvouts; i++)
77     {
78         //fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
79         if ( (assetoshis= IsPricesvout(cp,tx,i)) != 0 )
80             outputs += assetoshis;
81     }
82     if ( inputs != outputs+txfee )
83     {
84         fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
85         return eval->Invalid("mismatched inputs != outputs + txfee");
86     }
87     else return(true);
88 }
89
90 bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
91 {
92     int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
93     return(false);
94     std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
95     numvins = tx.vin.size();
96     numvouts = tx.vout.size();
97     preventCCvins = preventCCvouts = -1;
98     if ( numvouts < 1 )
99         return eval->Invalid("no vouts");
100     else
101     {
102         for (i=0; i<numvins; i++)
103         {
104             if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
105             {
106                 return eval->Invalid("illegal normal vini");
107             }
108         }
109         //fprintf(stderr,"check amounts\n");
110         if ( PricesExactAmounts(cp,eval,tx,1,10000) == false )
111         {
112             fprintf(stderr,"Pricesget invalid amount\n");
113             return false;
114         }
115         else
116         {
117             txid = tx.GetHash();
118             memcpy(hash,&txid,sizeof(hash));
119             retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
120             if ( retval != 0 )
121                 fprintf(stderr,"Pricesget validated\n");
122             else fprintf(stderr,"Pricesget invalid\n");
123             return(retval);
124         }
125     }
126 }
127 // end of consensus code
128
129 // helper functions for rpc calls in rpcwallet.cpp
130
131 int64_t AddPricesInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs)
132 {
133     char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
134     std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
135     GetCCaddress(cp,coinaddr,pk);
136     SetCCunspents(unspentOutputs,coinaddr);
137     for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
138     {
139         txid = it->first.txhash;
140         vout = (int32_t)it->first.index;
141         // no need to prevent dup
142         if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
143         {
144             if ( (nValue= IsPricesvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 )
145             {
146                 if ( total != 0 && maxinputs != 0 )
147                     mtx.vin.push_back(CTxIn(txid,vout,CScript()));
148                 nValue = it->second.satoshis;
149                 totalinputs += nValue;
150                 n++;
151                 if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
152                     break;
153             }
154         }
155     }
156     return(totalinputs);
157 }
158
159 /*
160  UniValue PriceInfo(uint256 origtxid)
161 {
162     UniValue result(UniValue::VOBJ),a(UniValue::VARR),obj(UniValue::VOBJ);
163     std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
164     CTransaction regtx,tx; std::string name,description,format; uint256 hashBlock,txid,oracletxid,batontxid; CPubKey markerpubkey,pk; struct CCcontract_info *cp,C; uint8_t buf33[33]; int64_t datafee,funding; char str[67],markeraddr[64],numstr[64],batonaddr[64]; std::vector <uint8_t> data;
165     cp = CCinit(&C,EVAL_ORACLES);
166     buf33[0] = 0x02;
167     endiancpy(&buf33[1],(uint8_t *)&origtxid,32);
168     markerpubkey = buf2pk(buf33);
169     Getscriptaddress(markeraddr,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG);
170     if ( GetTransaction(origtxid,tx,hashBlock,false) != 0 )
171     {
172         if ( tx.vout.size() > 0 && DecodeOraclesCreateOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,name,description,format) == 'C' )
173         {
174             result.push_back(Pair("result","success"));
175             result.push_back(Pair("txid",uint256_str(str,origtxid)));
176             result.push_back(Pair("name",name));
177             result.push_back(Pair("description",description));
178             result.push_back(Pair("format",format));
179             result.push_back(Pair("marker",markeraddr));
180             SetCCunspents(unspentOutputs,markeraddr);
181             for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
182             {
183                 txid = it->first.txhash;
184                 if ( GetTransaction(txid,regtx,hashBlock,false) != 0 )
185                 {
186                     if ( regtx.vout.size() > 0 && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == origtxid )
187                     {
188                         obj.push_back(Pair("provider",pubkey33_str(str,(uint8_t *)pk.begin())));
189                         Getscriptaddress(batonaddr,regtx.vout[1].scriptPubKey);
190                         batontxid = OracleBatonUtxo(10000,cp,oracletxid,batonaddr,pk,data);
191                         obj.push_back(Pair("baton",batonaddr));
192                         obj.push_back(Pair("batontxid",uint256_str(str,batontxid)));
193                         funding = LifetimeOraclesFunds(cp,oracletxid,pk);
194                         sprintf(numstr,"%.8f",(double)funding/COIN);
195                         obj.push_back(Pair("lifetime",numstr));
196                         funding = AddOracleInputs(cp,mtx,pk,0,0);
197                         sprintf(numstr,"%.8f",(double)funding/COIN);
198                         obj.push_back(Pair("funds",numstr));
199                         sprintf(numstr,"%.8f",(double)datafee/COIN);
200                         obj.push_back(Pair("datafee",numstr));
201                         a.push_back(obj);
202                     }
203                 }
204             }
205             result.push_back(Pair("registered",a));
206         }
207     }
208     return(result);
209 }
210
211 UniValue PricesList()
212 {
213     UniValue result(UniValue::VARR); std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; struct CCcontract_info *cp,C; uint256 txid,hashBlock; CTransaction createtx; std::string name,description,format; char str[65];
214     cp = CCinit(&C,EVAL_ORACLES);
215     SetCCtxids(addressIndex,cp->normaladdr);
216     for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
217     {
218         txid = it->first.txhash;
219         if ( GetTransaction(txid,createtx,hashBlock,false) != 0 )
220         {
221             if ( createtx.vout.size() > 0 && DecodeOraclesCreateOpRet(createtx.vout[createtx.vout.size()-1].scriptPubKey,name,description,format) == 'C' )
222             {
223                 result.push_back(uint256_str(str,txid));
224             }
225         }
226     }
227     return(result);
228 }
229 */
This page took 0.037334 seconds and 4 git commands to generate.