Beginning of N@S solution using CoinbaseGuard CC
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
#include "CCinclude.h"
|
||||
#include "../merkleblock.h"
|
||||
|
||||
bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys);
|
||||
std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount);
|
||||
std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#define EVAL_MOFN 0xea
|
||||
|
||||
bool MofNValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool MofNValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue MofNInfo();
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format);
|
||||
std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee);
|
||||
std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue PaymentsInfo();
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue PegsInfo();
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue PricesInfo();
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "CCinclude.h"
|
||||
|
||||
bool TriggersValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool TriggersValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
UniValue TriggersInfo();
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "CCinclude.h"
|
||||
|
||||
// CCcustom
|
||||
bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCassetsCore
|
||||
//CTxOut MakeAssetsVout(CAmount nValue,CPubKey pk);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#define EVAL_AUCTION 0xe8
|
||||
|
||||
bool AuctionValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool AuctionValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
std::string AuctionPost(uint64_t txfee,uint256 itemhash,int64_t minbid,char *title,char *description);
|
||||
std::string AuctionBid(uint64_t txfee,uint256 itemhash,int64_t amount);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "CCinclude.h"
|
||||
#define CHANNELS_MAXPAYMENTS 1000
|
||||
|
||||
bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment);
|
||||
std::string ChannelStop(uint64_t txfee,CPubKey destpub,uint256 origtxid);
|
||||
std::string ChannelPayment(uint64_t txfee,uint256 prevtxid,uint256 origtxid,int32_t n,int64_t amount);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "CCTriggers.h"
|
||||
#include "CCPayments.h"
|
||||
#include "CCGateways.h"
|
||||
#include "CoinbaseGuard.h"
|
||||
|
||||
/*
|
||||
CCcustom has most of the functions that need to be extended to create a new CC contract.
|
||||
@@ -221,11 +222,20 @@ uint8_t GatewaysCCpriv[32] = { 0xf7, 0x4b, 0x5b, 0xa2, 0x7a, 0x5e, 0x9c, 0xda, 0
|
||||
#undef FUNCNAME
|
||||
#undef EVALCODE
|
||||
|
||||
struct CCcontract_info *CCinit(struct CCcontract_info *cp,uint8_t evalcode)
|
||||
struct CCcontract_info *CCinit(struct CCcontract_info *cp, uint8_t evalcode)
|
||||
{
|
||||
cp->evalcode = evalcode;
|
||||
switch ( evalcode )
|
||||
{
|
||||
case EVAL_COINBASEGUARD:
|
||||
strcpy(cp->unspendableCCaddr,AssetsCCaddr);
|
||||
strcpy(cp->normaladdr,AssetsNormaladdr);
|
||||
strcpy(cp->CChexstr,AssetsCChexstr);
|
||||
memcpy(cp->CCpriv,AssetsCCpriv,32);
|
||||
cp->validate = AssetsValidate;
|
||||
cp->ismyvin = IsAssetsInput;
|
||||
break;
|
||||
|
||||
case EVAL_ASSETS:
|
||||
strcpy(cp->unspendableCCaddr,AssetsCCaddr);
|
||||
strcpy(cp->normaladdr,AssetsNormaladdr);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#define EVAL_DICE 0xe6
|
||||
|
||||
bool DiceValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool DiceValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet,int32_t odds);
|
||||
std::string DiceBetFinish(int32_t *resultp,uint64_t txfee,char *planstr,uint256 fundingtxid,uint256 bettxid,int32_t winlosetimeout);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define EVAL_FAUCET 0xe4
|
||||
#define FAUCETSIZE (COIN / 10)
|
||||
|
||||
bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
// CCcustom
|
||||
std::string FaucetFund(uint64_t txfee,int64_t funds);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#define EVAL_FSM 0xe7
|
||||
|
||||
bool FSMValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool FSMValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
std::string FSMList();
|
||||
std::string FSMInfo(uint256 fsmtxid);
|
||||
|
||||
@@ -64,13 +64,23 @@ struct CC_utxo
|
||||
int32_t vout;
|
||||
};
|
||||
|
||||
// these are the parameters stored after Verus crypto-condition vouts. new versions may change
|
||||
// the format
|
||||
struct CC_meta
|
||||
{
|
||||
std::vector<unsigned char> version;
|
||||
uint8_t evalCode;
|
||||
bool is1of2;
|
||||
uint8_t numDestinations;
|
||||
// followed by address destinations
|
||||
};
|
||||
|
||||
struct CCcontract_info
|
||||
{
|
||||
uint256 prevtxid;
|
||||
char unspendableCCaddr[64],CChexstr[72],normaladdr[64],unspendableaddr2[64],unspendableaddr3[64];
|
||||
uint8_t CCpriv[32],unspendablepriv2[32],unspendablepriv3[32];
|
||||
CPubKey unspendablepk2,unspendablepk3;
|
||||
bool (*validate)(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool (*validate)(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn);
|
||||
bool (*ismyvin)(CScript const& scriptSig);
|
||||
uint8_t evalcode,evalcode2,evalcode3,didinit;
|
||||
};
|
||||
@@ -102,6 +112,7 @@ int32_t iguana_rwbignum(int32_t rwflag,uint8_t *serialized,int32_t len,uint8_t *
|
||||
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys);
|
||||
int64_t CCaddress_balance(char *coinaddr);
|
||||
CPubKey CCtxidaddr(char *txidaddr,uint256 txid);
|
||||
bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn, std::vector<std::vector<unsigned char>> &preConditions, std::vector<std::vector<unsigned char>> ¶ms);
|
||||
|
||||
int64_t OraclePrice(int32_t height,uint256 reforacletxid,char *markeraddr,char *format);
|
||||
uint8_t DecodeOraclesCreateOpRet(const CScript &scriptPubKey,std::string &name,std::string &description,std::string &format);
|
||||
@@ -125,7 +136,8 @@ uint256 DiceHashEntropy(uint256 &entropy,uint256 _txidpriv);
|
||||
CTxOut MakeCC1vout(uint8_t evalcode,CAmount nValue,CPubKey pk);
|
||||
CTxOut MakeCC1of2vout(uint8_t evalcode,CAmount nValue,CPubKey pk,CPubKey pk2);
|
||||
CC *MakeCCcond1(uint8_t evalcode,CPubKey pk);
|
||||
CC* GetCryptoCondition(CScript const& scriptSig);
|
||||
CC *MakeCCcond1of2(uint8_t evalcode,CPubKey pk1,CPubKey pk2);
|
||||
CC *GetCryptoCondition(CScript const& scriptSig);
|
||||
void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr);
|
||||
void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr);
|
||||
bool IsCCInput(CScript const& scriptSig);
|
||||
@@ -149,6 +161,7 @@ bool Myprivkey(uint8_t myprivkey[]);
|
||||
int64_t CCduration(int32_t &numblocks,uint256 txid);
|
||||
|
||||
// CCtx
|
||||
bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey);
|
||||
std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret);
|
||||
void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr);
|
||||
void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#define EVAL_LOTTO 0xe9
|
||||
|
||||
bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
UniValue LottoInfo(uint256 lottoid);
|
||||
UniValue LottoList();
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define EVAL_REWARDS 0xe5
|
||||
#define REWARDSCC_MAXAPR (COIN * 25)
|
||||
|
||||
bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx);
|
||||
bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
UniValue RewardsInfo(uint256 rewardid);
|
||||
UniValue RewardsList();
|
||||
|
||||
|
||||
@@ -197,6 +197,32 @@ bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey)
|
||||
return(false);
|
||||
}
|
||||
|
||||
bool GetCCParams(Eval* eval, const CTransaction &tx, uint32_t nIn, std::vector<std::vector<unsigned char>> &preConditions, std::vector<std::vector<unsigned char>> ¶ms)
|
||||
{
|
||||
CTransaction txOut;
|
||||
uint256 blockHash;
|
||||
bool isValid = false;
|
||||
|
||||
if (myGetTransaction(tx.vin[nIn].prevout.hash, txOut, blockHash))
|
||||
{
|
||||
CBlockIndex index;
|
||||
if (eval->GetBlock(blockHash, index))
|
||||
{
|
||||
// read preconditions
|
||||
CScript subScript = CScript();
|
||||
preConditions.clear();
|
||||
if (txOut.vout[tx.vin[nIn].prevout.n].scriptPubKey.IsPayToCryptoCondition(&subScript, preConditions))
|
||||
{
|
||||
// read any available parameters in the output transaction
|
||||
params.clear();
|
||||
tx.vout[tx.vout.size() - 1].scriptPubKey.GetOpretData(params);
|
||||
isValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
CPubKey CCtxidaddr(char *txidaddr,uint256 txid)
|
||||
{
|
||||
uint8_t buf33[33]; CPubKey pk;
|
||||
@@ -361,7 +387,7 @@ bool ProcessCC(struct CCcontract_info *cp,Eval* eval, std::vector<uint8_t> param
|
||||
return eval->Invalid("Cannot have params");
|
||||
else if ( ctx.vout.size() == 0 )
|
||||
return eval->Invalid("no-vouts");
|
||||
else if ( (*cp->validate)(cp,eval,ctx) != 0 )
|
||||
else if ( (*cp->validate)(cp,eval,ctx,nIn) != 0 )
|
||||
{
|
||||
//fprintf(stderr,"done CC %02x\n",cp->evalcode);
|
||||
//cp->prevtxid = txid;
|
||||
|
||||
254
src/cc/CoinbaseGuard.cpp
Normal file
254
src/cc/CoinbaseGuard.cpp
Normal file
@@ -0,0 +1,254 @@
|
||||
/********************************************************************
|
||||
* (C) 2018 Michael Toutonghi
|
||||
*
|
||||
* Distributed under the MIT software license, see the accompanying
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
*
|
||||
* This crypto-condition eval solves the problem of nothing-at-stake
|
||||
* in a proof of stake consensus system.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "CoinbaseGuard.h"
|
||||
#include "main.h"
|
||||
|
||||
extern int32_t VERUS_MIN_STAKEAGE;
|
||||
|
||||
bool UnpackStakeOpRet(const CTransaction &stakeTx, std::vector<std::vector<unsigned char>> vData)
|
||||
{
|
||||
bool isValid = stakeTx.vout[stakeTx.vout.size() - 1].scriptPubKey.GetOpretData(vData);
|
||||
|
||||
if (isValid && (vData.size() >= CStakeParams::STAKE_MINPARAMS) && (vData.size() <= CStakeParams::STAKE_MAXPARAMS))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CStakeParams::CStakeParams(std::vector<std::vector<unsigned char>> vData)
|
||||
{
|
||||
// A stake OP_RETURN contains:
|
||||
// 1. source block height in little endian 32 bit
|
||||
// 2. target block height in little endian 32 bit
|
||||
// 3. 32 byte prev block hash
|
||||
// 4. alternate 20 byte pubkey hash, 33 byte pubkey, or not present to use same as stake destination
|
||||
|
||||
srcHeight = 0;
|
||||
blkHeight = 0;
|
||||
if (vData[0].size() == 1 &&
|
||||
vData[0][0] == OPRETTYPE_STAKEPARAMS && vData[1].size() <= 4 &&
|
||||
vData[2].size() <= 4 &&
|
||||
vData[3].size() == sizeof(prevHash) &&
|
||||
(vData.size() == STAKE_MINPARAMS || vData[4].size() == 20 || vData[5].size() == 33))
|
||||
{
|
||||
for (auto ch : vData[1])
|
||||
{
|
||||
srcHeight = srcHeight << 8 | ch;
|
||||
}
|
||||
for (auto ch : vData[2])
|
||||
{
|
||||
blkHeight = blkHeight << 8 | ch;
|
||||
}
|
||||
|
||||
prevHash = uint256(vData[3]);
|
||||
|
||||
if (vData.size() == 4)
|
||||
{
|
||||
dest = CTxDestination();
|
||||
}
|
||||
else if (vData[4].size() == 20)
|
||||
{
|
||||
dest = CTxDestination(CKeyID(uint160(vData[4])));
|
||||
}
|
||||
else if (vData[4].size() == 33)
|
||||
{
|
||||
CPubKey pk = CPubKey(vData[4]);
|
||||
if (pk.IsValid())
|
||||
{
|
||||
dest = pk;
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalidate
|
||||
srcHeight = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalidate
|
||||
srcHeight = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this validates everything, except the PoS eligibility and the actual stake spend. the only time it matters
|
||||
// is to validate a properly formed stake transaction for either pre-check before PoS validity check, or to
|
||||
// validate the stake transaction on a fork that will be used to spend a winning stake that cheated by being posted
|
||||
// on two fork chains
|
||||
bool ValidateStakeTransaction(const CTransaction &stakeTx, CStakeParams &stakeParams)
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
|
||||
|
||||
// a valid stake transaction has one input and two outputs, one output is the monetary value and one is an op_ret with CStakeParams
|
||||
// stake output #1 must be P2PK or P2PKH, unless a delegate for the coinbase is specified
|
||||
|
||||
bool isValid = false;;
|
||||
if (stakeTx.vin.size() == 1 &&
|
||||
stakeTx.vout.size() == 2 &&
|
||||
stakeTx.vout[0].nValue > 0 &&
|
||||
stakeTx.vout[1].scriptPubKey.IsOpReturn() &&
|
||||
UnpackStakeOpRet(stakeTx, vData))
|
||||
{
|
||||
stakeParams = CStakeParams(vData);
|
||||
if (stakeParams.IsValid())
|
||||
{
|
||||
// if we have gotten this far and are still valid, we need to validate everything else
|
||||
// even if the utxo is spent, this can succeed, as it only checks that is was ever valid
|
||||
CTransaction srcTx = CTransaction();
|
||||
uint256 blkHash = uint256();
|
||||
txnouttype txType;
|
||||
CBlockIndex *pindex;
|
||||
if (isValid && myGetTransaction(stakeTx.vin[0].prevout.hash, srcTx, blkHash))
|
||||
{
|
||||
isValid = false;
|
||||
if ((pindex = mapBlockIndex[blkHash]) != NULL)
|
||||
{
|
||||
std::vector<std::vector<unsigned char>> vAddr = std::vector<std::vector<unsigned char>>();
|
||||
|
||||
if (stakeParams.srcHeight == pindex->GetHeight() &&
|
||||
(stakeParams.blkHeight - stakeParams.srcHeight >= VERUS_MIN_STAKEAGE) &&
|
||||
Solver(srcTx.vout[stakeTx.vin[0].prevout.n].scriptPubKey, txType, vAddr))
|
||||
{
|
||||
if (txType == TX_PUBKEY)
|
||||
{
|
||||
if (stakeParams.dest.which() == 0)
|
||||
{
|
||||
stakeParams.dest = CPubKey(vAddr[0]);
|
||||
}
|
||||
}
|
||||
else if (txType == TX_PUBKEYHASH)
|
||||
{
|
||||
if (stakeParams.dest.which() == 0)
|
||||
{
|
||||
stakeParams.dest = CKeyID(uint160(vAddr[0]));
|
||||
}
|
||||
}
|
||||
if ((txType == TX_PUBKEY) && (txType == TX_PUBKEYHASH))
|
||||
{
|
||||
auto consensusBranchId = CurrentEpochBranchId(stakeParams.blkHeight, Params().GetConsensus());
|
||||
isValid = VerifyScript(stakeTx.vin[0].scriptSig,
|
||||
srcTx.vout[stakeTx.vin[0].prevout.n].scriptPubKey,
|
||||
STANDARD_SCRIPT_VERIFY_FLAGS + SCRIPT_VERIFY_SIGPUSHONLY,
|
||||
BaseSignatureChecker(),
|
||||
consensusBranchId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
bool MakeGuardedOutput(CAmount value, CPubKey &dest, CTransaction &stakeTx, CTxOut &vout)
|
||||
{
|
||||
CCcontract_info *cp, C;
|
||||
cp = CCinit(&C,EVAL_COINBASEGUARD);
|
||||
|
||||
CPubKey ccAddress = CPubKey(ParseHex(cp->CChexstr));
|
||||
|
||||
// return an output that is bound to the stake transaction and can be spent by presenting either a signed condition by the original
|
||||
// destination address or a properly signed stake transaction of the same utxo on a fork
|
||||
vout = MakeCC1of2vout(EVAL_COINBASEGUARD, value, dest, ccAddress);
|
||||
|
||||
// add parameters to scriptPubKey
|
||||
COptCCParams p = COptCCParams(COptCCParams::VERSION, EVAL_COINBASEGUARD, 1, 2);
|
||||
|
||||
std::vector<unsigned char> a1, a2;
|
||||
CKeyID id1 = dest.GetID();
|
||||
CKeyID id2 = ccAddress.GetID();
|
||||
a1 = std::vector<unsigned char>(id1.begin(), id1.end());
|
||||
a2 = std::vector<unsigned char>(id2.begin(), id2.end());
|
||||
|
||||
// version
|
||||
// utxo source hash
|
||||
// utxo source output
|
||||
// hashed address of destination's pubkey
|
||||
CKeyID key = dest.GetID();
|
||||
vout.scriptPubKey << p.AsVector() << OP_DROP
|
||||
<< a1 << OP_DROP << a2 << OP_DROP
|
||||
<< std::vector<unsigned char>(stakeTx.vin[0].prevout.hash.begin(), stakeTx.vin[0].prevout.hash.end()) << OP_DROP
|
||||
<< stakeTx.vin[0].prevout.n << OP_DROP;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is only needed to create a spend for cheating. normal spend and signing should work
|
||||
// for vins
|
||||
bool MakeGuardedSpend(CTxIn &vin, CPubKey &dest, CTransaction *pCheater)
|
||||
{
|
||||
CCcontract_info *cp,C;
|
||||
|
||||
cp = CCinit(&C,EVAL_COINBASEGUARD);
|
||||
CC cc;
|
||||
vin.scriptSig = CCPubKey(MakeCCcond1of2(EVAL_COINBASEGUARD, dest, CPubKey(ParseHex(cp->CChexstr))));
|
||||
}
|
||||
|
||||
bool CoinbaseGuardValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
// This also supports a variable blockstomaturity option for backward feature compatibility
|
||||
// validate this spend of a transaction with it being past any applicable time lock and one of the following statements being true:
|
||||
// 1. the spend is signed by the original output destination's private key and normal payment requirements, spends as normal
|
||||
// 2. the spend is signed by the private key of the CoinbaseGuard contract and pushes a signed stake transaction
|
||||
// with the same exact utxo source, a target block height of later than that of this tx that is also targeting a fork
|
||||
// of the chain
|
||||
|
||||
// first, check to see if the spending contract is signed by the default destination address
|
||||
// if so, success and we are done
|
||||
|
||||
// get preConditions and parameters
|
||||
std::vector<std::vector<unsigned char>> preConditions = std::vector<std::vector<unsigned char>>();
|
||||
std::vector<std::vector<unsigned char>> params = std::vector<std::vector<unsigned char>>();
|
||||
|
||||
if (GetCCParams(eval, tx, nIn, preConditions, params))
|
||||
{
|
||||
CC *cc = GetCryptoCondition(tx.vin[nIn].scriptSig);
|
||||
|
||||
printf("CryptoCondition code %x\n", *cc->code);
|
||||
// check any applicable time lock
|
||||
// determine who signed
|
||||
// if from receiver's priv key, success
|
||||
// if from contract priv key:
|
||||
// if data provided is valid stake spend of same utxo targeting same or later block height on a fork:
|
||||
// return success
|
||||
// endif
|
||||
// endif
|
||||
// return fail
|
||||
cc_free(cc);
|
||||
}
|
||||
}
|
||||
|
||||
UniValue CoinbaseGuardInfo()
|
||||
{
|
||||
UniValue result(UniValue::VOBJ); char numstr[64];
|
||||
CMutableTransaction mtx;
|
||||
CPubKey pk;
|
||||
|
||||
CCcontract_info *cp,C;
|
||||
|
||||
cp = CCinit(&C,EVAL_COINBASEGUARD);
|
||||
|
||||
result.push_back(Pair("result","success"));
|
||||
result.push_back(Pair("name","CoinbaseGuard"));
|
||||
|
||||
// all UTXOs to the contract address that are to any of the wallet addresses are to us
|
||||
// each is spendable as a normal transaction, but the spend may fail if it gets spent out
|
||||
// from under us
|
||||
pk = GetUnspendable(cp,0);
|
||||
return(result);
|
||||
}
|
||||
|
||||
47
src/cc/CoinbaseGuard.h
Normal file
47
src/cc/CoinbaseGuard.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/********************************************************************
|
||||
* (C) 2018 Michael Toutonghi
|
||||
*
|
||||
* Distributed under the MIT software license, see the accompanying
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
*
|
||||
* This crypto-condition eval solves the problem of nothing-at-stake
|
||||
* in a proof of stake consensus system.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CC_COINBASEGUARD_H
|
||||
#define CC_COINBASEGUARD_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "CCinclude.h"
|
||||
#include "streams.h"
|
||||
#include "script/script.h"
|
||||
|
||||
class CStakeParams
|
||||
{
|
||||
public:
|
||||
static const uint32_t STAKE_MINPARAMS = 4;
|
||||
static const uint32_t STAKE_MAXPARAMS = 5;
|
||||
|
||||
uint32_t srcHeight;
|
||||
uint32_t blkHeight;
|
||||
uint256 prevHash;
|
||||
CTxDestination dest;
|
||||
|
||||
CStakeParams() : srcHeight(0), blkHeight(0), prevHash(), dest() {}
|
||||
|
||||
CStakeParams(std::vector<std::vector<unsigned char>> vData);
|
||||
|
||||
bool IsValid() { return srcHeight != 0; }
|
||||
};
|
||||
|
||||
bool ValidateStakeTransaction(const CTransaction &stakeTx, CStakeParams &stakeParams);
|
||||
|
||||
bool MakeGuardedOutput(CAmount value, CPubKey &dest, CTransaction &stakeTx, CTxOut &vout);
|
||||
|
||||
bool CoinbaseGuardValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
|
||||
|
||||
UniValue CoinbaseGuardInfo();
|
||||
|
||||
#endif
|
||||
@@ -85,7 +85,7 @@ bool MofNExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool MofNValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool MofNValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
return(false);
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
|
||||
*/
|
||||
|
||||
bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
static uint256 zero;
|
||||
CTxDestination address; CTransaction vinTx,createTx; uint256 hashBlock,assetid,assetid2; int32_t i,starti,numvins,numvouts,preventCCvins,preventCCvouts; int64_t remaining_price,nValue,assetoshis,outputs,inputs,tmpprice,totalunits,ignore; std::vector<uint8_t> origpubkey,tmporigpubkey,ignorepubkey; uint8_t funcid; char destaddr[64],origaddr[64],CCaddr[64];
|
||||
|
||||
@@ -70,7 +70,7 @@ bool AuctionExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransactio
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool AuctionValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool AuctionValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval;
|
||||
return(false); // reject any auction CC for now
|
||||
|
||||
@@ -111,7 +111,7 @@ bool ChannelsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
return(false);
|
||||
|
||||
@@ -439,7 +439,7 @@ bool DiceVerifyTimeout(CTransaction &betTx,int32_t timeoutblocks)
|
||||
return(numblocks >= timeoutblocks);
|
||||
}
|
||||
|
||||
bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx)
|
||||
bool DiceValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
uint256 txid,fundingtxid,vinfundingtxid,vinhentropy,vinproof,hashBlock,hash,proof,entropy; int64_t minbet,maxbet,maxodds,timeoutblocks,odds,winnings; uint64_t vinsbits,sbits,amount,inputs,outputs,txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,iswin; uint8_t funcid; CScript fundingPubKey; CTransaction fundingTx,vinTx,vinofvinTx; char CCaddr[64];
|
||||
numvins = tx.vin.size();
|
||||
|
||||
@@ -34,9 +34,6 @@ extern pthread_mutex_t KOMODO_CC_mutex;
|
||||
|
||||
bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn)
|
||||
{
|
||||
// DISABLE CRYPTO CONDITIONS FOR NOW
|
||||
return false;
|
||||
|
||||
EvalRef eval;
|
||||
pthread_mutex_lock(&KOMODO_CC_mutex);
|
||||
bool out = eval->Dispatch(cond, tx, nIn);
|
||||
@@ -77,15 +74,17 @@ bool Eval::Dispatch(const CC *cond, const CTransaction &txTo, unsigned int nIn)
|
||||
switch ( ecode )
|
||||
{
|
||||
case EVAL_IMPORTPAYOUT:
|
||||
return ImportPayout(vparams, txTo, nIn);
|
||||
//return ImportPayout(vparams, txTo, nIn);
|
||||
break;
|
||||
|
||||
case EVAL_IMPORTCOIN:
|
||||
return ImportCoin(vparams, txTo, nIn);
|
||||
//return ImportCoin(vparams, txTo, nIn);
|
||||
break;
|
||||
|
||||
default:
|
||||
return(ProcessCC(cp,this, vparams, txTo, nIn));
|
||||
// only support coinbase guard for now
|
||||
if (ecode == EVAL_COINBASEGUARD)
|
||||
return(ProcessCC(cp,this, vparams, txTo, nIn));
|
||||
break;
|
||||
}
|
||||
return Invalid("invalid-code, dont forget to add EVAL_NEWCC to Eval::Dispatch");
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
* after the code is interpreted as a bitcoin script.
|
||||
*/
|
||||
#define FOREACH_EVAL(EVAL) \
|
||||
EVAL(EVAL_COINBASEGUARD, 0x1) \
|
||||
EVAL(EVAL_IMPORTPAYOUT, 0xe1) \
|
||||
EVAL(EVAL_IMPORTCOIN, 0xe2) \
|
||||
EVAL(EVAL_ASSETS, 0xe3) \
|
||||
|
||||
@@ -77,7 +77,7 @@ bool FaucetExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
|
||||
|
||||
@@ -72,7 +72,7 @@ bool FSMExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool FSMValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool FSMValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval;
|
||||
return(false); // reject any FSM CC for now
|
||||
|
||||
@@ -239,7 +239,7 @@ bool GatewaysExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx)
|
||||
bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
|
||||
|
||||
@@ -112,7 +112,7 @@ bool LottoExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval;
|
||||
return(false); // reject any lotto CC for now
|
||||
|
||||
@@ -593,7 +593,7 @@ bool OraclesDataValidate(struct CCcontract_info *cp,Eval* eval,const CTransactio
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
uint256 txid,oracletxid,batontxid; uint64_t txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts; uint8_t *script; std::vector<uint8_t> vopret,data; CScript scriptPubKey; CPubKey publisher;
|
||||
numvins = tx.vin.size();
|
||||
|
||||
@@ -72,7 +72,7 @@ bool PaymentsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
return(false);
|
||||
|
||||
@@ -79,7 +79,7 @@ bool PegsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
return(false);
|
||||
|
||||
@@ -91,7 +91,7 @@ bool PricesExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
return(false);
|
||||
|
||||
@@ -192,7 +192,7 @@ bool RewardsExactAmounts(struct CCcontract_info *cp,Eval *eval,const CTransactio
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
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;
|
||||
numvins = tx.vin.size();
|
||||
|
||||
@@ -71,7 +71,7 @@ bool TriggersExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
|
||||
else return(true);
|
||||
}
|
||||
|
||||
bool TriggersValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx)
|
||||
bool TriggersValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
|
||||
{
|
||||
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
|
||||
return(false);
|
||||
|
||||
Reference in New Issue
Block a user