|
|
@ -1,3 +1,6 @@ |
|
|
|
// Copyright (c) 2019-2020 The Hush developers
|
|
|
|
// Distributed under the GPLv3 software license, see the accompanying
|
|
|
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
|
|
/******************************************************************************
|
|
|
|
* Copyright © 2014-2019 The SuperNET Developers. * |
|
|
|
* * |
|
|
@ -19,13 +22,12 @@ |
|
|
|
#include "main.h" |
|
|
|
#include "notarizationdb.h" |
|
|
|
#include "merkleblock.h" |
|
|
|
|
|
|
|
#include "cc/CCinclude.h" |
|
|
|
|
|
|
|
/*
|
|
|
|
* The crosschain workflow. |
|
|
|
* |
|
|
|
* 3 chains, A, B, and KMD. We would like to prove TX on B. |
|
|
|
* 3 chains, A, B, and HUSH. We would like to prove TX on B. |
|
|
|
* There is a notarisation, nA0, which will include TX via an MoM. |
|
|
|
* The notarisation nA0 must fall between 2 notarisations of B, |
|
|
|
* ie, nB0 and nB1. An MoMoM including this range is propagated to |
|
|
@ -33,7 +35,7 @@ |
|
|
|
* |
|
|
|
* A: TX bnA0 |
|
|
|
* \ / |
|
|
|
* KMD: nB0 nA0 nB1 nB2 |
|
|
|
* HUSH: nB0 nA0 nB1 nB2 |
|
|
|
* \ \ \ |
|
|
|
* B: bnB0 bnB1 bnB2 |
|
|
|
*/ |
|
|
@ -42,21 +44,21 @@ |
|
|
|
// because it might be disconnecting blocks at the same time.
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: this assumes a blocktime of 60 seconds and limiting of 1 day of blocks
|
|
|
|
int NOTARISATION_SCAN_LIMIT_BLOCKS = 1440; |
|
|
|
CBlockIndex *komodo_getblockindex(uint256 hash); |
|
|
|
|
|
|
|
|
|
|
|
/* On KMD */ |
|
|
|
uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeight, |
|
|
|
/* On HUSH */ |
|
|
|
uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int hushHeight, |
|
|
|
std::vector<uint256> &moms, uint256 &destNotarizationTxid) |
|
|
|
{ |
|
|
|
/*
|
|
|
|
* Notaries don't wait for confirmation on KMD before performing a backnotarisation, |
|
|
|
* Notaries don't wait for confirmation on HUSH 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 |
|
|
|
* hushHeight notarisations-0 notarisations-1 |
|
|
|
* *********************| |
|
|
|
* > scan backwards > |
|
|
|
*/ |
|
|
@ -64,7 +66,7 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh |
|
|
|
if (targetCCid < 2) |
|
|
|
return uint256(); |
|
|
|
|
|
|
|
if (kmdHeight < 0 || kmdHeight > chainActive.Height()) |
|
|
|
if (hushHeight < 0 || hushHeight > chainActive.Height()) |
|
|
|
return uint256(); |
|
|
|
|
|
|
|
int seenOwnNotarizations = 0, i = 0; |
|
|
@ -73,9 +75,9 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh |
|
|
|
std::set<uint256> tmp_moms; |
|
|
|
|
|
|
|
for (i=0; i<NOTARISATION_SCAN_LIMIT_BLOCKS; i++) { |
|
|
|
if (i > kmdHeight) break; |
|
|
|
if (i > hushHeight) break; |
|
|
|
NotarizationsInBlock notarisations; |
|
|
|
uint256 blockHash = *chainActive[kmdHeight-i]->phashBlock; |
|
|
|
uint256 blockHash = *chainActive[hushHeight-i]->phashBlock; |
|
|
|
if (!GetBlockNotarizations(blockHash, notarisations)) |
|
|
|
continue; |
|
|
|
|
|
|
@ -144,31 +146,31 @@ int ScanNotarizationsFromHeight(int nHeight, const IsTarget f, Notarization &fou |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* On KMD */ |
|
|
|
/* On HUSH */ |
|
|
|
TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_t targetCCid, |
|
|
|
const TxProof assetChainProof, int32_t offset) |
|
|
|
{ |
|
|
|
/*
|
|
|
|
* 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 |
|
|
|
* backnotarisation for B (given by hushHeight 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.second.Exec(txid); |
|
|
|
|
|
|
|
// Get a kmd height for given notarisation Txid
|
|
|
|
int kmdHeight; |
|
|
|
// Get a Hush height for given notarisation Txid
|
|
|
|
int hushHeight; |
|
|
|
{ |
|
|
|
CTransaction sourceNotarization; |
|
|
|
uint256 hashBlock; |
|
|
|
CBlockIndex blockIdx; |
|
|
|
if (!eval->GetTxConfirmed(assetChainProof.first, sourceNotarization, blockIdx)) |
|
|
|
throw std::runtime_error("Notarization not found"); |
|
|
|
kmdHeight = blockIdx.GetHeight(); |
|
|
|
hushHeight = blockIdx.GetHeight(); |
|
|
|
} |
|
|
|
|
|
|
|
// We now have a kmdHeight of the notarisation from chain A. So we know that a MoM exists
|
|
|
|
// We now have a hushHeight of the notarisation from chain A. So we know that a MoM exists
|
|
|
|
// at that height.
|
|
|
|
// If we call CalculateProofRoot with that height, it'll scan backwards, until it finds
|
|
|
|
// a notarisation from B, and it might not include our notarisation from A
|
|
|
@ -178,17 +180,17 @@ TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_ |
|
|
|
auto isTarget = [&](Notarization ¬a) { |
|
|
|
return strcmp(nota.second.symbol, targetSymbol) == 0; |
|
|
|
}; |
|
|
|
kmdHeight = ScanNotarizationsFromHeight(kmdHeight, isTarget, nota); |
|
|
|
if (!kmdHeight) |
|
|
|
hushHeight = ScanNotarizationsFromHeight(hushHeight, isTarget, nota); |
|
|
|
if (!hushHeight) |
|
|
|
throw std::runtime_error("Cannot find notarisation for target inclusive of source"); |
|
|
|
|
|
|
|
if ( offset != 0 ) |
|
|
|
kmdHeight += offset; |
|
|
|
hushHeight += offset; |
|
|
|
|
|
|
|
// Get MoMs for kmd height and symbol
|
|
|
|
// Get MoMs for Hush height and symbol
|
|
|
|
std::vector<uint256> moms; |
|
|
|
uint256 targetChainNotarizationTxid; |
|
|
|
uint256 MoMoM = CalculateProofRoot(targetSymbol, targetCCid, kmdHeight, moms, targetChainNotarizationTxid); |
|
|
|
uint256 MoMoM = CalculateProofRoot(targetSymbol, targetCCid, hushHeight, moms, targetChainNotarizationTxid); |
|
|
|
if (MoMoM.IsNull()) |
|
|
|
throw std::runtime_error("No MoMs found"); |
|
|
|
|
|
|
@ -257,15 +259,15 @@ bool IsSameAssetChain(const Notarization ¬a) { |
|
|
|
|
|
|
|
|
|
|
|
/* On assetchain */ |
|
|
|
bool GetNextBacknotarisation(uint256 kmdNotarizationTxid, Notarization &out) |
|
|
|
bool GetNextBacknotarisation(uint256 hushNotarizationTxid, Notarization &out) |
|
|
|
{ |
|
|
|
/*
|
|
|
|
* Here we are given a txid, and a proof. |
|
|
|
* We go from the KMD notarisation txid to the backnotarisation, |
|
|
|
* We go from the HUSH notarisation txid to the backnotarisation, |
|
|
|
* then jump to the next backnotarisation, which contains the corresponding MoMoM. |
|
|
|
*/ |
|
|
|
Notarization bn; |
|
|
|
if (!GetBackNotarization(kmdNotarizationTxid, bn)) |
|
|
|
if (!GetBackNotarization(hushNotarizationTxid, bn)) |
|
|
|
return false; |
|
|
|
|
|
|
|
// Need to get block height of that backnotarisation
|
|
|
@ -281,17 +283,17 @@ bool GetNextBacknotarisation(uint256 kmdNotarizationTxid, Notarization &out) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CheckMoMoM(uint256 kmdNotarizationHash, uint256 momom) |
|
|
|
bool CheckMoMoM(uint256 hushNotarizationHash, uint256 momom) |
|
|
|
{ |
|
|
|
/*
|
|
|
|
* Given a notarisation hash and an MoMoM. Backnotarisations may arrive out of order |
|
|
|
* or multiple in the same block. So dereference the notarisation hash to the corresponding |
|
|
|
* backnotarisation and scan around the kmdheight to see if the MoMoM is a match. |
|
|
|
* backnotarisation and scan around the hushheight to see if the MoMoM is a match. |
|
|
|
* This is a sledgehammer approach... |
|
|
|
*/ |
|
|
|
|
|
|
|
Notarization bn; |
|
|
|
if (!GetBackNotarization(kmdNotarizationHash, bn)) |
|
|
|
if (!GetBackNotarization(hushNotarizationHash, bn)) |
|
|
|
return false; |
|
|
|
|
|
|
|
// Need to get block height of that backnotarisation
|
|
|
|