Browse Source

initial commit for -earlytxid use with ac_script and ccvout_opret

z_createrawtransaction
blackjok3r 5 years ago
parent
commit
451773dcc1
  1. 4
      src/cc/CCutils.cpp
  2. 62
      src/cc/payments.cpp
  3. 44
      src/komodo_bitcoind.h
  4. 2
      src/komodo_defs.h
  5. 1
      src/komodo_utils.h
  6. 11
      src/miner.cpp
  7. 1
      src/rpc/server.cpp
  8. 1
      src/rpc/server.h
  9. 36
      src/wallet/rpcwallet.cpp

4
src/cc/CCutils.cpp

@ -76,11 +76,9 @@ CScript getCCopret(const CScript &scriptPubKey)
CScript dummy; CScript opret;
if ( scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) )
{
//opret << E_MARSHAL(ss << 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());
}
//fprintf(stderr, "params_size.%li parmas_hexstr.%s\n", vParams.size(), HexStr(vParams[0].begin(),vParams[0].end()).c_str());
//opret = CScript(vParams[0].begin(), vParams[0].end());
return opret;
}

62
src/cc/payments.cpp

@ -16,11 +16,59 @@
#include "CCPayments.h"
/*
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ac_script + -earlytxid instructions with payments cc + rewards CC as an example.
How this works:
- earlytxid must be a transaction included in the chain before block 100. The chain MUST not have any other of these type of tx before block 100, or someone may be able to change it and mess things up.
- When it gets to block 100, it takes the txid specified by the -earlytxid param (does not affect magic)
- Looks up the transaction searches for the opreturn, then permenantly appends it to the end of ac_script in RAM.
- After every daemon restart, the first time the daemon mines a block, or receives a block that pays ac_script it will look up the op_return and save it again.
- this enables it to always reach consensus but doesnt need to constantly keep looking up the tx in the chain.
- The trick is to use ac_founders=101 or higher so that nothing is ever paid to the unspendable CC address. Although it should still work without this it burns coins.
-ac_script can be any Global CC address you can spend to with an OP_RETURN. Here we use example of paymentsCC being used to fund a rewards plan, and a set of founders address's.
you can get the ac_script from another chain, but the op_return payload must generated on the chain itself. this command gives you the needed info to get the scripPubKey Hex:
./komodo-cli -ac_name=TEST paymentsfund '["5d536f54332db09f2be04593c54f764cf569e225f4d8df5155658c679e663682",1000]'
append: b8, to the end of ac_script, this changes magic value for -earlytxid chains vs normal ac_script and allows bypass of ac_supply paid to the scritpt as it would be unspendable and you would be unable to create the needed plans with no coins.
-ac_script=2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401ccb8
start chain and make sure to do the following steps before block 100 (set generate false/true is a good idea between steps)
create rewards plan and fund it with all or a % of the premine. Must be some amount. eg.
./komodo-cli -ac_name=TEST rewardscreatefunding test 1000 10 0 10 10
do rewards add funding and get the script pubkey and op_return from this tx (no need to send it) eg.
scriptPubKey: 2ea22c802065686d47a4049c2c845a71895a915eb84c04445896eec5dc0be40df0b31372da8103120c008203000401cc
OP_RETURN: 6a2ae541746573740000000061e7063fa8f99ef92a47e4aebf7ea28c59aeadaf3c1784312de64e4bcb3666f1
create txidopreturn for this payment:
./komodo-cli -ac_name=TEST paymentstxidopret '[50,"2ea22c802065686d47a4049c2c845a71895a915eb84c04445896eec5dc0be40df0b31372da8103120c008203000401cc","6a2ae541746573740000000061e7063fa8f99ef92a47e4aebf7ea28c59aeadaf3c1784312de64e4bcb3666f1"]'
create the txidopret for the founders reward(s) pubkeys: should be able to be a few here, not sure of max number yet. These can pay anything that does not need an opreturn. allocation and scriptpubkey hex.
./komodo-cli -ac_name=TEST paymentstxidopret '[50,"76a9146bf5dd9f679c87a3f83ea176f82148d26653c04388ac"]'
create payments plan:
./komodo-cli -ac_name=TEST paymentscreate '[0,0,"273d193e5d09928e471926827dcac1f06c4801bdaa5524a84b17a00f4eaf8d38","81264daf7874b2041802ac681e49618413313cc2f29b47d47bd8e63dc2a06cad"]'
gives plan txid eg. 5d536f54332db09f2be04593c54f764cf569e225f4d8df5155658c679e663682
-earlytxid is not an -ac_param, so it doesnt affect the chain magics
extra data after the normal CCvout is whatever data we want and can represent whatever we want
so -ac_script=<payments CC vout + useearlytxid>
in the validation if you see the useearlytxid in the opreturn data or extra data, you use the earlytxid as the txid that specifies the payment
paymentsfund:
send some of the premine to this payments fund to get the rest of the scriptpubkey payload. (could skip send and just gen/decode the tx if required.)
send opret path this time to get the required script pubkey. For payments this mode is enabled by default rather than a traditional OP_RETURN,
for other CC we would need to modify daemon to get the correct info.
./komodo-cli -ac_name=TEST paymentsfund '["5d536f54332db09f2be04593c54f764cf569e225f4d8df5155658c679e663682",1000,1]'
get the payment fund script pubkey: (the split it at OP_CHECKCRYPTOCONDITION or 'cc' )
2ea22c8020987fad30df055db6fd922c3a57e55d76601229ed3da3b31340112e773df3d0d28103120c008203000401cc 2a0401f00101246a22f0466b75e35aa4d8ea6c3dd1b76141a0acbd06dfb4897288a62b8a8ec31b75a5b6cb75
put the second half into an OP_RETURN: (the remaining part of the the above scriptpubkey) eg.
./komodo-cli -ac_name=TEST opreturn_burn 1 2a0401f00101246a22f0466b75e35aa4d8ea6c3dd1b76141a0acbd06dfb4897288a62b8a8ec31b75a5b6cb75
opret_burn takes any burn amount and arbitrary hex string. (RPC works, but may have bugs, likely use this for LABS too with some fixes)
this gives a txid to locate it in the chain eg:
-earlytxid=1acd0b9b728feaea37a3f52d4106c35b0f8cfd19f9f3e64815d23ace0721d69d
restart the chain with earlytxid param before height 100 on BOTH NODES!
once the payments plan has been funded with the mined coinbase you can issue payments release when conditions of the plan are met to fund founders reward/rewards plan. eg.
./komodo-cli -ac_name=TEST paymentsrelease '["5d536f54332db09f2be04593c54f764cf569e225f4d8df5155658c679e663682",500]'
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0) txidopret <- allocation, scriptPubKey, opret
1) create <- locked_blocks, minrelease, list of txidopret
@ -643,13 +691,11 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
else
{
opret = EncodePaymentsFundOpRet(txid);
fprintf(stderr, "opret.%s\n", HexStr(opret.begin(), opret.end()).c_str());
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
if ( makeCCopret(opret, vData) )
{
mtx.vout.push_back(MakeCC1vout(EVAL_PAYMENTS,amount,Paymentspk,&vData));
fprintf(stderr, "params_size.%li parmas_hexstr.%s\n", vData.size(), HexStr(vData[0].begin(),vData[0].end()).c_str());
}
//fprintf(stderr, "scriptpubkey.%s\n", mtx.vout.back().scriptPubKey.ToString().c_str());
//fprintf(stderr, "hex.%s\n", HexStr(mtx.vout.back().scriptPubKey.begin(), mtx.vout.back().scriptPubKey.end()).c_str());
}
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,CScript());
if ( params != 0 )

44
src/komodo_bitcoind.h

@ -2030,9 +2030,39 @@ uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height)
return(0);
}
bool komodo_appendACscriptpub()
{
static bool didinit = false;
if ( didinit )
return didinit;
if ( ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] == 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] == 51 )
{
CTransaction tx; uint256 blockhash;
// get transaction and check that it occured before height 100.
if ( myGetTransaction(KOMODO_EARLYTXID,tx,blockhash) && mapBlockIndex[blockhash]->GetHeight() < 100 )
{
for (int i = 0; i < tx.vout.size(); i++)
{
if ( tx.vout[i].scriptPubKey[0] == OP_RETURN )
{
ASSETCHAINS_SCRIPTPUB.pop_back(); ASSETCHAINS_SCRIPTPUB.pop_back(); // remove last 2 chars.
// get OP_RETURN from txid and append the HexStr of it to scriptpub
ASSETCHAINS_SCRIPTPUB.append(HexStr(tx.vout[i].scriptPubKey.begin()+3, tx.vout[i].scriptPubKey.end()));
//fprintf(stderr, "ac_script.%s\n",ASSETCHAINS_SCRIPTPUB.c_str());
didinit = true;
return true;
}
}
}
fprintf(stderr, "could not get KOMODO_EARLYTXID.%s OP_RETURN data. Restart with correct txid!\n", KOMODO_EARLYTXID.GetHex().c_str());
StartShutdown();
}
return false;
}
int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
{
int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0;
int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0; static bool didinit = false;
if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 )
{
checktoshis = komodo_commission(pblock,height);
@ -2054,6 +2084,12 @@ int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
}
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 )
{
static bool didinit = false;
if ( !didinit && height > 100 && KOMODO_EARLYTXID != zeroid && komodo_appendACscriptpub() )
{
fprintf(stderr, "appended CC_op_return to ASSETCHAINS_SCRIPTPUB.%s\n", ASSETCHAINS_SCRIPTPUB.c_str());
didinit = true;
}
if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) )
{
decode_hex(scripthex,scriptlen,(char *)ASSETCHAINS_SCRIPTPUB.c_str());
@ -2190,11 +2226,11 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
else if ( ASSETCHAINS_STAKED != 0 )
failed = 0;
}
if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 )
{
if ( height == 1 )
{
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 )
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] != 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] != 51 )
{
int32_t scriptlen; uint8_t scripthex[10000];
script = (uint8_t *)&pblock->vtx[0].vout[0].scriptPubKey[0];
@ -2206,7 +2242,7 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
return(-1);
} else return(-1);
}
else
else if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
{
script = (uint8_t *)&pblock->vtx[0].vout[0].scriptPubKey[0];
scriptlen = (int32_t)pblock->vtx[0].vout[0].scriptPubKey.size();

2
src/komodo_defs.h

@ -63,7 +63,7 @@ extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS
extern std::vector<std::string> ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS;
extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD;
extern uint256 KOMODO_EARLYTXID;
extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE,KOMODO_DEALERNODE;
extern uint32_t ASSETCHAINS_CC;

1
src/komodo_utils.h

@ -2072,6 +2072,7 @@ void komodo_args(char *argv0)
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS),(void *)&ASSETCHAINS_FOUNDERS);
if ( ASSETCHAINS_FOUNDERS_REWARD != 0 )
{
fprintf(stderr, "set founders reward.%li\n",ASSETCHAINS_FOUNDERS_REWARD);
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS_REWARD),(void *)&ASSETCHAINS_FOUNDERS_REWARD);
}
}

11
src/miner.cpp

@ -156,6 +156,7 @@ uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector<int8_t> &Notar
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len);
CScript komodo_mineropret(int32_t nHeight);
bool komodo_appendACscriptpub();
CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake)
{
@ -652,6 +653,12 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
txNew.vout[1].nValue = commission;
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 )
{
static bool didinit = false;
if ( !didinit && nHeight > 100 && KOMODO_EARLYTXID != zeroid && komodo_appendACscriptpub() )
{
fprintf(stderr, "appended ccopreturn to ASSETCHAINS_SCRIPTPUB.%s\n", ASSETCHAINS_SCRIPTPUB.c_str());
didinit = true;
}
//fprintf(stderr,"mine to -ac_script\n");
//txNew.vout[1].scriptPubKey = CScript() << ParseHex();
int32_t len = strlen(ASSETCHAINS_SCRIPTPUB.c_str());
@ -895,14 +902,14 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake)
{
CPubKey pubkey; CScript scriptPubKey; uint8_t *script,*ptr; int32_t i,len;
if ( nHeight == 1 && ASSETCHAINS_COMMISSION != 0 )
if ( nHeight == 1 && ASSETCHAINS_COMMISSION != 0 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()] != 49 && ASSETCHAINS_SCRIPTPUB[ASSETCHAINS_SCRIPTPUB.back()-1] != 51 )
{
if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
{
pubkey = ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY);
scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG;
}
else
else
{
len = strlen(ASSETCHAINS_SCRIPTPUB.c_str());
len >>= 1;

1
src/rpc/server.cpp

@ -639,6 +639,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "z_importviewingkey", &z_importviewingkey, true },
{ "wallet", "z_exportwallet", &z_exportwallet, true },
{ "wallet", "z_importwallet", &z_importwallet, true },
{ "wallet", "opreturn_burn", &opreturn_burn, true },
// TODO: rearrange into another category
{ "disclosure", "z_getpaymentdisclosure", &z_getpaymentdisclosure, true },

1
src/rpc/server.h

@ -466,6 +466,7 @@ extern UniValue z_shieldcoinbase(const UniValue& params, bool fHelp); // in rpcw
extern UniValue z_getoperationstatus(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_getoperationresult(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_listoperationids(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue opreturn_burn(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue z_validateaddress(const UniValue& params, bool fHelp); // in rpcmisc.cpp
extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp); // in rpcdisclosure.cpp
extern UniValue z_validatepaymentdisclosure(const UniValue &params, bool fHelp); // in rpcdisclosure.cpp

36
src/wallet/rpcwallet.cpp

@ -7979,9 +7979,11 @@ UniValue test_ac(const UniValue& params, bool fHelp)
return(FinalizeCCTx(0, cp, mtx, myPubkey, txfee, opret));
}
extern bool komodo_appendACscriptpub();
UniValue test_heirmarker(const UniValue& params, bool fHelp)
{
// make fake token tx:
//make fake token tx:
struct CCcontract_info *cp, C;
if (fHelp || (params.size() != 1))
@ -8010,6 +8012,38 @@ UniValue test_heirmarker(const UniValue& params, bool fHelp)
return(FinalizeCCTx(0, cp, mtx, myPubkey, 10000, opret));
}
UniValue opreturn_burn(const UniValue& params, bool fHelp)
{
struct CCcontract_info *cp, C; UniValue ret(UniValue::VOBJ);
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");
cp = CCinit(&C, EVAL_PAYMENTS);
if (fHelp || (params.size() != 2))
throw runtime_error("amount to burn, hexstring to send\n");
CAmount nAmount = AmountFromValue(params[0]);
if (nAmount <= 10000)
throw JSONRPCError(RPC_TYPE_ERROR, "must send at least 10000 sat");
std::string strHex = params[1].get_str();
CPubKey myPubkey = pubkey2pk(Mypubkey());
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
int64_t normalInputs = AddNormalinputs(mtx, myPubkey, nAmount, 60);
if (normalInputs < nAmount)
throw runtime_error("not enough normals\n");
CScript opret; uint8_t scripthex[8192];
decode_hex(scripthex,strHex.size()/2,(char *)strHex.c_str());
std::string test;
test.append((char*)scripthex);
std::vector<uint8_t> opretdata(test.begin(), test.end());
opret << OP_RETURN << E_MARSHAL(ss << opretdata);
mtx.vout.push_back(CTxOut(nAmount,opret));
ret.push_back(Pair("hex",FinalizeCCTx(0, cp, mtx, myPubkey, 10000, CScript())));
return(ret);
}
UniValue test_burntx(const UniValue& params, bool fHelp)
{
// make fake token tx:

Loading…
Cancel
Save