Browse Source

cross chain rpc methods

pull/4/head
Scott Sadler 6 years ago
parent
commit
e4f943d86d
  1. 1
      src/Makefile.am
  2. 8
      src/cc/eval.cpp
  3. 6
      src/cc/eval.h
  4. 8
      src/cc/import.cpp
  5. 92
      src/crosschain.cpp
  6. 11
      src/crosschain.h
  7. 6
      src/importcoin.cpp
  8. 15
      src/importcoin.h
  9. 16
      src/notarisationdb.cpp
  10. 4
      src/notarisationdb.h
  11. 168
      src/rpcblockchain.cpp
  12. 1
      src/rpcclient.cpp
  13. 158
      src/rpccrosschain.cpp
  14. 12
      src/rpcserver.cpp
  15. 4
      src/rpcserver.h
  16. 2
      src/test-komodo/test_coinimport.cpp
  17. 53
      src/test-komodo/test_crosschain.cpp
  18. 4
      src/test-komodo/testutils.cpp

1
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 \

8
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;
}

6
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<uint256,MerkleBranch> TxProof;
uint256 GetMerkleRoot(const std::vector<uint256>& vLeaves);

8
src/cc/import.cpp

@ -15,7 +15,7 @@ bool Eval::ImportCoin(const std::vector<uint8_t> 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<uint8_t> 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");
}

92
src/crosschain.cpp

@ -5,29 +5,33 @@
/* On KMD */
uint256 GetProofRoot(char* symbol, uint32_t targetCCid, int kmdHeight, std::vector<uint256> &moms, int* assetChainHeight)
uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight,
std::vector<uint256> &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; i<moms.size(); i++) printf(" %s", moms[i].GetHex().data());
printf("\n R:%s\n", GetMerkleRoot(moms).GetHex().data());
printf("}\n");
return GetMerkleRoot(moms);
}
/* 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)
{
/*
* Here we are given a proof generated by an assetchain A which goes from given txid to
@ -70,7 +66,7 @@ MerkleBranch GetCrossChainProof(uint256 txid, char* targetSymbol,
* that range, and finally extend the proof to lead to the MoMoM (proof root).
*/
EvalRef eval;
uint256 MoM = assetChainProof.Exec(txid);
uint256 MoM = assetChainProof.second.Exec(txid);
// Get a kmd height for given notarisation Txid
int kmdHeight;
@ -78,9 +74,9 @@ MerkleBranch GetCrossChainProof(uint256 txid, char* targetSymbol,
CTransaction sourceNotarisation;
uint256 hashBlock;
CBlockIndex blockIdx;
if (eval->GetTxConfirmed(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<uint256> 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<moms.size(); nIndex++) {
printf("findMoM: %s == %s\n", moms[nIndex].GetHex().data(), MoM.GetHex().data());
if (moms[nIndex] == MoM)
goto cont;
}
@ -105,7 +99,7 @@ MerkleBranch GetCrossChainProof(uint256 txid, char* targetSymbol,
cont:
// Create a branch
std::vector<uint256> newBranch;
std::vector<uint256> vBranch;
{
CBlock fakeBlock;
for (int i=0; i<moms.size(); i++) {
@ -114,39 +108,48 @@ cont:
memcpy((void*)&fakeTx, moms[i].begin(), 32);
fakeBlock.vtx.push_back(fakeTx);
}
newBranch = fakeBlock.GetMerkleBranch(nIndex);
vBranch = fakeBlock.GetMerkleBranch(nIndex);
}
// Concatenate branches
MerkleBranch newProof = assetChainProof;
newProof << MerkleBranch(nIndex, newBranch);
MerkleBranch newBranch = assetChainProof.second;
newBranch << MerkleBranch(nIndex, vBranch);
// Check proof
printf("GetCrossChainProof {\n txid: %s\n momom: %s\n", txid.GetHex().data(), MoMoM.GetHex().data());
printf(" idx: %i\n", newProof.nIndex);
for (int i=0; i<newProof.branch.size(); i++) printf(" %s", newProof.branch[i].GetHex().data());
printf("\n}\n");
if (newProof.Exec(txid) != MoMoM)
if (newBranch.Exec(txid) != MoMoM)
throw std::runtime_error("Proof check failed");
return newProof;
return std::make_pair(targetChainNotarisationTxid,newBranch);
}
struct notarized_checkpoint *komodo_npptr_at(int idx);
struct notarized_checkpoint *komodo_npptr_for_height(int32_t height, int *idx);
/* On assetchain */
bool ValidateCrossChainProof(uint256 txid, int notarisationHeight, MerkleBranch proof)
bool GetNextBacknotarisation(uint256 kmdNotarisationTxid, std::pair<uint256,NotarisationData> &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<notarisationTxHash,merkleBranch>
*/
std::pair<uint256,MerkleBranch> GetAssetchainProof(uint256 hash, int &npIdx)
TxProof GetAssetchainProof(uint256 hash)
{
int nIndex;
CBlockIndex* blockIndex;
@ -169,11 +172,10 @@ std::pair<uint256,MerkleBranch> 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;
}

11
src/crosschain.h

@ -5,17 +5,18 @@
/* On assetchain */
std::pair<uint256,MerkleBranch> GetAssetchainProof(uint256 hash, int &npIdx);
TxProof GetAssetchainProof(uint256 hash);
/* On KMD */
uint256 GetProofRoot(char* symbol, uint32_t targetCCid, int kmdHeight, std::vector<uint256> &moms, int* assetChainHeight);
uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight,
std::vector<uint256> &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<uint256,NotarisationData> &bn);
#endif /* CROSSCHAIN_H */

6
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<CTxOut> payouts)
CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction burnTx, const std::vector<CTxOut> payouts)
{
std::vector<uint8_t> payload =
E_MARSHAL(ss << EVAL_IMPORTCOIN; ss << proof; ss << burnTx);
@ -30,7 +30,7 @@ CTxOut MakeBurnOutput(CAmount value, int targetChain, const std::vector<CTxOut>
}
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;

15
src/importcoin.h

@ -8,22 +8,9 @@
#include <cryptoconditions.h>
class MomoProof
{
public:
MerkleBranch branch;
int notarisationHeight;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
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<CTxOut> payouts);
CTxOut MakeBurnOutput(CAmount value, int targetChain, const std::vector<CTxOut> payouts);

16
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());
}
}
}

