Merge pull request #1468 from blackjok3rtt/jl777
major update to paymentsCC
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include <gmp.h>
|
||||
|
||||
#define PAYMENTS_TXFEE 10000
|
||||
#define PAYMENTS_MERGEOFSET 10 // 100?
|
||||
extern std::vector <std::pair<CAmount, CTxDestination>> vAddressSnapshot;
|
||||
extern int32_t lastSnapShotHeight;
|
||||
|
||||
@@ -29,6 +30,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
// CCcustom
|
||||
UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr);
|
||||
UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr);
|
||||
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);
|
||||
|
||||
@@ -229,7 +229,7 @@ uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv,int32_t entropyvout,i
|
||||
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk, std::vector<std::vector<unsigned char>>* vData = NULL);
|
||||
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2, std::vector<std::vector<unsigned char>>* vData = NULL);
|
||||
int32_t has_opret(const CTransaction &tx, uint8_t evalcode);
|
||||
CScript getCCopret(const CScript &scriptPubKey);
|
||||
bool getCCopret(const CScript &scriptPubKey, CScript &opret);
|
||||
bool makeCCopret(CScript &opret, std::vector<std::vector<unsigned char>> &vData);
|
||||
CC *MakeCCcond1(uint8_t evalcode,CPubKey pk);
|
||||
CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2);
|
||||
|
||||
@@ -63,23 +63,28 @@ int32_t has_opret(const CTransaction &tx, uint8_t evalcode)
|
||||
int i = 0;
|
||||
for ( auto vout : tx.vout )
|
||||
{
|
||||
if ( vout.scriptPubKey[0] == OP_RETURN && vout.scriptPubKey[1] == evalcode )
|
||||
//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[0] == OP_RETURN && vout.scriptPubKey[2] == evalcode )
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CScript getCCopret(const CScript &scriptPubKey)
|
||||
bool getCCopret(const CScript &scriptPubKey, CScript &opret)
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
|
||||
CScript dummy; CScript opret;
|
||||
if ( scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) && vParams.size() == 1 )
|
||||
CScript dummy; bool ret = false;
|
||||
if ( scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) != 0 )
|
||||
{
|
||||
//fprintf(stderr, "vparams.%s\n", HexStr(vParams[0].begin(), vParams[0].end()).c_str());
|
||||
opret = CScript(vParams[0].begin()+6, vParams[0].end());
|
||||
ret = true;
|
||||
if ( vParams.size() == 1)
|
||||
{
|
||||
opret = CScript(vParams[0].begin()+6, vParams[0].end());
|
||||
//fprintf(stderr, "vparams.%s\n", HexStr(vParams[0].begin(), vParams[0].end()).c_str());
|
||||
}
|
||||
}
|
||||
return opret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool makeCCopret(CScript &opret, std::vector<std::vector<unsigned char>> &vData)
|
||||
|
||||
@@ -82,12 +82,12 @@ UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
|
||||
bool custom_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
|
||||
{
|
||||
char expectedaddress[64]; CPubKey pk;
|
||||
CScript opret; int32_t numvout;
|
||||
CScript opret; int32_t numvout = 0;
|
||||
if ( has_opret(tx, EVAL_CUSTOM) == 0 )
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
|
||||
opret = getCCopret(tx.vout[0].scriptPubKey);
|
||||
numvout = 1;
|
||||
if ( getCCopret(tx.vout[0].scriptPubKey,opret) )
|
||||
numvout = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -535,6 +535,8 @@ bool CheckMigration(Eval *eval, const CTransaction &importTx, const CTransaction
|
||||
|
||||
uint256 tokenid = zeroid;
|
||||
if (vimportOpret.begin()[0] == EVAL_TOKENS) { // for tokens (new opret with tokens)
|
||||
if ( is_STAKED(ASSETCHAINS_SYMBOL) == 1 )
|
||||
return eval->Invalid("no-tokens-migrate-on-LABS");
|
||||
struct CCcontract_info *cpTokens, CCtokens_info;
|
||||
std::vector<std::pair<uint8_t, vscript_t>> oprets;
|
||||
uint8_t evalCodeInOpret;
|
||||
|
||||
@@ -4,6 +4,8 @@ rm *.so rogue/rogue games/tetris games/prices
|
||||
echo rogue
|
||||
make -f Makefile_rogue
|
||||
./makerogue
|
||||
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
|
||||
@@ -16,4 +18,3 @@ echo games prices
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -4,4 +4,3 @@ cp customcc.so ../libcc.so
|
||||
cd ..
|
||||
make
|
||||
cd cc
|
||||
|
||||
|
||||
@@ -157,22 +157,41 @@ uint8_t DecodePaymentsOpRet(CScript scriptPubKey,int32_t &lockedblocks,int32_t &
|
||||
return(0);
|
||||
}
|
||||
|
||||
CScript EncodePaymentsSnapsShotOpRet(int32_t lockedblocks,int32_t minrelease,int32_t top,int32_t bottom,int8_t fixedAmount,std::vector<std::vector<uint8_t>> excludeScriptPubKeys)
|
||||
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;
|
||||
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'S' << lockedblocks << minrelease << top << bottom << fixedAmount << excludeScriptPubKeys);
|
||||
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);
|
||||
return(opret);
|
||||
}
|
||||
|
||||
uint8_t DecodePaymentsSnapsShotOpRet(CScript scriptPubKey,int32_t &lockedblocks,int32_t &minrelease,int32_t &top,int32_t &bottom,int8_t &fixedAmount,std::vector<std::vector<uint8_t>> &excludeScriptPubKeys)
|
||||
uint8_t DecodePaymentsSnapsShotOpRet(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)
|
||||
{
|
||||
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 >> bottom; ss >> fixedAmount; ss >> excludeScriptPubKeys) != 0 )
|
||||
if ( (strcmp(ASSETCHAINS_SYMBOL, "CFEKPAY") == 0) ) // exempt for now, remove this after game completed.
|
||||
{
|
||||
if ( e == EVAL_PAYMENTS && f == 'S' )
|
||||
return(f);
|
||||
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);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -197,10 +216,11 @@ uint8_t DecodePaymentsTokensOpRet(CScript scriptPubKey,int32_t &lockedblocks,int
|
||||
return(0);
|
||||
}
|
||||
|
||||
int64_t IsPaymentsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v,char *cmpaddr)
|
||||
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 ( 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) )
|
||||
return(tx.vout[v].nValue);
|
||||
@@ -224,6 +244,34 @@ void pub2createtxid(char *str)
|
||||
free(rev);
|
||||
}
|
||||
|
||||
bool payments_game(int32_t &top, int32_t &bottom)
|
||||
{
|
||||
uint64_t x;
|
||||
uint256 tmphash = chainActive[lastSnapShotHeight]->GetBlockHash();
|
||||
memcpy(&x,&tmphash,sizeof(x));
|
||||
bottom = ((x & 0xff) % 50);
|
||||
if ( bottom == 0 ) bottom = 1;
|
||||
top = (((x>>8) & 0xff) % 100);
|
||||
if ( top < 50 ) top += 50;
|
||||
bottom = (vAddressSnapshot.size()*bottom)/100;
|
||||
top = (vAddressSnapshot.size()*top)/100;
|
||||
fprintf(stderr, "bottom.%i top.%i\n",bottom,top);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool payments_lockedblocks(uint256 blockhash,int32_t lockedblocks,int32_t &blocksleft)
|
||||
{
|
||||
int32_t ht = chainActive.Height();
|
||||
CBlockIndex* pblockindex = komodo_blockindex(blockhash);
|
||||
if ( pblockindex == 0 || pblockindex->GetHeight()+lockedblocks > ht)
|
||||
{
|
||||
blocksleft = pblockindex->GetHeight()+lockedblocks - ht;
|
||||
fprintf(stderr, "not elegible to be spent yet height.%i vs elegible_ht.%i blocksleft.%i\n",ht,(pblockindex!=0?pblockindex->GetHeight():0)+lockedblocks,blocksleft);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
// one of two addresses
|
||||
@@ -231,207 +279,216 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
// 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], 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; CPubKey txidpk,Paymentspk;
|
||||
int32_t top,bottom=0; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; bool fFixedAmount = false;
|
||||
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() < 2 )
|
||||
return(eval->Invalid("not enough vouts"));
|
||||
if ( tx.vout.back().scriptPubKey[0] == OP_RETURN )
|
||||
if ( tx.vout.size() == 1 )
|
||||
{
|
||||
if ( IsPaymentsvout(cp,tx,0,coinaddr,ccopret) != 0 && ccopret.size() > 2 && DecodePaymentsMergeOpRet(ccopret,createtxid) )
|
||||
{
|
||||
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);
|
||||
strcpy(temp, scriptpubkey.c_str());
|
||||
pub2createtxid(temp);
|
||||
createtxid = Parseuint256(temp);
|
||||
}
|
||||
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());
|
||||
|
||||
// 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,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,top,excludeScriptPubKeys,tokenid)) == 'O') )
|
||||
{
|
||||
if ( lockedblocks < 0 || minrelease < 0 || (totalallocations <= 0 && top <= 0 ) )
|
||||
return(eval->Invalid("negative values"));
|
||||
return(eval->Invalid("negative values"));
|
||||
if ( minimum < 10000 )
|
||||
return(eval->Invalid("minimum must be over 10000"));
|
||||
Paymentspk = GetUnspendable(cp,0);
|
||||
txidpk = CCtxidaddr(txidaddr,createtxid);
|
||||
GetCCaddress1of2(cp,coinaddr,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) )
|
||||
return eval->Invalid("txfee is too high");
|
||||
// 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)
|
||||
{
|
||||
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' )
|
||||
{
|
||||
scriptPubKeys.push_back(CScript(scriptPubKey.begin(), scriptPubKey.end()));
|
||||
allocations.push_back(allocation);
|
||||
//fprintf(stderr, "i.%i scriptpubkey.%s allocation.%li\n",i,scriptPubKeys[i].ToString().c_str(),allocation);
|
||||
checkallocations += allocation;
|
||||
// if we have an op_return to pay to need to check it exists and is paying the correct opret.
|
||||
if ( !opret.empty() )
|
||||
{
|
||||
if ( !fHasOpret )
|
||||
{
|
||||
fprintf(stderr, "missing opret.%s in payments release.\n",HexStr(opret.begin(), opret.end()).c_str());
|
||||
return(eval->Invalid("missing opret in payments release"));
|
||||
}
|
||||
else if ( CScript(opret.begin(),opret.end()) != tx.vout[tx.vout.size()-1].scriptPubKey )
|
||||
{
|
||||
fprintf(stderr, "opret.%s vs opret.%s\n",HexStr(opret.begin(), opret.end()).c_str(), HexStr(tx.vout[tx.vout.size()-1].scriptPubKey.begin(), tx.vout[tx.vout.size()-1].scriptPubKey.end()).c_str());
|
||||
return(eval->Invalid("pays incorrect opret"));
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
mpz_set_si(mpzTotalAllocations,totalallocations);
|
||||
}
|
||||
else if ( funcid == 'S' )
|
||||
{
|
||||
if ( KOMODO_SNAPSHOT_INTERVAL == 0 )
|
||||
return(eval->Invalid("snapshots not activated on this chain"));
|
||||
if ( vAddressSnapshot.size() == 0 )
|
||||
return(eval->Invalid("need first snapshot"));
|
||||
// need time for TX to me mined before the next snapshot.
|
||||
if ( top > 3999 )
|
||||
return(eval->Invalid("transaction too big"));
|
||||
if ( fixedAmount == 7 )
|
||||
{
|
||||
// game setting, randomise bottom and top values
|
||||
uint64_t x;
|
||||
uint256 tmphash = chainActive[lastSnapShotHeight]->GetBlockHash();
|
||||
memcpy(&x,&tmphash,sizeof(x));
|
||||
bottom = ((x & 0xff) % 50);
|
||||
if ( bottom == 0 ) bottom = 1;
|
||||
top = (((x>>8) & 0xff) % 100);
|
||||
if ( top < 50 ) top += 50;
|
||||
bottom = (vAddressSnapshot.size()*bottom)/100;
|
||||
top = (vAddressSnapshot.size()*top)/100;
|
||||
fprintf(stderr, "bottom.%i top.%i\n",bottom,top);
|
||||
fFixedAmount = true;
|
||||
}
|
||||
else if ( fixedAmount != 0 )
|
||||
{
|
||||
fFixedAmount = true;
|
||||
}
|
||||
for (int32_t j = bottom; j < vAddressSnapshot.size(); j++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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
|
||||
//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"));
|
||||
|
||||
// make sure change is in vout 0 and is paying to the contract address.
|
||||
if ( (change= IsPaymentsvout(cp,tx,0,coinaddr)) == 0 )
|
||||
if ( (change= IsPaymentsvout(cp,tx,0,coinaddr,ccopret)) == 0 )
|
||||
return(eval->Invalid("change is in wrong vout or is wrong tx type"));
|
||||
|
||||
// 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++)
|
||||
if ( !fIsMerge )
|
||||
{
|
||||
if ( scriptPubKeys[n] != tx.vout[i].scriptPubKey )
|
||||
// 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' )
|
||||
{
|
||||
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"));
|
||||
// normal payment
|
||||
for (const uint256& 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' )
|
||||
{
|
||||
scriptPubKeys.push_back(CScript(scriptPubKey.begin(), scriptPubKey.end()));
|
||||
allocations.push_back(allocation);
|
||||
//fprintf(stderr, "i.%i scriptpubkey.%s allocation.%li\n",i,scriptPubKeys[i].ToString().c_str(),allocation);
|
||||
checkallocations += allocation;
|
||||
// if we have an op_return to pay to need to check it exists and is paying the correct opret.
|
||||
if ( !opret.empty() )
|
||||
{
|
||||
if ( !fHasOpret )
|
||||
{
|
||||
fprintf(stderr, "missing opret.%s in payments release.\n",HexStr(opret.begin(), opret.end()).c_str());
|
||||
return(eval->Invalid("missing opret in payments release"));
|
||||
}
|
||||
else if ( CScript(opret.begin(),opret.end()) != tx.vout[tx.vout.size()-1].scriptPubKey )
|
||||
{
|
||||
fprintf(stderr, "opret.%s vs opret.%s\n",HexStr(opret.begin(), opret.end()).c_str(), HexStr(tx.vout[tx.vout.size()-1].scriptPubKey.begin(), tx.vout[tx.vout.size()-1].scriptPubKey.end()).c_str());
|
||||
return(eval->Invalid("pays incorrect opret"));
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
mpz_set_si(mpzTotalAllocations,totalallocations);
|
||||
}
|
||||
int64_t test;
|
||||
if ( fFixedAmount )
|
||||
else if ( funcid == 'S' )
|
||||
{
|
||||
test = checkamount / (top-bottom);
|
||||
if ( KOMODO_SNAPSHOT_INTERVAL == 0 )
|
||||
return(eval->Invalid("snapshots not activated on this chain"));
|
||||
if ( vAddressSnapshot.size() == 0 )
|
||||
return(eval->Invalid("need first snapshot"));
|
||||
if ( top > 3999 )
|
||||
return(eval->Invalid("transaction too big"));
|
||||
if ( fixedAmount == 7 )
|
||||
{
|
||||
// game setting, randomise bottom and top values
|
||||
fFixedAmount = payments_game(top,bottom);
|
||||
}
|
||||
else if ( fixedAmount != 0 )
|
||||
{
|
||||
fFixedAmount = true;
|
||||
}
|
||||
for (int32_t j = bottom; j < vAddressSnapshot.size(); j++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
if ( i != tx.vout.size()-2 )
|
||||
return(eval->Invalid("pays wrong amount of recipients"));
|
||||
}
|
||||
else
|
||||
else if ( funcid == 'O' )
|
||||
{
|
||||
mpz_init(mpzAllocation);
|
||||
mpz_set_si(mpzAllocation,allocations[n]);
|
||||
mpz_mul(mpzAllocation,mpzAllocation,mpzCheckamount);
|
||||
mpz_cdiv_q(mpzAllocation,mpzAllocation,mpzTotalAllocations);
|
||||
test = mpz_get_si(mpzAllocation);
|
||||
mpz_clear(mpzAllocation);
|
||||
// tokens snapshot.
|
||||
}
|
||||
// Vairance of 1 sat is allowed, for rounding errors.
|
||||
if ( test >= tx.vout[i].nValue+1 && test <= tx.vout[i].nValue-1 )
|
||||
// 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++)
|
||||
{
|
||||
fprintf(stderr, "vout.%i test.%li vs nVlaue.%li\n",i, test, tx.vout[i].nValue);
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
mpz_init(mpzAllocation);
|
||||
mpz_set_si(mpzAllocation,allocations[n]);
|
||||
mpz_mul(mpzAllocation,mpzAllocation,mpzCheckamount);
|
||||
mpz_cdiv_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 vs nVlaue.%li\n",i, test, tx.vout[i].nValue);
|
||||
return(eval->Invalid("amounts do not match"));
|
||||
}
|
||||
if ( test < 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 )
|
||||
{
|
||||
fprintf(stderr, "does not meet minrelease amount.%li minrelease.%li\n",amount, (int64_t)minrelease*COIN );
|
||||
return(eval->Invalid("amount is too small"));
|
||||
}
|
||||
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 )
|
||||
{
|
||||
fprintf(stderr, "does not meet minrelease amount.%li minrelease.%li\n",amount, (int64_t)minrelease*COIN );
|
||||
return(eval->Invalid("amount is too small"));
|
||||
}
|
||||
|
||||
// Check vins
|
||||
i = 0;
|
||||
int32_t ht = chainActive.LastTip()->GetHeight();
|
||||
i = 0; int32_t dust = 0;
|
||||
int32_t blocksleft;
|
||||
BOOST_FOREACH(const CTxIn& vin, tx.vin)
|
||||
{
|
||||
CTransaction txin;
|
||||
CTransaction txin;
|
||||
if ( myGetTransaction(vin.prevout.hash,txin,blockhash) )
|
||||
{
|
||||
// check the vin comes from the CC address's
|
||||
char destaddr[64];
|
||||
char destaddr[64]; int32_t mergeoffset = 0; CScript opret; uint256 checktxid;
|
||||
Getscriptaddress(destaddr,txin.vout[vin.prevout.n].scriptPubKey);
|
||||
if ( fIsMerge && txin.vout[vin.prevout.n].nValue < COIN )
|
||||
dust++;
|
||||
if ( strcmp(destaddr,coinaddr) != 0 )
|
||||
{
|
||||
// if does not come from address its in the global payments adddress and we need to check the opreturn.
|
||||
CScript opret; uint256 checktxid; int32_t opret_ind;
|
||||
uint256 checktxid; int32_t opret_ind;
|
||||
if ( (opret_ind= has_opret(txin, EVAL_PAYMENTS)) == 0 )
|
||||
opret = getCCopret(txin.vout[vin.prevout.n].scriptPubKey); // get op_return from CCvout,
|
||||
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 )
|
||||
@@ -440,15 +497,23 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
return(eval->Invalid("vin is not paymentsCC type"));
|
||||
}
|
||||
}
|
||||
// check the chain depth vs locked blocks requirement.
|
||||
CBlockIndex* pblockindex = komodo_blockindex(blockhash);
|
||||
if ( pblockindex == 0 || pblockindex->GetHeight() > ht-lockedblocks )
|
||||
else if ( fIsMerge && getCCopret(txin.vout[vin.prevout.n].scriptPubKey,opret) && opret.size() > 2 && DecodePaymentsMergeOpRet(opret,checktxid) == 'M' )
|
||||
{
|
||||
fprintf(stderr, "vin.%i is not elegible to be spent yet height.%i vs elegible_ht.%i\n", i, pblockindex!=0?pblockindex->GetHeight():0, ht-lockedblocks);
|
||||
return(eval->Invalid("vin not elegible"));
|
||||
mergeoffset = PAYMENTS_MERGEOFSET;
|
||||
}
|
||||
//fprintf(stderr, "mergeoffset.%i\n", mergeoffset);
|
||||
// check the chain depth vs locked blocks requirement.
|
||||
if ( !payments_lockedblocks(blockhash, lockedblocks+mergeoffset, blocksleft) )
|
||||
return(eval->Invalid("vin not elegible"));
|
||||
i++;
|
||||
} else return(eval->Invalid("cant get vin transaction"));
|
||||
i++;
|
||||
}
|
||||
if ( fIsMerge )
|
||||
{
|
||||
if ( i < 2 )
|
||||
return(eval->Invalid("must have at least 2 vins to carry out merge"));
|
||||
else if ( i == dust+1 )
|
||||
return(eval->Invalid("cannot merge only dust"));
|
||||
}
|
||||
} else return(eval->Invalid("create transaction cannot decode"));
|
||||
} else return(eval->Invalid("Could not get contract transaction"));
|
||||
@@ -457,19 +522,27 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
// end of consensus code
|
||||
|
||||
// helper functions for rpc calls in rpcwallet.cpp
|
||||
|
||||
int64_t AddPaymentsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey txidpk,int64_t total,int32_t maxinputs,uint256 createtxid,int32_t latestheight)
|
||||
int64_t AddPaymentsInputs(bool fLockedBlocks,int8_t GetBalance,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey txidpk,int64_t total,int32_t maxinputs,uint256 createtxid,int32_t lockedblocks,int64_t minrelease,int32_t &blocksleft)
|
||||
{
|
||||
char coinaddr[64]; CPubKey Paymentspk; int64_t nValue,threshold,price,totalinputs = 0; uint256 txid,checktxid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t iter,vout,ht,n = 0;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; CScript ccopret;
|
||||
std::vector<std::pair<int32_t,CAmount> > blocksleft_balance;
|
||||
if ( GetBalance == 0 )
|
||||
{
|
||||
if ( maxinputs > CC_MAXVINS )
|
||||
maxinputs = CC_MAXVINS;
|
||||
if ( maxinputs > 0 )
|
||||
threshold = total/maxinputs;
|
||||
else threshold = total;
|
||||
}
|
||||
else threshold = 0;
|
||||
Paymentspk = GetUnspendable(cp,0);
|
||||
for (iter=0; iter<2; iter++)
|
||||
{
|
||||
if ( GetBalance == 1 && iter == 1 )
|
||||
continue; // getbalance of global paymentsCC address.
|
||||
if ( GetBalance == 2 && iter == 0 )
|
||||
continue; // get balance of txidpk address.
|
||||
if ( iter == 0 )
|
||||
GetCCaddress(cp,coinaddr,Paymentspk);
|
||||
else GetCCaddress1of2(cp,coinaddr,Paymentspk,txidpk);
|
||||
@@ -481,26 +554,13 @@ int64_t AddPaymentsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
|
||||
//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 ( latestheight != 0 )
|
||||
{
|
||||
if ( (ht= komodo_blockheight(hashBlock)) == 0 )
|
||||
{
|
||||
fprintf(stderr,"null ht\n");
|
||||
continue;
|
||||
}
|
||||
else if ( ht > latestheight )
|
||||
{
|
||||
fprintf(stderr,"ht.%d > lastheight.%d\n",ht,latestheight);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
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
|
||||
opret = getCCopret(vintx.vout[vout].scriptPubKey);
|
||||
getCCopret(vintx.vout[vout].scriptPubKey,opret);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -513,18 +573,41 @@ int64_t AddPaymentsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( (nValue= IsPaymentsvout(cp,vintx,vout,coinaddr)) > PAYMENTS_TXFEE && nValue >= threshold && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
|
||||
if ( (nValue= IsPaymentsvout(cp,vintx,vout,coinaddr,ccopret)) > PAYMENTS_TXFEE && nValue >= threshold && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
|
||||
{
|
||||
if ( total != 0 && maxinputs != 0 )
|
||||
int32_t tmpblocksleft = 0;
|
||||
if ( fLockedBlocks && !payments_lockedblocks(hashBlock, lockedblocks+(GetBalance == 4 ? PAYMENTS_MERGEOFSET : 0), tmpblocksleft) )
|
||||
{
|
||||
blocksleft_balance.push_back(std::make_pair(tmpblocksleft,nValue));
|
||||
continue;
|
||||
}
|
||||
if ( (GetBalance == 0 && total != 0 && maxinputs != 0) || GetBalance == 4 )
|
||||
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
|
||||
nValue = it->second.satoshis;
|
||||
if ( nValue < COIN )
|
||||
blocksleft++; // count dust 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);
|
||||
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
|
||||
break;
|
||||
if ( GetBalance == 0 && ((total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs)) )
|
||||
break; // create tx. We have ebnough inputs to make it.
|
||||
} //else fprintf(stderr,"nValue %.8f vs threshold %.8f\n",(double)nValue/COIN,(double)threshold/COIN);
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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.
|
||||
std::sort(blocksleft_balance.begin(), blocksleft_balance.end());
|
||||
// iterate the utxos blocks left vector, to get block height min release is able to be released.
|
||||
for ( auto utxo : blocksleft_balance )
|
||||
{
|
||||
lockedblocks_balance += utxo.second;
|
||||
if ( lockedblocks_balance >= minrelease )
|
||||
{
|
||||
blocksleft = utxo.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -602,10 +685,11 @@ int32_t payments_parsehexdata(std::vector<uint8_t> &hexdata,cJSON *item,int32_t
|
||||
|
||||
UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
int32_t latestheight,nextheight = komodo_nextheight();
|
||||
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; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; int8_t funcid,fixedAmount=0; bool fFixedAmount = false;
|
||||
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);
|
||||
cJSON *params = payments_reparse(&n,jsonstr);
|
||||
mypk = pubkey2pk(Mypubkey());
|
||||
@@ -616,7 +700,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
amount = jdouble(jitem(params,1),0) * SATOSHIDEN + 0.0000000049;
|
||||
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,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,top,excludeScriptPubKeys,tokenid)) == 'O') )
|
||||
{
|
||||
if ( lockedblocks < 0 || minrelease < 0 || (totalallocations <= 0 && top <= 0 ) )
|
||||
{
|
||||
@@ -626,7 +710,10 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
latestheight = (nextheight - lockedblocks - 1);
|
||||
// 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"));
|
||||
@@ -713,21 +800,10 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
return(result);
|
||||
}
|
||||
i = 0;
|
||||
//for ( auto address : vAddressSnapshot )
|
||||
if ( fixedAmount == 7 )
|
||||
{
|
||||
// game setting, randomise bottom and top values
|
||||
uint64_t x;
|
||||
uint256 tmphash = chainActive[lastSnapShotHeight]->GetBlockHash();
|
||||
memcpy(&x,&tmphash,sizeof(x));
|
||||
bottom = ((x & 0xff) % 50);
|
||||
if ( bottom == 0 ) bottom = 1;
|
||||
top = (((x>>8) & 0xff) % 100);
|
||||
if ( top < 50 ) top += 50;
|
||||
bottom = (vAddressSnapshot.size()*bottom)/100;
|
||||
top = (vAddressSnapshot.size()*top)/100;
|
||||
fprintf(stderr, "bottom.%i top.%i\n",bottom,top);
|
||||
fFixedAmount = true;
|
||||
fFixedAmount = payments_game(top,bottom);
|
||||
}
|
||||
else if ( fixedAmount != 0 )
|
||||
{
|
||||
@@ -769,7 +845,6 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
newamount = amount;
|
||||
int64_t totalamountsent = 0;
|
||||
mpz_t mpzAmount; mpz_init(mpzAmount); mpz_set_si(mpzAmount,amount);
|
||||
fprintf(stderr, "m.%i\n",m);
|
||||
for (i=0; i<m; i++)
|
||||
{
|
||||
mpz_t mpzValue; mpz_init(mpzValue);
|
||||
@@ -796,13 +871,14 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
}
|
||||
//fprintf(stderr, "nValue.%li \n", mtx.vout[i+1].nValue);
|
||||
mpz_clear(mpzValue);
|
||||
/*
|
||||
replace this with default dust threshold of 10ksat
|
||||
if ( mtx.vout[i+1].nValue < PAYMENTS_TXFEE )
|
||||
if ( mtx.vout[i+1].nValue < minimum )
|
||||
{
|
||||
newamount += (PAYMENTS_TXFEE - mtx.vout[i+1].nValue);
|
||||
mtx.vout[i+1].nValue = PAYMENTS_TXFEE;
|
||||
} */
|
||||
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);
|
||||
}
|
||||
totalamountsent += mtx.vout[i+1].nValue;
|
||||
}
|
||||
if ( totalamountsent < amount ) newamount = totalamountsent;
|
||||
@@ -817,7 +893,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
if ( (inputsum= AddPaymentsInputs(cp,mtx,txidpk,newamount+2*PAYMENTS_TXFEE,CC_MAXVINS/2,createtxid,latestheight)) >= newamount+2*PAYMENTS_TXFEE )
|
||||
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 )
|
||||
@@ -858,7 +934,7 @@ 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;
|
||||
int32_t top,bottom; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; // snapshot
|
||||
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());
|
||||
@@ -869,7 +945,7 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
|
||||
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,top,bottom,fixedAmount,excludeScriptPubKeys) == 0 && DecodePaymentsTokensOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,top,excludeScriptPubKeys,tokenid) == 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) )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","invalid createtxid"));
|
||||
@@ -921,6 +997,64 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue PaymentsMerge(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); UniValue result(UniValue::VOBJ);
|
||||
CPubKey Paymentspk,mypk,txidpk; uint256 createtxid,hashBlock; int64_t inputsum,totalallocations=0; CScript opret; CTransaction tx; char txidaddr[64],destaddr[64]; std::string rawtx;
|
||||
int32_t n,lockedblocks,minrelease,top,bottom,minimum=10000,blocksleft; std::vector<uint256> txidoprets;
|
||||
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 )
|
||||
{
|
||||
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) )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","invalid createtxid"));
|
||||
}
|
||||
else if ( (inputsum= AddPaymentsInputs(true,4,cp,mtx,txidpk,0,CC_MAXVINS,createtxid,lockedblocks,minrelease,blocksleft)) > 0 && mtx.vin.size() > 1 )
|
||||
{
|
||||
int32_t dust = blocksleft;
|
||||
if ( mtx.vin.size() == dust+1 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","cannot merge only dust"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// encode the checktxid into the end of the ccvout, along with 'M' to flag merge type tx.
|
||||
opret = EncodePaymentsMergeOpRet(createtxid);
|
||||
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
|
||||
if ( makeCCopret(opret, vData) )
|
||||
mtx.vout.push_back(MakeCC1of2vout(EVAL_PAYMENTS,inputsum-PAYMENTS_TXFEE,Paymentspk,txidpk,&vData));
|
||||
GetCCaddress1of2(cp,destaddr,Paymentspk,txidpk);
|
||||
CCaddr1of2set(cp,Paymentspk,txidpk,cp->CCpriv,destaddr);
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,CScript());
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(payments_rawtxresult(result,rawtx,0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","couldnt find enough funds"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","parameters error"));
|
||||
}
|
||||
if ( params != 0 )
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
|
||||
UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); UniValue result(UniValue::VOBJ); CPubKey mypk; std::string rawtx;
|
||||
@@ -1041,7 +1175,7 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
|
||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||
UniValue result(UniValue::VOBJ);
|
||||
uint256 hashBlock; CTransaction tx; CPubKey Paymentspk,mypk; char markeraddr[64]; std::string rawtx;
|
||||
int32_t lockedblocks,minrelease,top,bottom,n,i; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; int8_t fixedAmount;
|
||||
int32_t lockedblocks,minrelease,top,bottom,n,i,minimum=10000; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; int8_t fixedAmount;
|
||||
if ( KOMODO_SNAPSHOT_INTERVAL == 0 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
@@ -1053,10 +1187,11 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
lockedblocks = juint(jitem(params,0),0);
|
||||
minrelease = juint(jitem(params,1),0);
|
||||
top = juint(jitem(params,2),0);
|
||||
bottom = juint(jitem(params,3),0);
|
||||
fixedAmount = juint(jitem(params,4),0); // fixed amount is a flag set to 0 or 1. It means allocations are equal rather than weighted by address balance.
|
||||
if ( lockedblocks < 0 || minrelease < 0 || top <= 0 || bottom < 0 || fixedAmount < 0 || top > 3999 )
|
||||
minimum = juint(jitem(params,2),0);
|
||||
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.
|
||||
if ( lockedblocks < 0 || minrelease < 0 || top <= 0 || bottom < 0 || minimum < 0 || fixedAmount < 0 || top > 3999 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","negative parameter, or top over 3999"));
|
||||
@@ -1064,15 +1199,15 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
if ( n > 5 )
|
||||
if ( n > 6 )
|
||||
{
|
||||
for (i=0; i<n-5; i++)
|
||||
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_);
|
||||
CScript scriptPubKey = GetScriptForDestination(destination);
|
||||
*/
|
||||
char *inputhex = jstri(params,3+i);
|
||||
char *inputhex = jstri(params,6+i);
|
||||
std::vector<uint8_t> scriptPubKey;
|
||||
int32_t len = strlen(inputhex)/2;
|
||||
scriptPubKey.resize(len);
|
||||
@@ -1085,7 +1220,16 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
|
||||
if ( AddNormalinputs(mtx,mypk,2*PAYMENTS_TXFEE,60) > 0 )
|
||||
{
|
||||
mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,PAYMENTS_TXFEE,Paymentspk,Paymentspk));
|
||||
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,EncodePaymentsSnapsShotOpRet(lockedblocks,minrelease,top,bottom,fixedAmount,excludeScriptPubKeys));
|
||||
CScript tempopret = EncodePaymentsSnapsShotOpRet(lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys);
|
||||
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 addresses."));
|
||||
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,1));
|
||||
@@ -1105,9 +1249,9 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
|
||||
|
||||
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; std::vector<uint256> txidoprets; int64_t funds,fundsopret,totalallocations=0,allocation; char fundsaddr[64],fundsopretaddr[64],txidaddr[64],*outstr; uint256 createtxid,hashBlock;
|
||||
int32_t top,bottom; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; // snapshot
|
||||
uint256 tokenid; int8_t fixedAmount;
|
||||
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;
|
||||
int32_t top,bottom,minimum=10000; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; // snapshot
|
||||
uint256 tokenid; int8_t fixedAmount; CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),komodo_nextheight());
|
||||
cJSON *params = payments_reparse(&n,jsonstr);
|
||||
if ( params != 0 && n == 1 )
|
||||
{
|
||||
@@ -1162,9 +1306,9 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
|
||||
result.push_back(Pair("error","too many opreturns"));
|
||||
} else result.push_back(Pair("txidoprets",a));
|
||||
}
|
||||
else if ( DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,top,bottom,fixedAmount,excludeScriptPubKeys) != 0 )
|
||||
else if ( DecodePaymentsSnapsShotOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,minimum,top,bottom,fixedAmount,excludeScriptPubKeys) != 0 )
|
||||
{
|
||||
if ( lockedblocks < 0 || minrelease < 0 || top <= 0 || bottom < 0 || fixedAmount < 0 || top > 3999 )
|
||||
if ( lockedblocks < 0 || minrelease < 0 || top <= 0 || bottom < 0 || fixedAmount < 0 || top > 3999 || minimum < 10000 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","negative parameter"));
|
||||
@@ -1172,11 +1316,15 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
|
||||
free_json(params);
|
||||
return(result);
|
||||
}
|
||||
result.push_back(Pair("plan_type","snapshot"));
|
||||
if ( fixedAmount == 7 && payments_game(top,bottom))
|
||||
result.push_back(Pair("plan_type","payments_game"));
|
||||
else
|
||||
result.push_back(Pair("plan_type","snapshot"));
|
||||
result.push_back(Pair("lockedblocks",(int64_t)lockedblocks));
|
||||
result.push_back(Pair("minrelease",(int64_t)minrelease));
|
||||
result.push_back(Pair("top",(int64_t)top));
|
||||
result.push_back(Pair("minimum",(int64_t)minimum));
|
||||
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 )
|
||||
@@ -1212,13 +1360,16 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
txidpk = CCtxidaddr(txidaddr,createtxid);
|
||||
GetCCaddress1of2(cp,fundsaddr,Paymentspk,txidpk);
|
||||
funds = CCaddress_balance(fundsaddr,1);
|
||||
funds = AddPaymentsInputs(false,2,cp,mtx,txidpk,0,CC_MAXVINS,createtxid,lockedblocks,minrelease,blocksleft);
|
||||
result.push_back(Pair(fundsaddr,ValueFromAmount(funds)));
|
||||
GetCCaddress(cp,fundsopretaddr,Paymentspk);
|
||||
// TODO: Shows balance for ALL payments plans, not just the one asked for! Needs to be reworked.
|
||||
fundsopret = CCaddress_balance(fundsopretaddr,1);
|
||||
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("totalfunds",ValueFromAmount(funds+fundsopret)));
|
||||
// Blocks until minrelease can be released.
|
||||
elegiblefunds = AddPaymentsInputs(true,3,cp,mtx,txidpk,0,CC_MAXVINS,createtxid,lockedblocks,minrelease,blocksleft);
|
||||
result.push_back(Pair("elegiblefunds",ValueFromAmount(elegiblefunds)));
|
||||
result.push_back(Pair("min_release_height",chainActive.Height()+blocksleft));
|
||||
result.push_back(Pair("result","success"));
|
||||
}
|
||||
}
|
||||
@@ -1242,7 +1393,7 @@ UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr)
|
||||
{
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; uint256 txid,hashBlock,tokenid;
|
||||
UniValue result(UniValue::VOBJ),a(UniValue::VARR); char markeraddr[64],str[65]; CPubKey Paymentspk; CTransaction tx; int32_t lockedblocks,minrelease; std::vector<uint256> txidoprets; int64_t totalallocations=0;
|
||||
int32_t top=0,bottom=0; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; int8_t fixedAmount = 0;
|
||||
int32_t top=0,bottom=0,minimum=10000; std::vector<std::vector<uint8_t>> excludeScriptPubKeys; int8_t fixedAmount = 0;
|
||||
Paymentspk = GetUnspendable(cp,0);
|
||||
GetCCaddress1of2(cp,markeraddr,Paymentspk,Paymentspk);
|
||||
SetCCtxids(addressIndex,markeraddr,true);
|
||||
@@ -1251,9 +1402,9 @@ 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,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,top,excludeScriptPubKeys,tokenid) == 'O') )
|
||||
{
|
||||
if ( lockedblocks < 0 || minrelease < 0 || (totalallocations <= 0 && top <= 0 ) || bottom < 0 || fixedAmount < 0 )
|
||||
if ( lockedblocks < 0 || minrelease < 0 || (totalallocations <= 0 && top <= 0 ) || bottom < 0 || fixedAmount < 0 || minimum < 10000 )
|
||||
{
|
||||
result.push_back(Pair("result","error"));
|
||||
result.push_back(Pair("error","negative parameter"));
|
||||
|
||||
13
src/chain.h
13
src/chain.h
@@ -28,6 +28,7 @@ class CChainPower;
|
||||
#include "pow.h"
|
||||
#include "tinyformat.h"
|
||||
#include "uint256.h"
|
||||
extern int8_t is_STAKED(const char *chain_name);
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -36,6 +37,8 @@ class CChainPower;
|
||||
static const int SPROUT_VALUE_VERSION = 1001400;
|
||||
static const int SAPLING_VALUE_VERSION = 1010100;
|
||||
extern int32_t ASSETCHAINS_LWMAPOS;
|
||||
extern char ASSETCHAINS_SYMBOL[65];
|
||||
extern uint64_t ASSETCHAINS_NOTARY_PAY[];
|
||||
|
||||
struct CDiskBlockPos
|
||||
{
|
||||
@@ -118,7 +121,7 @@ enum BlockStatus: uint32_t {
|
||||
BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
|
||||
|
||||
BLOCK_ACTIVATES_UPGRADE = 128, //! block activates a network upgrade
|
||||
BLOCK_IN_TMPFILE = 256
|
||||
BLOCK_IN_TMPFILE = 256
|
||||
};
|
||||
|
||||
//! Short-hand for the highest consensus validity we implement.
|
||||
@@ -238,7 +241,7 @@ public:
|
||||
CBlockIndex* pskip;
|
||||
|
||||
//! height of the entry in the chain. The genesis block has height 0
|
||||
int64_t newcoins,zfunds,sproutfunds; int8_t segid; // jl777 fields
|
||||
int64_t newcoins,zfunds,sproutfunds,nNotaryPay; int8_t segid; // jl777 fields
|
||||
//! Which # file this block is stored in (blk?????.dat)
|
||||
int nFile;
|
||||
|
||||
@@ -309,6 +312,7 @@ public:
|
||||
phashBlock = NULL;
|
||||
newcoins = zfunds = 0;
|
||||
segid = -2;
|
||||
nNotaryPay = 0;
|
||||
pprev = NULL;
|
||||
pskip = NULL;
|
||||
nFile = 0;
|
||||
@@ -543,6 +547,11 @@ public:
|
||||
if ((s.GetType() & SER_DISK) && (nVersion >= SAPLING_VALUE_VERSION)) {
|
||||
READWRITE(nSaplingValue);
|
||||
}
|
||||
if ( (s.GetType() & SER_DISK) && (is_STAKED(ASSETCHAINS_SYMBOL) != 0) && ASSETCHAINS_NOTARY_PAY[0] != 0 )
|
||||
{
|
||||
READWRITE(nNotaryPay);
|
||||
READWRITE(segid);
|
||||
}
|
||||
}
|
||||
|
||||
uint256 GetBlockHash() const
|
||||
|
||||
@@ -1539,7 +1539,7 @@ uint16_t komodo_port(char *symbol,uint64_t supply,uint32_t *magicp,uint8_t *extr
|
||||
printf("ports\n");
|
||||
}*/
|
||||
|
||||
char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\",\\\"sapling\\\":1}\"";
|
||||
char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\",\\\"sapling\\\":1,\\\"notarypay\\\":%i}\"";
|
||||
|
||||
|
||||
|
||||
@@ -2221,7 +2221,10 @@ void komodo_args(char *argv0)
|
||||
sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL);
|
||||
if ( (fp= fopen(fname,"wb")) != 0 )
|
||||
{
|
||||
fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146");
|
||||
int8_t notarypay = 0;
|
||||
if ( ASSETCHAINS_NOTARY_PAY[0] != 0 )
|
||||
notarypay = 1;
|
||||
fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146",notarypay);
|
||||
fclose(fp);
|
||||
//printf("created (%s)\n",fname);
|
||||
} else printf("error creating (%s)\n",fname);
|
||||
|
||||
11
src/main.cpp
11
src/main.cpp
@@ -3364,7 +3364,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
auto verifier = libzcash::ProofVerifier::Strict();
|
||||
auto disabledVerifier = libzcash::ProofVerifier::Disabled();
|
||||
int32_t futureblock;
|
||||
CAmount blockReward = 0;
|
||||
CAmount blockReward = 0; uint64_t notarypaycheque = 0;
|
||||
// Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in
|
||||
if (!CheckBlock(&futureblock,pindex->GetHeight(),pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 )
|
||||
{
|
||||
@@ -3402,7 +3402,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
return state.DoS(100, error("ConnectBlock(): Notaries have not been paid!"),
|
||||
REJECT_INVALID, "bad-cb-amount");
|
||||
// calculate the notaries compensation and validate the amounts and pubkeys are correct.
|
||||
uint64_t notarypaycheque = komodo_checknotarypay((CBlock *)&block,(int32_t)pindex->GetHeight());
|
||||
notarypaycheque = komodo_checknotarypay((CBlock *)&block,(int32_t)pindex->GetHeight());
|
||||
//fprintf(stderr, "notarypaycheque.%lu\n", notarypaycheque);
|
||||
if ( notarypaycheque > 0 )
|
||||
blockReward += notarypaycheque;
|
||||
@@ -3809,6 +3809,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
|
||||
//FlushStateToDisk();
|
||||
komodo_connectblock(false,pindex,*(CBlock *)&block); // dPoW state update.
|
||||
if ( ASSETCHAINS_NOTARY_PAY[0] != 0 )
|
||||
{
|
||||
// Update the notary pay with the latest payment.
|
||||
pindex->nNotaryPay = pindex->pprev->nNotaryPay + notarypaycheque;
|
||||
//fprintf(stderr, "total notary pay.%li\n", pindex->nNotaryPay);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4018,6 +4024,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
|
||||
DisconnectNotarisations(block);
|
||||
}
|
||||
pindexDelete->segid = -2;
|
||||
pindexDelete->nNotaryPay = 0;
|
||||
pindexDelete->newcoins = 0;
|
||||
pindexDelete->zfunds = 0;
|
||||
|
||||
|
||||
@@ -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 = 0x100000; // 1 MiB
|
||||
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
|
||||
/** Maximum number of script-checking threads allowed */
|
||||
static const int MAX_SCRIPTCHECK_THREADS = 16;
|
||||
/** -par default (number of script-checking threads, 0 = auto) */
|
||||
|
||||
@@ -728,7 +728,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
fprintf(stderr, "Created notary payment coinbase totalsat.%lu\n",totalsats);
|
||||
//fprintf(stderr, "Created notary payment coinbase totalsat.%lu\n",totalsats);
|
||||
} else fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen);
|
||||
}
|
||||
if ( ASSETCHAINS_CBOPRET != 0 )
|
||||
|
||||
@@ -18,7 +18,7 @@ int8_t is_STAKED(const char *chain_name)
|
||||
if (doneinit == 1 && ASSETCHAINS_SYMBOL[0] != 0)
|
||||
return(STAKED);
|
||||
else STAKED = 0;
|
||||
if ( (strcmp(chain_name, "LABS") == 0) || (strcmp(chain_name, "LABSTH") == 0) )
|
||||
if ( (strcmp(chain_name, "LABS") == 0) || (strcmp(chain_name, "LABSRCTEST") == 0) )
|
||||
STAKED = 1; // These chains are allowed coin emissions.
|
||||
else if ( (strncmp(chain_name, "LABS", 4) == 0) )
|
||||
STAKED = 2; // These chains have no coin emission, block subsidy is always 0, and comission is 0. Notary pay is allowed.
|
||||
|
||||
@@ -300,6 +300,9 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp)
|
||||
uint256 tokenid = zeroid;
|
||||
if( params.size() == 4 )
|
||||
tokenid = Parseuint256(params[3].get_str().c_str());
|
||||
|
||||
if ( tokenid != zeroid && strcmp("LABS", targetSymbol.c_str()))
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "There is no tokens support on LABS.");
|
||||
|
||||
CPubKey myPubKey = Mypubkey();
|
||||
struct CCcontract_info *cpTokens, C;
|
||||
@@ -312,8 +315,8 @@ UniValue migrate_createburntransaction(const UniValue& params, bool fHelp)
|
||||
|
||||
if (tokenid.IsNull()) { // coins
|
||||
int64_t inputs;
|
||||
if ((inputs = AddNormalinputs(mtx, myPubKey, burnAmount + txfee, 60)) == 0) {
|
||||
throw runtime_error("Cannot find normal inputs\n");
|
||||
if ((inputs = AddNormalinputs(mtx, myPubKey, burnAmount + txfee, 10)) == 0) {
|
||||
throw runtime_error("not enough funds, or need to merge utxos first\n");
|
||||
}
|
||||
|
||||
CTxDestination txdest = DecodeDestination(dest_addr_or_pubkey.c_str());
|
||||
@@ -1145,36 +1148,43 @@ UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp)
|
||||
//out.push_back(make_pair("blocktime",(int)));
|
||||
UniValue labs(UniValue::VARR);
|
||||
UniValue kmd(UniValue::VARR);
|
||||
// Gets KMD notaries on KMD... but LABS notaries on labs chains needs to be fixed so LABS are identified on KMD.
|
||||
int8_t numNN = 0; uint8_t notarypubkeys[64][33] = {0};
|
||||
int8_t numNN = 0, numSN = 0; uint8_t notarypubkeys[64][33] = {0}; uint8_t LABSpubkeys[64][33] = {0};
|
||||
numNN = komodo_notaries(notarypubkeys, height, chainActive[height]->nTime);
|
||||
|
||||
numSN = numStakedNotaries(LABSpubkeys,STAKED_era(chainActive[height]->nTime));
|
||||
|
||||
BOOST_FOREACH(const Notarisation& n, nibs)
|
||||
{
|
||||
UniValue item(UniValue::VOBJ); UniValue notaryarr(UniValue::VARR); std::vector<int8_t> NotarisationNotaries;
|
||||
if ( is_STAKED(n.second.symbol) != 0 )
|
||||
continue; // for now just skip this... need to fetch diff pubkeys for these chains. labs.push_back(item);
|
||||
uint256 hash; CTransaction tx;
|
||||
if ( GetTransaction(n.first,tx,hash,false) )
|
||||
{
|
||||
if ( !GetNotarisationNotaries(notarypubkeys, numNN, tx.vin, NotarisationNotaries) )
|
||||
continue;
|
||||
if ( NotarisationNotaries.size() < numNN/5 )
|
||||
continue;
|
||||
if ( is_STAKED(n.second.symbol) != 0 )
|
||||
{
|
||||
if ( !GetNotarisationNotaries(LABSpubkeys, numSN, tx.vin, NotarisationNotaries) )
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !GetNotarisationNotaries(notarypubkeys, numNN, tx.vin, NotarisationNotaries) )
|
||||
continue;
|
||||
}
|
||||
}
|
||||
item.push_back(make_pair("txid", n.first.GetHex()));
|
||||
item.push_back(make_pair("chain", n.second.symbol));
|
||||
item.push_back(make_pair("height", (int)n.second.height));
|
||||
item.push_back(make_pair("blockhash", n.second.blockHash.GetHex()));
|
||||
item.push_back(make_pair("KMD_height", height)); // for when timstamp input is used.
|
||||
//item.push_back(make_pair("KMD_height", height)); // for when timstamp input is used.
|
||||
|
||||
for ( auto notary : NotarisationNotaries )
|
||||
notaryarr.push_back(notary);
|
||||
item.push_back(make_pair("notaries",notaryarr));
|
||||
kmd.push_back(item);
|
||||
if ( is_STAKED(n.second.symbol) != 0 )
|
||||
labs.push_back(item);
|
||||
else
|
||||
kmd.push_back(item);
|
||||
}
|
||||
out.push_back(make_pair("KMD", kmd));
|
||||
//out.push_back(make_pair("LABS", labs));
|
||||
out.push_back(make_pair("LABS", labs));
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -1308,7 +1318,7 @@ UniValue getimports(const UniValue& params, bool fHelp)
|
||||
UniValue objTx(UniValue::VOBJ);
|
||||
objTx.push_back(Pair("txid",tx.GetHash().ToString()));
|
||||
ImportProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; CTxDestination importaddress;
|
||||
TotalImported += tx.vout[1].nValue;
|
||||
TotalImported += tx.vout[0].nValue; // were vouts swapped?
|
||||
objTx.push_back(Pair("amount", ValueFromAmount(tx.vout[1].nValue)));
|
||||
if (ExtractDestination(tx.vout[1].scriptPubKey, importaddress))
|
||||
{
|
||||
@@ -1481,4 +1491,4 @@ UniValue getwalletburntransactions(const UniValue& params, bool fHelp)
|
||||
ret.push_backV(arrTmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
109
src/rpc/misc.cpp
109
src/rpc/misc.cpp
@@ -75,6 +75,8 @@ uint32_t komodo_segid32(char *coinaddr);
|
||||
int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height);
|
||||
int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp);
|
||||
int8_t StakedNotaryID(std::string ¬aryname, char *Raddress);
|
||||
uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount);
|
||||
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
|
||||
|
||||
#define KOMODO_VERSION "0.3.3b"
|
||||
#define VERUS_VERSION "0.4.0g"
|
||||
@@ -168,7 +170,7 @@ UniValue geterablockheights(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getnotarysendmany\n"
|
||||
"geterablockheights\n"
|
||||
"Returns a JSON object with the first block in each era.\n"
|
||||
);
|
||||
|
||||
@@ -1216,6 +1218,106 @@ UniValue getaddressdeltas(const UniValue& params, bool fHelp)
|
||||
}
|
||||
}
|
||||
|
||||
CAmount checkburnaddress(CAmount &received, int64_t &nNotaryPay, int32_t &height, std::string sAddress)
|
||||
{
|
||||
CBitcoinAddress address(sAddress);
|
||||
uint160 hashBytes; int type = 0; CAmount balance = 0;
|
||||
if (address.GetIndexKey(hashBytes, type, false))
|
||||
{
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
|
||||
if (GetAddressIndex(hashBytes, type, addressIndex))
|
||||
{
|
||||
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
|
||||
{
|
||||
if (it->second > 0)
|
||||
received += it->second;
|
||||
balance += it->second;
|
||||
}
|
||||
// Get notary pay from current chain tip
|
||||
CBlockIndex* pindex = chainActive.LastTip();
|
||||
nNotaryPay = pindex->nNotaryPay;
|
||||
height = pindex->GetHeight();
|
||||
}
|
||||
}
|
||||
return balance;
|
||||
}
|
||||
|
||||
UniValue checknotarization(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"checknotarization\n"
|
||||
"\nReturns true if burn address balance is greater than total notary pay. (requires addressindex to be enabled).\n"
|
||||
);
|
||||
|
||||
UniValue result(UniValue::VOBJ); CAmount balance = 0, received = 0; int64_t nNotaryPay = 0; int32_t height;
|
||||
|
||||
// helper to test burn address's
|
||||
/*uint8_t priv[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t pub[33] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
char coinaddr[64]; uint8_t buf33[33];
|
||||
//pubkey2addr(coinaddr, pub);
|
||||
priv2addr(coinaddr,buf33,priv);
|
||||
fprintf(stderr, "what.%s\n", coinaddr);
|
||||
result.push_back(Pair("address", coinaddr));
|
||||
return result;
|
||||
*/
|
||||
|
||||
if ( ASSETCHAINS_NOTARY_PAY[0] == 0 )
|
||||
throw runtime_error("only works for ac_notarypay chains");
|
||||
// pubkey 020000000000000000000000000000000
|
||||
balance = checkburnaddress(received, nNotaryPay, height, "REDVp3ox1pbcWYCzySadfHhk8UU3HM4k5x");
|
||||
if ( nNotaryPay >= balance || received != balance )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
UniValue getnotarypayinfo(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 0)
|
||||
throw runtime_error(
|
||||
"getnotarypayinfo\n"
|
||||
"\nReturns infomation about ac_notaypay status (requires addressindex to be enabled).\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"height\" (number) The current block height\n"
|
||||
" \"balance\" (number) The current balance of the burn address\n"
|
||||
" \"spent\" (bool) true if coins have been spent from the burn address\n"
|
||||
" \"Total_NotaryPay\" (number) Total amount paid to notaries\n"
|
||||
" \"Estimated_Notarizations_Left\" (number) the estimated amount of notarizations left before the balance is consumed\n"
|
||||
" \"Estimated_Days_Left\" (number) the estimated amount of days the current balance will last\n"
|
||||
" \"Estimated_Height\" (number) the estimated block height funds will run out\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
if ( ASSETCHAINS_NOTARY_PAY[0] == 0 )
|
||||
throw runtime_error("only works for ac_notarypay chains");
|
||||
|
||||
UniValue result(UniValue::VOBJ); CAmount balance = 0, received = 0; int64_t TotalNotaryPay = 0, NotaryPay, notaleft = 0, daysleft = 0, notarycount; int32_t height, endheight = 0; uint8_t notarypubkeys[64][33] = {0};
|
||||
|
||||
// pubkey 020000000000000000000000000000000
|
||||
balance = checkburnaddress(received, TotalNotaryPay, height, "REDVp3ox1pbcWYCzySadfHhk8UU3HM4k5x");
|
||||
|
||||
notarycount = komodo_notaries(notarypubkeys, height, chainActive[height]->GetBlockTime());
|
||||
NotaryPay = komodo_notarypayamount(height, notarycount)*notarycount;
|
||||
bool spent = (received != balance);
|
||||
if ( !spent )
|
||||
{
|
||||
notaleft = ((int64_t)balance - TotalNotaryPay) / NotaryPay;
|
||||
daysleft = (((ASSETCHAINS_BLOCKTIME * 5) * notaleft) / 3600) / 24;
|
||||
endheight = (notaleft * 5) + height;
|
||||
}
|
||||
|
||||
result.push_back(Pair("height", height));
|
||||
result.push_back(Pair("balance", ValueFromAmount(balance)));
|
||||
result.push_back(Pair("spent", spent));
|
||||
result.push_back(Pair("Total_NotaryPay", ValueFromAmount(TotalNotaryPay)));
|
||||
result.push_back(Pair("Estimated_Notarizations_Left", notaleft));
|
||||
result.push_back(Pair("Estimated_Days_Left", daysleft));
|
||||
result.push_back(Pair("Estimated_Height", endheight));
|
||||
return result;
|
||||
}
|
||||
|
||||
UniValue getaddressbalance(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp ||params.size() > 2 || params.size() == 0)
|
||||
@@ -1281,8 +1383,9 @@ 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");
|
||||
if (top < 0)
|
||||
//throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, top must be a positive integer");
|
||||
top = -1;
|
||||
}
|
||||
|
||||
if ( fHelp || params.size() > 1)
|
||||
|
||||
@@ -487,6 +487,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "payments", "paymentslist", &payments_list, true },
|
||||
{ "payments", "paymentsinfo", &payments_info, true },
|
||||
{ "payments", "paymentsfund", &payments_fund, true },
|
||||
{ "payments", "paymentsmerge", &payments_merge, true },
|
||||
{ "payments", "paymentsrelease", &payments_release, true },
|
||||
|
||||
{ "CClib", "cclibaddress", &cclibaddress, true },
|
||||
@@ -543,6 +544,8 @@ static const CRPCCommand vRPCCommands[] =
|
||||
/* Address index */
|
||||
{ "addressindex", "getaddressmempool", &getaddressmempool, true },
|
||||
{ "addressindex", "getaddressutxos", &getaddressutxos, false },
|
||||
{ "addressindex", "checknotarization", &checknotarization, false },
|
||||
{ "addressindex", "getnotarypayinfo", &getnotarypayinfo, false },
|
||||
{ "addressindex", "getaddressdeltas", &getaddressdeltas, false },
|
||||
{ "addressindex", "getaddresstxids", &getaddresstxids, false },
|
||||
{ "addressindex", "getaddressbalance", &getaddressbalance, false },
|
||||
|
||||
@@ -210,6 +210,8 @@ extern UniValue getaddresstxids(const UniValue& params, bool fHelp);
|
||||
extern UniValue getsnapshot(const UniValue& params, bool fHelp);
|
||||
extern UniValue getaddressbalance(const UniValue& params, bool fHelp);
|
||||
extern UniValue getpeerinfo(const UniValue& params, bool fHelp);
|
||||
extern UniValue checknotarization(const UniValue& params, bool fHelp);
|
||||
extern UniValue getnotarypayinfo(const UniValue& params, bool fHelp);
|
||||
extern UniValue ping(const UniValue& params, bool fHelp);
|
||||
extern UniValue addnode(const UniValue& params, bool fHelp);
|
||||
extern UniValue disconnectnode(const UniValue& params, bool fHelp);
|
||||
@@ -285,6 +287,7 @@ extern UniValue marmara_lock(const UniValue& params, bool fHelp);
|
||||
extern UniValue paymentsaddress(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_release(const UniValue& params, bool fHelp);
|
||||
extern UniValue payments_fund(const UniValue& params, bool fHelp);
|
||||
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);
|
||||
|
||||
23
src/txdb.cpp
23
src/txdb.cpp
@@ -481,6 +481,8 @@ bool CBlockTreeDB::Snapshot2(std::map <std::string, CAmount> &addressAmounts, Un
|
||||
try {
|
||||
CAmount nValue;
|
||||
iter->GetValue(nValue);
|
||||
if ( nValue == 0 )
|
||||
continue;
|
||||
getAddressFromIndex(indexKey.type, indexKey.hashBytes, address);
|
||||
if ( indexKey.type == 3 )
|
||||
{
|
||||
@@ -555,6 +557,8 @@ bool CBlockTreeDB::Snapshot2(std::map <std::string, CAmount> &addressAmounts, Un
|
||||
return true;
|
||||
}
|
||||
|
||||
extern std::vector <std::pair<CAmount, CTxDestination>> vAddressSnapshot;
|
||||
|
||||
UniValue CBlockTreeDB::Snapshot(int top)
|
||||
{
|
||||
int topN = 0;
|
||||
@@ -564,11 +568,20 @@ UniValue CBlockTreeDB::Snapshot(int top)
|
||||
UniValue result(UniValue::VOBJ);
|
||||
UniValue addressesSorted(UniValue::VARR);
|
||||
result.push_back(Pair("start_time", (int) time(NULL)));
|
||||
if ( Snapshot2(addressAmounts,&result) )
|
||||
if ( (vAddressSnapshot.size() > 0 && top < 0) || (Snapshot2(addressAmounts,&result) && top >= 0) )
|
||||
{
|
||||
for (std::pair<std::string, CAmount> element : addressAmounts)
|
||||
vaddr.push_back( make_pair(element.second, element.first) );
|
||||
std::sort(vaddr.rbegin(), vaddr.rend());
|
||||
if ( top > -1 )
|
||||
{
|
||||
for (std::pair<std::string, CAmount> element : addressAmounts)
|
||||
vaddr.push_back( make_pair(element.second, element.first) );
|
||||
std::sort(vaddr.rbegin(), vaddr.rend());
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( auto address : vAddressSnapshot )
|
||||
vaddr.push_back(make_pair(address.first, CBitcoinAddress(address.second).ToString()));
|
||||
top = vAddressSnapshot.size();
|
||||
}
|
||||
int topN = 0;
|
||||
for (std::vector<std::pair<CAmount, std::string>>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it)
|
||||
{
|
||||
@@ -705,6 +718,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||
pindexNew->nTx = diskindex.nTx;
|
||||
pindexNew->nSproutValue = diskindex.nSproutValue;
|
||||
pindexNew->nSaplingValue = diskindex.nSaplingValue;
|
||||
pindexNew->segid = diskindex.segid;
|
||||
pindexNew->nNotaryPay = diskindex.nNotaryPay;
|
||||
//fprintf(stderr,"loadguts ht.%d\n",pindexNew->GetHeight());
|
||||
// Consistency checks
|
||||
auto header = pindexNew->GetBlockHeader();
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
@@ -5603,6 +5603,19 @@ UniValue payments_fund(const UniValue& params, bool fHelp)
|
||||
return(PaymentsFund(cp,(char *)params[0].get_str().c_str()));
|
||||
}
|
||||
|
||||
UniValue payments_merge(const UniValue& params, bool fHelp)
|
||||
{
|
||||
struct CCcontract_info *cp,C;
|
||||
if ( fHelp || params.size() != 1 )
|
||||
throw runtime_error("paymentsmerge \"[%22createtxid%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(PaymentsMerge(cp,(char *)params[0].get_str().c_str()));
|
||||
}
|
||||
|
||||
UniValue payments_txidopret(const UniValue& params, bool fHelp)
|
||||
{
|
||||
struct CCcontract_info *cp,C;
|
||||
@@ -5633,7 +5646,7 @@ UniValue payments_airdrop(const UniValue& params, bool fHelp)
|
||||
{
|
||||
struct CCcontract_info *cp,C;
|
||||
if ( fHelp || params.size() != 1 )
|
||||
throw runtime_error("paymentsairdrop \"[lockedblocks,minamount,top,bottom,fixedFlag,%22excludeAddress%22,...,%22excludeAddressN%22]\"\n");
|
||||
throw runtime_error("paymentsairdrop \"[lockedblocks,minamount,mintoaddress,top,bottom,fixedFlag,%22excludeAddress%22,...,%22excludeAddressN%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;
|
||||
|
||||
@@ -106,7 +106,7 @@ CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG"
|
||||
WD=$PWD
|
||||
cd src/cc
|
||||
echo $PWD
|
||||
./makerogue
|
||||
./makecclib
|
||||
cd $WD
|
||||
|
||||
"$MAKE" "$@" V=1
|
||||
|
||||
Reference in New Issue
Block a user