From e4f943d86dcc57df25d7843bfca6e2a483d9eda6 Mon Sep 17 00:00:00 2001 From: Scott Sadler Date: Fri, 18 May 2018 19:29:33 -0300 Subject: [PATCH] cross chain rpc methods --- src/Makefile.am | 1 + src/cc/eval.cpp | 8 +- src/cc/eval.h | 6 +- src/cc/import.cpp | 8 +- src/crosschain.cpp | 92 +++++++-------- src/crosschain.h | 11 +- src/importcoin.cpp | 6 +- src/importcoin.h | 15 +-- src/notarisationdb.cpp | 16 ++- src/notarisationdb.h | 4 +- src/rpcblockchain.cpp | 168 ---------------------------- src/rpcclient.cpp | 1 - src/rpccrosschain.cpp | 158 ++++++++++++++++++++++++++ src/rpcserver.cpp | 12 +- src/rpcserver.h | 4 +- src/test-komodo/test_coinimport.cpp | 2 +- src/test-komodo/test_crosschain.cpp | 53 ++------- src/test-komodo/testutils.cpp | 4 - 18 files changed, 264 insertions(+), 305 deletions(-) create mode 100644 src/rpccrosschain.cpp diff --git a/src/Makefile.am b/src/Makefile.am index fa475b4e1..f9b19978b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -279,6 +279,7 @@ libbitcoin_server_a_SOURCES = \ pow.cpp \ rest.cpp \ rpcblockchain.cpp \ + rpccrosschain.cpp \ rpcmining.cpp \ rpcmisc.cpp \ rpcnet.cpp \ diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index 6dc72f2a0..8ed29da9d 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -154,7 +154,7 @@ uint32_t Eval::GetCurrentLedgerID() const /* - * Get MoM from a notarisation tx hash + * Get MoM from a notarisation tx hash (on KMD) */ bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) const { @@ -166,9 +166,11 @@ bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) return true; } -bool Eval::GetNotarisationData(int notarisationHeight, NotarisationData &data, bool verifyCanonical) const +/* + * Get MoMoM corresponding to a notarisation tx hash (on assetchain) + */ +bool Eval::GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const { - return false; } diff --git a/src/cc/eval.h b/src/cc/eval.h index 0625a47e8..2a30bba90 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -72,8 +72,7 @@ public: virtual bool GetBlock(uint256 hash, CBlockIndex& blockIdx) const; virtual int32_t GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const; virtual bool GetNotarisationData(uint256 notarisationHash, NotarisationData &data) const; - virtual bool GetNotarisationData(int notarisationHeight, NotarisationData &data, - bool verifyCanonical) const; + virtual bool GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const; virtual bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const; virtual uint32_t GetCurrentLedgerID() const; }; @@ -228,6 +227,9 @@ public: }; +typedef std::pair TxProof; + + uint256 GetMerkleRoot(const std::vector& vLeaves); diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 9d9daddc0..202d75468 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -15,7 +15,7 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp if (importTx.vout.size() == 0) return Invalid("no-vouts"); // params - MomoProof proof; + TxProof proof; CTransaction burnTx; if (!E_UNMARSHAL(params, ss >> proof; ss >> burnTx)) return Invalid("invalid-params"); @@ -56,11 +56,11 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp // Check proof confirms existance of burnTx { - NotarisationData data(1); - if (!GetNotarisationData(proof.notarisationHeight, data, true)) + uint256 momom; + if (!GetProofRoot(proof.first, momom)) return Invalid("coudnt-load-momom"); - if (data.MoMoM != proof.branch.Exec(burnTx.GetHash())) + if (momom != proof.second.Exec(burnTx.GetHash())) return Invalid("momom-check-fail"); } diff --git a/src/crosschain.cpp b/src/crosschain.cpp index bb2717515..b68b77b33 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -5,29 +5,33 @@ /* On KMD */ -uint256 GetProofRoot(char* symbol, uint32_t targetCCid, int kmdHeight, std::vector &moms, int* assetChainHeight) +uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, + std::vector &moms, uint256 &destNotarisationTxid) { /* * Notaries don't wait for confirmation on KMD before performing a backnotarisation, * but we need a determinable range that will encompass all merkle roots. Include MoMs * including the block height of the last notarisation until the height before the * previous notarisation. + * + * kmdHeight notarisations-0 notarisations-1 + * | |********************| + * > scan backwards > */ - *assetChainHeight = -1; if (targetCCid <= 1) return uint256(); - int seenOwnNotarisations = 0; + if (kmdHeight < 0 || kmdHeight > chainActive.Height()) + return uint256(); - // TODO: test height out of range - // TODO: Make sure that boundary for moms is notarisation tx not block + int seenOwnNotarisations = 0; for (int i=0; i<1440; i++) { if (i > kmdHeight) break; NotarisationsInBlock notarisations; uint256 blockHash = *chainActive[kmdHeight-i]->phashBlock; - if (!pnotarisations->Read(blockHash, notarisations)) + if (!GetBlockNotarisations(blockHash, notarisations)) continue; BOOST_FOREACH(Notarisation& nota, notarisations) { NotarisationData& data = nota.second; @@ -36,32 +40,24 @@ uint256 GetProofRoot(char* symbol, uint32_t targetCCid, int kmdHeight, std::vect if (strcmp(data.symbol, symbol) == 0) { seenOwnNotarisations++; - printf("seenOwnNotarisations:%i\n", seenOwnNotarisations); if (seenOwnNotarisations == 2) goto end; if (seenOwnNotarisations == 1) - *assetChainHeight = data.height; // TODO: Needed? + destNotarisationTxid = nota.first; } - if (seenOwnNotarisations == 1) { + if (seenOwnNotarisations == 1) moms.push_back(data.MoM); - printf("Pushed a MoM@%i:%s\n", kmdHeight-i, data.MoM.GetHex().data()); - } } } end: - printf("GetProofRoot {\n"); - printf(" CC:%i S:%s H:%i\n", targetCCid, symbol, kmdHeight); - for (int i=0; iGetTxConfirmed(notarisationTxid, sourceNotarisation, blockIdx)) + if (eval->GetTxConfirmed(assetChainProof.first, sourceNotarisation, blockIdx)) kmdHeight = blockIdx.nHeight; - else if (eval->GetTxUnconfirmed(notarisationTxid, sourceNotarisation, hashBlock)) + else if (eval->GetTxUnconfirmed(assetChainProof.first, sourceNotarisation, hashBlock)) kmdHeight = chainActive.Tip()->nHeight; else throw std::runtime_error("Notarisation not found"); @@ -88,16 +84,14 @@ MerkleBranch GetCrossChainProof(uint256 txid, char* targetSymbol, // Get MoMs for kmd height and symbol std::vector moms; - int targetChainStartHeight; - printf("Getting Proof Root\n"); - uint256 MoMoM = GetProofRoot(targetSymbol, targetCCid, kmdHeight, moms, &targetChainStartHeight); + uint256 targetChainNotarisationTxid; + uint256 MoMoM = CalculateProofRoot(targetSymbol, targetCCid, kmdHeight, moms, targetChainNotarisationTxid); if (MoMoM.IsNull()) throw std::runtime_error("No MoMs found"); // Find index of source MoM in MoMoM int nIndex; for (nIndex=0; nIndex newBranch; + std::vector vBranch; { CBlock fakeBlock; for (int i=0; i &out) { /* - * Here we are given a notarisation txid, and a proof. - * We go from the notarisation to get the backnotarisation, and verify the proof - * against the MoMoM it contains. + * Here we are given a txid, and a proof. + * We go from the KMD notarisation txid to the backnotarisation, + * then jump to the next backnotarisation, which contains the corresponding MoMoM. */ + Notarisation bn; + if (!GetBackNotarisation(kmdNotarisationTxid, bn)) + return false; + + int npIdx; + struct notarized_checkpoint* np = komodo_npptr_for_height(bn.second.height, &npIdx); + if (!(np = komodo_npptr_at(npIdx+1))) + return false; + + return GetBackNotarisation(np->notarized_desttxid, out); + throw std::runtime_error("Can't get backnotarisation"); } - -struct notarized_checkpoint* komodo_npptr_for_height(int32_t height, int *idx); +struct notarized_checkpoint* komodo_npptr(int32_t height); int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); @@ -155,7 +158,7 @@ int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_ * in: txid * out: pair */ -std::pair GetAssetchainProof(uint256 hash, int &npIdx) +TxProof GetAssetchainProof(uint256 hash) { int nIndex; CBlockIndex* blockIndex; @@ -169,11 +172,10 @@ std::pair GetAssetchainProof(uint256 hash, int &npIdx) throw std::runtime_error("cannot find transaction"); blockIndex = mapBlockIndex[blockHash]; - if (!(np = komodo_npptr_for_height(blockIndex->nHeight, &npIdx))) + if (!(np = komodo_npptr(blockIndex->nHeight))) throw std::runtime_error("notarisation not found"); // index of block in MoM leaves - printf("notarised at: %i\n", np->notarized_height); nIndex = np->notarized_height - blockIndex->nHeight; } diff --git a/src/crosschain.h b/src/crosschain.h index e490fbd0e..64bacb759 100644 --- a/src/crosschain.h +++ b/src/crosschain.h @@ -5,17 +5,18 @@ /* On assetchain */ -std::pair GetAssetchainProof(uint256 hash, int &npIdx); +TxProof GetAssetchainProof(uint256 hash); /* On KMD */ -uint256 GetProofRoot(char* symbol, uint32_t targetCCid, int kmdHeight, std::vector &moms, int* assetChainHeight); +uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, + std::vector &moms, uint256 &destNotarisationTxid); /* On KMD */ -MerkleBranch GetCrossChainProof(uint256 txid, char* targetSymbol, - uint32_t targetCCid, uint256 notarisationTxid, MerkleBranch assetChainProof); +TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid, + const TxProof assetChainProof); /* On assetchain */ -bool ValidateCrossChainProof(uint256 txid, int notarisationHeight, MerkleBranch proof); +bool GetNextBacknotarisation(uint256 txid, std::pair &bn); #endif /* CROSSCHAIN_H */ diff --git a/src/importcoin.cpp b/src/importcoin.cpp index 3874ed7d6..e0c260916 100644 --- a/src/importcoin.cpp +++ b/src/importcoin.cpp @@ -13,7 +13,7 @@ * import. If it doesn't contain this it's invalid. The empty OP_RETURN will hang around * in the UTXO set and the transaction will be detected as a duplicate. */ -CTransaction MakeImportCoinTransaction(const MomoProof proof, const CTransaction burnTx, const std::vector payouts) +CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction burnTx, const std::vector payouts) { std::vector payload = E_MARSHAL(ss << EVAL_IMPORTCOIN; ss << proof; ss << burnTx); @@ -30,7 +30,7 @@ CTxOut MakeBurnOutput(CAmount value, int targetChain, const std::vector } -static bool UnmarshalImportTx(const CTransaction &importTx, MomoProof &proof, CTransaction &burnTx) +static bool UnmarshalImportTx(const CTransaction &importTx, TxProof &proof, CTransaction &burnTx) { CScript scriptSig = importTx.vin[0].scriptSig; auto pc = scriptSig.begin(); @@ -51,7 +51,7 @@ static bool UnmarshalImportTx(const CTransaction &importTx, MomoProof &proof, CT */ CAmount GetCoinImportValue(const CTransaction &tx) { - MomoProof proof; + TxProof proof; CTransaction burnTx; if (UnmarshalImportTx(tx, proof, burnTx)) { return burnTx.vout.size() ? burnTx.vout[0].nValue : 0; diff --git a/src/importcoin.h b/src/importcoin.h index 6f712a1e9..f59851c44 100644 --- a/src/importcoin.h +++ b/src/importcoin.h @@ -8,22 +8,9 @@ #include -class MomoProof -{ -public: - MerkleBranch branch; - int notarisationHeight; - ADD_SERIALIZE_METHODS; - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(branch); - READWRITE(notarisationHeight); - } -}; - CAmount GetCoinImportValue(const CTransaction &tx); -CTransaction MakeImportCoinTransaction(const MomoProof proof, +CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction burnTx, const std::vector payouts); CTxOut MakeBurnOutput(CAmount value, int targetChain, const std::vector payouts); diff --git a/src/notarisationdb.cpp b/src/notarisationdb.cpp index b16968614..7ef5a0cf8 100644 --- a/src/notarisationdb.cpp +++ b/src/notarisationdb.cpp @@ -32,6 +32,18 @@ NotarisationsInBlock GetNotarisationsInBlock(const CBlock &block, int nHeight) } +bool GetBlockNotarisations(uint256 blockHash, NotarisationsInBlock &nibs) +{ + return pnotarisations->Read(blockHash, nibs); +} + + +bool GetBackNotarisation(uint256 notarisationHash, Notarisation &n) +{ + return pnotarisations->Read(notarisationHash, n); +} + + /* * Write an index of KMD notarisation id -> backnotarisation */ @@ -39,9 +51,7 @@ void WriteBackNotarisations(NotarisationsInBlock notarisations) { BOOST_FOREACH(Notarisation &n, notarisations) { - if (n.second.IsBackNotarisation) { + if (n.second.IsBackNotarisation) pnotarisations->Write(n.second.txHash, n); - printf("WriteBackNotarisations {\n m3:%s\n}\n", n.second.MoMoM.GetHex().data()); - } } } diff --git a/src/notarisationdb.h b/src/notarisationdb.h index bd2c15685..0e3d48c00 100644 --- a/src/notarisationdb.h +++ b/src/notarisationdb.h @@ -15,12 +15,12 @@ public: extern NotarisationDB *pnotarisations; - typedef std::pair Notarisation; typedef std::vector NotarisationsInBlock; NotarisationsInBlock GetNotarisationsInBlock(const CBlock &block, int nHeight); - +bool GetBlockNotarisations(uint256 blockHash, NotarisationsInBlock &nibs); +bool GetBackNotarisation(uint256 notarisationHash, Notarisation &n); void WriteBackNotarisations(NotarisationsInBlock notarisations); #endif /* NOTARISATIONDB_H */ diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 99584c7bb..7f191a2b3 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -761,10 +761,6 @@ char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160, //uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n); int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); -int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); -int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height); -struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); -uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); UniValue kvsearch(const UniValue& params, bool fHelp) { @@ -801,170 +797,6 @@ UniValue kvsearch(const UniValue& params, bool fHelp) return ret; } -UniValue allMoMs(const UniValue& params, bool fHelp) -{ - struct komodo_ccdata_entry *allMoMs; uint256 MoMoM; int32_t num,i,kmdstarti,kmdendi; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); - if ( fHelp || params.size() != 2 ) - throw runtime_error("allMoMs kmdstarti kmdendi\n"); - LOCK(cs_main); - kmdstarti = atoi(params[0].get_str().c_str()); - kmdendi = atoi(params[1].get_str().c_str()); - ret.push_back(Pair("kmdstarti",kmdstarti)); - ret.push_back(Pair("kmdendi",kmdendi)); - if ( (allMoMs= komodo_allMoMs(&num,&MoMoM,kmdstarti,kmdendi)) != 0 ) - { - for (i=0; i= height ) - throw runtime_error("calc_MoM illegal height or MoMdepth\n"); - //fprintf(stderr,"height_MoM height.%d\n",height); - MoM = komodo_calcMoM(height,MoMdepth); - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - ret.push_back(Pair("height",height)); - ret.push_back(Pair("MoMdepth",MoMdepth)); - ret.push_back(Pair("MoM",MoM.GetHex())); - return ret; -} - -UniValue height_MoM(const UniValue& params, bool fHelp) -{ - int32_t height,depth,notarized_height,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi; uint256 MoM,MoMoM,kmdtxid; uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); - if ( fHelp || params.size() != 1 ) - throw runtime_error("height_MoM height\n"); - LOCK(cs_main); - height = atoi(params[0].get_str().c_str()); - if ( height <= 0 ) - { - if ( chainActive.Tip() == 0 ) - { - ret.push_back(Pair("error",(char *)"no active chain yet")); - return(ret); - } - height = chainActive.Tip()->nHeight; - } - //fprintf(stderr,"height_MoM height.%d\n",height); - depth = komodo_MoM(¬arized_height,&MoM,&kmdtxid,height,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi); - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - ret.push_back(Pair("height",height)); - ret.push_back(Pair("timestamp",(uint64_t)timestamp)); - if ( depth > 0 ) - { - ret.push_back(Pair("depth",depth)); - ret.push_back(Pair("notarized_height",notarized_height)); - ret.push_back(Pair("MoM",MoM.GetHex())); - ret.push_back(Pair("kmdtxid",kmdtxid.GetHex())); - if ( ASSETCHAINS_SYMBOL[0] != 0 ) - { - ret.push_back(Pair("MoMoM",MoMoM.GetHex())); - ret.push_back(Pair("MoMoMoffset",MoMoMoffset)); - ret.push_back(Pair("MoMoMdepth",MoMoMdepth)); - ret.push_back(Pair("kmdstarti",kmdstarti)); - ret.push_back(Pair("kmdendi",kmdendi)); - } - } else ret.push_back(Pair("error",(char *)"no MoM for height")); - - return ret; -} - -UniValue txMoMproof(const UniValue& params, bool fHelp) -{ - uint256 hash, notarisationHash, MoM,MoMoM; int32_t notarisedHeight, depth; CBlockIndex* blockIndex; - std::vector branch; - int nIndex,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi; - - // parse params and get notarisation data for tx - if ( fHelp || params.size() != 1) - throw runtime_error("txMoMproof needs a txid"); - - hash = uint256S(params[0].get_str()); - - int npIdx; - std::vector proofData = E_MARSHAL(ss << GetAssetchainProof(hash, npIdx)); - return HexStr(proofData); -} - - -UniValue getproofroot(const UniValue& params, bool fHelp) -{ - std::string symbol; - int kmdHeight; - - - // parse params and get notarisation data for tx - if ( fHelp || params.size() != 2) - throw runtime_error("getproofroot needs a symbol and a kmdHeight"); - symbol = params[0].get_str(); - kmdHeight = atoi(params[0].get_str().c_str()); - if (kmdHeight <= 0) - throw runtime_error("Invalid kmdHeight"); - - UniValue ret(UniValue::VOBJ); - return ret; -} - - UniValue minerids(const UniValue& params, bool fHelp) { uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129]; diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 5b3f0c9eb..e421feb4c 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -136,7 +136,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "notaries", 2 }, { "height_MoM", 1 }, { "MoMoMdata", 3 }, - { "allMoMs", 2 }, { "txMoMproof", 1 }, { "minerids", 1 }, { "kvsearch", 1 }, diff --git a/src/rpccrosschain.cpp b/src/rpccrosschain.cpp new file mode 100644 index 000000000..a7bb49d2e --- /dev/null +++ b/src/rpccrosschain.cpp @@ -0,0 +1,158 @@ +#include "amount.h" +#include "chain.h" +#include "chainparams.h" +#include "checkpoints.h" +#include "crosschain.h" +#include "base58.h" +#include "consensus/validation.h" +#include "cc/eval.h" +#include "main.h" +#include "primitives/transaction.h" +#include "rpcserver.h" +#include "sync.h" +#include "util.h" +#include "script/script.h" +#include "script/script_error.h" +#include "script/sign.h" +#include "script/standard.h" + +#include + +#include + +#include + +using namespace std; + +int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); +int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height); +struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); +uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); + + +UniValue assetchainproof(const UniValue& params, bool fHelp) +{ + uint256 hash; + + // parse params and get notarisation data for tx + if ( fHelp || params.size() != 1) + throw runtime_error("assetchainproof needs a txid"); + + hash = uint256S(params[0].get_str()); + + auto proof = GetAssetchainProof(hash); + auto proofData = E_MARSHAL(ss << proof); + return HexStr(proofData); +} + + +UniValue crosschainproof(const UniValue& params, bool fHelp) +{ + + +} + + +UniValue getproofroot(const UniValue& params, bool fHelp) +{ + std::string symbol; + int kmdHeight; + + // parse params and get notarisation data for tx + if ( fHelp || params.size() != 2) + throw runtime_error("getproofroot needs a symbol and a kmdHeight"); + symbol = params[0].get_str(); + kmdHeight = atoi(params[0].get_str().c_str()); + if (kmdHeight <= 0) + throw runtime_error("Invalid kmdHeight"); + + UniValue ret(UniValue::VOBJ); + return ret; +} + + +UniValue height_MoM(const UniValue& params, bool fHelp) +{ + int32_t height,depth,notarized_height,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi; uint256 MoM,MoMoM,kmdtxid; uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); + if ( fHelp || params.size() != 1 ) + throw runtime_error("height_MoM height\n"); + LOCK(cs_main); + height = atoi(params[0].get_str().c_str()); + if ( height <= 0 ) + { + if ( chainActive.Tip() == 0 ) + { + ret.push_back(Pair("error",(char *)"no active chain yet")); + return(ret); + } + height = chainActive.Tip()->nHeight; + } + //fprintf(stderr,"height_MoM height.%d\n",height); + depth = komodo_MoM(¬arized_height,&MoM,&kmdtxid,height,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi); + ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); + ret.push_back(Pair("height",height)); + ret.push_back(Pair("timestamp",(uint64_t)timestamp)); + if ( depth > 0 ) + { + ret.push_back(Pair("depth",depth)); + ret.push_back(Pair("notarized_height",notarized_height)); + ret.push_back(Pair("MoM",MoM.GetHex())); + ret.push_back(Pair("kmdtxid",kmdtxid.GetHex())); + if ( ASSETCHAINS_SYMBOL[0] != 0 ) + { + ret.push_back(Pair("MoMoM",MoMoM.GetHex())); + ret.push_back(Pair("MoMoMoffset",MoMoMoffset)); + ret.push_back(Pair("MoMoMdepth",MoMoMdepth)); + ret.push_back(Pair("kmdstarti",kmdstarti)); + ret.push_back(Pair("kmdendi",kmdendi)); + } + } else ret.push_back(Pair("error",(char *)"no MoM for height")); + + return ret; +} + +UniValue MoMoMdata(const UniValue& params, bool fHelp) +{ + if ( fHelp || params.size() != 3 ) + throw runtime_error("MoMoMdata symbol kmdheight ccid\n"); + UniValue ret(UniValue::VOBJ); + char* symbol = (char *)params[0].get_str().c_str(); + int kmdheight = atoi(params[1].get_str().c_str()); + int ccid = atoi(params[2].get_str().c_str()); + ret.push_back(Pair("coin",symbol)); + ret.push_back(Pair("kmdheight",kmdheight)); + ret.push_back(Pair("ccid", ccid)); + + uint256 destNotarisationTxid; + std::vector moms; + uint256 MoMoM = CalculateProofRoot(symbol, ccid, kmdheight, moms, destNotarisationTxid); + + UniValue valMoms(UniValue::VARR); + for (int i=0; i= height ) + throw runtime_error("calc_MoM illegal height or MoMdepth\n"); + //fprintf(stderr,"height_MoM height.%d\n",height); + MoM = komodo_calcMoM(height,MoMdepth); + ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); + ret.push_back(Pair("height",height)); + ret.push_back(Pair("MoMdepth",MoMdepth)); + ret.push_back(Pair("MoM",MoM.GetHex())); + return ret; +} diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 4eb2270fb..cd579c83c 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -302,15 +302,17 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "paxpending", &paxpending, true }, { "blockchain", "paxprices", &paxprices, true }, { "blockchain", "notaries", ¬aries, true }, - { "blockchain", "allMoMs", &allMoMs, true }, - { "blockchain", "MoMoMdata", &MoMoMdata, true }, - { "blockchain", "calc_MoM", &calc_MoM, true }, - { "blockchain", "height_MoM", &height_MoM, true }, - { "blockchain", "txMoMproof", &txMoMproof, true }, { "blockchain", "minerids", &minerids, true }, { "blockchain", "kvsearch", &kvsearch, true }, { "blockchain", "kvupdate", &kvupdate, true }, + /* Cross chain utilities */ + { "crosschain", "MoMoMdata", &MoMoMdata, true }, + { "crosschain", "calc_MoM", &calc_MoM, true }, + { "crosschain", "height_MoM", &height_MoM, true }, + { "crosschain", "assetchainproof", &assetchainproof, true }, + { "crosschain", "crosschainproof", &crosschainproof, true }, + /* Mining */ { "mining", "getblocktemplate", &getblocktemplate, true }, { "mining", "getmininginfo", &getmininginfo, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index ce412cdb9..7d7ef5d7e 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -312,11 +312,11 @@ extern UniValue z_validateaddress(const UniValue& params, bool fHelp); // in rpc extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp); // in rpcdisclosure.cpp extern UniValue z_validatepaymentdisclosure(const UniValue ¶ms, bool fHelp); // in rpcdisclosure.cpp -extern UniValue allMoMs(const UniValue& params, bool fHelp); extern UniValue MoMoMdata(const UniValue& params, bool fHelp); extern UniValue calc_MoM(const UniValue& params, bool fHelp); extern UniValue height_MoM(const UniValue& params, bool fHelp); -extern UniValue txMoMproof(const UniValue& params, bool fHelp); +extern UniValue assetchainproof(const UniValue& params, bool fHelp); +extern UniValue crosschainproof(const UniValue& params, bool fHelp); extern UniValue notaries(const UniValue& params, bool fHelp); extern UniValue minerids(const UniValue& params, bool fHelp); extern UniValue kvsearch(const UniValue& params, bool fHelp); diff --git a/src/test-komodo/test_coinimport.cpp b/src/test-komodo/test_coinimport.cpp index fe2f3ce96..81ccd71d7 100644 --- a/src/test-komodo/test_coinimport.cpp +++ b/src/test-komodo/test_coinimport.cpp @@ -28,7 +28,7 @@ class TestCoinImport : public ::testing::Test, public Eval { public: CMutableTransaction burnTx; std::vector payouts; - MomoProof proof; + TxProof proof; uint256 MoMoM; CMutableTransaction importTx; uint32_t chainId = 2; diff --git a/src/test-komodo/test_crosschain.cpp b/src/test-komodo/test_crosschain.cpp index ebf52fa13..6ff261247 100644 --- a/src/test-komodo/test_crosschain.cpp +++ b/src/test-komodo/test_crosschain.cpp @@ -28,7 +28,6 @@ extern uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); -extern struct notarized_checkpoint *komodo_npptr_at(int idx); /* @@ -109,8 +108,6 @@ TEST_F(TestCrossChain, testCreateAndValidateImportProof) mtx.vin[0].scriptSig << getSig(mtx, inputTx.vout[0].scriptPubKey); acceptTxFail(CTransaction(mtx)); - printf("accept %snotarisation: %s\n", data.IsBackNotarisation ? "back" : "", - mtx.GetHash().GetHex().data()); return mtx.GetHash(); }; @@ -139,34 +136,13 @@ TEST_F(TestCrossChain, testCreateAndValidateImportProof) * Generate proof */ uint256 txid = blocks[7].vtx[0].GetHash(); - int npIdx; - std::pair proof = GetAssetchainProof(txid, npIdx); + TxProof proof = GetAssetchainProof(txid); SendIPC(E_MARSHAL(ss << txid; ss << proof)); + E_UNMARSHAL(RecvIPC(), ss >> proof); - /* - * Test proof - */ - std::pair ccProof; - E_UNMARSHAL(RecvIPC(), ss >> ccProof); - - // Now we have the branch with the hash of the notarisation on KMD - // What we'd like is the notarised height on PIZZA so we can go forward - // to the next backnotarisation, and then to the next, to get the M3. - uint256 result = ccProof.second.Exec(txid); - printf("result m3: %s\n", result.GetHex().data()); - struct notarized_checkpoint* np = komodo_npptr_at(npIdx+1); - std::pair b; - pnotarisations->Read(np->notarized_desttxid, b); - printf("m3@1: %s\n", b.second.MoMoM.GetHex().data()); - - { - printf("RunTestAssetChain.test {\n txid: %s\n momom: %s\n", txid.GetHex().data(), b.second.MoMoM.GetHex().data()); - printf(" idx: %i\n", ccProof.second.nIndex); - for (int i=0; i bn; + if (!GetNextBacknotarisation(proof.first, bn)) return 1; + return proof.second.Exec(txid) == bn.second.MoMoM ? 0 : 1; }; auto RunTestKmd = [&] () @@ -186,10 +162,9 @@ TEST_F(TestCrossChain, testCreateAndValidateImportProof) n.txHash = RecordNotarisation(blocks[height].vtx[0], n); { std::vector moms; - int assetChainHeight; - n.MoMoM = GetProofRoot(n.symbol, 2, height, moms, &assetChainHeight); + uint256 destNotarisationTxid; + n.MoMoM = CalculateProofRoot(n.symbol, 2, height, moms, destNotarisationTxid); } - printf("RunTestKmd {\n kmdnotid:%s\n momom:%s\n}\n", n.txHash.GetHex().data(), n.MoMoM.GetHex().data()); n.IsBackNotarisation = 1; SendIPC(E_MARSHAL(ss << n)); } @@ -197,11 +172,11 @@ TEST_F(TestCrossChain, testCreateAndValidateImportProof) /* * Extend proof */ - std::pair proof; + TxProof proof; uint256 txid; // Extend proof to MoMoM assert(E_UNMARSHAL(RecvIPC(), ss >> txid; ss >> proof)); - proof.second = GetCrossChainProof(txid, (char*)"PIZZA", 2, proof.first, proof.second); + proof = GetCrossChainProof(txid, (char*)"PIZZA", 2, proof); SendIPC(E_MARSHAL(ss << proof)); }; @@ -217,20 +192,12 @@ TEST_F(TestCrossChain, testCreateAndValidateImportProof) else { assert(0 == zmq_bind(socket, endpoint)); RunTestKmd(); - int returnStatus; + int returnStatus; waitpid(childPid, &returnStatus, 0); unlink("tmpKomodoTestCrossChainSock"); ASSERT_EQ(0, returnStatus); } - - /* - * We can now prove a tx from A on A, via a merkle root backpropagated from KMD. - * - * The transaction that we'll try to prove is the coinbase from the 3rd block. - * We should be able to start with only that transaction ID, and generate a merkle - * proof. - */ } diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index a6a2b8def..e8b57b6b9 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -72,13 +72,9 @@ void generateBlock(CBlock *block) SetMockTime(nMockTime+=100); // CreateNewBlock can fail if not enough time passes - char symbolPrefix = ASSETCHAINS_SYMBOL[0]; - //ASSETCHAINS_SYMBOL[0] = 0; // generate block fails otherwise - try { UniValue out = generate(params, false); blockId.SetHex(out[0].getValStr()); - ASSETCHAINS_SYMBOL[0] = symbolPrefix; if (block) ASSERT_TRUE(ReadBlockFromDisk(*block, mapBlockIndex[blockId], false)); } catch (const UniValue& e) { FAIL() << "failed to create block: " << e.write().data();