4
src/notarisationdb.h

@ -15,12 +15,12 @@ public:
extern NotarisationDB *pnotarisations;
typedef std::pair<uint256,NotarisationData> Notarisation;
typedef std::vector<Notarisation> 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 */

168
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<num; i++)
{
UniValue item(UniValue::VOBJ);
item.push_back(Pair("MoM",allMoMs[i].MoM.ToString()));
item.push_back(Pair("coin",allMoMs[i].symbol));
item.push_back(Pair("notarized_height",allMoMs[i].notarized_height));
item.push_back(Pair("kmdheight",allMoMs[i].kmdheight));
item.push_back(Pair("txi",allMoMs[i].txi));
a.push_back(item);
}
ret.push_back(Pair("MoMs",a));
ret.push_back(Pair("MoMoM",MoMoM.ToString()));
ret.push_back(Pair("MoMoMdepth",(int)num));
free(allMoMs);
}
return(ret);
}
UniValue MoMoMdata(const UniValue& params, bool fHelp)
{
char *symbol,hexstr[16384+1]; struct komodo_ccdataMoMoM mdata; int32_t i,kmdheight,notarized_height; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR);
if ( fHelp || params.size() != 3 )
throw runtime_error("MoMoMdata symbol kmdheight notarized_height\n");
LOCK(cs_main);
symbol = (char *)params[0].get_str().c_str();
kmdheight = atoi(params[1].get_str().c_str());
notarized_height = atoi(params[2].get_str().c_str());
ret.push_back(Pair("coin",symbol));
ret.push_back(Pair("kmdheight",kmdheight));
ret.push_back(Pair("notarized_height",notarized_height));
memset(&mdata,0,sizeof(mdata));
if ( komodo_MoMoMdata(hexstr,sizeof(hexstr),&mdata,symbol,kmdheight,notarized_height) == 0 )
{
ret.push_back(Pair("kmdstarti",mdata.kmdstarti));
ret.push_back(Pair("kmdendi",mdata.kmdendi));
ret.push_back(Pair("MoMoM",mdata.MoMoM.ToString()));
ret.push_back(Pair("MoMoMdepth",mdata.MoMoMdepth));
ret.push_back(Pair("numnotarizations",mdata.numpairs));
if ( mdata.pairs != 0 )
{
//fprintf(stderr,"mdata.pairs free %p, numpairs.%d\n",mdata.pairs,mdata.numpairs);
for (i=0; i<mdata.numpairs; i++)
{
UniValue item(UniValue::VOBJ);
item.push_back(Pair("height",(int)mdata.pairs[i].notarized_height));
item.push_back(Pair("MoMoMoffset",(int)mdata.pairs[i].MoMoMoffset));
a.push_back(item);
}
free(mdata.pairs);
}
ret.push_back(Pair("notarizations",a));
ret.push_back(Pair("data",hexstr));
} else ret.push_back(Pair("error","cant calculate MoMoM"));
return(ret);
}
UniValue calc_MoM(const UniValue& params, bool fHelp)
{
int32_t height,MoMdepth; uint256 MoM; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR);
if ( fHelp || params.size() != 2 )
throw runtime_error("calc_MoM height MoMdepth\n");
LOCK(cs_main);
height = atoi(params[0].get_str().c_str());
MoMdepth = atoi(params[1].get_str().c_str());
if ( height <= 0 || MoMdepth <= 0 || MoMdepth >= 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(&notarized_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<uint256> 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<uint8_t> 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];

1
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 },

