1 /******************************************************************************
2 * Copyright © 2014-2018 The SuperNET Developers. *
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. *
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 *
12 * Removal or modification of this copyright notice is prohibited. *
14 ******************************************************************************/
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.
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.
23 int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format);
25 Using the above function, a consensus price can be obtained for a datasource.
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!
29 Funds work like with dice, ie. there is a Prices plan that traders bet against.
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
39 // start of consensus code
41 int64_t IsPricesvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
44 if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
46 if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 )
47 return(tx.vout[v].nValue);
52 bool PricesExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee)
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++)
60 //fprintf(stderr,"vini.%d\n",i);
61 if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
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");
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 )
76 for (i=0; i<numvouts; i++)
78 //fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
79 if ( (assetoshis= IsPricesvout(cp,tx,i)) != 0 )
80 outputs += assetoshis;
82 if ( inputs != outputs+txfee )
84 fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
85 return eval->Invalid("mismatched inputs != outputs + txfee");
90 bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
92 int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
94 std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
95 numvins = tx.vin.size();
96 numvouts = tx.vout.size();
97 preventCCvins = preventCCvouts = -1;
99 return eval->Invalid("no vouts");
102 for (i=0; i<numvins; i++)
104 if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
106 return eval->Invalid("illegal normal vini");
109 //fprintf(stderr,"check amounts\n");
110 if ( PricesExactAmounts(cp,eval,tx,1,10000) == false )
112 fprintf(stderr,"Pricesget invalid amount\n");
118 memcpy(hash,&txid,sizeof(hash));
119 retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
121 fprintf(stderr,"Pricesget validated\n");
122 else fprintf(stderr,"Pricesget invalid\n");
127 // end of consensus code
129 // helper functions for rpc calls in rpcwallet.cpp
131 int64_t AddPricesInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs)
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++)
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 )
144 if ( (nValue= IsPricesvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 )
146 if ( total != 0 && maxinputs != 0 )
147 mtx.vin.push_back(CTxIn(txid,vout,CScript()));
148 nValue = it->second.satoshis;
149 totalinputs += nValue;
151 if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
160 UniValue PriceInfo(uint256 origtxid)
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);
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 )
172 if ( tx.vout.size() > 0 && DecodeOraclesCreateOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,name,description,format) == 'C' )
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++)
183 txid = it->first.txhash;
184 if ( GetTransaction(txid,regtx,hashBlock,false) != 0 )
186 if ( regtx.vout.size() > 0 && DecodeOraclesOpRet(regtx.vout[regtx.vout.size()-1].scriptPubKey,oracletxid,pk,datafee) == 'R' && oracletxid == origtxid )
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));
205 result.push_back(Pair("registered",a));
211 UniValue PricesList()
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++)
218 txid = it->first.txhash;
219 if ( GetTransaction(txid,createtx,hashBlock,false) != 0 )
221 if ( createtx.vout.size() > 0 && DecodeOraclesCreateOpRet(createtx.vout[createtx.vout.size()-1].scriptPubKey,name,description,format) == 'C' )
223 result.push_back(uint256_str(str,txid));