Hush Full Node software. We were censored from Github, this is where all development happens now.
https://hush.is
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
7.5 KiB
217 lines
7.5 KiB
#include "cc/eval.h"
|
|
#include "main.h"
|
|
#include "notarisationdb.h"
|
|
|
|
|
|
/* On KMD */
|
|
uint256 GetProofRoot(char* symbol, uint32_t targetCCid, int kmdHeight, std::vector<uint256> &moms, int* assetChainHeight)
|
|
{
|
|
/*
|
|
* 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.
|
|
*/
|
|
if (targetCCid <= 1)
|
|
return uint256();
|
|
|
|
int seenOwnNotarisations = 0;
|
|
|
|
// TODO: test height out of range
|
|
// TODO: Make sure that boundary for moms is notarisation tx not block
|
|
|
|
for (int i=0; i<1440; i++) {
|
|
if (i > kmdHeight) break;
|
|
NotarisationsInBlock notarisations;
|
|
uint256 blockHash = *chainActive[kmdHeight-i]->phashBlock;
|
|
if (!pnotarisations->Read(blockHash, notarisations))
|
|
continue;
|
|
BOOST_FOREACH(Notarisation& nota, notarisations) {
|
|
NotarisationData& data = nota.second;
|
|
if (data.ccId != targetCCid)
|
|
continue;
|
|
if (strcmp(data.symbol, symbol) == 0)
|
|
{
|
|
seenOwnNotarisations++;
|
|
if (seenOwnNotarisations == 2)
|
|
goto end;
|
|
if (seenOwnNotarisations == 1)
|
|
*assetChainHeight = data.height; // TODO: Needed?
|
|
continue; // Don't include own MoMs
|
|
}
|
|
if (seenOwnNotarisations == 1)
|
|
moms.push_back(data.MoM);
|
|
}
|
|
}
|
|
|
|
end:
|
|
return GetMerkleRoot(moms);
|
|
}
|
|
|
|
|
|
/* On KMD */
|
|
std::pair<uint256,MerkleBranch> GetCrossChainProof(uint256 txid, char* targetSymbol,
|
|
uint32_t targetCCid, uint256 notarisationTxid, MerkleBranch assetChainProof)
|
|
{
|
|
/*
|
|
* Here we are given a proof generated by an assetchain A which goes from given txid to
|
|
* an assetchain MoM. We need to go from the notarisationTxid for A to the MoMoM range of the
|
|
* backnotarisation for B (given by kmdheight of notarisation), find the MoM within the MoMs for
|
|
* that range, and finally extend the proof to lead to the MoMoM (proof root).
|
|
*/
|
|
EvalRef eval;
|
|
uint256 MoM = assetChainProof.Exec(txid);
|
|
|
|
// Get a kmd height for given notarisation Txid
|
|
int kmdHeight;
|
|
{
|
|
CTransaction sourceNotarisation;
|
|
uint256 hashBlock;
|
|
CBlockIndex blockIdx;
|
|
if (eval->GetTxConfirmed(notarisationTxid, sourceNotarisation, blockIdx))
|
|
kmdHeight = blockIdx.nHeight;
|
|
else if (eval->GetTxUnconfirmed(notarisationTxid, sourceNotarisation, hashBlock))
|
|
kmdHeight = chainActive.Tip()->nHeight;
|
|
else
|
|
throw std::runtime_error("Notarisation not found");
|
|
}
|
|
|
|
// Get MoMs for kmd height and symbol
|
|
std::vector<uint256> moms;
|
|
int targetChainStartHeight;
|
|
uint256 MoMoM = GetProofRoot(targetSymbol, targetCCid, kmdHeight, moms, &targetChainStartHeight);
|
|
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++)
|
|
if (moms[nIndex] == MoM)
|
|
goto cont;
|
|
throw std::runtime_error("Couldn't find MoM within MoMoM set");
|
|
cont:
|
|
|
|
// Create a branch
|
|
std::vector<uint256> newBranch;
|
|
{
|
|
CBlock fakeBlock;
|
|
for (int i=0; i<moms.size(); i++) {
|
|
CTransaction fakeTx;
|
|
// first value in CTransaction memory is it's hash
|
|
memcpy((void*)&fakeTx, moms[i].begin(), 32);
|
|
fakeBlock.vtx.push_back(fakeTx);
|
|
}
|
|
newBranch = fakeBlock.GetMerkleBranch(nIndex);
|
|
}
|
|
|
|
// Concatenate branches
|
|
MerkleBranch newProof = assetChainProof;
|
|
newProof << MerkleBranch(nIndex, newBranch);
|
|
|
|
// Check proof
|
|
if (newProof.Exec(txid) != MoMoM)
|
|
throw std::runtime_error("Proof check failed");
|
|
|
|
return std::make_pair(uint256(), newProof);
|
|
}
|
|
|
|
|
|
/* On assetchain */
|
|
bool ValidateCrossChainProof(uint256 txid, int notarisationHeight, MerkleBranch proof)
|
|
{
|
|
/*
|
|
* 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.
|
|
*/
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
/*
|
|
* On assetchain
|
|
* in: txid
|
|
* out: pair<notarisationTxHash,merkleBranch>
|
|
*/
|
|
std::pair<uint256,MerkleBranch> GetAssetchainProof(uint256 hash)
|
|
{
|
|
uint256 notarisationHash, MoM,MoMoM; int32_t notarisedHeight, depth; CBlockIndex* blockIndex;
|
|
std::vector<uint256> branch;
|
|
int nIndex,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi;
|
|
|
|
{
|
|
uint256 blockHash;
|
|
CTransaction tx;
|
|
if (!GetTransaction(hash, tx, blockHash, true))
|
|
throw std::runtime_error("cannot find transaction");
|
|
|
|
blockIndex = mapBlockIndex[blockHash];
|
|
|
|
depth = komodo_MoM(¬arisedHeight, &MoM, ¬arisationHash, blockIndex->nHeight,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi);
|
|
|
|
if (!depth)
|
|
throw std::runtime_error("notarisation not found");
|
|
|
|
// index of block in MoM leaves
|
|
nIndex = notarisedHeight - blockIndex->nHeight;
|
|
}
|
|
|
|
// build merkle chain from blocks to MoM
|
|
{
|
|
// since the merkle branch code is tied up in a block class
|
|
// and we want to make a merkle branch for something that isnt transactions
|
|
CBlock fakeBlock;
|
|
for (int i=0; i<depth; i++) {
|
|
uint256 mRoot = chainActive[notarisedHeight - i]->hashMerkleRoot;
|
|
CTransaction fakeTx;
|
|
// first value in CTransaction memory is it's hash
|
|
memcpy((void*)&fakeTx, mRoot.begin(), 32);
|
|
fakeBlock.vtx.push_back(fakeTx);
|
|
}
|
|
branch = fakeBlock.GetMerkleBranch(nIndex);
|
|
|
|
// Check branch
|
|
if (MoM != CBlock::CheckMerkleBranch(blockIndex->hashMerkleRoot, branch, nIndex))
|
|
throw std::runtime_error("Failed merkle block->MoM");
|
|
}
|
|
|
|
// Now get the tx merkle branch
|
|
{
|
|
CBlock block;
|
|
|
|
if (fHavePruned && !(blockIndex->nStatus & BLOCK_HAVE_DATA) && blockIndex->nTx > 0)
|
|
throw std::runtime_error("Block not available (pruned data)");
|
|
|
|
if(!ReadBlockFromDisk(block, blockIndex,1))
|
|
throw std::runtime_error("Can't read block from disk");
|
|
|
|
// Locate the transaction in the block
|
|
int nTxIndex;
|
|
for (nTxIndex = 0; nTxIndex < (int)block.vtx.size(); nTxIndex++)
|
|
if (block.vtx[nTxIndex].GetHash() == hash)
|
|
break;
|
|
|
|
if (nTxIndex == (int)block.vtx.size())
|
|
throw std::runtime_error("Error locating tx in block");
|
|
|
|
std::vector<uint256> txBranch = block.GetMerkleBranch(nTxIndex);
|
|
|
|
// Check branch
|
|
if (block.hashMerkleRoot != CBlock::CheckMerkleBranch(hash, txBranch, nTxIndex))
|
|
throw std::runtime_error("Failed merkle tx->block");
|
|
|
|
// concatenate branches
|
|
nIndex = (nIndex << txBranch.size()) + nTxIndex;
|
|
branch.insert(branch.begin(), txBranch.begin(), txBranch.end());
|
|
}
|
|
|
|
// Check the proof
|
|
if (MoM != CBlock::CheckMerkleBranch(hash, branch, nIndex))
|
|
throw std::runtime_error("Failed validating MoM");
|
|
|
|
// All done!
|
|
CDataStream ssProof(SER_NETWORK, PROTOCOL_VERSION);
|
|
return std::make_pair(notarisationHash, MerkleBranch(nIndex, branch));
|
|
}
|
|
|