158
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 <stdint.h>
#include <univalue.h>
#include <regex>
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(&notarized_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<uint256> moms;
uint256 MoMoM = CalculateProofRoot(symbol, ccid, kmdheight, moms, destNotarisationTxid);
UniValue valMoms(UniValue::VARR);
for (int i=0; i<moms.size(); i++) valMoms.push_back(moms[i].GetHex());
ret.push_back(Pair("MoMs", valMoms));
ret.push_back(Pair("notarization_hash", destNotarisationTxid.GetHex()));
ret.push_back(Pair("MoMoM", MoMoM.GetHex()));
auto vmomomdata = E_MARSHAL(ss << MoMoM; ss << ((uint32_t)0));
ret.push_back(Pair("data", HexStr(vmomomdata)));
return ret;
}
UniValue calc_MoM(const UniValue& params, bool fHelp)
{
int32_t height,MoMdepth; uint256 MoM; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR);
if ( fHelp || params.size() != 2 )
throw runtime_error("calc_MoM height MoMdepth\n");
LOCK(cs_main);
height = atoi(params[0].get_str().c_str());
MoMdepth = atoi(params[1].get_str().c_str());
if ( height <= 0 || MoMdepth <= 0 || MoMdepth >= 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;
}

12
src/rpcserver.cpp

@ -302,15 +302,17 @@ static const CRPCCommand vRPCCommands[] =
{ "blockchain", "paxpending", &paxpending, true },
{ "blockchain", "paxprices", &paxprices, true },
{ "blockchain", "notaries", &notaries, 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 },

4
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 &params, 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);

2
src/test-komodo/test_coinimport.cpp

@ -28,7 +28,7 @@ class TestCoinImport : public ::testing::Test, public Eval {
public:
CMutableTransaction burnTx;
std::vector<CTxOut> payouts;
MomoProof proof;
TxProof proof;
uint256 MoMoM;
CMutableTransaction importTx;
uint32_t chainId = 2;

53
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<uint256,MerkleBranch> proof = GetAssetchainProof(txid, npIdx);
TxProof proof = GetAssetchainProof(txid);
SendIPC(E_MARSHAL(ss << txid; ss << proof));
E_UNMARSHAL(RecvIPC(), ss >> proof);
/*
* Test proof
*/
std::pair<uint256,MerkleBranch> 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<uint256,NotarisationData> 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<ccProof.second.branch.size(); i++) printf(" %s", ccProof.second.branch[i].GetHex().data());
printf("\n}\n");
}
return b.second.MoMoM == result ? 0 : 1;
std::pair<uint256,NotarisationData> 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<uint256> 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<uint256,MerkleBranch> 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.
*/
}

4
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();

Loading…
Cancel
Save