@@ -524,6 +524,11 @@ if GLIBC_BACK_COMPAT
|
||||
libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp
|
||||
endif
|
||||
|
||||
if ENABLE_TESTS
|
||||
libbitcoin_server_a_SOURCES += rpc/testtransactions.cpp
|
||||
endif
|
||||
|
||||
|
||||
# cli: zcash-cli
|
||||
libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
|
||||
libbitcoin_cli_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
|
||||
@@ -51,3 +51,4 @@ echo $pubkey
|
||||
./komodod -pubkey=$pubkey -ac_name=MORTY -ac_supply=90000000000 -ac_reward=100000000 -ac_cc=3 -addnode=138.201.136.145 &
|
||||
./komodod -pubkey=$pubkey -ac_name=VOTE2019 -ac_supply=123651638 -ac_public=1 -addnode=95.213.238.98 &
|
||||
./komodod -pubkey=$pubkey -ac_name=KOIN -ac_supply=125000000 -addnode=3.0.32.10 &
|
||||
~/hush3/src/komodod -pubkey=$pubkey -ac_name=HUSH3 -ac_sapling=1 -ac_reward=0,1125000000,562500000 -ac_halving=129,340000,840000 -ac_end=128,340000,5422111 -ac_eras=3 -ac_blocktime=150 -ac_cc=2 -ac_ccenable=228,234,235,236,241 -ac_founders=1 -ac_supply=6178674 -ac_perc=11111111 -clientname=GoldenSandtrout -addnode=188.165.212.101 -ac_cclib=hush3 -ac_script=76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac &
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
|
||||
#include "CCinclude.h"
|
||||
#include <gmp.h>
|
||||
#include <key_io.h>
|
||||
|
||||
#define PAYMENTS_TXFEE 10000
|
||||
#define PAYMENTS_MERGEOFSET 10 // 100?
|
||||
#define PAYMENTS_MERGEOFSET 60 // 1H extra.
|
||||
extern std::vector <std::pair<CAmount, CTxDestination>> vAddressSnapshot;
|
||||
extern int32_t lastSnapShotHeight;
|
||||
|
||||
@@ -34,6 +35,7 @@ UniValue PaymentsMerge(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsAirdropTokens(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr);
|
||||
|
||||
|
||||
@@ -17,34 +17,41 @@
|
||||
#ifndef CC_PRICES_H
|
||||
#define CC_PRICES_H
|
||||
|
||||
#include "komodo_defs.h"
|
||||
#include "CCinclude.h"
|
||||
int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks);
|
||||
extern void GetKomodoEarlytxidScriptPub();
|
||||
extern CScript KOMODO_EARLYTXID_SCRIPTPUB;
|
||||
|
||||
#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1)
|
||||
// #define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1) // defined in komodo_defs.h
|
||||
#define PRICES_TXFEE 10000
|
||||
#define PRICES_MAXLEVERAGE 777
|
||||
#define PRICES_SMOOTHWIDTH 1
|
||||
#define KOMODO_MAXPRICES 2048 // must be power of 2 and less than 8192
|
||||
#define KOMODO_PRICEMASK (~(KOMODO_MAXPRICES - 1))
|
||||
#define PRICES_WEIGHT (KOMODO_MAXPRICES * 1)
|
||||
#define PRICES_MULT (KOMODO_MAXPRICES * 2)
|
||||
#define PRICES_DIV (KOMODO_MAXPRICES * 3)
|
||||
#define PRICES_INV (KOMODO_MAXPRICES * 4)
|
||||
#define PRICES_MDD (KOMODO_MAXPRICES * 5)
|
||||
#define PRICES_MMD (KOMODO_MAXPRICES * 6)
|
||||
#define PRICES_MMM (KOMODO_MAXPRICES * 7)
|
||||
#define PRICES_DDD (KOMODO_MAXPRICES * 8)
|
||||
#define KOMODO_PRICEMASK (~(KOMODO_MAXPRICES - 1)) // actually 1111 1000 0000 0000
|
||||
#define PRICES_WEIGHT (KOMODO_MAXPRICES * 1) // 0000 1000 0000 0000
|
||||
#define PRICES_MULT (KOMODO_MAXPRICES * 2) // 0001 0000 0000 0000
|
||||
#define PRICES_DIV (KOMODO_MAXPRICES * 3) // 0001 1000 0000 0000
|
||||
#define PRICES_INV (KOMODO_MAXPRICES * 4) // 0010 0000 0000 0000
|
||||
#define PRICES_MDD (KOMODO_MAXPRICES * 5) // 0010 1000 0000 0000
|
||||
#define PRICES_MMD (KOMODO_MAXPRICES * 6) // 0011 0000 0000 0000
|
||||
#define PRICES_MMM (KOMODO_MAXPRICES * 7) // 0011 1000 0000 0000
|
||||
#define PRICES_DDD (KOMODO_MAXPRICES * 8) // 0100 0000 0000 0000
|
||||
|
||||
#define PRICES_NORMFACTOR (int64_t)(SATOSHIDEN)
|
||||
#define PRICES_POINTFACTOR (int64_t)10000
|
||||
|
||||
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue PricesBet(uint64_t txfee,int64_t amount,int16_t leverage,std::vector<std::string> synthetic);
|
||||
UniValue PricesAddFunding(uint64_t txfee,uint256 bettxid,int64_t amount);
|
||||
UniValue PricesSetcostbasis(uint64_t txfee,uint256 bettxid);
|
||||
UniValue PricesRekt(uint64_t txfee,uint256 bettxid,int32_t rektheight);
|
||||
UniValue PricesCashout(uint64_t txfee,uint256 bettxid);
|
||||
UniValue PricesBet(int64_t txfee,int64_t amount,int16_t leverage,std::vector<std::string> synthetic);
|
||||
UniValue PricesAddFunding(int64_t txfee,uint256 bettxid,int64_t amount);
|
||||
UniValue PricesSetcostbasis(int64_t txfee,uint256 bettxid);
|
||||
UniValue PricesRekt(int64_t txfee,uint256 bettxid,int32_t rektheight);
|
||||
UniValue PricesCashout(int64_t txfee,uint256 bettxid);
|
||||
UniValue PricesInfo(uint256 bettxid,int32_t refheight);
|
||||
UniValue PricesList();
|
||||
UniValue PricesList(uint32_t filter, CPubKey mypk);
|
||||
UniValue PricesGetOrderbook();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -251,7 +251,7 @@ void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, c
|
||||
int32_t CClib_initcp(struct CCcontract_info *cp,uint8_t evalcode);
|
||||
|
||||
bool IsCCInput(CScript const& scriptSig);
|
||||
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime);
|
||||
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime,int64_t &actualtxfee);
|
||||
int32_t unstringbits(char *buf,uint64_t bits);
|
||||
uint64_t stringbits(char *str);
|
||||
uint256 revuint256(uint256 txid);
|
||||
@@ -298,6 +298,7 @@ UniValue ValueFromAmount(const CAmount& amount);
|
||||
|
||||
int64_t TotalPubkeyNormalInputs(const CTransaction &tx, const CPubKey &pubkey);
|
||||
int64_t TotalPubkeyCCInputs(const CTransaction &tx, const CPubKey &pubkey);
|
||||
inline std::string STR_TOLOWER(const std::string &str) { std::string out; for (std::string::const_iterator i = str.begin(); i != str.end(); i++) out += std::tolower(*i); return out; }
|
||||
|
||||
// bitcoin LogPrintStr with category "-debug" cmdarg support for C++ ostringstream:
|
||||
#define CCLOG_INFO 0
|
||||
|
||||
@@ -937,6 +937,12 @@ UniValue TokenInfo(uint256 tokenid)
|
||||
result.push_back(Pair("error", "cant find tokenid"));
|
||||
return(result);
|
||||
}
|
||||
if (hashBlock.IsNull()) {
|
||||
result.push_back(Pair("result", "error"));
|
||||
result.push_back(Pair("error", "the transaction is still in mempool"));
|
||||
return(result);
|
||||
}
|
||||
|
||||
if (tokenbaseTx.vout.size() > 0 && DecodeTokenCreateOpRet(tokenbaseTx.vout[tokenbaseTx.vout.size() - 1].scriptPubKey, origpubkey, name, description, oprets) != 'c')
|
||||
{
|
||||
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenInfo() passed tokenid isnt token creation txid" << std::endl);
|
||||
|
||||
@@ -241,7 +241,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
|
||||
{
|
||||
char coinaddr[64];
|
||||
GetCCaddress1of2(cp,coinaddr,globalpk,pubkeys[i]);
|
||||
fprintf(stderr,"%s + %s -> %s vs %s\n",HexStr(globalpk).c_str(),HexStr(pubkeys[i]).c_str(),coinaddr,destaddr);
|
||||
//fprintf(stderr,"%s + %s -> %s vs %s\n",HexStr(globalpk).c_str(),HexStr(pubkeys[i]).c_str(),coinaddr,destaddr);
|
||||
if ( strcmp(destaddr,coinaddr) == 0 )
|
||||
{
|
||||
privkey = cp->CCpriv;
|
||||
|
||||
@@ -64,7 +64,7 @@ int32_t has_opret(const CTransaction &tx, uint8_t evalcode)
|
||||
for ( auto vout : tx.vout )
|
||||
{
|
||||
//fprintf(stderr, "[txid.%s] 1.%i 2.%i 3.%i 4.%i\n",tx.GetHash().GetHex().c_str(), vout.scriptPubKey[0], vout.scriptPubKey[1], vout.scriptPubKey[2], vout.scriptPubKey[3]);
|
||||
if ( vout.scriptPubKey.size() > 2 && vout.scriptPubKey[0] == OP_RETURN && vout.scriptPubKey[2] == evalcode )
|
||||
if ( vout.scriptPubKey.size() > 3 && vout.scriptPubKey[0] == OP_RETURN && vout.scriptPubKey[2] == evalcode )
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
@@ -150,7 +150,7 @@ bool IsCCInput(CScript const& scriptSig)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime)
|
||||
bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_t blocktime, int64_t &actualtxfee)
|
||||
{
|
||||
LOCK(mempool.cs);
|
||||
CCoinsView dummy;
|
||||
@@ -159,9 +159,10 @@ bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_
|
||||
CCoinsViewMemPool viewMemPool(pcoinsTip, mempool);
|
||||
view.SetBackend(viewMemPool);
|
||||
valuein = view.GetValueIn(height,&interest,tx,blocktime);
|
||||
if ( valuein-tx.GetValueOut() > txfee )
|
||||
actualtxfee = valuein-tx.GetValueOut();
|
||||
if ( actualtxfee > txfee )
|
||||
{
|
||||
//fprintf(stderr, "txfee.%li vs txfee.%li\n", valuein-tx.GetValueOut(), txfee);
|
||||
fprintf(stderr, "actualtxfee.%li vs txfee.%li\n", actualtxfee, txfee);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -7,14 +7,14 @@ make -f Makefile_rogue
|
||||
rm ../libcc.so
|
||||
cp librogue.so ../libcc.so
|
||||
|
||||
#echo sudoku/musig/dilithium
|
||||
#gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o sudokucc.so cclib.cpp
|
||||
echo sudoku/musig/dilithium
|
||||
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o sudokucc.so cclib.cpp
|
||||
|
||||
#echo games tetris
|
||||
#./maketetris
|
||||
echo games tetris
|
||||
./maketetris
|
||||
|
||||
#echo games prices
|
||||
#./makeprices
|
||||
echo games prices
|
||||
./makeprices
|
||||
|
||||
#echo customcc stub
|
||||
#gcc -O3 -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o customcc.so cclib.cpp
|
||||
echo customcc stub
|
||||
gcc -O3 -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o customcc.so cclib.cpp
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/sh
|
||||
gcc -O3 -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o customcc.so cclib.cpp
|
||||
cp customcc.so ../libcc.so
|
||||
#cd ..
|
||||
#make
|
||||
#cd cc
|
||||
|
||||
cd ..
|
||||
make
|
||||
cd cc
|
||||
|
||||
@@ -137,6 +137,26 @@ uint8_t DecodePaymentsMergeOpRet(CScript scriptPubKey,uint256 &checktxid)
|
||||
return(0);
|
||||
}
|
||||
|
||||
CScript EncodePaymentsReleaseOpRet(uint256 checktxid, int64_t amountReleased)
|
||||
{
|
||||
CScript opret; uint8_t evalcode = EVAL_PAYMENTS;
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'R' << checktxid << amountReleased);
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t DecodePaymentsReleaseOpRet(CScript scriptPubKey,uint256 &checktxid,int64_t &amountReleased)
|
||||
{
|
||||
std::vector<uint8_t> vopret; uint8_t *script,e,f;
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
script = (uint8_t *)vopret.data();
|
||||
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> checktxid; ss >> amountReleased) != 0 )
|
||||
{
|
||||
if ( e == EVAL_PAYMENTS && f == 'R' )
|
||||
return(f);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
CScript EncodePaymentsOpRet(int32_t lockedblocks,int32_t minrelease,int64_t totalallocations,std::vector<uint256> txidoprets)
|
||||
{
|
||||
CScript opret; uint8_t evalcode = EVAL_PAYMENTS;
|
||||
@@ -160,13 +180,7 @@ uint8_t DecodePaymentsOpRet(CScript scriptPubKey,int32_t &lockedblocks,int32_t &
|
||||
CScript EncodePaymentsSnapsShotOpRet(int32_t lockedblocks,int32_t minrelease,int32_t minimum,int32_t top,int32_t bottom,int8_t fixedAmount,std::vector<std::vector<uint8_t>> excludeScriptPubKeys)
|
||||
{
|
||||
CScript opret; uint8_t evalcode = EVAL_PAYMENTS;
|
||||
if ( (strcmp(ASSETCHAINS_SYMBOL, "CFEKPAY") == 0) ) // exempt for now, remove this after game completed.
|
||||
{
|
||||
minimum = 10000;
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'S' << lockedblocks << minrelease << top << bottom << fixedAmount << excludeScriptPubKeys);
|
||||
}
|
||||
else
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'S' << lockedblocks << minrelease << minimum << top << bottom << fixedAmount << excludeScriptPubKeys);
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'S' << lockedblocks << minrelease << minimum << top << bottom << fixedAmount << excludeScriptPubKeys);
|
||||
return(opret);
|
||||
}
|
||||
|
||||
@@ -175,40 +189,27 @@ uint8_t DecodePaymentsSnapsShotOpRet(CScript scriptPubKey,int32_t &lockedblocks,
|
||||
std::vector<uint8_t> vopret; uint8_t *script,e,f;
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
script = (uint8_t *)vopret.data();
|
||||
if ( (strcmp(ASSETCHAINS_SYMBOL, "CFEKPAY") == 0) ) // exempt for now, remove this after game completed.
|
||||
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> lockedblocks; ss >> minrelease; ss >> minimum; ss >> top; ; ss >> bottom; ss >> fixedAmount; ss >> excludeScriptPubKeys) != 0 )
|
||||
{
|
||||
minimum = 10000;
|
||||
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> lockedblocks; ss >> minrelease; ss >> top; ; ss >> bottom; ss >> fixedAmount; ss >> excludeScriptPubKeys) != 0 )
|
||||
{
|
||||
if ( e == EVAL_PAYMENTS && f == 'S' )
|
||||
return(f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> lockedblocks; ss >> minrelease; ss >> minimum; ss >> top; ; ss >> bottom; ss >> fixedAmount; ss >> excludeScriptPubKeys) != 0 )
|
||||
{
|
||||
if ( e == EVAL_PAYMENTS && f == 'S' )
|
||||
return(f);
|
||||
}
|
||||
if ( e == EVAL_PAYMENTS && f == 'S' )
|
||||
return(f);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
CScript EncodePaymentsTokensOpRet(int32_t lockedblocks,int32_t minrelease,int32_t top,std::vector<std::vector<uint8_t>> excludeScriptPubKeys, uint256 tokenid)
|
||||
CScript EncodePaymentsTokensOpRet(int32_t lockedblocks,int32_t minrelease,int32_t minimum,int32_t top,int32_t bottom,int8_t fixedAmount,std::vector<std::vector<uint8_t>> excludeScriptPubKeys,uint256 tokenid)
|
||||
{
|
||||
CScript opret; uint8_t evalcode = EVAL_PAYMENTS;
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'O' << lockedblocks << minrelease << top << excludeScriptPubKeys << tokenid);
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'O' << lockedblocks << minrelease << minimum << top << bottom << fixedAmount << excludeScriptPubKeys << tokenid);
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t DecodePaymentsTokensOpRet(CScript scriptPubKey,int32_t &lockedblocks,int32_t &minrelease,int32_t &top,std::vector<std::vector<uint8_t>> &excludeScriptPubKeys, uint256 &tokenid)
|
||||
uint8_t DecodePaymentsTokensOpRet(CScript scriptPubKey,int32_t &lockedblocks,int32_t &minrelease,int32_t &minimum,int32_t &top,int32_t &bottom,int8_t &fixedAmount,std::vector<std::vector<uint8_t>> &excludeScriptPubKeys, uint256 &tokenid)
|
||||
{
|
||||
std::vector<uint8_t> vopret; uint8_t *script,e,f;
|
||||
GetOpReturnData(scriptPubKey, vopret);
|
||||
script = (uint8_t *)vopret.data();
|
||||
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> lockedblocks; ss >> minrelease; ss >> top; ss >> excludeScriptPubKeys; ss >> tokenid) != 0 )
|
||||
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> lockedblocks; ss >> minimum; ss >> top; ; ss >> bottom; ss >> fixedAmount; ss >> excludeScriptPubKeys; ss >> tokenid) != 0 )
|
||||
{
|
||||
if ( e == EVAL_PAYMENTS && f == 'O' )
|
||||
return(f);
|
||||
@@ -219,7 +220,6 @@ uint8_t DecodePaymentsTokensOpRet(CScript scriptPubKey,int32_t &lockedblocks,int
|
||||
int64_t IsPaymentsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v,char *cmpaddr, CScript &ccopret)
|
||||
{
|
||||
char destaddr[64];
|
||||
//if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
|
||||
if ( getCCopret(tx.vout[v].scriptPubKey, ccopret) )
|
||||
{
|
||||
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && (cmpaddr[0] == 0 || strcmp(destaddr,cmpaddr) == 0) )
|
||||
@@ -228,22 +228,6 @@ int64_t IsPaymentsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t
|
||||
return(0);
|
||||
}
|
||||
|
||||
void pub2createtxid(char *str)
|
||||
{
|
||||
int i,n;
|
||||
char *rev;
|
||||
n = (int32_t)strlen(str);
|
||||
rev = (char *)malloc(n + 1);
|
||||
for (i=0; i<n; i+=2)
|
||||
{
|
||||
rev[n-2-i] = str[i];
|
||||
rev[n-1-i] = str[i+1];
|
||||
}
|
||||
rev[n] = 0;
|
||||
strcpy(str,rev);
|
||||
free(rev);
|
||||
}
|
||||
|
||||
bool payments_game(int32_t &top, int32_t &bottom)
|
||||
{
|
||||
uint64_t x;
|
||||
@@ -255,7 +239,7 @@ bool payments_game(int32_t &top, int32_t &bottom)
|
||||
if ( top < 50 ) top += 50;
|
||||
bottom = (vAddressSnapshot.size()*bottom)/100;
|
||||
top = (vAddressSnapshot.size()*top)/100;
|
||||
fprintf(stderr, "bottom.%i top.%i\n",bottom,top);
|
||||
//fprintf(stderr, "bottom.%i top.%i\n",bottom,top);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -272,69 +256,102 @@ bool payments_lockedblocks(uint256 blockhash,int32_t lockedblocks,int32_t &block
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t payments_getallocations(int32_t top, int32_t bottom, const std::vector<std::vector<uint8_t>> &excludeScriptPubKeys, mpz_t &mpzTotalAllocations, std::vector<CScript> &scriptPubKeys, std::vector<int64_t> &allocations)
|
||||
{
|
||||
mpz_t mpzAllocation; int32_t i =0;
|
||||
for (int32_t j = bottom; j < vAddressSnapshot.size(); j++)
|
||||
{
|
||||
auto &address = vAddressSnapshot[j];
|
||||
CScript scriptPubKey = GetScriptForDestination(address.second);
|
||||
bool skip = false;
|
||||
// skip excluded addresses.
|
||||
for ( auto skipkey : excludeScriptPubKeys )
|
||||
{
|
||||
if ( scriptPubKey == CScript(skipkey.begin(), skipkey.end()) )
|
||||
skip = true;
|
||||
}
|
||||
if ( !skip )
|
||||
{
|
||||
mpz_init(mpzAllocation);
|
||||
i++;
|
||||
//fprintf(stderr, "address: %s nValue.%li \n", CBitcoinAddress(address.second).ToString().c_str(), address.first);
|
||||
scriptPubKeys.push_back(scriptPubKey);
|
||||
allocations.push_back(address.first);
|
||||
mpz_set_si(mpzAllocation,address.first);
|
||||
mpz_add(mpzTotalAllocations,mpzTotalAllocations,mpzAllocation);
|
||||
mpz_clear(mpzAllocation);
|
||||
}
|
||||
if ( i+bottom == top )
|
||||
break; // we reached top amount to pay, it can be less than this, if less address exist on chain, return the number we got.
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
int32_t payments_gettokenallocations(int32_t top, int32_t bottom, const std::vector<std::vector<uint8_t>> &excludeScriptPubKeys, uint256 tokenid, mpz_t &mpzTotalAllocations, std::vector<CScript> &scriptPubKeys, std::vector<int64_t> &allocations)
|
||||
{
|
||||
/*
|
||||
- check tokenid exists.
|
||||
- iterate tokenid address and extract all pubkeys, add to map.
|
||||
- rewind to last notarized height for balances?
|
||||
- convert balances to mpz_t and add up totalallocations
|
||||
- sort the map into a vector, then convert to the correct output.
|
||||
*/
|
||||
return(0);
|
||||
}
|
||||
|
||||
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
// one of two addresses
|
||||
// change must go to 1of2 txidaddr
|
||||
// change is/must be in vout[0]
|
||||
// only 'F' or 1of2 txidaddr can be spent
|
||||
// all vouts must match exactly
|
||||
char temp[128], coinaddr[64]={0}, txidaddr[64]; std::string scriptpubkey; uint256 createtxid, blockhash, tokenid; CTransaction plantx; int8_t funcid=0, fixedAmount=0;
|
||||
int32_t i,lockedblocks,minrelease; int64_t change,totalallocations; std::vector<uint256> txidoprets; bool fHasOpret = false,fIsMerge = false; CPubKey txidpk,Paymentspk;
|
||||
int32_t top,bottom=0,minimum=10000; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; bool fFixedAmount = false; CScript ccopret;
|
||||
mpz_t mpzTotalAllocations, mpzAllocation;; mpz_init(mpzTotalAllocations);
|
||||
// user marker vout to get the createtxid
|
||||
if ( tx.vout.size() == 1 )
|
||||
char temp[128], txidaddr[64]={0}; std::string scriptpubkey; uint256 createtxid, blockhash, tokenid; CTransaction plantx; int8_t funcid=0, fixedAmount=0;
|
||||
int32_t i,lockedblocks,minrelease,blocksleft,dust = 0, top,bottom=0,minimum=10000; int64_t change,totalallocations,actualtxfee,amountReleased=0; std::vector<uint256> txidoprets; bool fHasOpret = false,fIsMerge = false; CPubKey txidpk,Paymentspk;
|
||||
std::vector<std::vector<uint8_t>> excludeScriptPubKeys; bool fFixedAmount = false; CScript ccopret;
|
||||
mpz_t mpzTotalAllocations,mpzAllocation,mpzCheckamount;
|
||||
mpz_init(mpzCheckamount); mpz_init(mpzTotalAllocations);
|
||||
// Check change is in vout[0], and also fetch the ccopret to determine what type of tx this is. txidaddr is unknown, recheck this later.
|
||||
if ( (change= IsPaymentsvout(cp,tx,0,txidaddr,ccopret)) != 0 && ccopret.size() > 2 )
|
||||
{
|
||||
if ( IsPaymentsvout(cp,tx,0,coinaddr,ccopret) != 0 && ccopret.size() > 2 && DecodePaymentsMergeOpRet(ccopret,createtxid) )
|
||||
{
|
||||
// get the checktxid and the amount released if doing release tx.
|
||||
if ( DecodePaymentsMergeOpRet(ccopret,createtxid) == 'M' )
|
||||
fIsMerge = true;
|
||||
} else return(eval->Invalid("not enough vouts"));
|
||||
}
|
||||
else if ( tx.vout.back().scriptPubKey[0] == OP_RETURN )
|
||||
{
|
||||
scriptpubkey = HexStr(tx.vout[tx.vout.size()-2].scriptPubKey.begin()+2, tx.vout[tx.vout.size()-2].scriptPubKey.end()-1);
|
||||
fHasOpret = true;
|
||||
}
|
||||
else scriptpubkey = HexStr(tx.vout[tx.vout.size()-1].scriptPubKey.begin()+2,tx.vout[tx.vout.size()-1].scriptPubKey.end()-1);
|
||||
if ( !fIsMerge )
|
||||
{
|
||||
strcpy(temp, scriptpubkey.c_str());
|
||||
pub2createtxid(temp);
|
||||
createtxid = Parseuint256(temp);
|
||||
}
|
||||
//printf("createtxid.%s\n",createtxid.ToString().c_str());
|
||||
else if ( DecodePaymentsReleaseOpRet(ccopret,createtxid,amountReleased) != 'R' )
|
||||
return(eval->Invalid("could not decode ccopret"));
|
||||
mpz_set_si(mpzCheckamount,amountReleased);
|
||||
} else return(eval->Invalid("could not decode ccopret"));
|
||||
|
||||
// use the createtxid to fetch the tx and all of the plans info.
|
||||
if ( myGetTransaction(createtxid,plantx,blockhash) != 0 && plantx.vout.size() > 0 )
|
||||
{
|
||||
if ( ((funcid= DecodePaymentsOpRet(plantx.vout[plantx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets)) == 'C' || (funcid= DecodePaymentsSnapsShotOpRet(plantx.vout[plantx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys)) == 'S' || (funcid= DecodePaymentsTokensOpRet(plantx.vout[plantx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,top,excludeScriptPubKeys,tokenid)) == 'O') )
|
||||
if ( ((funcid= DecodePaymentsOpRet(plantx.vout[plantx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets)) == 'C' || (funcid= DecodePaymentsSnapsShotOpRet(plantx.vout[plantx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys)) == 'S' || (funcid= DecodePaymentsTokensOpRet(plantx.vout[plantx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys,tokenid)) == 'O') )
|
||||
{
|
||||
if ( lockedblocks < 0 || minrelease < 0 || (totalallocations <= 0 && top <= 0 ) )
|
||||
return(eval->Invalid("negative values"));
|
||||
if ( minimum < 10000 )
|
||||
return(eval->Invalid("minimum must be over 10000"));
|
||||
if ( amountReleased < minrelease*COIN )
|
||||
{
|
||||
fprintf(stderr, "does not meet minrelease amount.%li minrelease.%li\n",amountReleased, (int64_t)minrelease*COIN);
|
||||
return(eval->Invalid("amount is too small"));
|
||||
}
|
||||
Paymentspk = GetUnspendable(cp,0);
|
||||
txidpk = CCtxidaddr(txidaddr,createtxid);
|
||||
GetCCaddress1of2(cp,coinaddr,Paymentspk,txidpk);
|
||||
GetCCaddress1of2(cp,txidaddr,Paymentspk,txidpk);
|
||||
//fprintf(stderr, "lockedblocks.%i minrelease.%i totalallocations.%i txidopret1.%s txidopret2.%s\n",lockedblocks, minrelease, totalallocations, txidoprets[0].ToString().c_str(), txidoprets[1].ToString().c_str() );
|
||||
if ( !CheckTxFee(tx, PAYMENTS_TXFEE+1, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
|
||||
if ( !CheckTxFee(tx, PAYMENTS_TXFEE+1, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime, actualtxfee) )
|
||||
return eval->Invalid("txfee is too high");
|
||||
// make sure change is in vout 0 and is paying to the contract address.
|
||||
if ( (change= IsPaymentsvout(cp,tx,0,coinaddr,ccopret)) == 0 )
|
||||
return(eval->Invalid("change is in wrong vout or is wrong tx type"));
|
||||
|
||||
// Check that the change vout is playing the txid address.
|
||||
if ( IsPaymentsvout(cp,tx,0,txidaddr,ccopret) == 0 )
|
||||
return eval->Invalid("change pays wrong address");
|
||||
|
||||
if ( !fIsMerge )
|
||||
{
|
||||
// Get all the script pubkeys and allocations
|
||||
std::vector<int64_t> allocations;
|
||||
std::vector<CScript> scriptPubKeys;
|
||||
int64_t checkallocations = 0;
|
||||
i = 0;
|
||||
if ( funcid == 'C' )
|
||||
{
|
||||
// normal payment
|
||||
for (const uint256& txidopret : txidoprets)
|
||||
int64_t checkallocations = 0;
|
||||
for ( auto txidopret : txidoprets)
|
||||
{
|
||||
CTransaction tx0; std::vector<uint8_t> scriptPubKey,opret; int64_t allocation;
|
||||
if ( myGetTransaction(txidopret,tx0,blockhash) != 0 && tx0.vout.size() > 1 && DecodePaymentsTxidOpRet(tx0.vout[tx0.vout.size()-1].scriptPubKey,allocation,scriptPubKey,opret) == 'T' )
|
||||
@@ -360,10 +377,14 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
}
|
||||
i++;
|
||||
}
|
||||
//fprintf(stderr, "totalallocations.%li checkallocations.%li\n",totalallocations, checkallocations);
|
||||
if ( totalallocations != checkallocations )
|
||||
return(eval->Invalid("allocation missmatch"));
|
||||
mpz_set_si(mpzTotalAllocations,totalallocations);
|
||||
}
|
||||
else if ( funcid == 'S' )
|
||||
else if ( funcid == 'S' || funcid == 'O' )
|
||||
{
|
||||
// snapshot payment
|
||||
if ( KOMODO_SNAPSHOT_INTERVAL == 0 )
|
||||
return(eval->Invalid("snapshots not activated on this chain"));
|
||||
if ( vAddressSnapshot.size() == 0 )
|
||||
@@ -379,132 +400,115 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
{
|
||||
fFixedAmount = true;
|
||||
}
|
||||
for (int32_t j = bottom; j < vAddressSnapshot.size(); j++)
|
||||
if ( funcid == 'S' )
|
||||
payments_getallocations(top, bottom, excludeScriptPubKeys, mpzTotalAllocations, scriptPubKeys, allocations);
|
||||
else
|
||||
{
|
||||
auto &address = vAddressSnapshot[j];
|
||||
CScript scriptPubKey = GetScriptForDestination(address.second); bool skip = false;
|
||||
for ( auto skipkey : excludeScriptPubKeys )
|
||||
{
|
||||
if ( scriptPubKey == CScript(skipkey.begin(), skipkey.end()) )
|
||||
{
|
||||
skip = true;
|
||||
//fprintf(stderr, "SKIPPED::: %s\n", CBitcoinAddress(address.second).ToString().c_str());
|
||||
}
|
||||
}
|
||||
if ( !skip )
|
||||
{
|
||||
mpz_init(mpzAllocation);
|
||||
i++;
|
||||
scriptPubKeys.push_back(scriptPubKey);
|
||||
allocations.push_back(address.first);
|
||||
mpz_set_si(mpzAllocation,address.first);
|
||||
mpz_add(mpzTotalAllocations,mpzTotalAllocations,mpzAllocation);
|
||||
mpz_clear(mpzAllocation);
|
||||
}
|
||||
if ( i+bottom == top ) // we reached top amount to pay, it can be less than this!
|
||||
break;
|
||||
// token snapshot
|
||||
// payments_gettokenallocations(top, bottom, excludeScriptPubKeys, tokenid, mpzTotalAllocations, scriptPubKeys, allocations);
|
||||
}
|
||||
if ( i != tx.vout.size()-2 )
|
||||
return(eval->Invalid("pays wrong amount of recipients"));
|
||||
}
|
||||
else if ( funcid == 'O' )
|
||||
{
|
||||
// tokens snapshot.
|
||||
}
|
||||
// sanity check to make sure we got all the required info, skip for merge type tx
|
||||
//fprintf(stderr, " allocations.size().%li scriptPubKeys.size.%li\n",allocations.size(), scriptPubKeys.size());
|
||||
if ( (allocations.size() == 0 || scriptPubKeys.size() == 0 || allocations.size() != scriptPubKeys.size()) )
|
||||
return(eval->Invalid("missing data cannot validate"));
|
||||
|
||||
//fprintf(stderr, "totalallocations.%li checkallocations.%li\n",totalallocations, checkallocations);
|
||||
if ( funcid == 'C' && totalallocations != checkallocations ) // only check for normal payments release.
|
||||
return(eval->Invalid("allocation missmatch"));
|
||||
|
||||
// Check vouts go to the right place and pay the right amounts.
|
||||
int64_t amount = 0, checkamount; int32_t n = 0;
|
||||
checkamount = tx.GetValueOut() - change - PAYMENTS_TXFEE;
|
||||
mpz_t mpzCheckamount; mpz_init(mpzCheckamount); mpz_set_si(mpzCheckamount,checkamount);
|
||||
for (i = 1; i < (fHasOpret ? tx.vout.size()-2 : tx.vout.size()-1); i++)
|
||||
int64_t amount = 0; int32_t n = 0;
|
||||
// We place amount released into ccopret, so that these calcualtion are accurate!
|
||||
// If you change the amount released in the RPC these calcs will be wrong, and validation will fail.
|
||||
for (i = 1; i < (fHasOpret ? tx.vout.size()-1 : tx.vout.size()); i++)
|
||||
{
|
||||
int64_t test;
|
||||
if ( scriptPubKeys[n] != tx.vout[i].scriptPubKey )
|
||||
{
|
||||
fprintf(stderr, "pays wrong destination destscriptPubKey.%s voutscriptPubKey.%s\n", HexStr(scriptPubKeys[n].begin(),scriptPubKeys[n].end()).c_str(), HexStr(tx.vout[i].scriptPubKey.begin(),tx.vout[i].scriptPubKey.end()).c_str());
|
||||
return(eval->Invalid("pays wrong address"));
|
||||
}
|
||||
int64_t test;
|
||||
if ( fFixedAmount )
|
||||
{
|
||||
test = checkamount / (top-bottom);
|
||||
if ( (top-bottom) > 0 )
|
||||
test = amountReleased / (top-bottom);
|
||||
else
|
||||
return(eval->Invalid("top/bottom range is illegal"));
|
||||
}
|
||||
else
|
||||
{
|
||||
mpz_init(mpzAllocation);
|
||||
mpz_set_si(mpzAllocation,allocations[n]);
|
||||
mpz_mul(mpzAllocation,mpzAllocation,mpzCheckamount);
|
||||
mpz_cdiv_q(mpzAllocation,mpzAllocation,mpzTotalAllocations);
|
||||
mpz_tdiv_q(mpzAllocation,mpzAllocation,mpzTotalAllocations);
|
||||
test = mpz_get_si(mpzAllocation);
|
||||
mpz_clear(mpzAllocation);
|
||||
}
|
||||
// Vairance of 1 sat is allowed, for rounding errors.
|
||||
if ( test >= tx.vout[i].nValue+1 && test <= tx.vout[i].nValue-1 )
|
||||
//fprintf(stderr, "vout %i test.%li nValue.%li\n", i, test, tx.vout[i].nValue);
|
||||
if ( test != tx.vout[i].nValue )
|
||||
{
|
||||
fprintf(stderr, "vout.%i test.%li vs nVlaue.%li\n",i, test, tx.vout[i].nValue);
|
||||
return(eval->Invalid("amounts do not match"));
|
||||
}
|
||||
if ( test < minimum )
|
||||
{
|
||||
// prevent anyone being paid the minimum.
|
||||
fprintf(stderr, "vout.%i test.%li vs minimum.%i\n",i, test, minimum);
|
||||
return(eval->Invalid("under minimum size"));
|
||||
}
|
||||
amount += tx.vout[i].nValue;
|
||||
n++;
|
||||
}
|
||||
mpz_clear(mpzTotalAllocations);
|
||||
// This is a backup check to make sure there are no extra vouts paying something else!
|
||||
if ( checkamount != amount )
|
||||
return(eval->Invalid("amounts do not match"));
|
||||
|
||||
if ( amount < minrelease*COIN )
|
||||
if ( allocations.size() > n )
|
||||
{
|
||||
fprintf(stderr, "does not meet minrelease amount.%li minrelease.%li\n",amount, (int64_t)minrelease*COIN );
|
||||
return(eval->Invalid("amount is too small"));
|
||||
// need to check that the next allocation was less than minimum, otherwise ppl can truncate the tx at any place not paying all elegible addresses.
|
||||
mpz_init(mpzAllocation);
|
||||
mpz_set_si(mpzAllocation,allocations[n+1]);
|
||||
mpz_mul(mpzAllocation,mpzAllocation,mpzCheckamount);
|
||||
mpz_tdiv_q(mpzAllocation,mpzAllocation,mpzTotalAllocations);
|
||||
int64_t test = mpz_get_si(mpzAllocation);
|
||||
//fprintf(stderr, "check next vout pays under min: test.%li > minimuim.%i\n", test, minimum);
|
||||
if ( test > minimum )
|
||||
return(eval->Invalid("next allocation was not under minimum"));
|
||||
}
|
||||
mpz_clear(mpzTotalAllocations); mpz_clear(mpzCheckamount);
|
||||
}
|
||||
// Check vins
|
||||
i = 0; int32_t dust = 0;
|
||||
int32_t blocksleft;
|
||||
BOOST_FOREACH(const CTxIn& vin, tx.vin)
|
||||
i = 0;
|
||||
for (auto vin : tx.vin)
|
||||
{
|
||||
CTransaction txin;
|
||||
if ( myGetTransaction(vin.prevout.hash,txin,blockhash) )
|
||||
{
|
||||
// check the vin comes from the CC address's
|
||||
char destaddr[64]; int32_t mergeoffset = 0; CScript opret; uint256 checktxid;
|
||||
Getscriptaddress(destaddr,txin.vout[vin.prevout.n].scriptPubKey);
|
||||
char fromaddr[64]; int32_t mergeoffset = 0; CScript vinccopret; uint256 checktxid;
|
||||
Getscriptaddress(fromaddr,txin.vout[vin.prevout.n].scriptPubKey);
|
||||
if ( fIsMerge && txin.vout[vin.prevout.n].nValue < COIN )
|
||||
dust++;
|
||||
if ( strcmp(destaddr,coinaddr) != 0 )
|
||||
if ( IsPaymentsvout(cp,txin,vin.prevout.n,cp->unspendableCCaddr,vinccopret) != 0 )
|
||||
{
|
||||
// if does not come from address its in the global payments adddress and we need to check the opreturn.
|
||||
uint256 checktxid; int32_t opret_ind;
|
||||
if ( (opret_ind= has_opret(txin, EVAL_PAYMENTS)) == 0 )
|
||||
getCCopret(txin.vout[vin.prevout.n].scriptPubKey,opret); // get op_return from CCvout,
|
||||
else
|
||||
opret = txin.vout[opret_ind].scriptPubKey;
|
||||
if ( DecodePaymentsFundOpRet(opret,checktxid) != 'F' || checktxid != createtxid )
|
||||
// if from global payments address get ccopret to detemine pays correct plan.
|
||||
uint256 checktxid;
|
||||
if ( vinccopret.size() < 2 || DecodePaymentsFundOpRet(vinccopret,checktxid) != 'F' || checktxid != createtxid )
|
||||
{
|
||||
fprintf(stderr, "vin.%i is not a payments CC vout: txid.%s\n", i, txin.GetHash().ToString().c_str());
|
||||
fprintf(stderr, "vin.%i is not a payments CC vout: txid.%s vout.%i\n", i, txin.GetHash().ToString().c_str(), vin.prevout.n);
|
||||
return(eval->Invalid("vin is not paymentsCC type"));
|
||||
}
|
||||
}
|
||||
else if ( fIsMerge && getCCopret(txin.vout[vin.prevout.n].scriptPubKey,opret) && opret.size() > 2 && DecodePaymentsMergeOpRet(opret,checktxid) == 'M' )
|
||||
else if ( IsPaymentsvout(cp,txin,vin.prevout.n,txidaddr,vinccopret) != 0 )
|
||||
{
|
||||
mergeoffset = PAYMENTS_MERGEOFSET;
|
||||
}
|
||||
//fprintf(stderr, "mergeoffset.%i\n", mergeoffset);
|
||||
// if in txid address apply merge offset if applicable.
|
||||
if ( fIsMerge && vinccopret.size() > 2 && DecodePaymentsMergeOpRet(vinccopret,checktxid) == 'M' )
|
||||
{
|
||||
// Apply merge offset to locked blocks, this prevents people spaming payments fund and payments merge to prevent release happening.
|
||||
mergeoffset = PAYMENTS_MERGEOFSET;
|
||||
}
|
||||
}
|
||||
else // not from global payments plan, or txid address.
|
||||
return(eval->Invalid("utxo comes from incorrect address"));
|
||||
// check the chain depth vs locked blocks requirement.
|
||||
if ( !payments_lockedblocks(blockhash, lockedblocks+mergeoffset, blocksleft) )
|
||||
{
|
||||
fprintf(stderr, "vin.%i is not elegible for.%i blocks \n",i, blocksleft);
|
||||
return(eval->Invalid("vin not elegible"));
|
||||
}
|
||||
i++;
|
||||
} else return(eval->Invalid("cant get vin transaction"));
|
||||
}
|
||||
@@ -554,29 +558,23 @@ int64_t AddPaymentsInputs(bool fLockedBlocks,int8_t GetBalance,struct CCcontract
|
||||
//fprintf(stderr,"iter.%d %s/v%d %s\n",iter,txid.GetHex().c_str(),vout,coinaddr);
|
||||
if ( (vout == 0 || vout == 1) && GetTransaction(txid,vintx,hashBlock,false) != 0 )
|
||||
{
|
||||
if ( iter == 0 )
|
||||
{
|
||||
CScript opret; uint256 checktxid; int32_t opret_ind;
|
||||
if ( (opret_ind= has_opret(vintx, EVAL_PAYMENTS)) == 0 )
|
||||
{
|
||||
// get op_return from CCvout
|
||||
getCCopret(vintx.vout[vout].scriptPubKey,opret);
|
||||
}
|
||||
else
|
||||
{
|
||||
// get op_return from the op_return
|
||||
opret = vintx.vout[opret_ind].scriptPubKey;
|
||||
}
|
||||
if ( DecodePaymentsFundOpRet(opret,checktxid) != 'F' || checktxid != createtxid )
|
||||
{
|
||||
fprintf(stderr,"bad opret %s vs %s\n",checktxid.GetHex().c_str(),createtxid.GetHex().c_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( (nValue= IsPaymentsvout(cp,vintx,vout,coinaddr,ccopret)) > PAYMENTS_TXFEE && nValue >= threshold && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
|
||||
{
|
||||
int32_t offset = 0;
|
||||
if ( ccopret.size() > 2 )
|
||||
{
|
||||
if ( iter == 0 && (DecodePaymentsFundOpRet(ccopret,checktxid) != 'F' || checktxid != createtxid) )
|
||||
{
|
||||
// global address but not for this plan.
|
||||
fprintf(stderr,"bad opret %s vs %s\n",checktxid.GetHex().c_str(),createtxid.GetHex().c_str());
|
||||
continue;
|
||||
}
|
||||
// increase merge offset, if this is a merge tx, merging merged utxos.
|
||||
if ( iter == 1 && GetBalance == 4 && DecodePaymentsMergeOpRet(ccopret,checktxid) == 'M' )
|
||||
offset = PAYMENTS_MERGEOFSET;
|
||||
}
|
||||
int32_t tmpblocksleft = 0;
|
||||
if ( fLockedBlocks && !payments_lockedblocks(hashBlock, lockedblocks+(GetBalance == 4 ? PAYMENTS_MERGEOFSET : 0), tmpblocksleft) )
|
||||
if ( fLockedBlocks && !payments_lockedblocks(hashBlock, lockedblocks+offset, tmpblocksleft) )
|
||||
{
|
||||
blocksleft_balance.push_back(std::make_pair(tmpblocksleft,nValue));
|
||||
continue;
|
||||
@@ -584,8 +582,10 @@ int64_t AddPaymentsInputs(bool fLockedBlocks,int8_t GetBalance,struct CCcontract
|
||||
if ( (GetBalance == 0 && total != 0 && maxinputs != 0) || GetBalance == 4 )
|
||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
||||
nValue = it->second.satoshis;
|
||||
if ( nValue < COIN )
|
||||
if ( GetBalance == 4 && nValue < COIN )
|
||||
blocksleft++; // count dust with unused variable.
|
||||
if ( GetBalance == 2 || GetBalance == 1 )
|
||||
blocksleft++; // count all utxos with unused variable.
|
||||
totalinputs += nValue;
|
||||
n++;
|
||||
//fprintf(stderr,"iter.%d %s/v%d %s %.8f\n",iter,txid.GetHex().c_str(),vout,coinaddr,(double)nValue/COIN);
|
||||
@@ -595,7 +595,7 @@ int64_t AddPaymentsInputs(bool fLockedBlocks,int8_t GetBalance,struct CCcontract
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( GetBalance == 3 && totalinputs < minrelease*COIN ) // return elegible balance to be spent, and blocks left until min release can be released.
|
||||
if ( GetBalance == 3 && totalinputs < minrelease ) // return elegible balance to be spent, and blocks left until min release can be released.
|
||||
{
|
||||
int64_t lockedblocks_balance = totalinputs; // inputs that can be spent already.
|
||||
// sort utxos by blocks until able to be spent, smallest at top.
|
||||
@@ -685,22 +685,23 @@ int32_t payments_parsehexdata(std::vector<uint8_t> &hexdata,cJSON *item,int32_t
|
||||
|
||||
UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
int32_t nextheight = komodo_nextheight();
|
||||
//int32_t latestheight,nextheight = komodo_nextheight();
|
||||
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),nextheight); UniValue result(UniValue::VOBJ); uint256 createtxid,hashBlock,tokenid;
|
||||
CTransaction tx,txO; CPubKey mypk,txidpk,Paymentspk; int32_t i,n,m,numoprets=0,lockedblocks,minrelease; int64_t newamount,inputsum,amount,CCchange=0,totalallocations=0,checkallocations=0,allocation; CTxOut vout; CScript onlyopret; char txidaddr[64],destaddr[64]; std::vector<uint256> txidoprets;
|
||||
int32_t top,bottom=0,blocksleft=0,minimum=10000; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; int8_t funcid,fixedAmount=0; bool fFixedAmount = false;
|
||||
mpz_t mpzTotalAllocations; mpz_init(mpzTotalAllocations);
|
||||
LOCK(cs_main);
|
||||
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),komodo_nextheight()); UniValue result(UniValue::VOBJ); uint256 createtxid,hashBlock,tokenid;
|
||||
CTransaction tx,txO; CPubKey mypk,txidpk,Paymentspk; int32_t i,n,m,numoprets=0,lockedblocks,minrelease; int64_t newamount,inputsum,amount,CCchange=0,totalallocations=0,checkallocations=0,allocation; CTxOut vout; CScript onlyopret,ccopret; char txidaddr[64],destaddr[64]; std::vector<uint256> txidoprets;
|
||||
int32_t top,bottom=0,blocksleft=0,minimum=10000; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; int8_t funcid,fixedAmount=0,skipminimum=0; bool fFixedAmount = false;
|
||||
mpz_t mpzTotalAllocations, mpzAllocation; mpz_init(mpzTotalAllocations);
|
||||
cJSON *params = payments_reparse(&n,jsonstr);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
Paymentspk = GetUnspendable(cp,0);
|
||||
if ( params != 0 && n == 2 )
|
||||
if ( params != 0 && n >= 2 )
|
||||
{
|
||||
createtxid = payments_juint256(jitem(params,0));
|
||||
amount = jdouble(jitem(params,1),0) * SATOSHIDEN + 0.0000000049;
|
||||
if ( n == 3 )
|
||||
skipminimum = juint(jitem(params,2),0);
|
||||
if ( myGetTransaction(createtxid,tx,hashBlock) != 0 && tx.vout.size() > 0 )
|
||||
{
|
||||
if ( ((funcid= DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets)) == 'C' || (funcid= DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys)) == 'S' || (funcid= DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,top,excludeScriptPubKeys,tokenid)) == 'O') )
|
||||
if ( ((funcid= DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets)) == 'C' || (funcid= DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys)) == 'S' || (funcid= DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys,tokenid)) == 'O') )
|
||||
{
|
||||
if ( lockedblocks < 0 || minrelease < 0 || (totalallocations <= 0 && top <= 0 ) )
|
||||
{
|
||||
@@ -713,7 +714,6 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
// set minimum size to 10k sat otherwise the tx will be invalid.
|
||||
if ( minimum < 10000 )
|
||||
minimum = 10000;
|
||||
//latestheight = (nextheight - lockedblocks - 1);
|
||||
if ( amount < minrelease*COIN )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
@@ -725,11 +725,15 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
return(result);
|
||||
}
|
||||
txidpk = CCtxidaddr(txidaddr,createtxid);
|
||||
mtx.vout.push_back(MakeCC1of2vout(EVAL_PAYMENTS,0,Paymentspk,txidpk));
|
||||
ccopret = EncodePaymentsReleaseOpRet(createtxid, amount);
|
||||
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
|
||||
if ( makeCCopret(ccopret, vData) )
|
||||
mtx.vout.push_back(MakeCC1of2vout(EVAL_PAYMENTS,0,Paymentspk,txidpk,&vData));
|
||||
//fprintf(stderr, "funcid.%i\n", funcid);
|
||||
if ( funcid == 'C' )
|
||||
{
|
||||
// normal payments
|
||||
m = txidoprets.size();
|
||||
for (i=0; i<m; i++)
|
||||
{
|
||||
std::vector<uint8_t> scriptPubKey,opret;
|
||||
@@ -780,7 +784,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
// set totalallocations to a mpz_t bignum, for amounts calculation later.
|
||||
mpz_set_si(mpzTotalAllocations,totalallocations);
|
||||
}
|
||||
else if ( funcid == 'S' )
|
||||
else if ( funcid == 'S' || funcid == 'O' )
|
||||
{
|
||||
// normal snapshot
|
||||
if ( vAddressSnapshot.size() == 0 )
|
||||
@@ -799,7 +803,6 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
i = 0;
|
||||
if ( fixedAmount == 7 )
|
||||
{
|
||||
// game setting, randomise bottom and top values
|
||||
@@ -809,38 +812,40 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
fFixedAmount = true;
|
||||
}
|
||||
for (int32_t j = bottom; j < vAddressSnapshot.size(); j++)
|
||||
if ( (top-bottom) < 0 )
|
||||
{
|
||||
auto &address = vAddressSnapshot[j];
|
||||
CScript scriptPubKey = GetScriptForDestination(address.second); bool skip = false;
|
||||
for ( auto skipkey : excludeScriptPubKeys )
|
||||
{
|
||||
if ( scriptPubKey == CScript(skipkey.begin(), skipkey.end()) )
|
||||
{
|
||||
skip = true;
|
||||
//fprintf(stderr, "SKIPPED::: %s\n", CBitcoinAddress(address.second).ToString().c_str());
|
||||
}
|
||||
}
|
||||
if ( !skip )
|
||||
{
|
||||
mpz_t mpzAllocation; mpz_init(mpzAllocation);
|
||||
i++;
|
||||
//fprintf(stderr, "address: %s nValue.%li \n", CBitcoinAddress(address.second).ToString().c_str(), address.first);
|
||||
vout.nValue = address.first;
|
||||
vout.scriptPubKey = scriptPubKey;
|
||||
mpz_set_si(mpzAllocation,address.first);
|
||||
mpz_add(mpzTotalAllocations,mpzTotalAllocations,mpzAllocation);
|
||||
mtx.vout.push_back(vout);
|
||||
mpz_clear(mpzAllocation);
|
||||
}
|
||||
if ( i+bottom == top ) // we reached top amount to pay, it can be less than this!
|
||||
break;
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","invalid range top/bottom"));
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
|
||||
std::vector<int64_t> allocations;
|
||||
std::vector<CScript> scriptPubKeys;
|
||||
if ( funcid == 'S' )
|
||||
m = payments_getallocations(top, bottom, excludeScriptPubKeys, mpzTotalAllocations, scriptPubKeys, allocations);
|
||||
else
|
||||
{
|
||||
// token snapshot
|
||||
// payments_gettokenallocations(top, bottom, excludeScriptPubKeys, tokenid, mpzTotalAllocations, scriptPubKeys, allocations);
|
||||
}
|
||||
if ( (allocations.size() == 0 || scriptPubKeys.size() == 0 || allocations.size() != scriptPubKeys.size()) )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","mismatched allocations, scriptpubkeys"));
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
i = 0;
|
||||
for ( auto allocation : allocations )
|
||||
{
|
||||
vout.nValue = allocation;
|
||||
vout.scriptPubKey = scriptPubKeys[i];
|
||||
mtx.vout.push_back(vout);
|
||||
i++;
|
||||
}
|
||||
m = i; // this is the amount we got, either top, or all of the address on the chain.
|
||||
}
|
||||
else if ( funcid == 'O' )
|
||||
{
|
||||
// token snapshot
|
||||
}
|
||||
newamount = amount;
|
||||
int64_t totalamountsent = 0;
|
||||
@@ -849,15 +854,12 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
mpz_t mpzValue; mpz_init(mpzValue);
|
||||
if ( fFixedAmount )
|
||||
{
|
||||
mtx.vout[i+1].nValue = amount / (top-bottom);
|
||||
//fprintf(stderr, "amount.%li / top-bottom.%i = value.%li\n", amount, (top-bottom-2), mtx.vout[i+1].nValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mpz_set_si(mpzValue,mtx.vout[i+1].nValue);
|
||||
mpz_mul(mpzValue,mpzValue,mpzAmount);
|
||||
mpz_cdiv_q(mpzValue,mpzValue,mpzTotalAllocations);
|
||||
mpz_tdiv_q(mpzValue,mpzValue,mpzTotalAllocations);
|
||||
if ( mpz_fits_slong_p(mpzValue) )
|
||||
mtx.vout[i+1].nValue = mpz_get_si(mpzValue);
|
||||
else
|
||||
@@ -869,20 +871,30 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
//fprintf(stderr, "nValue.%li \n", mtx.vout[i+1].nValue);
|
||||
mpz_clear(mpzValue);
|
||||
//fprintf(stderr, "[%i] nValue.%li minimum.%i scriptpubkey.%s\n", i, mtx.vout[i+1].nValue, minimum, HexStr(mtx.vout[i+1].scriptPubKey.begin(),mtx.vout[i+1].scriptPubKey.end()).c_str());
|
||||
if ( mtx.vout[i+1].nValue < minimum )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","value too small, try releasing a larger amount"));
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
if ( skipminimum == 0 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","value too small, try releasing a larger amount, or use skipminimum flag"));
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// truncate off any vouts that are less than minimum.
|
||||
mtx.vout.resize(i+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
totalamountsent += mtx.vout[i+1].nValue;
|
||||
}
|
||||
if ( totalamountsent < amount ) newamount = totalamountsent;
|
||||
fprintf(stderr, "newamount.%li totalamountsent.%li\n", newamount, totalamountsent);
|
||||
//int64_t temptst = mpz_get_si(mpzTotalAllocations);
|
||||
//fprintf(stderr, "checkamount RPC.%li totalallocations.%li\n",totalamountsent, temptst);
|
||||
mpz_clear(mpzAmount); mpz_clear(mpzTotalAllocations);
|
||||
}
|
||||
else
|
||||
@@ -896,9 +908,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
if ( (inputsum= AddPaymentsInputs(true,0,cp,mtx,txidpk,newamount+2*PAYMENTS_TXFEE,CC_MAXVINS/2,createtxid,lockedblocks,minrelease,blocksleft)) >= newamount+2*PAYMENTS_TXFEE )
|
||||
{
|
||||
std::string rawtx;
|
||||
if ( (CCchange= (inputsum - newamount - 2*PAYMENTS_TXFEE)) >= PAYMENTS_TXFEE )
|
||||
mtx.vout[0].nValue = CCchange;
|
||||
mtx.vout.push_back(CTxOut(PAYMENTS_TXFEE,CScript() << ParseHex(HexStr(txidpk)) << OP_CHECKSIG));
|
||||
mtx.vout[0].nValue = inputsum - newamount - PAYMENTS_TXFEE; // only 1 txfee, so the minimum in this vout is a tx fee.
|
||||
GetCCaddress1of2(cp,destaddr,Paymentspk,txidpk);
|
||||
CCaddr1of2set(cp,Paymentspk,txidpk,cp->CCpriv,destaddr);
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,onlyopret);
|
||||
@@ -933,19 +943,21 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); UniValue result(UniValue::VOBJ);
|
||||
CPubKey Paymentspk,mypk,txidpk; uint256 txid,hashBlock; int64_t amount,totalallocations; CScript opret; CTransaction tx; char txidaddr[64]; std::string rawtx; int32_t n,useopret = 0,lockedblocks,minrelease; std::vector<uint256> txidoprets;
|
||||
CPubKey Paymentspk,mypk,txidpk; uint256 txid,hashBlock; int64_t amount,totalallocations; CScript opret; CTransaction tx; char txidaddr[64]; std::string rawtx; int32_t n,useopret = 0,broadcast=0,lockedblocks,minrelease; std::vector<uint256> txidoprets;
|
||||
int32_t top,bottom,minimum=10000; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; // snapshot
|
||||
uint256 tokenid; int8_t fixedAmount;
|
||||
cJSON *params = payments_reparse(&n,jsonstr);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
Paymentspk = GetUnspendable(cp,0);
|
||||
if ( params != 0 && n > 1 && n <= 3 )
|
||||
if ( params != 0 && n > 1 && n <= 4 )
|
||||
{
|
||||
txid = payments_juint256(jitem(params,0));
|
||||
amount = jdouble(jitem(params,1),0) * SATOSHIDEN + 0.0000000049;
|
||||
if ( n == 3 )
|
||||
useopret = jint(jitem(params,2),0) != 0;
|
||||
if ( myGetTransaction(txid,tx,hashBlock) == 0 || tx.vout.size() == 1 || (DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) == 0 && DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys) == 0 && DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,top,excludeScriptPubKeys,tokenid) == 0) )
|
||||
if ( n == 4 )
|
||||
broadcast = jint(jitem(params,3),0) != 0;
|
||||
if ( myGetTransaction(txid,tx,hashBlock) == 0 || tx.vout.size() == 1 || (DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) == 0 && DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys) == 0 && DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys,tokenid) == 0) )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","invalid createtxid"));
|
||||
@@ -967,18 +979,14 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
|
||||
}
|
||||
else
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_PAYMENTS,amount,Paymentspk));
|
||||
opret = EncodePaymentsFundOpRet(txid);
|
||||
// Use the below one along with other FinalizeCCTx/return, to get the ccvout scriptpubkey
|
||||
/*std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
|
||||
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
|
||||
if ( makeCCopret(opret, vData) )
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_PAYMENTS,amount,Paymentspk,&vData)); */
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_PAYMENTS,amount,Paymentspk,&vData));
|
||||
}
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,opret);
|
||||
//rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,CScript()); // use this one to get ccvout scriptpubkey.
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,CScript());
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
//return(payments_rawtxresult(result,rawtx,0)); // disable sending for CCvout, as we only need to decode the tx.
|
||||
free_json(params);
|
||||
return(payments_rawtxresult(result,rawtx,1));
|
||||
}
|
||||
else
|
||||
@@ -1011,7 +1019,7 @@ UniValue PaymentsMerge(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
createtxid = payments_juint256(jitem(params,0));
|
||||
txidpk = CCtxidaddr(txidaddr,createtxid);
|
||||
if ( myGetTransaction(createtxid,tx,hashBlock) == 0 || tx.vout.size() == 1 || (DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) == 0 && DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys) == 0 && DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,top,excludeScriptPubKeys,tokenid) == 0) )
|
||||
if ( myGetTransaction(createtxid,tx,hashBlock) == 0 || tx.vout.size() == 1 || (DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) == 0 && DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys) == 0 && DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys,tokenid) == 0) )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","invalid createtxid"));
|
||||
@@ -1036,7 +1044,7 @@ UniValue PaymentsMerge(struct CCcontract_info *cp,char *jsonstr)
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,CScript());
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(payments_rawtxresult(result,rawtx,0));
|
||||
return(payments_rawtxresult(result,rawtx,1));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1121,6 +1129,7 @@ UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr)
|
||||
for (i=0; i<txidoprets.size(); i++)
|
||||
{
|
||||
std::vector<uint8_t> scriptPubKey,opret; int64_t allocation;
|
||||
//fprintf(stderr, "txid.%s\n",txidoprets[i].GetHex().c_str());
|
||||
if ( myGetTransaction(txidoprets[i],tx,hashBlock) != 0 && tx.vout.size() > 1 && DecodePaymentsTxidOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,allocation,scriptPubKey,opret) == 'T' )
|
||||
{
|
||||
totalallocations += allocation;
|
||||
@@ -1188,6 +1197,7 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
|
||||
lockedblocks = juint(jitem(params,0),0);
|
||||
minrelease = juint(jitem(params,1),0);
|
||||
minimum = juint(jitem(params,2),0);
|
||||
if ( minimum < 10000 ) minimum = 10000;
|
||||
top = juint(jitem(params,3),0);
|
||||
bottom = juint(jitem(params,4),0);
|
||||
fixedAmount = juint(jitem(params,5),0); // fixed amount is a flag, set to 7 does game mode, 0 normal snapshot, anything else fixed allocations.
|
||||
@@ -1199,20 +1209,34 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
if ( top-bottom < 0 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","invalid range, top/bottom"));
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
if ( n > 6 )
|
||||
{
|
||||
for (i=0; i<n-6; i++)
|
||||
{
|
||||
/* TODO: Change this RPC to take an address. Because a tokens airdrop needs its own RPC anyway.
|
||||
CTxDestination destination = DecodeDestination(name_);
|
||||
std::string address;
|
||||
address.append(jstri(params,6+i));
|
||||
CTxDestination destination = DecodeDestination(address);
|
||||
if (!IsValidDestination(destination))
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","address is not valid."));
|
||||
result.push_back(Pair("invalid_address",address));
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
std::vector<uint8_t> vscriptPubKey;
|
||||
CScript scriptPubKey = GetScriptForDestination(destination);
|
||||
*/
|
||||
char *inputhex = jstri(params,6+i);
|
||||
std::vector<uint8_t> scriptPubKey;
|
||||
int32_t len = strlen(inputhex)/2;
|
||||
scriptPubKey.resize(len);
|
||||
decode_hex((uint8_t *)scriptPubKey.data(),len,(char *)inputhex);
|
||||
excludeScriptPubKeys.push_back(scriptPubKey);
|
||||
vscriptPubKey.assign(scriptPubKey.begin(), scriptPubKey.end());
|
||||
excludeScriptPubKeys.push_back(vscriptPubKey);
|
||||
}
|
||||
}
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
@@ -1247,6 +1271,87 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue PaymentsAirdropTokens(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
UniValue result(UniValue::VOBJ);
|
||||
uint256 hashBlock, tokenid = zeroid; CTransaction tx; CPubKey Paymentspk,mypk; char markeraddr[64]; std::string rawtx;
|
||||
int32_t lockedblocks,minrelease,top,bottom,n,i,minimum=10000; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; int8_t fixedAmount;
|
||||
cJSON *params = payments_reparse(&n,jsonstr);
|
||||
if ( params != 0 && n >= 6 )
|
||||
{
|
||||
tokenid = payments_juint256(jitem(params,0));
|
||||
lockedblocks = juint(jitem(params,1),0);
|
||||
minrelease = juint(jitem(params,2),0);
|
||||
minimum = juint(jitem(params,3),0);
|
||||
if ( minimum < 10000 ) minimum = 10000;
|
||||
top = juint(jitem(params,4),0);
|
||||
bottom = juint(jitem(params,5),0);
|
||||
fixedAmount = juint(jitem(params,6),0); // fixed amount is a flag, set to 7 does game mode, 0 normal snapshot, anything else fixed allocations.
|
||||
if ( lockedblocks < 0 || minrelease < 0 || top <= 0 || bottom < 0 || minimum < 0 || fixedAmount < 0 || top > 3999 || tokenid == zeroid )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","negative parameter, or top over 3999"));
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
// TODO: lookup tokenid and make sure it exists.
|
||||
if ( n > 7 )
|
||||
{
|
||||
for (i=0; i<n-7; i++)
|
||||
{
|
||||
// Change to pubkeys! tokens are owned by a pubkey not an address.
|
||||
std::string address;
|
||||
address.append(jstri(params,7+i));
|
||||
CTxDestination destination = DecodeDestination(address);
|
||||
if (!IsValidDestination(destination))
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","address is not valid."));
|
||||
result.push_back(Pair("invalid_address",address));
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
std::vector<uint8_t> vscriptPubKey;
|
||||
CScript scriptPubKey = GetScriptForDestination(destination);
|
||||
vscriptPubKey.assign(scriptPubKey.begin(), scriptPubKey.end());
|
||||
excludeScriptPubKeys.push_back(vscriptPubKey);
|
||||
}
|
||||
}
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
Paymentspk = GetUnspendable(cp,0);
|
||||
if ( AddNormalinputs(mtx,mypk,2*PAYMENTS_TXFEE,60) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,PAYMENTS_TXFEE,Paymentspk,Paymentspk));
|
||||
CScript tempopret = EncodePaymentsTokensOpRet(lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys,tokenid);
|
||||
if ( tempopret.size() > 10000 ) // TODO: Check this!
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","op_return is too big, try with less exclude pubkeys."));
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,tempopret);
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(payments_rawtxresult(result,rawtx,0));
|
||||
}
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","not enough normal funds"));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","parameters error"));
|
||||
}
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ),a(UniValue::VARR); CTransaction tx,txO; CPubKey Paymentspk,txidpk; int32_t i,j,n,flag=0,numoprets=0,lockedblocks,minrelease,blocksleft=0; std::vector<uint256> txidoprets; int64_t funds,fundsopret,elegiblefunds,totalallocations=0,allocation; char fundsaddr[64],fundsopretaddr[64],txidaddr[64],*outstr; uint256 createtxid,hashBlock;
|
||||
@@ -1326,12 +1431,15 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
|
||||
result.push_back(Pair("bottom",(int64_t)bottom));
|
||||
result.push_back(Pair("top",(int64_t)top));
|
||||
result.push_back(Pair("fixedFlag",(int64_t)fixedAmount));
|
||||
// TODO: convert to show addresses instead of scriptpubkey.
|
||||
for ( auto scriptPubKey : excludeScriptPubKeys )
|
||||
a.push_back(HexStr(scriptPubKey.begin(),scriptPubKey.end()));
|
||||
result.push_back(Pair("excludeScriptPubkeys",a));
|
||||
{
|
||||
CTxDestination dest;
|
||||
if ( ExtractDestination(CScript(scriptPubKey.begin(),scriptPubKey.end()), dest) )
|
||||
a.push_back(CBitcoinAddress(dest).ToString());
|
||||
}
|
||||
result.push_back(Pair("excludeAddresses",a));
|
||||
}
|
||||
else if ( DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,top,excludeScriptPubKeys,tokenid) != 0 )
|
||||
else if ( DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys,tokenid) != 0 )
|
||||
{
|
||||
if ( lockedblocks < 0 || minrelease < 0 || top <= 0 )
|
||||
{
|
||||
@@ -1360,11 +1468,15 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
txidpk = CCtxidaddr(txidaddr,createtxid);
|
||||
GetCCaddress1of2(cp,fundsaddr,Paymentspk,txidpk);
|
||||
blocksleft = 0;
|
||||
funds = AddPaymentsInputs(false,2,cp,mtx,txidpk,0,CC_MAXVINS,createtxid,lockedblocks,minrelease,blocksleft);
|
||||
result.push_back(Pair(fundsaddr,ValueFromAmount(funds)));
|
||||
result.push_back(Pair("utxos", (int64_t)blocksleft));
|
||||
blocksleft = 0;
|
||||
GetCCaddress(cp,fundsopretaddr,Paymentspk);
|
||||
fundsopret = AddPaymentsInputs(false,1,cp,mtx,txidpk,0,CC_MAXVINS,createtxid,lockedblocks,minrelease,blocksleft);
|
||||
result.push_back(Pair(fundsopretaddr,ValueFromAmount(fundsopret)));
|
||||
result.push_back(Pair("utxos", (int64_t)blocksleft));
|
||||
result.push_back(Pair("totalfunds",ValueFromAmount(funds+fundsopret)));
|
||||
// Blocks until minrelease can be released.
|
||||
elegiblefunds = AddPaymentsInputs(true,3,cp,mtx,txidpk,0,CC_MAXVINS,createtxid,lockedblocks,minrelease,blocksleft);
|
||||
@@ -1402,7 +1514,7 @@ UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr)
|
||||
txid = it->first.txhash;
|
||||
if ( it->first.index == 0 && myGetTransaction(txid,tx,hashBlock) != 0 )
|
||||
{
|
||||
if ( tx.vout.size() > 0 && (DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) == 'C' || DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys) == 'S' || DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,top,excludeScriptPubKeys,tokenid) == 'O') )
|
||||
if ( tx.vout.size() > 0 && (DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) == 'C' || DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys) == 'S' || DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys,tokenid) == 'O') )
|
||||
{
|
||||
if ( lockedblocks < 0 || minrelease < 0 || (totalallocations <= 0 && top <= 0 ) || bottom < 0 || fixedAmount < 0 || minimum < 10000 )
|
||||
{
|
||||
|
||||
2236
src/cc/prices.cpp
2236
src/cc/prices.cpp
File diff suppressed because it is too large
Load Diff
@@ -195,6 +195,7 @@ bool RewardsExactAmounts(struct CCcontract_info *cp,Eval *eval,const CTransactio
|
||||
bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
uint256 txid,fundingtxid,hashBlock,vinfundingtxid; uint64_t vinsbits,sbits,APR,minseconds,maxseconds,mindeposit,amount,reward,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; uint8_t funcid; CScript scriptPubKey; CTransaction fundingTx,vinTx;
|
||||
int64_t dummy;
|
||||
numvins = tx.vin.size();
|
||||
numvouts = tx.vout.size();
|
||||
preventCCvins = preventCCvouts = -1;
|
||||
@@ -255,7 +256,7 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
|
||||
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) == 0 )
|
||||
return eval->Invalid("unexpected normal vin for unlock");
|
||||
}
|
||||
if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime) )
|
||||
if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime, dummy) )
|
||||
return eval->Invalid("txfee is too high");
|
||||
amount = vinTx.vout[0].nValue;
|
||||
reward = RewardsCalc(amount,tx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit);
|
||||
|
||||
@@ -29,6 +29,7 @@ int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notar
|
||||
unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params);
|
||||
bool EnsureWalletIsAvailable(bool avoidException);
|
||||
extern bool fRequestShutdown;
|
||||
extern CScript KOMODO_EARLYTXID_SCRIPTPUB;
|
||||
|
||||
int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &txNew);
|
||||
uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht);
|
||||
@@ -2062,7 +2063,6 @@ bool komodo_appendACscriptpub()
|
||||
{
|
||||
ASSETCHAINS_SCRIPTPUB.pop_back(); ASSETCHAINS_SCRIPTPUB.pop_back(); // remove last 2 chars.
|
||||
// get OP_RETURN from txid and append the HexStr of it to scriptpub
|
||||
// encoded opreturn incorrectly on TESTHC chain, once we no longer need this it can be changed to a straight +1 to drop OP_RETURN opcode.
|
||||
ASSETCHAINS_SCRIPTPUB.append(HexStr(tx.vout[i].scriptPubKey.begin()+3, tx.vout[i].scriptPubKey.end()));
|
||||
//fprintf(stderr, "ac_script.%s\n",ASSETCHAINS_SCRIPTPUB.c_str());
|
||||
didinit = true;
|
||||
@@ -2076,6 +2076,44 @@ bool komodo_appendACscriptpub()
|
||||
return false;
|
||||
}
|
||||
|
||||
void GetKomodoEarlytxidScriptPub()
|
||||
{
|
||||
if ( KOMODO_EARLYTXID == zeroid )
|
||||
{
|
||||
fprintf(stderr, "Restart deamon with -earlytxid.\n");
|
||||
StartShutdown();
|
||||
return;
|
||||
}
|
||||
if ( ASSETCHAINS_EARLYTXIDCONTRACT == EVAL_PRICES && KOMODO_SNAPSHOT_INTERVAL == 0 )
|
||||
{
|
||||
fprintf(stderr, "Prices->paymentsCC contract must have -ac_snapshot enabled to pay out.\n");
|
||||
StartShutdown();
|
||||
return;
|
||||
}
|
||||
if ( chainActive.Height() < 100 )
|
||||
{
|
||||
fprintf(stderr, "Cannot fetch -earlytxid before block 100.\n");
|
||||
StartShutdown();
|
||||
return;
|
||||
}
|
||||
CTransaction tx; uint256 blockhash; int32_t i;
|
||||
// get transaction and check that it occured before height 100.
|
||||
if ( myGetTransaction(KOMODO_EARLYTXID,tx,blockhash) && mapBlockIndex[blockhash]->GetHeight() < 100 )
|
||||
{
|
||||
for (i = 0; i < tx.vout.size(); i++)
|
||||
if ( tx.vout[i].scriptPubKey[0] == OP_RETURN )
|
||||
break;
|
||||
if ( i < tx.vout.size() )
|
||||
{
|
||||
KOMODO_EARLYTXID_SCRIPTPUB = CScript(tx.vout[i].scriptPubKey.begin()+3, tx.vout[i].scriptPubKey.end());
|
||||
fprintf(stderr, "KOMODO_EARLYTXID_SCRIPTPUB.%s\n", HexStr(KOMODO_EARLYTXID_SCRIPTPUB.begin(),KOMODO_EARLYTXID_SCRIPTPUB.end()).c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "INVALID -earlytxid, restart daemon with correct txid.\n");
|
||||
StartShutdown();
|
||||
}
|
||||
|
||||
int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
|
||||
{
|
||||
int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0; static bool didinit = false;
|
||||
|
||||
@@ -38,7 +38,12 @@
|
||||
#define KOMODO_MAXNVALUE (((uint64_t)1 << 63) - 1)
|
||||
#define KOMODO_BIT63SET(x) ((x) & ((uint64_t)1 << 63))
|
||||
#define KOMODO_VALUETOOBIG(x) ((x) > (uint64_t)10000000001*COIN)
|
||||
|
||||
//#ifndef TESTMODE
|
||||
#define PRICES_DAYWINDOW ((3600*24/ASSETCHAINS_BLOCKTIME) + 1)
|
||||
//#else
|
||||
//#define PRICES_DAYWINDOW (7)
|
||||
//#endif
|
||||
|
||||
extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC;
|
||||
int32_t MAX_BLOCK_SIZE(int32_t height);
|
||||
@@ -79,6 +84,7 @@ extern uint8_t ASSETCHAINS_PRIVATE;
|
||||
extern int32_t USE_EXTERNAL_PUBKEY;
|
||||
extern char NOTARYADDRS[64][64];
|
||||
extern int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL;
|
||||
extern int32_t ASSETCHAINS_EARLYTXIDCONTRACT;
|
||||
int tx_height( const uint256 &hash );
|
||||
extern std::vector<std::string> vWhiteListAddress;
|
||||
void komodo_netevent(std::vector<uint8_t> payload);
|
||||
@@ -101,7 +107,7 @@ int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
|
||||
int8_t komodo_segid(int32_t nocache,int32_t height);
|
||||
int32_t komodo_heightpricebits(uint64_t *seedp,uint32_t *heightbits,int32_t nHeight);
|
||||
char *komodo_pricename(char *name,int32_t ind);
|
||||
int32_t komodo_priceind(char *symbol);
|
||||
int32_t komodo_priceind(const char *symbol);
|
||||
int32_t komodo_pricesinit();
|
||||
int64_t komodo_priceave(int64_t *tmpbuf,int64_t *correlated,int32_t cskip);
|
||||
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth);
|
||||
|
||||
@@ -2400,8 +2400,8 @@ char *komodo_pricename(char *name,int32_t ind)
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int32_t komodo_priceind(char *symbol)
|
||||
// finds index for its symbol name
|
||||
int32_t komodo_priceind(const char *symbol)
|
||||
{
|
||||
char name[65]; int32_t i,n = (int32_t)(komodo_cbopretsize(ASSETCHAINS_CBOPRET) / sizeof(uint32_t));
|
||||
for (i=1; i<n; i++)
|
||||
@@ -2412,7 +2412,7 @@ int32_t komodo_priceind(char *symbol)
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// returns price value which is in a 10% interval for more than 50% points for the preceding 24 hours
|
||||
int64_t komodo_pricecorrelated(uint64_t seed,int32_t ind,uint32_t *rawprices,int32_t rawskip,uint32_t *nonzprices,int32_t smoothwidth)
|
||||
{
|
||||
int32_t i,j,k,n,iter,correlation,maxcorrelation=0; int64_t firstprice,price,sum,den,mult,refprice,lowprice,highprice;
|
||||
@@ -2801,4 +2801,3 @@ int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblo
|
||||
pthread_mutex_unlock(&pricemutex);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,8 @@ extern int32_t KOMODO_LOADINGBLOCKS;
|
||||
unsigned int MAX_BLOCK_SIGOPS = 20000;
|
||||
|
||||
int32_t KOMODO_TESTNODE, KOMODO_SNAPSHOT_INTERVAL;
|
||||
CScript KOMODO_EARLYTXID_SCRIPTPUB;
|
||||
int32_t ASSETCHAINS_EARLYTXIDCONTRACT;
|
||||
|
||||
struct komodo_kv *KOMODO_KV;
|
||||
pthread_mutex_t KOMODO_KV_mutex,KOMODO_CC_mutex;
|
||||
|
||||
@@ -1759,6 +1759,8 @@ void komodo_args(char *argv0)
|
||||
printf("KOMODO_REWIND %d\n",KOMODO_REWIND);
|
||||
}
|
||||
KOMODO_EARLYTXID = Parseuint256(GetArg("-earlytxid","0").c_str());
|
||||
ASSETCHAINS_EARLYTXIDCONTRACT = GetArg("-ac_earlytxidcontract",0);
|
||||
fprintf(stderr, "ASSETCHAINS_EARLYTXIDCONTRACT.%i\n", ASSETCHAINS_EARLYTXIDCONTRACT);
|
||||
if ( name.c_str()[0] != 0 )
|
||||
{
|
||||
std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0]));
|
||||
@@ -2013,7 +2015,7 @@ void komodo_args(char *argv0)
|
||||
fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n");
|
||||
StartShutdown();
|
||||
}
|
||||
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 )
|
||||
if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 )
|
||||
{
|
||||
fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size());
|
||||
extraptr = extrabuf;
|
||||
@@ -2152,7 +2154,10 @@ void komodo_args(char *argv0)
|
||||
if ( KOMODO_SNAPSHOT_INTERVAL != 0 )
|
||||
{
|
||||
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(KOMODO_SNAPSHOT_INTERVAL),(void *)&KOMODO_SNAPSHOT_INTERVAL);
|
||||
fprintf(stderr, "snapshot interval.%i\n",KOMODO_SNAPSHOT_INTERVAL);
|
||||
}
|
||||
if ( ASSETCHAINS_EARLYTXIDCONTRACT != 0 )
|
||||
{
|
||||
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_EARLYTXIDCONTRACT),(void *)&ASSETCHAINS_EARLYTXIDCONTRACT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -731,7 +731,7 @@ bool komodo_dailysnapshot(int32_t height)
|
||||
std::sort(vAddressSnapshot.rbegin(), vAddressSnapshot.rend());
|
||||
//for (int j = 0; j < 50; j++)
|
||||
// fprintf(stderr, "j.%i address.%s nValue.%li\n",j, CBitcoinAddress(vAddressSnapshot[j].second).ToString().c_str(), vAddressSnapshot[j].first );
|
||||
// include only top 5000 address.
|
||||
// include only top 3999 address.
|
||||
if ( vAddressSnapshot.size() > 3999 ) vAddressSnapshot.resize(3999);
|
||||
lastSnapShotHeight = undo_height;
|
||||
fprintf(stderr, "vAddressSnapshot.size.%li\n", vAddressSnapshot.size());
|
||||
@@ -6469,7 +6469,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
|
||||
try {
|
||||
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
|
||||
//CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE, MAX_BLOCK_SIZE+8, SER_DISK, CLIENT_VERSION);
|
||||
CBufferedFile blkdat(fileIn, 32*MAX_BLOCK_SIZE(10000000), MAX_BLOCK_SIZE(10000000)+8, SER_DISK, CLIENT_VERSION);
|
||||
CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE(10000000), MAX_BLOCK_SIZE(10000000)+8, SER_DISK, CLIENT_VERSION);
|
||||
uint64_t nRewind = blkdat.GetPos();
|
||||
while (!blkdat.eof()) {
|
||||
boost::this_thread::interruption_point();
|
||||
@@ -6503,7 +6503,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
|
||||
blkdat.SetPos(nBlockPos);
|
||||
CBlock block;
|
||||
blkdat >> block;
|
||||
nRewind = blkdat.GetPos();
|
||||
nRewind = blkdat.GetPos();
|
||||
|
||||
// detect out of order blocks, and store them for later
|
||||
uint256 hash = block.GetHash();
|
||||
|
||||
@@ -95,7 +95,7 @@ static const unsigned int MAX_TEMPFILE_SIZE = 0x1000000; // 16 MiB 0x8000000
|
||||
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
|
||||
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
|
||||
/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
|
||||
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
|
||||
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
|
||||
/** Maximum number of script-checking threads allowed */
|
||||
static const int MAX_SCRIPTCHECK_THREADS = 16;
|
||||
/** -par default (number of script-checking threads, 0 = auto) */
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include "cc/CCinclude.h"
|
||||
#include "cc/CCPrices.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
|
||||
@@ -1155,17 +1158,17 @@ UniValue paxprice(const UniValue& params, bool fHelp)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// fills pricedata with raw price, correlated and smoothed values for numblock
|
||||
/*int32_t prices_extract(int64_t *pricedata,int32_t firstheight,int32_t numblocks,int32_t ind)
|
||||
{
|
||||
int32_t height,i,n,width,numpricefeeds = -1; uint64_t seed,ignore,rngval; uint32_t rawprices[1440*6],*ptr; int64_t *tmpbuf;
|
||||
width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH;
|
||||
width = numblocks+PRICES_DAYWINDOW*2+PRICES_SMOOTHWIDTH; // need 2*PRICES_DAYWINDOW previous raw price points to calc PRICES_DAYWINDOW correlated points to calc, in turn, smoothed point
|
||||
komodo_heightpricebits(&seed,rawprices,firstheight + numblocks - 1);
|
||||
if ( firstheight < width )
|
||||
return(-1);
|
||||
for (i=0; i<width; i++)
|
||||
{
|
||||
if ( (n= komodo_heightpricebits(&ignore,rawprices,firstheight + numblocks - 1 - i)) < 0 )
|
||||
if ( (n= komodo_heightpricebits(&ignore,rawprices,firstheight + numblocks - 1 - i)) < 0 ) // stores raw prices in backward order
|
||||
return(-1);
|
||||
if ( numpricefeeds < 0 )
|
||||
numpricefeeds = n;
|
||||
@@ -1176,16 +1179,18 @@ UniValue paxprice(const UniValue& params, bool fHelp)
|
||||
ptr[1] = rawprices[0]; // timestamp
|
||||
}
|
||||
rngval = seed;
|
||||
for (i=0; i<numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH; i++)
|
||||
for (i=0; i<numblocks+PRICES_DAYWINDOW+PRICES_SMOOTHWIDTH; i++) // calculates +PRICES_DAYWINDOW more correlated values
|
||||
{
|
||||
rngval = (rngval*11109 + 13849);
|
||||
ptr = (uint32_t *)&pricedata[i*3];
|
||||
if ( (pricedata[i*3+1]= komodo_pricecorrelated(rngval,ind,(uint32_t *)&pricedata[i*3],6,0,PRICES_SMOOTHWIDTH)) < 0 )
|
||||
// takes previous PRICES_DAYWINDOW raw prices and calculates correlated price value
|
||||
if ( (pricedata[i*3+1]= komodo_pricecorrelated(rngval,ind,(uint32_t *)&pricedata[i*3],6,0,PRICES_SMOOTHWIDTH)) < 0 ) // skip is 6 == sizeof(int64_t)/sizeof(int32_t)*3
|
||||
return(-3);
|
||||
}
|
||||
tmpbuf = (int64_t *)calloc(sizeof(int64_t),2*PRICES_DAYWINDOW);
|
||||
for (i=0; i<numblocks; i++)
|
||||
pricedata[i*3+2] = komodo_priceave(tmpbuf,&pricedata[i*3+1],3);
|
||||
// takes previous PRICES_DAYWINDOW correlated price values and calculates smoothed value
|
||||
pricedata[i*3+2] = komodo_priceave(tmpbuf,&pricedata[i*3+1],3);
|
||||
free(tmpbuf);
|
||||
return(0);
|
||||
}*/
|
||||
@@ -1315,6 +1320,139 @@ UniValue prices(const UniValue& params, bool fHelp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// pricesbet rpc implementation
|
||||
UniValue pricesbet(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 3)
|
||||
throw runtime_error("pricesbet amount leverage \"synthetic-expression\"\n"
|
||||
"amount is in coins\n"
|
||||
"leverage is integer non-zero value, positive for long, negative for short position\n"
|
||||
"synthetic-expression example \"BTC_USD, 1\"\n");
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
|
||||
if (ASSETCHAINS_CBOPRET == 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
|
||||
|
||||
CAmount txfee = 10000;
|
||||
CAmount amount = atof(params[0].get_str().c_str()) * COIN;
|
||||
int16_t leverage = (int16_t)atoi(params[1].get_str().c_str());
|
||||
if (leverage == 0)
|
||||
throw runtime_error("invalid leverage\n");
|
||||
|
||||
std::string sexpr = params[2].get_str();
|
||||
std::vector<std::string> vexpr;
|
||||
SplitStr(sexpr, vexpr);
|
||||
|
||||
// debug print parsed strings:
|
||||
std::cerr << "parsed synthetic: ";
|
||||
for (auto s : vexpr)
|
||||
std::cerr << s << " ";
|
||||
std::cerr << std::endl;
|
||||
|
||||
return PricesBet(txfee, amount, leverage, vexpr);
|
||||
}
|
||||
|
||||
// pricesaddfunding rpc implementation
|
||||
UniValue pricesaddfunding(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 2)
|
||||
throw runtime_error("pricesaddfunding bettxid amount\n"
|
||||
"where amount is in coins\n");
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
|
||||
if (ASSETCHAINS_CBOPRET == 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
|
||||
|
||||
CAmount txfee = 10000;
|
||||
uint256 bettxid = Parseuint256(params[0].get_str().c_str());
|
||||
if (bettxid.IsNull())
|
||||
throw runtime_error("invalid bettxid\n");
|
||||
|
||||
CAmount amount = atof(params[1].get_str().c_str()) * COIN;
|
||||
if (amount <= 0)
|
||||
throw runtime_error("invalid amount\n");
|
||||
|
||||
return PricesAddFunding(txfee, bettxid, amount);
|
||||
}
|
||||
|
||||
// rpc pricessetcostbasis implementation
|
||||
UniValue pricessetcostbasis(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error("pricessetcostbasis bettxid\n");
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
|
||||
if (ASSETCHAINS_CBOPRET == 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
|
||||
|
||||
uint256 bettxid = Parseuint256(params[0].get_str().c_str());
|
||||
if (bettxid.IsNull())
|
||||
throw runtime_error("invalid bettxid\n");
|
||||
|
||||
int64_t txfee = 10000;
|
||||
|
||||
return PricesSetcostbasis(txfee, bettxid);
|
||||
}
|
||||
|
||||
// pricescashout rpc implementation
|
||||
UniValue pricescashout(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error("pricescashout bettxid\n");
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
|
||||
if (ASSETCHAINS_CBOPRET == 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
|
||||
|
||||
uint256 bettxid = Parseuint256(params[0].get_str().c_str());
|
||||
if (bettxid.IsNull())
|
||||
throw runtime_error("invalid bettxid\n");
|
||||
|
||||
int64_t txfee = 10000;
|
||||
|
||||
return PricesCashout(txfee, bettxid);
|
||||
}
|
||||
|
||||
// pricesrekt rpc implementation
|
||||
UniValue pricesrekt(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 2)
|
||||
throw runtime_error("pricesrekt bettxid height\n");
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
|
||||
if (ASSETCHAINS_CBOPRET == 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
|
||||
|
||||
uint256 bettxid = Parseuint256(params[0].get_str().c_str());
|
||||
if (bettxid.IsNull())
|
||||
throw runtime_error("invalid bettxid\n");
|
||||
|
||||
int32_t height = atoi(params[0].get_str().c_str());
|
||||
|
||||
int64_t txfee = 10000;
|
||||
|
||||
return PricesRekt(txfee, bettxid, height);
|
||||
}
|
||||
|
||||
// pricesrekt rpc implementation
|
||||
UniValue pricesgetorderbook(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error("pricesgetorderbook\n");
|
||||
LOCK(cs_main);
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
|
||||
if (ASSETCHAINS_CBOPRET == 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "only -ac_cbopret chains have prices");
|
||||
|
||||
return PricesGetOrderbook();
|
||||
}
|
||||
|
||||
UniValue gettxout(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() < 2 || params.size() > 3)
|
||||
@@ -1944,4 +2082,4 @@ void RegisterBlockchainRPCCommands(CRPCTable &tableRPC)
|
||||
{
|
||||
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
|
||||
tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
|
||||
}
|
||||
}
|
||||
@@ -1383,9 +1383,13 @@ UniValue getsnapshot(const UniValue& params, bool fHelp)
|
||||
|
||||
if (params.size() > 0 && !params[0].isNull()) {
|
||||
top = atoi(params[0].get_str().c_str());
|
||||
if (top < 0)
|
||||
//throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, top must be a positive integer");
|
||||
top = -1;
|
||||
if ( top < 0 )
|
||||
{
|
||||
if ( KOMODO_SNAPSHOT_INTERVAL == 0 )
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, top must be a positive integer");
|
||||
else
|
||||
top = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( fHelp || params.size() > 1)
|
||||
|
||||
@@ -35,6 +35,10 @@ void RegisterMiningRPCCommands(CRPCTable &tableRPC);
|
||||
/** Register raw transaction RPC commands */
|
||||
void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC);
|
||||
|
||||
/** Register test transaction RPC commands */
|
||||
void RegisterTesttransactionsRPCCommands(CRPCTable &tableRPC);
|
||||
|
||||
|
||||
static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC)
|
||||
{
|
||||
RegisterBlockchainRPCCommands(tableRPC);
|
||||
@@ -42,6 +46,9 @@ static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC)
|
||||
RegisterMiscRPCCommands(tableRPC);
|
||||
RegisterMiningRPCCommands(tableRPC);
|
||||
RegisterRawTransactionRPCCommands(tableRPC);
|
||||
#ifdef TESTMODE
|
||||
RegisterTesttransactionsRPCCommands(tableRPC);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -463,7 +463,15 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "prices", "prices", &prices, true },
|
||||
{ "prices", "pricesaddress", &pricesaddress, true },
|
||||
{ "prices", "priceslist", &priceslist, true },
|
||||
{ "prices", "mypriceslist", &mypriceslist, true },
|
||||
{ "prices", "pricesinfo", &pricesinfo, true },
|
||||
{ "prices", "pricesbet", &pricesbet, true },
|
||||
{ "prices", "pricessetcostbasis", &pricessetcostbasis, true },
|
||||
{ "prices", "pricescashout", &pricescashout, true },
|
||||
{ "prices", "pricesrekt", &pricesrekt, true },
|
||||
{ "prices", "pricesaddfunding", &pricesaddfunding, true },
|
||||
{ "prices", "pricesgetorderbook", &pricesgetorderbook, true },
|
||||
|
||||
|
||||
// Pegs
|
||||
{ "pegs", "pegsaddress", &pegsaddress, true },
|
||||
@@ -484,6 +492,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "payments", "paymentstxidopret", &payments_txidopret, true },
|
||||
{ "payments", "paymentscreate", &payments_create, true },
|
||||
{ "payments", "paymentsairdrop", &payments_airdrop, true },
|
||||
{ "payments", "paymentsairdroptokens", &payments_airdroptokens, true },
|
||||
{ "payments", "paymentslist", &payments_list, true },
|
||||
{ "payments", "paymentsinfo", &payments_info, true },
|
||||
{ "payments", "paymentsfund", &payments_fund, true },
|
||||
@@ -569,10 +578,6 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "util", "reconsiderblock", &reconsiderblock, true },
|
||||
/* Not shown in help */
|
||||
{ "hidden", "setmocktime", &setmocktime, true },
|
||||
{ "hidden", "test_ac", &test_ac, true },
|
||||
{ "hidden", "test_heirmarker", &test_heirmarker, true },
|
||||
{ "hidden", "test_proof", &test_proof, true },
|
||||
{ "hidden", "test_burntx", &test_burntx, true },
|
||||
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
|
||||
@@ -273,6 +273,7 @@ extern UniValue oraclesdata(const UniValue& params, bool fHelp);
|
||||
extern UniValue oraclessamples(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesaddress(const UniValue& params, bool fHelp);
|
||||
extern UniValue priceslist(const UniValue& params, bool fHelp);
|
||||
extern UniValue mypriceslist(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesinfo(const UniValue& params, bool fHelp);
|
||||
extern UniValue pegsaddress(const UniValue& params, bool fHelp);
|
||||
extern UniValue marmaraaddress(const UniValue& params, bool fHelp);
|
||||
@@ -291,6 +292,7 @@ extern UniValue payments_merge(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_txidopret(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_create(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_airdrop(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_airdroptokens(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_info(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_list(const UniValue& params, bool fHelp);
|
||||
|
||||
@@ -502,11 +504,13 @@ extern UniValue paxdeposit(const UniValue& params, bool fHelp);
|
||||
extern UniValue paxwithdraw(const UniValue& params, bool fHelp);
|
||||
|
||||
extern UniValue prices(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesbet(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricessetcostbasis(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricescashout(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesrekt(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesaddfunding(const UniValue& params, bool fHelp);
|
||||
extern UniValue pricesgetorderbook(const UniValue& params, bool fHelp);
|
||||
|
||||
|
||||
// test rpc:
|
||||
extern UniValue test_ac(const UniValue& params, bool fHelp);
|
||||
extern UniValue test_heirmarker(const UniValue& params, bool fHelp);
|
||||
extern UniValue test_burntx(const UniValue& params, bool fHelp);
|
||||
extern UniValue test_proof(const UniValue& params, bool fHelp);
|
||||
|
||||
#endif // BITCOIN_RPCSERVER_H
|
||||
|
||||
268
src/rpc/testtransactions.cpp
Normal file
268
src/rpc/testtransactions.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
||||
* *
|
||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
||||
* the top-level directory of this distribution for the individual copyright *
|
||||
* holder information and the developer policies on copyright and licensing. *
|
||||
* *
|
||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
||||
* SuperNET software, including this file may be copied, modified, propagated *
|
||||
* or distributed except according to the terms contained in the LICENSE file *
|
||||
* *
|
||||
* Removal or modification of this copyright notice is prohibited. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "amount.h"
|
||||
#include "chain.h"
|
||||
#include "chainparams.h"
|
||||
#include "checkpoints.h"
|
||||
#include "crosschain.h"
|
||||
#include "base58.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "cc/eval.h"
|
||||
#include "main.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "rpc/server.h"
|
||||
#include "streams.h"
|
||||
#include "sync.h"
|
||||
#include "util.h"
|
||||
#include "script/script.h"
|
||||
#include "script/script_error.h"
|
||||
#include "script/sign.h"
|
||||
#include "script/standard.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
#include <regex>
|
||||
|
||||
|
||||
#include "cc/CCinclude.h"
|
||||
#include "cc/CCPrices.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int32_t ensure_CCrequirements(uint8_t evalcode);
|
||||
|
||||
UniValue test_ac(const UniValue& params, bool fHelp)
|
||||
{
|
||||
// make fake token tx:
|
||||
struct CCcontract_info *cp, C;
|
||||
|
||||
if (fHelp || (params.size() != 4))
|
||||
throw runtime_error("incorrect params\n");
|
||||
if (ensure_CCrequirements(EVAL_HEIR) < 0)
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
|
||||
std::vector<unsigned char> pubkey1;
|
||||
std::vector<unsigned char> pubkey2;
|
||||
|
||||
pubkey1 = ParseHex(params[0].get_str().c_str());
|
||||
pubkey2 = ParseHex(params[1].get_str().c_str());
|
||||
|
||||
CPubKey pk1 = pubkey2pk(pubkey1);
|
||||
CPubKey pk2 = pubkey2pk(pubkey2);
|
||||
|
||||
if (!pk1.IsValid() || !pk2.IsValid())
|
||||
throw runtime_error("invalid pubkey\n");
|
||||
|
||||
int64_t txfee = 10000;
|
||||
int64_t amount = atoll(params[2].get_str().c_str()) * COIN;
|
||||
uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str());
|
||||
|
||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
|
||||
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60);
|
||||
|
||||
if (normalInputs < txfee + amount)
|
||||
throw runtime_error("not enough normals\n");
|
||||
|
||||
mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2));
|
||||
|
||||
CScript opret;
|
||||
fundingtxid = revuint256(fundingtxid);
|
||||
|
||||
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0);
|
||||
|
||||
cp = CCinit(&C, EVAL_HEIR);
|
||||
return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret));
|
||||
}
|
||||
|
||||
UniValue test_heirmarker(const UniValue& params, bool fHelp)
|
||||
{
|
||||
// make fake token tx:
|
||||
struct CCcontract_info *cp, C;
|
||||
|
||||
if (fHelp || (params.size() != 1))
|
||||
throw runtime_error("incorrect params\n");
|
||||
if (ensure_CCrequirements(EVAL_HEIR) < 0)
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
|
||||
uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
|
||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
|
||||
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
|
||||
if (normalInputs < 10000)
|
||||
throw runtime_error("not enough normals\n");
|
||||
|
||||
mtx.vin.push_back(CTxIn(fundingtxid, 1));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey));
|
||||
|
||||
CScript opret;
|
||||
fundingtxid = revuint256(fundingtxid);
|
||||
|
||||
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0);
|
||||
|
||||
cp = CCinit(&C, EVAL_HEIR);
|
||||
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret));
|
||||
}
|
||||
|
||||
UniValue test_burntx(const UniValue& params, bool fHelp)
|
||||
{
|
||||
// make fake token tx:
|
||||
struct CCcontract_info *cp, C;
|
||||
|
||||
if (fHelp || (params.size() != 1))
|
||||
throw runtime_error("incorrect params\n");
|
||||
if (ensure_CCrequirements(EVAL_TOKENS) < 0)
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
|
||||
uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
|
||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
|
||||
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
|
||||
if (normalInputs < 10000)
|
||||
throw runtime_error("not enough normals\n");
|
||||
|
||||
CPubKey burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY));
|
||||
|
||||
mtx.vin.push_back(CTxIn(tokenid, 0));
|
||||
mtx.vin.push_back(CTxIn(tokenid, 1));
|
||||
mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, 1, burnpk));
|
||||
|
||||
std::vector<CPubKey> voutPubkeys;
|
||||
voutPubkeys.push_back(burnpk);
|
||||
|
||||
cp = CCinit(&C, EVAL_TOKENS);
|
||||
|
||||
std::vector<uint8_t> vopret;
|
||||
GetNonfungibleData(tokenid, vopret);
|
||||
if (vopret.size() > 0)
|
||||
cp->additionalTokensEvalcode2 = vopret.begin()[0];
|
||||
|
||||
uint8_t tokenpriv[33];
|
||||
char unspendableTokenAddr[64];
|
||||
CPubKey unspPk = GetUnspendable(cp, tokenpriv);
|
||||
GetCCaddress(cp, unspendableTokenAddr, unspPk);
|
||||
CCaddr2set(cp, EVAL_TOKENS, unspPk, tokenpriv, unspendableTokenAddr);
|
||||
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, EncodeTokenOpRet(tokenid, voutPubkeys, std::make_pair(0, vscript_t()))));
|
||||
}
|
||||
|
||||
UniValue test_proof(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
std::vector<uint8_t>proof;
|
||||
|
||||
if (fHelp || (params.size() != 2))
|
||||
throw runtime_error("incorrect params\n");
|
||||
|
||||
|
||||
proof = ParseHex(params[0].get_str());
|
||||
uint256 cointxid = Parseuint256((char *)params[1].get_str().c_str());
|
||||
|
||||
std::vector<uint256> txids;
|
||||
|
||||
CMerkleBlock merkleBlock;
|
||||
if (!E_UNMARSHAL(proof, ss >> merkleBlock)) {
|
||||
result.push_back(Pair("error", "could not unmarshal proof"));
|
||||
return result;
|
||||
}
|
||||
uint256 merkleRoot = merkleBlock.txn.ExtractMatches(txids);
|
||||
|
||||
result.push_back(Pair("source_root", merkleRoot.GetHex()));
|
||||
|
||||
for (int i = 0; i < txids.size(); i++)
|
||||
std::cerr << "merkle block txid=" << txids[0].GetHex() << std::endl;
|
||||
|
||||
|
||||
std::vector<bool> vMatches(txids.size());
|
||||
for (auto v : vMatches) v = true;
|
||||
CPartialMerkleTree verifTree(txids, vMatches);
|
||||
|
||||
result.push_back(Pair("verif_root", verifTree.ExtractMatches(txids).GetHex()));
|
||||
|
||||
if (std::find(txids.begin(), txids.end(), cointxid) == txids.end()) {
|
||||
fprintf(stderr, "invalid proof for this cointxid\n");
|
||||
}
|
||||
|
||||
std::vector<uint256> vMerkleTree;
|
||||
bool f;
|
||||
::BuildMerkleTree(&f, txids, vMerkleTree);
|
||||
|
||||
std::vector<uint256> vMerkleBranch = ::GetMerkleBranch(0, txids.size(), vMerkleTree);
|
||||
|
||||
uint256 ourResult = SafeCheckMerkleBranch(zeroid, vMerkleBranch, 0);
|
||||
result.push_back(Pair("SafeCheckMerkleBranch", ourResult.GetHex()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
extern CScript prices_costbasisopret(uint256 bettxid, CPubKey mypk, int32_t height, int64_t costbasis);
|
||||
UniValue test_pricesmarker(const UniValue& params, bool fHelp)
|
||||
{
|
||||
// make fake token tx:
|
||||
struct CCcontract_info *cp, C;
|
||||
|
||||
if (fHelp || (params.size() != 1))
|
||||
throw runtime_error("incorrect params\n");
|
||||
if (ensure_CCrequirements(EVAL_PRICES) < 0)
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
|
||||
uint256 bettxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
|
||||
cp = CCinit(&C, EVAL_PRICES);
|
||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
|
||||
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
|
||||
if (normalInputs < 10000)
|
||||
throw runtime_error("not enough normals\n");
|
||||
|
||||
mtx.vin.push_back(CTxIn(bettxid, 1));
|
||||
mtx.vout.push_back(CTxOut(1000, CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG));
|
||||
|
||||
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, prices_costbasisopret(bettxid, myPubkey, 100, 100)));
|
||||
}
|
||||
|
||||
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) okSafeMode
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
|
||||
/* Not shown in help */
|
||||
{ "hidden", "test_ac", &test_ac, true },
|
||||
{ "hidden", "test_heirmarker", &test_heirmarker, true },
|
||||
{ "hidden", "test_proof", &test_proof, true },
|
||||
{ "hidden", "test_burntx", &test_burntx, true },
|
||||
{ "hidden", "test_pricesmarker", &test_pricesmarker, true }
|
||||
};
|
||||
|
||||
void RegisterTesttransactionsRPCCommands(CRPCTable &tableRPC)
|
||||
{
|
||||
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
|
||||
tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
|
||||
}
|
||||
28
src/util.cpp
28
src/util.cpp
@@ -394,27 +394,23 @@ void ParseParameters(int argc, const char* const argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// split string using by space or comma as a delimiter char
|
||||
void SplitStr(const std::string& strVal, std::vector<std::string> &outVals)
|
||||
{
|
||||
stringstream ss(strVal);
|
||||
std::string str;
|
||||
|
||||
while ( ss.peek() == ' ' )
|
||||
ss.ignore();
|
||||
|
||||
while ( ss >> str )
|
||||
{
|
||||
if ( str.size() == 0 )
|
||||
continue;
|
||||
if ( str[str.size()-1] == ',' )
|
||||
str.resize(str.size()-1);
|
||||
outVals.push_back(str);
|
||||
while ( ss.peek() == ' ' )
|
||||
ss.ignore();
|
||||
if ( ss.peek() == ',' )
|
||||
ss.ignore();
|
||||
while ( ss.peek() == ' ' )
|
||||
while (!ss.eof()) {
|
||||
int c;
|
||||
std::string str;
|
||||
|
||||
while (std::isspace(ss.peek()))
|
||||
ss.ignore();
|
||||
|
||||
while ((c = ss.get()) != EOF && !std::isspace(c) && c != ',')
|
||||
str += c;
|
||||
|
||||
if (!str.empty())
|
||||
outVals.push_back(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -287,6 +287,9 @@ template <typename Callable> void TraceThread(const char* name, Callable func)
|
||||
}
|
||||
}
|
||||
|
||||
// split string using by space or comma as a delimiter char
|
||||
void SplitStr(const std::string& strVal, std::vector<std::string> &outVals);
|
||||
|
||||
#define KOMODO_ASSETCHAIN_MAXLEN 65
|
||||
|
||||
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
// CCLIB fails to compile with this!
|
||||
//#include <db_cxx.h>
|
||||
#include "../depends/x86_64-unknown-linux-gnu/include/db_cxx.h"
|
||||
// If CCLIB fails to compile with this, use the one below.
|
||||
#include <db_cxx.h>
|
||||
//#include "../depends/x86_64-unknown-linux-gnu/include/db_cxx.h"
|
||||
|
||||
extern unsigned int nWalletDBUpdated;
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include <numeric>
|
||||
|
||||
#include "komodo_defs.h"
|
||||
#include <string.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -5581,7 +5582,7 @@ UniValue payments_release(const UniValue& params, bool fHelp)
|
||||
{
|
||||
struct CCcontract_info *cp,C;
|
||||
if ( fHelp || params.size() != 1 )
|
||||
throw runtime_error("paymentsrelease \"[%22createtxid%22,amount]\"\n");
|
||||
throw runtime_error("paymentsrelease \"[%22createtxid%22,amount,(skipminimum)]\"\n");
|
||||
if ( ensure_CCrequirements(EVAL_PAYMENTS) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
const CKeyStore& keystore = *pwalletMain;
|
||||
@@ -5655,6 +5656,19 @@ UniValue payments_airdrop(const UniValue& params, bool fHelp)
|
||||
return(PaymentsAirdrop(cp,(char *)params[0].get_str().c_str()));
|
||||
}
|
||||
|
||||
UniValue payments_airdroptokens(const UniValue& params, bool fHelp)
|
||||
{
|
||||
struct CCcontract_info *cp,C;
|
||||
if ( fHelp || params.size() != 1 )
|
||||
throw runtime_error("paymentsairdrop \"[%22tokenid%22,lockedblocks,minamount,mintoaddress,top,bottom,fixedFlag,%22excludePubKey%22,...,%22excludePubKeyN%22]\"\n");
|
||||
if ( ensure_CCrequirements(EVAL_PAYMENTS) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
const CKeyStore& keystore = *pwalletMain;
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
cp = CCinit(&C,EVAL_PAYMENTS);
|
||||
return(PaymentsAirdropTokens(cp,(char *)params[0].get_str().c_str()));
|
||||
}
|
||||
|
||||
UniValue payments_info(const UniValue& params, bool fHelp)
|
||||
{
|
||||
struct CCcontract_info *cp,C;
|
||||
@@ -6945,25 +6959,61 @@ UniValue faucetget(const UniValue& params, bool fHelp)
|
||||
return(result);
|
||||
}
|
||||
|
||||
uint32_t pricesGetParam(UniValue param) {
|
||||
uint32_t filter = 0;
|
||||
if (STR_TOLOWER(param.get_str()) == "all")
|
||||
filter = 0;
|
||||
else if (STR_TOLOWER(param.get_str()) == "open")
|
||||
filter = 1;
|
||||
else if (STR_TOLOWER(param.get_str()) == "closed")
|
||||
filter = 2;
|
||||
else
|
||||
throw runtime_error("incorrect parameter\n");
|
||||
return filter;
|
||||
}
|
||||
|
||||
UniValue priceslist(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if ( fHelp || params.size() > 0 )
|
||||
throw runtime_error("priceslist\n");
|
||||
if ( fHelp || params.size() != 0 && params.size() != 1)
|
||||
throw runtime_error("priceslist [all|open|closed]\n");
|
||||
if ( ensure_CCrequirements(EVAL_PRICES) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
return(PricesList());
|
||||
uint32_t filter = 0;
|
||||
if (params.size() == 1)
|
||||
filter = pricesGetParam(params[0]);
|
||||
|
||||
CPubKey emptypk;
|
||||
|
||||
return(PricesList(filter, emptypk));
|
||||
}
|
||||
|
||||
UniValue mypriceslist(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0 && params.size() != 1)
|
||||
throw runtime_error("mypriceslist [all|open|closed]\n");
|
||||
if (ensure_CCrequirements(EVAL_PRICES) < 0)
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
|
||||
uint32_t filter = 0;
|
||||
if (params.size() == 1)
|
||||
filter = pricesGetParam(params[0]);
|
||||
CPubKey mypk = pubkey2pk(Mypubkey());
|
||||
|
||||
return(PricesList(filter, mypk));
|
||||
}
|
||||
|
||||
UniValue pricesinfo(const UniValue& params, bool fHelp)
|
||||
{
|
||||
uint256 bettxid; int32_t height;
|
||||
if ( fHelp || params.size() != 2 )
|
||||
throw runtime_error("pricesinfo fundingtxid\n");
|
||||
if ( fHelp || params.size() != 1 && params.size() != 2)
|
||||
throw runtime_error("pricesinfo bettxid [height]\n");
|
||||
if ( ensure_CCrequirements(EVAL_PRICES) < 0 )
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
bettxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
height = atoi(params[1].get_str().c_str());
|
||||
return(PricesInfo(bettxid,height));
|
||||
height = 0;
|
||||
if (params.size() == 2)
|
||||
height = atoi(params[1].get_str().c_str());
|
||||
return(PricesInfo(bettxid, height));
|
||||
}
|
||||
|
||||
UniValue dicefund(const UniValue& params, bool fHelp)
|
||||
@@ -7302,9 +7352,13 @@ UniValue tokencreate(const UniValue& params, bool fHelp)
|
||||
|
||||
if (params.size() == 4) {
|
||||
nonfungibleData = ParseHex(params[3].get_str());
|
||||
if (nonfungibleData.size() > 10000) // opret limit
|
||||
if (nonfungibleData.size() > IGUANA_MAXSCRIPTSIZE) // opret limit
|
||||
{
|
||||
ERR_RESULT("Non-fungible data must be <= 10000");
|
||||
ERR_RESULT("Non-fungible data size must be <= " + std::to_string(IGUANA_MAXSCRIPTSIZE));
|
||||
return(result);
|
||||
}
|
||||
if( nonfungibleData.empty() ) {
|
||||
ERR_RESULT("Non-fungible data incorrect");
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
@@ -7961,86 +8015,9 @@ void RegisterWalletRPCCommands(CRPCTable &tableRPC)
|
||||
tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
|
||||
}
|
||||
|
||||
UniValue test_ac(const UniValue& params, bool fHelp)
|
||||
{
|
||||
// make fake token tx:
|
||||
struct CCcontract_info *cp, C;
|
||||
|
||||
if (fHelp || (params.size() != 4))
|
||||
throw runtime_error("incorrect params\n");
|
||||
if (ensure_CCrequirements(EVAL_HEIR) < 0)
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
|
||||
std::vector<unsigned char> pubkey1;
|
||||
std::vector<unsigned char> pubkey2;
|
||||
|
||||
pubkey1 = ParseHex(params[0].get_str().c_str());
|
||||
pubkey2 = ParseHex(params[1].get_str().c_str());
|
||||
|
||||
CPubKey pk1 = pubkey2pk(pubkey1);
|
||||
CPubKey pk2 = pubkey2pk(pubkey2);
|
||||
|
||||
if(!pk1.IsValid() || !pk2.IsValid())
|
||||
throw runtime_error("invalid pubkey\n");
|
||||
|
||||
int64_t txfee = 10000;
|
||||
int64_t amount = atoll(params[2].get_str().c_str()) * COIN;
|
||||
uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str());
|
||||
|
||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
|
||||
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60);
|
||||
|
||||
if( normalInputs < txfee + amount)
|
||||
throw runtime_error("not enough normals\n");
|
||||
|
||||
mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2));
|
||||
|
||||
CScript opret;
|
||||
fundingtxid = revuint256(fundingtxid);
|
||||
|
||||
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0);
|
||||
|
||||
cp = CCinit(&C, EVAL_HEIR);
|
||||
return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret));
|
||||
}
|
||||
|
||||
extern bool komodo_appendACscriptpub();
|
||||
|
||||
UniValue test_heirmarker(const UniValue& params, bool fHelp)
|
||||
{
|
||||
//make fake token tx:
|
||||
struct CCcontract_info *cp, C;
|
||||
|
||||
if (fHelp || (params.size() != 1))
|
||||
throw runtime_error("incorrect params\n");
|
||||
if (ensure_CCrequirements(EVAL_HEIR) < 0)
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
|
||||
uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
|
||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
|
||||
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
|
||||
if (normalInputs < 10000)
|
||||
throw runtime_error("not enough normals\n");
|
||||
|
||||
mtx.vin.push_back(CTxIn(fundingtxid, 1));
|
||||
mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey));
|
||||
|
||||
CScript opret;
|
||||
fundingtxid = revuint256(fundingtxid);
|
||||
|
||||
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0);
|
||||
|
||||
cp = CCinit(&C, EVAL_HEIR);
|
||||
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret));
|
||||
}
|
||||
|
||||
UniValue opreturn_burn(const UniValue& params, bool fHelp)
|
||||
{
|
||||
std::vector<uint8_t> vHexStr; CScript opret; int32_t txfee = 10000;
|
||||
if (fHelp || (params.size() != 2))
|
||||
throw runtime_error("amount to burn, hexstring to send\n");
|
||||
struct CCcontract_info *cp, C; UniValue ret(UniValue::VOBJ);
|
||||
@@ -8050,122 +8027,22 @@ UniValue opreturn_burn(const UniValue& params, bool fHelp)
|
||||
|
||||
CAmount nAmount = AmountFromValue(params[0]);
|
||||
if (nAmount <= 10000)
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "must send at least 10000 sat");
|
||||
std::string strHex = params[1].get_str();
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "must burn at least 10000 sat");
|
||||
vHexStr = ParseHex(params[1].get_str());
|
||||
if ( vHexStr.size() == 0 )
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "hexstring is not valid.");
|
||||
|
||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
|
||||
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, nAmount, 60);
|
||||
if (normalInputs < nAmount)
|
||||
throw runtime_error("not enough normals\n");
|
||||
|
||||
CScript opret; uint8_t scripthex[8192];
|
||||
|
||||
decode_hex(scripthex,strHex.size()/2,(char *)strHex.c_str());
|
||||
std::string test;
|
||||
test.append((char*)scripthex);
|
||||
std::vector<uint8_t> opretdata(test.begin(), test.end());
|
||||
opret << OP_RETURN << E_MARSHAL(ss << opretdata);
|
||||
/*CScript opret; uint8_t *ptr;
|
||||
opret << OP_RETURN << 0;
|
||||
int32_t len = strlen(strHex.c_str());
|
||||
len >>=1;
|
||||
opret.resize(len+2);
|
||||
ptr = (uint8_t *)&opret[1];
|
||||
decode_hex(ptr,len,(char *)strHex.c_str()); */
|
||||
mtx.vout.push_back(CTxOut(nAmount,opret));
|
||||
ret.push_back(Pair("hex",FinalizeCCTx(0, cp, mtx, myPubkey, 10000, CScript())));
|
||||
|
||||
opret << OP_RETURN << E_MARSHAL(ss << vHexStr);
|
||||
|
||||
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(myPubkey)) << OP_CHECKSIG));
|
||||
mtx.vout.push_back(CTxOut(nAmount,opret));
|
||||
ret.push_back(Pair("hex",FinalizeCCTx(0, cp, mtx, myPubkey, txfee, CScript())));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
UniValue test_burntx(const UniValue& params, bool fHelp)
|
||||
{
|
||||
// make fake token tx:
|
||||
struct CCcontract_info *cp, C;
|
||||
|
||||
if (fHelp || (params.size() != 1))
|
||||
throw runtime_error("incorrect params\n");
|
||||
if (ensure_CCrequirements(EVAL_TOKENS) < 0)
|
||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||
|
||||
uint256 tokenid = Parseuint256((char *)params[0].get_str().c_str());
|
||||
|
||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
|
||||
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
|
||||
if (normalInputs < 10000)
|
||||
throw runtime_error("not enough normals\n");
|
||||
|
||||
CPubKey burnpk = pubkey2pk(ParseHex(CC_BURNPUBKEY));
|
||||
|
||||
mtx.vin.push_back(CTxIn(tokenid, 0));
|
||||
mtx.vin.push_back(CTxIn(tokenid, 1));
|
||||
mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS, 1, burnpk));
|
||||
|
||||
std::vector<CPubKey> voutPubkeys;
|
||||
voutPubkeys.push_back(burnpk);
|
||||
|
||||
cp = CCinit(&C, EVAL_TOKENS);
|
||||
|
||||
std::vector<uint8_t> vopret;
|
||||
GetNonfungibleData(tokenid, vopret);
|
||||
if (vopret.size() > 0)
|
||||
cp->additionalTokensEvalcode2 = vopret.begin()[0];
|
||||
|
||||
uint8_t tokenpriv[33];
|
||||
char unspendableTokenAddr[64];
|
||||
CPubKey unspPk = GetUnspendable(cp, tokenpriv);
|
||||
GetCCaddress(cp, unspendableTokenAddr, unspPk);
|
||||
CCaddr2set(cp, EVAL_TOKENS, unspPk, tokenpriv, unspendableTokenAddr);
|
||||
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, EncodeTokenOpRet(tokenid, voutPubkeys, std::make_pair(0, vscript_t()))));
|
||||
}
|
||||
|
||||
UniValue test_proof(const UniValue& params, bool fHelp)
|
||||
{
|
||||
UniValue result(UniValue::VOBJ);
|
||||
std::vector<uint8_t>proof;
|
||||
|
||||
if (fHelp || (params.size() != 2))
|
||||
throw runtime_error("incorrect params\n");
|
||||
|
||||
|
||||
proof = ParseHex(params[0].get_str());
|
||||
uint256 cointxid = Parseuint256((char *)params[1].get_str().c_str());
|
||||
|
||||
std::vector<uint256> txids;
|
||||
|
||||
CMerkleBlock merkleBlock;
|
||||
if (!E_UNMARSHAL(proof, ss >> merkleBlock)) {
|
||||
result.push_back(Pair("error", "could not unmarshal proof"));
|
||||
return result;
|
||||
}
|
||||
uint256 merkleRoot = merkleBlock.txn.ExtractMatches(txids);
|
||||
|
||||
result.push_back(Pair("source_root", merkleRoot.GetHex()));
|
||||
|
||||
for (int i = 0; i < txids.size(); i++)
|
||||
std::cerr << "merkle block txid=" << txids[0].GetHex() << std::endl;
|
||||
|
||||
|
||||
std::vector<bool> vMatches(txids.size());
|
||||
for (auto v : vMatches) v = true;
|
||||
CPartialMerkleTree verifTree(txids, vMatches);
|
||||
|
||||
result.push_back(Pair("verif_root", verifTree.ExtractMatches(txids).GetHex()));
|
||||
|
||||
if (std::find(txids.begin(), txids.end(), cointxid) == txids.end()) {
|
||||
fprintf(stderr, "invalid proof for this cointxid\n");
|
||||
}
|
||||
|
||||
std::vector<uint256> vMerkleTree;
|
||||
bool f;
|
||||
::BuildMerkleTree(&f, txids, vMerkleTree);
|
||||
|
||||
std::vector<uint256> vMerkleBranch = ::GetMerkleBranch(0, txids.size(), vMerkleTree);
|
||||
|
||||
uint256 ourResult = SafeCheckMerkleBranch(zeroid, vMerkleBranch, 0);
|
||||
result.push_back(Pair("SafeCheckMerkleBranch", ourResult.GetHex()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user