Merge pull request #1196 from dimxy/heir-fix-donations
Heir fix donations
This commit is contained in:
@@ -27,10 +27,10 @@ bool HeirValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,
|
|||||||
class CoinHelper;
|
class CoinHelper;
|
||||||
class TokenHelper;
|
class TokenHelper;
|
||||||
|
|
||||||
UniValue HeirFundCoinCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid);
|
UniValue HeirFundCoinCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid);
|
||||||
UniValue HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid);
|
UniValue HeirFundTokenCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid);
|
||||||
UniValue HeirClaimCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount);
|
UniValue HeirClaimCaller(uint256 fundingtxid, int64_t txfee, std::string amount);
|
||||||
UniValue HeirAddCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount);
|
UniValue HeirAddCaller(uint256 fundingtxid, int64_t txfee, std::string amount);
|
||||||
|
|
||||||
UniValue HeirInfo(uint256 fundingtxid);
|
UniValue HeirInfo(uint256 fundingtxid);
|
||||||
UniValue HeirList();
|
UniValue HeirList();
|
||||||
|
|||||||
214
src/cc/heir.cpp
214
src/cc/heir.cpp
@@ -56,13 +56,14 @@ template <typename Helper> bool RunValidationPlans(uint8_t funcId, struct CCcont
|
|||||||
// only for tokens:
|
// only for tokens:
|
||||||
CMyPubkeyVoutValidator<TokenHelper> ownerCCaddrValidator(cp, fundingOpretScript, false); // check if this correct owner's cc user addr corresponding to opret
|
CMyPubkeyVoutValidator<TokenHelper> ownerCCaddrValidator(cp, fundingOpretScript, false); // check if this correct owner's cc user addr corresponding to opret
|
||||||
COpRetValidator<Helper> opRetValidator(cp, fundingOpretScript); // compare opRets in this and last tx
|
COpRetValidator<Helper> opRetValidator(cp, fundingOpretScript); // compare opRets in this and last tx
|
||||||
|
CMarkerValidator<Helper> markerValidator(cp); // initial tx marker spending protection
|
||||||
CNullValidator<Helper> nullValidator(cp);
|
CNullValidator<Helper> nullValidator(cp);
|
||||||
|
|
||||||
switch (funcId) {
|
switch (funcId) {
|
||||||
case 'F': // fund tokens
|
case 'F': // fund tokens (only for tokens)
|
||||||
// vin validation plan:
|
// vin validation plan:
|
||||||
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin
|
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin
|
||||||
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &ownerCCaddrValidator); // check cc owner addr
|
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &markerValidator, &ownerCCaddrValidator); // check cc owner addr
|
||||||
|
|
||||||
// vout validation plan:
|
// vout validation plan:
|
||||||
voutPlan.pushValidators<CValidatorBase>(0, &cc1of2ValidatorThis); // check 1of2 addr funding
|
voutPlan.pushValidators<CValidatorBase>(0, &cc1of2ValidatorThis); // check 1of2 addr funding
|
||||||
@@ -70,10 +71,10 @@ template <typename Helper> bool RunValidationPlans(uint8_t funcId, struct CCcont
|
|||||||
// no checking for opret yet
|
// no checking for opret yet
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'A': // add tokens
|
case 'A': // add tokens (only for tokens)
|
||||||
// vin validation plan:
|
// vin validation plan:
|
||||||
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin
|
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin
|
||||||
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &ownerCCaddrValidator); // check cc owner addr
|
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &markerValidator, &ownerCCaddrValidator); // check cc owner addr
|
||||||
|
|
||||||
// vout validation plan:
|
// vout validation plan:
|
||||||
voutPlan.pushValidators<CValidatorBase>(0, &cc1of2ValidatorThis); // check 1of2 addr funding
|
voutPlan.pushValidators<CValidatorBase>(0, &cc1of2ValidatorThis); // check 1of2 addr funding
|
||||||
@@ -81,10 +82,10 @@ template <typename Helper> bool RunValidationPlans(uint8_t funcId, struct CCcont
|
|||||||
voutPlan.pushValidators<CValidatorBase>(numvouts - 1, &opRetValidator); // opreturn check, NOTE: only for C or A:
|
voutPlan.pushValidators<CValidatorBase>(numvouts - 1, &opRetValidator); // opreturn check, NOTE: only for C or A:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'C':
|
case 'C': // spend coins or tokens
|
||||||
// vin validation plan:
|
// vin validation plan:
|
||||||
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin
|
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&normalInputIdentifier, &nullValidator); // txfee vin
|
||||||
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &cc1of2ValidatorThis); // cc1of2 funding addr
|
vinPlan.pushValidators<CValidatorBase>((CInputIdentifierBase*)&ccInputIdentifier, &markerValidator, &cc1of2ValidatorThis); // cc1of2 funding addr
|
||||||
|
|
||||||
// vout validation plan:
|
// vout validation plan:
|
||||||
voutPlan.pushValidators<CValidatorBase>(0, &heirSpendValidator); // check if heir is allowed to spend
|
voutPlan.pushValidators<CValidatorBase>(0, &heirSpendValidator); // check if heir is allowed to spend
|
||||||
@@ -400,6 +401,23 @@ uint8_t DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, uint256 &f
|
|||||||
return _DecodeHeirEitherOpRet(scriptPubKey, tokenid, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingTxidInOpret, hasHeirSpendingBegun, noLogging);
|
return _DecodeHeirEitherOpRet(scriptPubKey, tokenid, dummyOwnerPubkey, dummyHeirPubkey, dummyInactivityTime, dummyHeirName, fundingTxidInOpret, hasHeirSpendingBegun, noLogging);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if pubkey is in vins
|
||||||
|
void CheckVinPubkey(std::vector<CTxIn> vins, CPubKey pubkey, bool &hasPubkey, bool &hasOtherPubkey) {
|
||||||
|
|
||||||
|
hasPubkey = false;
|
||||||
|
hasOtherPubkey = false;
|
||||||
|
|
||||||
|
for (auto vin : vins) {
|
||||||
|
CPubKey vinPubkey = check_signing_pubkey(vin.scriptSig);
|
||||||
|
if (vinPubkey.IsValid()) {
|
||||||
|
if (vinPubkey == pubkey)
|
||||||
|
hasPubkey = true;
|
||||||
|
if (vinPubkey != pubkey)
|
||||||
|
hasOtherPubkey = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find the latest funding tx: it may be the first F tx or one of A or C tx's
|
* find the latest funding tx: it may be the first F tx or one of A or C tx's
|
||||||
* Note: this function is also called from validation code (use non-locking calls)
|
* Note: this function is also called from validation code (use non-locking calls)
|
||||||
@@ -471,10 +489,20 @@ uint256 _FindLatestFundingTx(uint256 fundingtxid, uint8_t& funcId, uint256 &toke
|
|||||||
if (tmpFuncId != 0 && fundingtxid == fundingTxidInOpret && (tokenid == zeroid || tokenid == tokenidInOpret)) { // check tokenid also
|
if (tmpFuncId != 0 && fundingtxid == fundingTxidInOpret && (tokenid == zeroid || tokenid == tokenidInOpret)) { // check tokenid also
|
||||||
|
|
||||||
if (blockHeight > maxBlockHeight) {
|
if (blockHeight > maxBlockHeight) {
|
||||||
maxBlockHeight = blockHeight;
|
|
||||||
latesttxid = txid;
|
// check owner pubkey in vins
|
||||||
funcId = tmpFuncId;
|
bool isOwner = false;
|
||||||
hasHeirSpendingBegun = hasHeirSpendingBegunInOpret;
|
bool isNonOwner = false;
|
||||||
|
|
||||||
|
CheckVinPubkey(regtx.vin, ownerPubkey, isOwner, isNonOwner);
|
||||||
|
|
||||||
|
// we ignore 'donations' tx (with non-owner inputs) for calculating if heir is allowed to spend:
|
||||||
|
if (isOwner && !isNonOwner) {
|
||||||
|
hasHeirSpendingBegun = hasHeirSpendingBegunInOpret;
|
||||||
|
maxBlockHeight = blockHeight;
|
||||||
|
latesttxid = txid;
|
||||||
|
funcId = tmpFuncId;
|
||||||
|
}
|
||||||
|
|
||||||
//std::cerr << "FindLatestFundingTx() txid=" << latesttxid.GetHex() << " at blockHeight=" << maxBlockHeight
|
//std::cerr << "FindLatestFundingTx() txid=" << latesttxid.GetHex() << " at blockHeight=" << maxBlockHeight
|
||||||
// << " opreturn type=" << (char)(funcId ? funcId : ' ') << " hasHeirSpendingBegun=" << (int)hasHeirSpendingBegun << " - set as current lasttxid" << '\n';
|
// << " opreturn type=" << (char)(funcId ? funcId : ' ') << " hasHeirSpendingBegun=" << (int)hasHeirSpendingBegun << " - set as current lasttxid" << '\n';
|
||||||
@@ -615,7 +643,7 @@ template <class Helper> int64_t LifetimeHeirContractFunds(struct CCcontract_info
|
|||||||
* and also for setting spending plan for the funds' owner and heir
|
* and also for setting spending plan for the funds' owner and heir
|
||||||
* @return fundingtxid handle for subsequent references to this heir funding plan
|
* @return fundingtxid handle for subsequent references to this heir funding plan
|
||||||
*/
|
*/
|
||||||
template <typename Helper> UniValue HeirFund(uint64_t txfee, int64_t amount, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid)
|
template <typename Helper> UniValue _HeirFund(int64_t txfee, int64_t amount, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid)
|
||||||
{
|
{
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||||
@@ -625,26 +653,32 @@ template <typename Helper> UniValue HeirFund(uint64_t txfee, int64_t amount, std
|
|||||||
if (txfee == 0)
|
if (txfee == 0)
|
||||||
txfee = 10000;
|
txfee = 10000;
|
||||||
|
|
||||||
|
int64_t markerfee = 10000;
|
||||||
|
|
||||||
//std::cerr << "HeirFund() amount=" << amount << " txfee=" << txfee << " heirPubkey IsValid()=" << heirPubkey.IsValid() << " inactivityTime(sec)=" << inactivityTimeSec << " tokenid=" << tokenid.GetHex() << std::endl;
|
//std::cerr << "HeirFund() amount=" << amount << " txfee=" << txfee << " heirPubkey IsValid()=" << heirPubkey.IsValid() << " inactivityTime(sec)=" << inactivityTimeSec << " tokenid=" << tokenid.GetHex() << std::endl;
|
||||||
|
|
||||||
if (!heirPubkey.IsValid()) {
|
if (!heirPubkey.IsValid()) {
|
||||||
std::cerr << "HeirFund() heirPubkey is not valid!" << std::endl;
|
std::cerr << "HeirFund() heirPubkey is not valid!" << std::endl;
|
||||||
return std::string("");
|
result.push_back(Pair("result", "error"));
|
||||||
|
result.push_back(Pair("error", "invalid heir pubkey"));
|
||||||
}
|
}
|
||||||
|
|
||||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||||
|
|
||||||
if (AddNormalinputs(mtx, myPubkey, txfee, 3) > 0) { // txfee for miners
|
if (AddNormalinputs(mtx, myPubkey, markerfee, 3) > 0) {
|
||||||
int64_t inputs, change;
|
int64_t inputs, change;
|
||||||
|
|
||||||
if ((inputs=Helper::addOwnerInputs(tokenid, mtx, myPubkey, amount, (int32_t)64)) > 0) { // 2 x txfee: 1st for marker vout, 2nd to miners
|
if ((inputs=Helper::addOwnerInputs(tokenid, mtx, myPubkey, amount, (int32_t)64)) > 0) {
|
||||||
//mtx.vout.push_back(MakeTokensCC1of2vout(/*Helper::getMyEval()*/EVAL_HEIR, amount, myPubkey, heirPubkey)); // add cryptocondition to spend amount for either pk
|
|
||||||
mtx.vout.push_back(Helper::make1of2Vout(amount, myPubkey, heirPubkey));
|
mtx.vout.push_back(Helper::make1of2Vout(amount, myPubkey, heirPubkey));
|
||||||
|
|
||||||
// add a marker for finding all plans in HeirList()
|
// add a marker for finding all plans in HeirList()
|
||||||
// TODO: change marker either to cc or normal txidaddr unspendable
|
// TODO: change marker either to cc or normal txidaddr unspendable
|
||||||
CPubKey heirUnspendablePubKey = GetUnspendable(cp, 0);
|
struct CCcontract_info *cpHeir, heirC;
|
||||||
mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(heirUnspendablePubKey)) << OP_CHECKSIG)); // TODO: do we need this marker?
|
cpHeir = CCinit(&heirC, EVAL_HEIR);
|
||||||
|
CPubKey heirUnspendablePubKey = GetUnspendable(cpHeir, 0);
|
||||||
|
// mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(heirUnspendablePubKey)) << OP_CHECKSIG)); <-- bad marker cause it was spendable by anyone
|
||||||
|
mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, markerfee, heirUnspendablePubKey)); // this marker spending is disabled in the validation code
|
||||||
|
|
||||||
// calc and add change vout:
|
// calc and add change vout:
|
||||||
if (inputs > amount)
|
if (inputs > amount)
|
||||||
@@ -656,6 +690,19 @@ template <typename Helper> UniValue HeirFund(uint64_t txfee, int64_t amount, std
|
|||||||
mtx.vout.push_back(Helper::makeUserVout(change, myPubkey));
|
mtx.vout.push_back(Helper::makeUserVout(change, myPubkey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check owner pubkey in vins
|
||||||
|
bool hasMypubkey = false;
|
||||||
|
bool hasNotMypubkey = false;
|
||||||
|
|
||||||
|
CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey);
|
||||||
|
|
||||||
|
// for initial funding do not allow to sign by non-owner key:
|
||||||
|
if (hasNotMypubkey) {
|
||||||
|
result.push_back(Pair("result", "error"));
|
||||||
|
result.push_back(Pair("error", "using non-owner inputs not allowed"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// add 1of2 vout validation pubkeys:
|
// add 1of2 vout validation pubkeys:
|
||||||
std::vector<CPubKey> voutTokenPubkeys;
|
std::vector<CPubKey> voutTokenPubkeys;
|
||||||
voutTokenPubkeys.push_back(myPubkey);
|
voutTokenPubkeys.push_back(myPubkey);
|
||||||
@@ -689,12 +736,12 @@ template <typename Helper> UniValue HeirFund(uint64_t txfee, int64_t amount, std
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if no these callers - it could not link
|
// if no these callers - it could not link
|
||||||
UniValue HeirFundCoinCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid){
|
UniValue HeirFundCoinCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid){
|
||||||
return HeirFund<CoinHelper>(txfee, funds, heirName, heirPubkey, inactivityTimeSec, tokenid);
|
return _HeirFund<CoinHelper>(txfee, satoshis, heirName, heirPubkey, inactivityTimeSec, tokenid);
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) {
|
UniValue HeirFundTokenCaller(int64_t txfee, int64_t satoshis, std::string heirName, CPubKey heirPubkey, int64_t inactivityTimeSec, uint256 tokenid) {
|
||||||
return HeirFund<TokenHelper>(txfee, funds, heirName, heirPubkey, inactivityTimeSec, tokenid);
|
return _HeirFund<TokenHelper>(txfee, satoshis, heirName, heirPubkey, inactivityTimeSec, tokenid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -702,7 +749,7 @@ UniValue HeirFundTokenCaller(uint64_t txfee, int64_t funds, std::string heirName
|
|||||||
* creates tx to add more funds to cryptocondition address for spending by either funds' owner or heir
|
* creates tx to add more funds to cryptocondition address for spending by either funds' owner or heir
|
||||||
* @return result object with raw tx or error text
|
* @return result object with raw tx or error text
|
||||||
*/
|
*/
|
||||||
template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun)
|
template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, int64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun)
|
||||||
{
|
{
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||||
@@ -715,6 +762,8 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
|
|||||||
if (txfee == 0)
|
if (txfee == 0)
|
||||||
txfee = 10000;
|
txfee = 10000;
|
||||||
|
|
||||||
|
int64_t markerfee = 10000;
|
||||||
|
|
||||||
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||||
|
|
||||||
// check if it is the owner
|
// check if it is the owner
|
||||||
@@ -724,7 +773,7 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AddNormalinputs(mtx, myPubkey, txfee, 3) > 0) { // txfee for miners
|
if (AddNormalinputs(mtx, myPubkey, markerfee, 3) > 0) { // some for marker
|
||||||
|
|
||||||
int64_t inputs, change;
|
int64_t inputs, change;
|
||||||
|
|
||||||
@@ -740,6 +789,10 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
|
|||||||
// add cryptocondition to spend this funded amount for either pk
|
// add cryptocondition to spend this funded amount for either pk
|
||||||
mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey));
|
mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey));
|
||||||
|
|
||||||
|
char markeraddr[64];
|
||||||
|
CPubKey markerPubkey = CCtxidaddr(markeraddr, fundingtxid);
|
||||||
|
mtx.vout.push_back(CTxOut(markerfee, CScript() << ParseHex(HexStr(markerPubkey)) << OP_CHECKSIG)); // marker to prevent archiving of the funds add vouts
|
||||||
|
|
||||||
if (inputs > amount)
|
if (inputs > amount)
|
||||||
change = (inputs - amount); // -txfee <-- txfee pays user
|
change = (inputs - amount); // -txfee <-- txfee pays user
|
||||||
|
|
||||||
@@ -749,6 +802,28 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
|
|||||||
mtx.vout.push_back(Helper::makeUserVout(change, myPubkey));
|
mtx.vout.push_back(Helper::makeUserVout(change, myPubkey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check owner pubkey in vins
|
||||||
|
bool hasMypubkey = false;
|
||||||
|
bool hasNotMypubkey = false;
|
||||||
|
|
||||||
|
CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey);
|
||||||
|
|
||||||
|
// for additional funding do not allow to sign by both owner and non-owner keys (is this a donation or not?):
|
||||||
|
if (hasMypubkey && hasNotMypubkey) {
|
||||||
|
result.push_back(Pair("result", "error"));
|
||||||
|
result.push_back(Pair("error", "using both owner and non-owner inputs is not allowed"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// warn the user he's making a donation if this is all non-owner keys:
|
||||||
|
if (hasNotMypubkey) {
|
||||||
|
result.push_back(Pair("result", "warning"));
|
||||||
|
result.push_back(Pair("warning", "you are about to make a donation to heir fund"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.push_back(Pair("result", "success"));
|
||||||
|
}
|
||||||
|
|
||||||
// add 1of2 vout validation pubkeys - needed only for tokens:
|
// add 1of2 vout validation pubkeys - needed only for tokens:
|
||||||
std::vector<CPubKey> voutTokenPubkeys;
|
std::vector<CPubKey> voutTokenPubkeys;
|
||||||
voutTokenPubkeys.push_back(ownerPubkey);
|
voutTokenPubkeys.push_back(ownerPubkey);
|
||||||
@@ -759,11 +834,11 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
|
|||||||
Helper::makeAddOpRet(tokenid, voutTokenPubkeys, fundingtxid, hasHeirSpendingBegun)));
|
Helper::makeAddOpRet(tokenid, voutTokenPubkeys, fundingtxid, hasHeirSpendingBegun)));
|
||||||
|
|
||||||
if (!rawhextx.empty()) {
|
if (!rawhextx.empty()) {
|
||||||
result.push_back(Pair("result", "success"));
|
|
||||||
result.push_back(Pair("hextx", rawhextx));
|
result.push_back(Pair("hextx", rawhextx));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl;
|
std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl;
|
||||||
|
result.clear();
|
||||||
result.push_back(Pair("result", "error"));
|
result.push_back(Pair("result", "error"));
|
||||||
result.push_back(Pair("error", "sign error"));
|
result.push_back(Pair("error", "sign error"));
|
||||||
}
|
}
|
||||||
@@ -781,13 +856,11 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, uint64_t txfee, i
|
|||||||
result.push_back(Pair("error", "can't find normal inputs for tx fee"));
|
result.push_back(Pair("error", "can't find normal inputs for tx fee"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UniValue HeirAddCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) {
|
UniValue HeirAddCaller(uint256 fundingtxid, int64_t txfee, std::string strAmount) {
|
||||||
|
|
||||||
CPubKey ownerPubkey, heirPubkey;
|
CPubKey ownerPubkey, heirPubkey;
|
||||||
int64_t inactivityTimeSec;
|
int64_t inactivityTimeSec;
|
||||||
@@ -798,10 +871,27 @@ UniValue HeirAddCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) {
|
|||||||
uint8_t hasHeirSpendingBegun = 0;
|
uint8_t hasHeirSpendingBegun = 0;
|
||||||
|
|
||||||
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) {
|
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) {
|
||||||
if (tokenid == zeroid)
|
if (tokenid == zeroid) {
|
||||||
return _HeirAdd<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
|
int64_t amount = (int64_t)(atof(strAmount.c_str()) * COIN);
|
||||||
else
|
if (amount <= 0) {
|
||||||
return _HeirAdd<TokenHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
|
UniValue result(UniValue::VOBJ);
|
||||||
|
result.push_back(Pair("result", "error"));
|
||||||
|
result.push_back(Pair("error", "invalid amount"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _HeirAdd<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int64_t amount = atoll(strAmount.c_str());
|
||||||
|
if (amount <= 0) {
|
||||||
|
UniValue result(UniValue::VOBJ);
|
||||||
|
result.push_back(Pair("result", "error"));
|
||||||
|
result.push_back(Pair("error", "invalid amount"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return _HeirAdd<TokenHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
@@ -819,7 +909,7 @@ UniValue HeirAddCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) {
|
|||||||
* creates tx to spend funds from cryptocondition address by either funds' owner or heir
|
* creates tx to spend funds from cryptocondition address by either funds' owner or heir
|
||||||
* @return result object with raw tx or error text
|
* @return result object with raw tx or error text
|
||||||
*/
|
*/
|
||||||
template <typename Helper>UniValue _HeirClaim(uint256 fundingtxid, uint64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun)
|
template <typename Helper>UniValue _HeirClaim(uint256 fundingtxid, int64_t txfee, int64_t amount, uint256 latesttxid, uint8_t funcId, uint256 tokenid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, uint8_t hasHeirSpendingBegun)
|
||||||
{
|
{
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||||
@@ -940,7 +1030,7 @@ template <typename Helper>UniValue _HeirClaim(uint256 fundingtxid, uint64_t txfe
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue HeirClaimCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) {
|
UniValue HeirClaimCaller(uint256 fundingtxid, int64_t txfee, std::string strAmount) {
|
||||||
|
|
||||||
CPubKey ownerPubkey, heirPubkey;
|
CPubKey ownerPubkey, heirPubkey;
|
||||||
int64_t inactivityTimeSec;
|
int64_t inactivityTimeSec;
|
||||||
@@ -951,10 +1041,26 @@ UniValue HeirClaimCaller(uint256 fundingtxid, uint64_t txfee, int64_t amount) {
|
|||||||
uint8_t hasHeirSpendingBegun = 0;
|
uint8_t hasHeirSpendingBegun = 0;
|
||||||
|
|
||||||
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) {
|
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun)) != zeroid) {
|
||||||
if( tokenid == zeroid )
|
if (tokenid == zeroid) {
|
||||||
return _HeirClaim<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
|
int64_t amount = (int64_t)(atof(strAmount.c_str()) * COIN);
|
||||||
else
|
if (amount < 0) {
|
||||||
return _HeirClaim<TokenHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
|
UniValue result(UniValue::VOBJ);
|
||||||
|
result.push_back(Pair("result", "error"));
|
||||||
|
result.push_back(Pair("error", "invalid amount"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return _HeirClaim<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int64_t amount = atoll(strAmount.c_str());
|
||||||
|
if (amount <= 0) {
|
||||||
|
UniValue result(UniValue::VOBJ);
|
||||||
|
result.push_back(Pair("result", "error"));
|
||||||
|
result.push_back(Pair("error", "invalid amount"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return _HeirClaim<TokenHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, hasHeirSpendingBegun);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1022,6 +1128,8 @@ UniValue HeirInfo(uint256 fundingtxid)
|
|||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
std::string msg;
|
std::string msg;
|
||||||
|
|
||||||
|
//sleep(10);
|
||||||
|
|
||||||
result.push_back(Pair("fundingtxid", fundingtxid.GetHex()));
|
result.push_back(Pair("fundingtxid", fundingtxid.GetHex()));
|
||||||
result.push_back(Pair("name", heirName.c_str()));
|
result.push_back(Pair("name", heirName.c_str()));
|
||||||
|
|
||||||
@@ -1090,13 +1198,13 @@ UniValue HeirInfo(uint256 fundingtxid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream << inactivityTimeSec;
|
stream << inactivityTimeSec;
|
||||||
result.push_back(Pair("inactivity time setting", stream.str().c_str()));
|
result.push_back(Pair("inactivity time setting, sec", stream.str().c_str()));
|
||||||
stream.str("");
|
stream.str("");
|
||||||
stream.clear();
|
stream.clear();
|
||||||
|
|
||||||
if (!hasHeirSpendingBegun) { // we do not need find duration if the spending already has begun
|
if (!hasHeirSpendingBegun) { // we do not need find duration if the spending already has begun
|
||||||
durationSec = CCduration(numblocks, latestFundingTxid);
|
durationSec = CCduration(numblocks, latestFundingTxid);
|
||||||
std::cerr << "HeirInfo() duration=" << durationSec << " inactivityTime=" << inactivityTimeSec << " numblocks=" << numblocks << '\n';
|
std::cerr << "HeirInfo() duration (sec)=" << durationSec << " inactivityTime (sec)=" << inactivityTimeSec << " numblocks=" << numblocks << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
stream << std::boolalpha << (hasHeirSpendingBegun || durationSec > inactivityTimeSec);
|
stream << std::boolalpha << (hasHeirSpendingBegun || durationSec > inactivityTimeSec);
|
||||||
@@ -1104,6 +1212,14 @@ UniValue HeirInfo(uint256 fundingtxid)
|
|||||||
stream.str("");
|
stream.str("");
|
||||||
stream.clear();
|
stream.clear();
|
||||||
|
|
||||||
|
// adding owner current inactivity time:
|
||||||
|
if (!hasHeirSpendingBegun && durationSec <= inactivityTimeSec) {
|
||||||
|
stream << durationSec;
|
||||||
|
result.push_back(Pair("owner inactivity time, sec", stream.str().c_str()));
|
||||||
|
stream.str("");
|
||||||
|
stream.clear();
|
||||||
|
}
|
||||||
|
|
||||||
result.push_back(Pair("result", "success"));
|
result.push_back(Pair("result", "success"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1123,15 +1239,15 @@ UniValue HeirInfo(uint256 fundingtxid)
|
|||||||
* @return list of heir plan handles (fundingtxid)
|
* @return list of heir plan handles (fundingtxid)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename Helper>void _HeirList(struct CCcontract_info *cp, UniValue &result)
|
void _HeirList(struct CCcontract_info *cp, UniValue &result)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
|
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
|
||||||
char coinaddr[64];
|
char markeraddr[64];
|
||||||
CPubKey ccPubKeyEmpty;
|
|
||||||
GetCCaddress(cp, coinaddr, ccPubKeyEmpty);
|
|
||||||
SetCCunspents(unspentOutputs, cp->normaladdr);
|
|
||||||
|
|
||||||
//std::cerr << "HeirList() finding heir marker from Heir contract addr=" << cp->normaladdr << " unspentOutputs.size()=" << unspentOutputs.size() << '\n';
|
GetCCaddress(cp, markeraddr, GetUnspendable(cp, NULL));
|
||||||
|
SetCCunspents(unspentOutputs, markeraddr);
|
||||||
|
|
||||||
|
//std::cerr << "HeirList() finding heir marker from unspendable addr=" << markeraddr << " unspentOutputs.size()=" << unspentOutputs.size() << '\n';
|
||||||
|
|
||||||
// TODO: move marker to special cc addr to prevent checking all tokens
|
// TODO: move marker to special cc addr to prevent checking all tokens
|
||||||
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) {
|
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>>::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++) {
|
||||||
@@ -1177,10 +1293,10 @@ UniValue HeirList()
|
|||||||
struct CCcontract_info *cpHeir, *cpTokens, heirC, tokenC; // NOTE we must use a separate 'C' structure for each CCinit!
|
struct CCcontract_info *cpHeir, *cpTokens, heirC, tokenC; // NOTE we must use a separate 'C' structure for each CCinit!
|
||||||
|
|
||||||
cpHeir = CCinit(&heirC, EVAL_HEIR);
|
cpHeir = CCinit(&heirC, EVAL_HEIR);
|
||||||
cpTokens = CCinit(&tokenC, EVAL_TOKENS);
|
//cpTokens = CCinit(&tokenC, EVAL_TOKENS);
|
||||||
|
|
||||||
_HeirList<CoinHelper>(cpHeir, result);
|
_HeirList(cpHeir, result);
|
||||||
_HeirList<TokenHelper>(cpTokens, result);
|
//_HeirList<TokenHelper>(cpTokens, result); not used anymore
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,8 +125,8 @@ class CValidatorBase
|
|||||||
public:
|
public:
|
||||||
CValidatorBase(CCcontract_info* cp) : m_cp(cp) {}
|
CValidatorBase(CCcontract_info* cp) : m_cp(cp) {}
|
||||||
virtual bool isVinValidator() const = 0;
|
virtual bool isVinValidator() const = 0;
|
||||||
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const = 0;
|
virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const = 0;
|
||||||
virtual bool validateVout(CTxOut vout, std::string& message) const = 0;
|
virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CCcontract_info * m_cp;
|
CCcontract_info * m_cp;
|
||||||
@@ -258,10 +258,10 @@ private:
|
|||||||
|
|
||||||
if (v->isVinValidator())
|
if (v->isVinValidator())
|
||||||
// validate this vin and previous vout:
|
// validate this vin and previous vout:
|
||||||
result = v->validateVin(pTx->vin[iv], pPrevTx->vout[pTx->vin[iv].prevout.n], refMessage);
|
result = v->validateVin(pTx->vin[iv], pPrevTx->vout, pTx->vin[iv].prevout.n, refMessage);
|
||||||
else
|
else
|
||||||
// if it is vout validator pass the previous tx vout:
|
// if it is vout validator pass the previous tx vout:
|
||||||
result = v->validateVout( pPrevTx->vout[pTx->vin[iv].prevout.n], refMessage);
|
result = v->validateVout( pPrevTx->vout[pTx->vin[iv].prevout.n], pTx->vin[iv].prevout.n, refMessage);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -359,7 +359,7 @@ private:
|
|||||||
|
|
||||||
if (!v->isVinValidator()) {
|
if (!v->isVinValidator()) {
|
||||||
// if this is a 'in' validation plan then pass the previous tx vout:
|
// if this is a 'in' validation plan then pass the previous tx vout:
|
||||||
bool result = v->validateVout(pTx->vout[iv], refMessage);
|
bool result = v->validateVout(pTx->vout[iv], iv, refMessage);
|
||||||
if (!result)
|
if (!result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -402,7 +402,7 @@ public:
|
|||||||
m_fundingOpretScript(opRetScript), m_customMessage(customMessage), CValidatorBase(cp) {}
|
m_fundingOpretScript(opRetScript), m_customMessage(customMessage), CValidatorBase(cp) {}
|
||||||
|
|
||||||
virtual bool isVinValidator() const { return false; }
|
virtual bool isVinValidator() const { return false; }
|
||||||
virtual bool validateVout(CTxOut vout, std::string& message) const
|
virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const
|
||||||
{
|
{
|
||||||
//std::cerr << "CCC1of2AddressValidator::validateVout() entered" << std::endl;
|
//std::cerr << "CCC1of2AddressValidator::validateVout() entered" << std::endl;
|
||||||
CPubKey ownerPubkey, heirPubkey;
|
CPubKey ownerPubkey, heirPubkey;
|
||||||
@@ -438,7 +438,7 @@ public:
|
|||||||
std::cerr << "CCC1of2AddressValidator::validateVout() exits with false: " << message << std::endl;
|
std::cerr << "CCC1of2AddressValidator::validateVout() exits with false: " << message << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return false; }
|
virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CScript m_fundingOpretScript;
|
CScript m_fundingOpretScript;
|
||||||
@@ -456,7 +456,7 @@ public:
|
|||||||
: m_fundingOpretScript(opRetScript), m_checkNormals(checkNormals), CValidatorBase(cp) { }
|
: m_fundingOpretScript(opRetScript), m_checkNormals(checkNormals), CValidatorBase(cp) { }
|
||||||
|
|
||||||
virtual bool isVinValidator() const { return false; }
|
virtual bool isVinValidator() const { return false; }
|
||||||
virtual bool validateVout(CTxOut vout, std::string& message) const
|
virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const
|
||||||
{
|
{
|
||||||
//std::cerr << "CMyPubkeyVoutValidator::validateVout() entered" << std::endl;
|
//std::cerr << "CMyPubkeyVoutValidator::validateVout() entered" << std::endl;
|
||||||
|
|
||||||
@@ -498,7 +498,7 @@ public:
|
|||||||
message = std::string("invalid pubkey");
|
message = std::string("invalid pubkey");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return true; }
|
virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CScript m_fundingOpretScript;
|
CScript m_fundingOpretScript;
|
||||||
@@ -516,7 +516,7 @@ public:
|
|||||||
: m_fundingOpretScript(opRetScript), m_latesttxid(latesttxid), m_isHeirSpendingBegan(isHeirSpendingBegan), CValidatorBase(cp) {}
|
: m_fundingOpretScript(opRetScript), m_latesttxid(latesttxid), m_isHeirSpendingBegan(isHeirSpendingBegan), CValidatorBase(cp) {}
|
||||||
|
|
||||||
virtual bool isVinValidator() const { return false; }
|
virtual bool isVinValidator() const { return false; }
|
||||||
virtual bool validateVout(CTxOut vout, std::string& message) const
|
virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const
|
||||||
{
|
{
|
||||||
//std::cerr << "CHeirSpendValidator::validateVout() entered" << std::endl;
|
//std::cerr << "CHeirSpendValidator::validateVout() entered" << std::endl;
|
||||||
|
|
||||||
@@ -554,7 +554,7 @@ public:
|
|||||||
// this is not heir:
|
// this is not heir:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return true; }
|
virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CScript m_fundingOpretScript;
|
CScript m_fundingOpretScript;
|
||||||
@@ -572,7 +572,7 @@ public:
|
|||||||
: m_fundingOpretScript(opret), CValidatorBase(cp) {}
|
: m_fundingOpretScript(opret), CValidatorBase(cp) {}
|
||||||
|
|
||||||
virtual bool isVinValidator() const { return false; }
|
virtual bool isVinValidator() const { return false; }
|
||||||
virtual bool validateVout(CTxOut vout, std::string& message) const
|
virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const
|
||||||
{
|
{
|
||||||
//std::cerr << "COpRetValidator::validateVout() entered" << std::endl;
|
//std::cerr << "COpRetValidator::validateVout() entered" << std::endl;
|
||||||
|
|
||||||
@@ -607,12 +607,48 @@ public:
|
|||||||
//std::cerr << "COpRetValidator::validateVout() exits with true" << std::endl;
|
//std::cerr << "COpRetValidator::validateVout() exits with true" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return true; }
|
virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CScript m_fundingOpretScript;
|
CScript m_fundingOpretScript;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* marker spending prevention validator,
|
||||||
|
* returns false if for tx with funcid=F vout.1 is being tried to spend
|
||||||
|
*/
|
||||||
|
template <class Helper> class CMarkerValidator : CValidatorBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMarkerValidator(CCcontract_info* cp)
|
||||||
|
: CValidatorBase(cp) { }
|
||||||
|
|
||||||
|
virtual bool isVinValidator() const { return true; } // this is vin validator
|
||||||
|
virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const { return true; }
|
||||||
|
virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const {
|
||||||
|
|
||||||
|
uint256 fundingTxidInOpret = zeroid, dummyTxid, tokenid = zeroid, initialTokenid = zeroid;
|
||||||
|
uint8_t dummyIsHeirSpendingBegan;
|
||||||
|
|
||||||
|
//std::cerr << "CMarkerValidator::validateVin() prevVout.size()=" << prevVout.size() << " prevN=" << prevN << std::endl;
|
||||||
|
if (prevVout.size() > 0) {
|
||||||
|
|
||||||
|
// get funcId for prev tx:
|
||||||
|
uint8_t funcId = DecodeHeirEitherOpRet(prevVout[prevVout.size()-1].scriptPubKey, tokenid, fundingTxidInOpret, dummyIsHeirSpendingBegan, true);
|
||||||
|
|
||||||
|
//std::cerr << "CMarkerValidator::validateVin() funcId=" << (funcId?funcId:' ') << std::endl;
|
||||||
|
|
||||||
|
if (funcId == 'F' && prevN == 1) { // do not allow to spend 'F' marker's vout
|
||||||
|
message = std::string("spending marker not allowed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//std::cerr << "CMarkerValidator::validateVin() exits with true" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* empty validator always returns true
|
* empty validator always returns true
|
||||||
*/
|
*/
|
||||||
@@ -623,8 +659,8 @@ public:
|
|||||||
: CValidatorBase(cp) { }
|
: CValidatorBase(cp) { }
|
||||||
|
|
||||||
virtual bool isVinValidator() const { return false; }
|
virtual bool isVinValidator() const { return false; }
|
||||||
virtual bool validateVout(CTxOut vout, std::string& message) const { return true; }
|
virtual bool validateVout(CTxOut vout, int32_t vout_n, std::string& message) const { return true; }
|
||||||
virtual bool validateVin(CTxIn vin, CTxOut prevVout, std::string& message) const { return true; }
|
virtual bool validateVin(CTxIn vin, std::vector<CTxOut> prevVout, int32_t prevN, std::string& message) const { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -537,6 +537,9 @@ static const CRPCCommand vRPCCommands[] =
|
|||||||
{ "util", "reconsiderblock", &reconsiderblock, true },
|
{ "util", "reconsiderblock", &reconsiderblock, true },
|
||||||
/* Not shown in help */
|
/* Not shown in help */
|
||||||
{ "hidden", "setmocktime", &setmocktime, true },
|
{ "hidden", "setmocktime", &setmocktime, true },
|
||||||
|
{ "hidden", "test_ac", &test_ac, true },
|
||||||
|
{ "hidden", "test_heirmarker", &test_heirmarker, true },
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
/* Wallet */
|
/* Wallet */
|
||||||
{ "wallet", "resendwallettransactions", &resendwallettransactions, true},
|
{ "wallet", "resendwallettransactions", &resendwallettransactions, true},
|
||||||
|
|||||||
@@ -471,4 +471,8 @@ extern UniValue paxprices(const UniValue& params, bool fHelp);
|
|||||||
extern UniValue paxdeposit(const UniValue& params, bool fHelp);
|
extern UniValue paxdeposit(const UniValue& params, bool fHelp);
|
||||||
extern UniValue paxwithdraw(const UniValue& params, bool fHelp);
|
extern UniValue paxwithdraw(const UniValue& params, bool fHelp);
|
||||||
|
|
||||||
|
// test rpc:
|
||||||
|
extern UniValue test_ac(const UniValue& params, bool fHelp);
|
||||||
|
extern UniValue test_heirmarker(const UniValue& params, bool fHelp);
|
||||||
|
|
||||||
#endif // BITCOIN_RPCSERVER_H
|
#endif // BITCOIN_RPCSERVER_H
|
||||||
|
|||||||
@@ -7362,7 +7362,7 @@ UniValue heirfund(const UniValue& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
UniValue result(UniValue::VOBJ);
|
UniValue result(UniValue::VOBJ);
|
||||||
uint256 tokenid = zeroid;
|
uint256 tokenid = zeroid;
|
||||||
uint64_t txfee;
|
int64_t txfee;
|
||||||
int64_t amount;
|
int64_t amount;
|
||||||
int64_t inactivitytime;
|
int64_t inactivitytime;
|
||||||
std::string hex;
|
std::string hex;
|
||||||
@@ -7373,21 +7373,34 @@ UniValue heirfund(const UniValue& params, bool fHelp)
|
|||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
|
||||||
if (fHelp || params.size() != 5 && params.size() != 6)
|
if (fHelp || params.size() != 5 && params.size() != 6)
|
||||||
throw runtime_error("heirfundtokens fee funds heirname heirpubkey inactivitytime [tokenid]\n");
|
throw runtime_error("heirfund txfee funds heirname heirpubkey inactivitytime [tokenid]\n");
|
||||||
if (ensure_CCrequirements() < 0)
|
if (ensure_CCrequirements() < 0)
|
||||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
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;
|
const CKeyStore& keystore = *pwalletMain;
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
|
||||||
txfee = atoll((char*)params[0].get_str().c_str());
|
txfee = atoll(params[0].get_str().c_str());
|
||||||
amount = atoll((char*)params[1].get_str().c_str());
|
if (txfee < 0)
|
||||||
|
throw runtime_error("incorrect txfee param\n");
|
||||||
|
|
||||||
|
if(params.size() == 6) // tokens in satoshis:
|
||||||
|
amount = atoll(params[1].get_str().c_str());
|
||||||
|
else // coins:
|
||||||
|
amount = atof(params[1].get_str().c_str()) * COIN;
|
||||||
|
|
||||||
|
if( amount <= 0 )
|
||||||
|
throw runtime_error("incorrect amount\n");
|
||||||
|
|
||||||
name = params[2].get_str();
|
name = params[2].get_str();
|
||||||
pubkey = ParseHex(params[3].get_str().c_str());
|
pubkey = ParseHex(params[3].get_str().c_str());
|
||||||
if( !pubkey2pk(pubkey).IsValid() )
|
if( !pubkey2pk(pubkey).IsValid() )
|
||||||
throw runtime_error("incorrect pubkey\n");
|
throw runtime_error("incorrect pubkey\n");
|
||||||
|
|
||||||
inactivitytime = atof((char*)params[4].get_str().c_str());
|
inactivitytime = atoll(params[4].get_str().c_str());
|
||||||
|
if (inactivitytime <= 0)
|
||||||
|
throw runtime_error("incorrect inactivity time param\n");
|
||||||
|
|
||||||
if (params.size() == 6) {
|
if (params.size() == 6) {
|
||||||
tokenid = Parseuint256((char*)params[5].get_str().c_str());
|
tokenid = Parseuint256((char*)params[5].get_str().c_str());
|
||||||
if(tokenid == zeroid)
|
if(tokenid == zeroid)
|
||||||
@@ -7406,7 +7419,7 @@ UniValue heiradd(const UniValue& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
UniValue result;
|
UniValue result;
|
||||||
uint256 fundingtxid;
|
uint256 fundingtxid;
|
||||||
uint64_t txfee;
|
int64_t txfee;
|
||||||
int64_t amount;
|
int64_t amount;
|
||||||
int64_t inactivitytime;
|
int64_t inactivitytime;
|
||||||
std::string hex;
|
std::string hex;
|
||||||
@@ -7417,18 +7430,20 @@ UniValue heiradd(const UniValue& params, bool fHelp)
|
|||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
|
||||||
if (fHelp || params.size() != 3)
|
if (fHelp || params.size() != 3)
|
||||||
throw runtime_error("heiraddtokens fee funds fundingtxid\n");
|
throw runtime_error("heiradd txfee funds fundingtxid\n");
|
||||||
if (ensure_CCrequirements() < 0)
|
if (ensure_CCrequirements() < 0)
|
||||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
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;
|
const CKeyStore& keystore = *pwalletMain;
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
|
||||||
txfee = atoll((char*)params[0].get_str().c_str());
|
txfee = atoll(params[0].get_str().c_str());
|
||||||
amount = atoll((char*)params[1].get_str().c_str());
|
if (txfee < 0)
|
||||||
|
throw runtime_error("incorrect txfee param\n");
|
||||||
|
|
||||||
fundingtxid = Parseuint256((char*)params[2].get_str().c_str());
|
fundingtxid = Parseuint256((char*)params[2].get_str().c_str());
|
||||||
|
|
||||||
result = HeirAddCaller(fundingtxid, txfee, amount);
|
result = HeirAddCaller(fundingtxid, txfee, params[1].get_str());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7437,7 +7452,6 @@ UniValue heirclaim(const UniValue& params, bool fHelp)
|
|||||||
UniValue result; // result(UniValue::VOBJ);
|
UniValue result; // result(UniValue::VOBJ);
|
||||||
uint256 fundingtxid;
|
uint256 fundingtxid;
|
||||||
int64_t txfee;
|
int64_t txfee;
|
||||||
int64_t amount;
|
|
||||||
int64_t inactivitytime;
|
int64_t inactivitytime;
|
||||||
std::string hex;
|
std::string hex;
|
||||||
std::vector<unsigned char> pubkey;
|
std::vector<unsigned char> pubkey;
|
||||||
@@ -7448,18 +7462,20 @@ UniValue heirclaim(const UniValue& params, bool fHelp)
|
|||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
|
|
||||||
if (fHelp || params.size() != 3)
|
if (fHelp || params.size() != 3)
|
||||||
throw runtime_error("heirclaimtokens fee funds fundingtxid\n");
|
throw runtime_error("heirclaim txfee funds fundingtxid\n");
|
||||||
if (ensure_CCrequirements() < 0)
|
if (ensure_CCrequirements() < 0)
|
||||||
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
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;
|
const CKeyStore& keystore = *pwalletMain;
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
|
||||||
txfee = atoll((char*)params[0].get_str().c_str());
|
txfee = atoll(params[0].get_str().c_str());
|
||||||
amount = atoll((char*)params[1].get_str().c_str());
|
if (txfee < 0)
|
||||||
|
throw runtime_error("incorrect txfee param\n");
|
||||||
|
|
||||||
fundingtxid = Parseuint256((char*)params[2].get_str().c_str());
|
fundingtxid = Parseuint256((char*)params[2].get_str().c_str());
|
||||||
|
|
||||||
result = HeirClaimCaller(fundingtxid, txfee, amount);
|
result = HeirClaimCaller(fundingtxid, txfee, params[1].get_str());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7581,3 +7597,79 @@ void RegisterWalletRPCCommands(CRPCTable &tableRPC)
|
|||||||
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
|
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
|
||||||
tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
|
tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue test_ac(const UniValue& params, bool fHelp)
|
||||||
|
{
|
||||||
|
// make fake token tx:
|
||||||
|
struct CCcontract_info *cp, C;
|
||||||
|
|
||||||
|
if (fHelp || (params.size() != 4))
|
||||||
|
throw runtime_error("incorrect params\n");
|
||||||
|
if (ensure_CCrequirements() < 0)
|
||||||
|
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||||
|
|
||||||
|
std::vector<unsigned char> pubkey1;
|
||||||
|
std::vector<unsigned char> pubkey2;
|
||||||
|
|
||||||
|
pubkey1 = ParseHex(params[0].get_str().c_str());
|
||||||
|
pubkey2 = ParseHex(params[1].get_str().c_str());
|
||||||
|
|
||||||
|
CPubKey pk1 = pubkey2pk(pubkey1);
|
||||||
|
CPubKey pk2 = pubkey2pk(pubkey2);
|
||||||
|
|
||||||
|
if(!pk1.IsValid() || !pk2.IsValid())
|
||||||
|
throw runtime_error("invalid pubkey\n");
|
||||||
|
|
||||||
|
int64_t txfee = 10000;
|
||||||
|
int64_t amount = atoll(params[2].get_str().c_str()) * COIN;
|
||||||
|
uint256 fundingtxid = Parseuint256((char *)params[3].get_str().c_str());
|
||||||
|
|
||||||
|
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||||
|
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||||
|
|
||||||
|
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, txfee + amount, 60);
|
||||||
|
|
||||||
|
if( normalInputs < txfee + amount)
|
||||||
|
throw runtime_error("not enough normals\n");
|
||||||
|
|
||||||
|
mtx.vout.push_back(MakeCC1of2vout(EVAL_HEIR, amount, pk1, pk2));
|
||||||
|
|
||||||
|
CScript opret;
|
||||||
|
fundingtxid = revuint256(fundingtxid);
|
||||||
|
|
||||||
|
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'A' << fundingtxid << (uint8_t)0);
|
||||||
|
|
||||||
|
cp = CCinit(&C, EVAL_HEIR);
|
||||||
|
return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret));
|
||||||
|
}
|
||||||
|
|
||||||
|
UniValue test_heirmarker(const UniValue& params, bool fHelp)
|
||||||
|
{
|
||||||
|
// make fake token tx:
|
||||||
|
struct CCcontract_info *cp, C;
|
||||||
|
|
||||||
|
if (fHelp || (params.size() != 1))
|
||||||
|
throw runtime_error("incorrect params\n");
|
||||||
|
if (ensure_CCrequirements() < 0)
|
||||||
|
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
|
||||||
|
|
||||||
|
uint256 fundingtxid = Parseuint256((char *)params[0].get_str().c_str());
|
||||||
|
|
||||||
|
CPubKey myPubkey = pubkey2pk(Mypubkey());
|
||||||
|
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
|
||||||
|
|
||||||
|
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, 10000, 60);
|
||||||
|
if (normalInputs < 10000)
|
||||||
|
throw runtime_error("not enough normals\n");
|
||||||
|
|
||||||
|
mtx.vin.push_back(CTxIn(fundingtxid, 1));
|
||||||
|
mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, 10000, myPubkey));
|
||||||
|
|
||||||
|
CScript opret;
|
||||||
|
fundingtxid = revuint256(fundingtxid);
|
||||||
|
|
||||||
|
opret << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_HEIR << (uint8_t)'C' << fundingtxid << (uint8_t)0);
|
||||||
|
|
||||||
|
cp = CCinit(&C, EVAL_HEIR);
|
||||||
|
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user