2023-12-31 01:00:00 +01:00
// Copyright (c) 2017-2024 The Dash Core developers
2018-04-09 10:35:43 +02:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2021-10-25 15:55:34 +02:00
# include <evo/simplifiedmns.h>
2020-03-19 23:46:56 +01:00
# include <evo/cbtx.h>
# include <core_io.h>
2023-12-04 19:04:51 +01:00
# include <deploymentstatus.h>
2020-03-19 23:46:56 +01:00
# include <evo/deterministicmns.h>
2021-10-02 19:32:24 +02:00
# include <llmq/blockprocessor.h>
# include <llmq/commitment.h>
2023-07-10 18:23:09 +02:00
# include <llmq/quorums.h>
2023-07-24 20:42:13 +02:00
# include <node/blockstorage.h>
2020-03-19 23:46:56 +01:00
# include <evo/specialtx.h>
2018-04-09 10:35:43 +02:00
2021-04-16 05:41:16 +02:00
# include <pubkey.h>
# include <serialize.h>
# include <version.h>
2020-03-19 23:46:56 +01:00
# include <base58.h>
# include <chainparams.h>
# include <consensus/merkle.h>
# include <univalue.h>
# include <validation.h>
2022-01-24 15:20:50 +01:00
# include <key_io.h>
2023-02-20 11:12:12 +01:00
# include <util/underlying.h>
2023-07-10 18:23:09 +02:00
# include <util/enumerate.h>
2018-04-09 10:35:43 +02:00
CSimplifiedMNListEntry : : CSimplifiedMNListEntry ( const CDeterministicMN & dmn ) :
proRegTxHash ( dmn . proTxHash ) ,
2018-11-23 10:40:46 +01:00
confirmedHash ( dmn . pdmnState - > confirmedHash ) ,
2018-04-09 10:35:43 +02:00
service ( dmn . pdmnState - > addr ) ,
2018-10-21 21:45:16 +02:00
pubKeyOperator ( dmn . pdmnState - > pubKeyOperator ) ,
2018-04-09 10:35:43 +02:00
keyIDVoting ( dmn . pdmnState - > keyIDVoting ) ,
2022-06-24 20:35:23 +02:00
isValid ( ! dmn . pdmnState - > IsBanned ( ) ) ,
2023-08-22 22:19:48 +02:00
platformHTTPPort ( dmn . pdmnState - > platformHTTPPort ) ,
platformNodeID ( dmn . pdmnState - > platformNodeID ) ,
2022-06-24 20:35:23 +02:00
scriptPayout ( dmn . pdmnState - > scriptPayout ) ,
2023-02-14 19:48:33 +01:00
scriptOperatorPayout ( dmn . pdmnState - > scriptOperatorPayout ) ,
2023-06-11 19:29:00 +02:00
nVersion ( dmn . pdmnState - > nVersion = = CProRegTx : : LEGACY_BLS_VERSION ? LEGACY_BLS_VERSION : BASIC_BLS_VERSION ) ,
2023-08-22 22:19:48 +02:00
nType ( dmn . nType )
2018-04-09 10:35:43 +02:00
{
}
uint256 CSimplifiedMNListEntry : : CalcHash ( ) const
{
CHashWriter hw ( SER_GETHASH , CLIENT_VERSION ) ;
hw < < * this ;
return hw . GetHash ( ) ;
}
std : : string CSimplifiedMNListEntry : : ToString ( ) const
{
2022-06-24 20:35:23 +02:00
CTxDestination dest ;
std : : string payoutAddress = " unknown " ;
std : : string operatorPayoutAddress = " none " ;
if ( ExtractDestination ( scriptPayout , dest ) ) {
payoutAddress = EncodeDestination ( dest ) ;
}
if ( ExtractDestination ( scriptOperatorPayout , dest ) ) {
operatorPayoutAddress = EncodeDestination ( dest ) ;
}
2023-06-11 09:00:10 +02:00
return strprintf ( " CSimplifiedMNListEntry(nVersion=%d, nType=%d, proRegTxHash=%s, confirmedHash=%s, service=%s, pubKeyOperator=%s, votingAddress=%s, isValid=%d, payoutAddress=%s, operatorPayoutAddress=%s, platformHTTPPort=%d, platformNodeID=%s) " ,
2024-05-18 06:00:54 +02:00
nVersion , ToUnderlying ( nType ) , proRegTxHash . ToString ( ) , confirmedHash . ToString ( ) , service . ToString ( ) , pubKeyOperator . ToString ( ) , EncodeDestination ( PKHash ( keyIDVoting ) ) , isValid , payoutAddress , operatorPayoutAddress , platformHTTPPort , platformNodeID . ToString ( ) ) ;
2018-04-09 10:35:43 +02:00
}
2023-09-29 19:56:52 +02:00
UniValue CSimplifiedMNListEntry : : ToJson ( bool extended ) const
2018-04-09 10:35:43 +02:00
{
2023-09-29 19:56:52 +02:00
UniValue obj ;
2018-04-09 10:35:43 +02:00
obj . setObject ( ) ;
2023-06-11 09:00:10 +02:00
obj . pushKV ( " nVersion " , nVersion ) ;
2023-06-17 17:50:26 +02:00
obj . pushKV ( " nType " , ToUnderlying ( nType ) ) ;
2020-06-18 11:17:23 +02:00
obj . pushKV ( " proRegTxHash " , proRegTxHash . ToString ( ) ) ;
obj . pushKV ( " confirmedHash " , confirmedHash . ToString ( ) ) ;
2024-05-18 06:00:54 +02:00
obj . pushKV ( " service " , service . ToString ( ) ) ;
2023-06-11 19:29:00 +02:00
obj . pushKV ( " pubKeyOperator " , pubKeyOperator . ToString ( ) ) ;
2019-05-09 18:04:52 +02:00
obj . pushKV ( " votingAddress " , EncodeDestination ( PKHash ( keyIDVoting ) ) ) ;
2020-06-18 11:17:23 +02:00
obj . pushKV ( " isValid " , isValid ) ;
2023-08-17 21:01:12 +02:00
if ( nType = = MnType : : Evo ) {
2023-02-14 19:48:33 +01:00
obj . pushKV ( " platformHTTPPort " , platformHTTPPort ) ;
obj . pushKV ( " platformNodeID " , platformNodeID . ToString ( ) ) ;
}
2022-06-24 20:35:23 +02:00
2023-09-29 19:56:52 +02:00
if ( extended ) {
CTxDestination dest ;
if ( ExtractDestination ( scriptPayout , dest ) ) {
obj . pushKV ( " payoutAddress " , EncodeDestination ( dest ) ) ;
}
if ( ExtractDestination ( scriptOperatorPayout , dest ) ) {
obj . pushKV ( " operatorPayoutAddress " , EncodeDestination ( dest ) ) ;
}
2022-06-24 20:35:23 +02:00
}
2023-09-29 19:56:52 +02:00
return obj ;
2018-04-09 10:35:43 +02:00
}
2018-08-22 12:39:41 +02:00
CSimplifiedMNList : : CSimplifiedMNList ( const std : : vector < CSimplifiedMNListEntry > & smlEntries )
{
2023-11-14 10:13:02 +01:00
mnList . reserve ( smlEntries . size ( ) ) ;
for ( const auto & entry : smlEntries ) {
mnList . emplace_back ( std : : make_unique < CSimplifiedMNListEntry > ( entry ) ) ;
2019-07-02 22:46:03 +02:00
}
2018-08-22 12:39:41 +02:00
2019-07-02 22:46:03 +02:00
std : : sort ( mnList . begin ( ) , mnList . end ( ) , [ & ] ( const std : : unique_ptr < CSimplifiedMNListEntry > & a , const std : : unique_ptr < CSimplifiedMNListEntry > & b ) {
return a - > proRegTxHash . Compare ( b - > proRegTxHash ) < 0 ;
2018-08-22 12:39:41 +02:00
} ) ;
}
2023-06-11 19:29:00 +02:00
CSimplifiedMNList : : CSimplifiedMNList ( const CDeterministicMNList & dmnList )
2018-04-09 10:35:43 +02:00
{
2023-11-14 10:13:02 +01:00
mnList . reserve ( dmnList . GetAllMNsCount ( ) ) ;
dmnList . ForEachMN ( false , [ this ] ( auto & dmn ) {
mnList . emplace_back ( std : : make_unique < CSimplifiedMNListEntry > ( dmn ) ) ;
2018-10-02 11:03:05 +02:00
} ) ;
2018-04-09 10:35:43 +02:00
2019-07-02 22:46:03 +02:00
std : : sort ( mnList . begin ( ) , mnList . end ( ) , [ & ] ( const std : : unique_ptr < CSimplifiedMNListEntry > & a , const std : : unique_ptr < CSimplifiedMNListEntry > & b ) {
return a - > proRegTxHash . Compare ( b - > proRegTxHash ) < 0 ;
2018-04-09 10:35:43 +02:00
} ) ;
}
2018-11-06 09:54:23 +01:00
uint256 CSimplifiedMNList : : CalcMerkleRoot ( bool * pmutated ) const
2018-04-09 10:35:43 +02:00
{
std : : vector < uint256 > leaves ;
leaves . reserve ( mnList . size ( ) ) ;
for ( const auto & e : mnList ) {
2019-07-02 22:46:03 +02:00
leaves . emplace_back ( e - > CalcHash ( ) ) ;
2018-04-09 10:35:43 +02:00
}
return ComputeMerkleRoot ( leaves , pmutated ) ;
}
2018-04-09 14:49:34 +02:00
2022-08-06 10:45:02 +02:00
bool CSimplifiedMNList : : operator = = ( const CSimplifiedMNList & rhs ) const
{
return mnList . size ( ) = = rhs . mnList . size ( ) & &
std : : equal ( mnList . begin ( ) , mnList . end ( ) , rhs . mnList . begin ( ) ,
[ ] ( const std : : unique_ptr < CSimplifiedMNListEntry > & left , const std : : unique_ptr < CSimplifiedMNListEntry > & right )
{
return * left = = * right ;
}
) ;
}
2020-08-09 23:34:26 +02:00
CSimplifiedMNListDiff : : CSimplifiedMNListDiff ( ) = default ;
2019-04-04 10:27:17 +02:00
2020-08-09 23:34:26 +02:00
CSimplifiedMNListDiff : : ~ CSimplifiedMNListDiff ( ) = default ;
2019-04-04 10:27:17 +02:00
2022-09-22 13:14:48 +02:00
bool CSimplifiedMNListDiff : : BuildQuorumsDiff ( const CBlockIndex * baseBlockIndex , const CBlockIndex * blockIndex ,
const llmq : : CQuorumBlockProcessor & quorum_block_processor )
2019-04-04 10:27:17 +02:00
{
2022-09-22 13:14:48 +02:00
auto baseQuorums = quorum_block_processor . GetMinedAndActiveCommitmentsUntilBlock ( baseBlockIndex ) ;
auto quorums = quorum_block_processor . GetMinedAndActiveCommitmentsUntilBlock ( blockIndex ) ;
2019-04-04 10:27:17 +02:00
std : : set < std : : pair < Consensus : : LLMQType , uint256 > > baseQuorumHashes ;
std : : set < std : : pair < Consensus : : LLMQType , uint256 > > quorumHashes ;
2023-02-20 00:04:57 +01:00
for ( const auto & [ llmqType , vecBlockIndex ] : baseQuorums ) {
for ( const auto & blockindex : vecBlockIndex ) {
baseQuorumHashes . emplace ( llmqType , blockindex - > GetBlockHash ( ) ) ;
2019-04-04 10:27:17 +02:00
}
}
2023-02-20 00:04:57 +01:00
for ( const auto & [ llmqType , vecBlockIndex ] : quorums ) {
for ( const auto & blockindex : vecBlockIndex ) {
quorumHashes . emplace ( llmqType , blockindex - > GetBlockHash ( ) ) ;
2019-04-04 10:27:17 +02:00
}
}
2023-02-20 00:04:57 +01:00
for ( const auto & p : baseQuorumHashes ) {
2019-04-04 10:27:17 +02:00
if ( ! quorumHashes . count ( p ) ) {
deletedQuorums . emplace_back ( ( uint8_t ) p . first , p . second ) ;
}
}
2023-02-20 00:04:57 +01:00
for ( const auto & p : quorumHashes ) {
const auto & [ llmqType , hash ] = p ;
2019-04-04 10:27:17 +02:00
if ( ! baseQuorumHashes . count ( p ) ) {
2019-04-04 11:11:25 +02:00
uint256 minedBlockHash ;
2023-02-20 00:04:57 +01:00
llmq : : CFinalCommitmentPtr qc = quorum_block_processor . GetMinedCommitment ( llmqType , hash , minedBlockHash ) ;
2021-04-16 05:41:16 +02:00
if ( qc = = nullptr ) {
2019-04-04 10:27:17 +02:00
return false ;
}
2021-04-16 05:41:16 +02:00
newQuorums . emplace_back ( * qc ) ;
2019-04-04 10:27:17 +02:00
}
}
2023-07-10 18:23:09 +02:00
return true ;
}
2024-05-19 21:10:35 +02:00
void CSimplifiedMNListDiff : : BuildQuorumChainlockInfo ( const llmq : : CQuorumManager & qman , const CBlockIndex * blockIndex )
2023-07-10 18:23:09 +02:00
{
// Group quorums (indexes corresponding to entries of newQuorums) per CBlockIndex containing the expected CL signature in CbTx.
// We want to avoid to load CbTx now, as more than one quorum will target the same block: hence we want to load CbTxs once per block (heavy operation).
std : : multimap < const CBlockIndex * , uint16_t > workBaseBlockIndexMap ;
for ( const auto [ idx , e ] : enumerate ( newQuorums ) ) {
2024-05-19 21:10:35 +02:00
auto quorum = qman . GetQuorum ( e . llmqType , e . quorumHash ) ;
2023-07-10 18:23:09 +02:00
// In case of rotation, all rotated quorums rely on the CL sig expected in the cycleBlock (the block of the first DKG) - 8
// In case of non-rotation, quorums rely on the CL sig expected in the block of the DKG - 8
const CBlockIndex * pWorkBaseBlockIndex =
blockIndex - > GetAncestor ( quorum - > m_quorum_base_block_index - > nHeight - quorum - > qc - > quorumIndex - 8 ) ;
workBaseBlockIndexMap . insert ( std : : make_pair ( pWorkBaseBlockIndex , idx ) ) ;
}
for ( auto it = workBaseBlockIndexMap . begin ( ) ; it ! = workBaseBlockIndexMap . end ( ) ; ) {
// Process each key (CBlockIndex containing the expected CL signature in CbTx) of the std::multimap once
const CBlockIndex * pWorkBaseBlockIndex = it - > first ;
const auto cbcl = GetNonNullCoinbaseChainlock ( pWorkBaseBlockIndex ) ;
CBLSSignature sig ;
if ( cbcl . has_value ( ) ) {
sig = cbcl . value ( ) . first ;
}
// Get the range of indexes (values) for the current key and merge them into a single std::set
2023-10-03 16:52:33 +02:00
const auto [ it_begin , it_end ] = workBaseBlockIndexMap . equal_range ( it - > first ) ;
2023-07-10 18:23:09 +02:00
std : : set < uint16_t > idx_set ;
2023-10-03 16:52:33 +02:00
std : : transform ( it_begin , it_end , std : : inserter ( idx_set , idx_set . end ( ) ) , [ ] ( const auto & pair ) { return pair . second ; } ) ;
2023-07-10 18:23:09 +02:00
// Advance the iterator to the next key
2023-10-03 16:52:33 +02:00
it = it_end ;
2023-07-10 18:23:09 +02:00
// Different CBlockIndex can contain the same CL sig in CbTx (both non-null or null during the first blocks after v20 activation)
// Hence, we need to merge the std::set if another std::set already exists for the same sig.
if ( auto [ it_sig , inserted ] = quorumsCLSigs . insert ( { sig , idx_set } ) ; ! inserted ) {
it_sig - > second . insert ( idx_set . begin ( ) , idx_set . end ( ) ) ;
}
}
2019-04-04 10:27:17 +02:00
}
2023-09-29 19:56:52 +02:00
UniValue CSimplifiedMNListDiff : : ToJson ( bool extended ) const
2018-04-09 14:49:34 +02:00
{
2023-09-29 19:56:52 +02:00
UniValue obj ;
2018-04-09 14:49:34 +02:00
obj . setObject ( ) ;
2023-06-17 17:50:26 +02:00
obj . pushKV ( " nVersion " , nVersion ) ;
2020-06-18 11:17:23 +02:00
obj . pushKV ( " baseBlockHash " , baseBlockHash . ToString ( ) ) ;
obj . pushKV ( " blockHash " , blockHash . ToString ( ) ) ;
2018-04-09 14:49:34 +02:00
2018-10-30 10:59:32 +01:00
CDataStream ssCbTxMerkleTree ( SER_NETWORK , PROTOCOL_VERSION ) ;
ssCbTxMerkleTree < < cbTxMerkleTree ;
2021-05-18 19:17:10 +02:00
obj . pushKV ( " cbTxMerkleTree " , HexStr ( ssCbTxMerkleTree ) ) ;
2018-10-30 10:59:32 +01:00
2020-06-18 11:17:23 +02:00
obj . pushKV ( " cbTx " , EncodeHexTx ( * cbTx ) ) ;
2018-10-30 10:59:32 +01:00
2018-04-09 14:49:34 +02:00
UniValue deletedMNsArr ( UniValue : : VARR ) ;
for ( const auto & h : deletedMNs ) {
deletedMNsArr . push_back ( h . ToString ( ) ) ;
}
2020-06-18 11:17:23 +02:00
obj . pushKV ( " deletedMNs " , deletedMNsArr ) ;
2018-04-09 14:49:34 +02:00
UniValue mnListArr ( UniValue : : VARR ) ;
for ( const auto & e : mnList ) {
2023-09-29 19:56:52 +02:00
mnListArr . push_back ( e . ToJson ( extended ) ) ;
2018-04-09 14:49:34 +02:00
}
2020-06-18 11:17:23 +02:00
obj . pushKV ( " mnList " , mnListArr ) ;
2018-04-09 14:49:34 +02:00
2019-04-04 10:27:17 +02:00
UniValue deletedQuorumsArr ( UniValue : : VARR ) ;
for ( const auto & e : deletedQuorums ) {
UniValue eObj ( UniValue : : VOBJ ) ;
2020-06-18 11:17:23 +02:00
eObj . pushKV ( " llmqType " , e . first ) ;
eObj . pushKV ( " quorumHash " , e . second . ToString ( ) ) ;
2019-04-04 10:27:17 +02:00
deletedQuorumsArr . push_back ( eObj ) ;
}
2020-06-18 11:17:23 +02:00
obj . pushKV ( " deletedQuorums " , deletedQuorumsArr ) ;
2019-04-04 10:27:17 +02:00
UniValue newQuorumsArr ( UniValue : : VARR ) ;
for ( const auto & e : newQuorums ) {
2023-09-29 19:56:52 +02:00
newQuorumsArr . push_back ( e . ToJson ( ) ) ;
2019-04-04 10:27:17 +02:00
}
2020-06-18 11:17:23 +02:00
obj . pushKV ( " newQuorums " , newQuorumsArr ) ;
2019-04-04 10:27:17 +02:00
2024-01-12 04:43:01 +01:00
if ( const auto opt_cbTxPayload = GetTxPayload < CCbTx > ( * cbTx ) ) {
obj . pushKV ( " merkleRootMNList " , opt_cbTxPayload - > merkleRootMNList . ToString ( ) ) ;
if ( opt_cbTxPayload - > nVersion > = CCbTx : : Version : : MERKLE_ROOT_QUORUMS ) {
obj . pushKV ( " merkleRootQuorums " , opt_cbTxPayload - > merkleRootQuorums . ToString ( ) ) ;
2019-04-04 10:27:17 +02:00
}
2018-04-09 14:49:34 +02:00
}
2023-07-10 18:23:09 +02:00
UniValue quorumsCLSigsArr ( UniValue : : VARR ) ;
for ( const auto & [ signature , quorumsIndexes ] : quorumsCLSigs ) {
UniValue j ( UniValue : : VOBJ ) ;
UniValue idxArr ( UniValue : : VARR ) ;
for ( const auto & idx : quorumsIndexes ) {
idxArr . push_back ( idx ) ;
}
j . pushKV ( signature . ToString ( ) , idxArr ) ;
quorumsCLSigsArr . push_back ( j ) ;
}
obj . pushKV ( " quorumsCLSigs " , quorumsCLSigsArr ) ;
2023-09-29 19:56:52 +02:00
return obj ;
2018-04-09 14:49:34 +02:00
}
2023-05-18 19:03:19 +02:00
CSimplifiedMNListDiff BuildSimplifiedDiff ( const CDeterministicMNList & from , const CDeterministicMNList & to , bool extended )
{
CSimplifiedMNListDiff diffRet ;
diffRet . baseBlockHash = from . GetBlockHash ( ) ;
diffRet . blockHash = to . GetBlockHash ( ) ;
to . ForEachMN ( false , [ & ] ( const auto & toPtr ) {
auto fromPtr = from . GetMN ( toPtr . proTxHash ) ;
if ( fromPtr = = nullptr ) {
CSimplifiedMNListEntry sme ( toPtr ) ;
diffRet . mnList . push_back ( std : : move ( sme ) ) ;
} else {
CSimplifiedMNListEntry sme1 ( toPtr ) ;
CSimplifiedMNListEntry sme2 ( * fromPtr ) ;
if ( ( sme1 ! = sme2 ) | |
( extended & & ( sme1 . scriptPayout ! = sme2 . scriptPayout | | sme1 . scriptOperatorPayout ! = sme2 . scriptOperatorPayout ) ) ) {
diffRet . mnList . push_back ( std : : move ( sme1 ) ) ;
}
}
} ) ;
from . ForEachMN ( false , [ & ] ( auto & fromPtr ) {
auto toPtr = to . GetMN ( fromPtr . proTxHash ) ;
if ( toPtr = = nullptr ) {
diffRet . deletedMNs . emplace_back ( fromPtr . proTxHash ) ;
}
} ) ;
return diffRet ;
}
2024-06-25 00:57:00 +02:00
bool BuildSimplifiedMNListDiff ( CDeterministicMNManager & dmnman , const ChainstateManager & chainman , const llmq : : CQuorumBlockProcessor & qblockman ,
const llmq : : CQuorumManager & qman , const uint256 & baseBlockHash , const uint256 & blockHash ,
CSimplifiedMNListDiff & mnListDiffRet , std : : string & errorRet , bool extended )
2018-04-09 14:49:34 +02:00
{
AssertLockHeld ( cs_main ) ;
mnListDiffRet = CSimplifiedMNListDiff ( ) ;
2024-06-25 00:57:00 +02:00
const CBlockIndex * baseBlockIndex = chainman . ActiveChain ( ) . Genesis ( ) ;
2018-04-09 14:49:34 +02:00
if ( ! baseBlockHash . IsNull ( ) ) {
2024-06-25 00:57:00 +02:00
baseBlockIndex = chainman . m_blockman . LookupBlockIndex ( baseBlockHash ) ;
2018-03-13 19:04:28 +01:00
if ( ! baseBlockIndex ) {
2019-02-12 20:52:06 +01:00
errorRet = strprintf ( " block %s not found " , baseBlockHash . ToString ( ) ) ;
return false ;
}
2018-04-09 14:49:34 +02:00
}
2018-03-13 19:04:28 +01:00
2024-06-25 00:57:00 +02:00
const CBlockIndex * blockIndex = chainman . m_blockman . LookupBlockIndex ( blockHash ) ;
2018-03-13 19:04:28 +01:00
if ( ! blockIndex ) {
2018-04-09 14:49:34 +02:00
errorRet = strprintf ( " block %s not found " , blockHash . ToString ( ) ) ;
return false ;
}
2024-06-25 00:57:00 +02:00
if ( ! chainman . ActiveChain ( ) . Contains ( baseBlockIndex ) | | ! chainman . ActiveChain ( ) . Contains ( blockIndex ) ) {
2018-04-09 14:49:34 +02:00
errorRet = strprintf ( " block %s and %s are not in the same chain " , baseBlockHash . ToString ( ) , blockHash . ToString ( ) ) ;
return false ;
}
2019-02-12 20:52:06 +01:00
if ( baseBlockIndex - > nHeight > blockIndex - > nHeight ) {
2018-04-09 14:49:34 +02:00
errorRet = strprintf ( " base block %s is higher then block %s " , baseBlockHash . ToString ( ) , blockHash . ToString ( ) ) ;
return false ;
}
2024-03-15 16:45:00 +01:00
auto baseDmnList = dmnman . GetListForBlock ( baseBlockIndex ) ;
auto dmnList = dmnman . GetListForBlock ( blockIndex ) ;
2023-05-18 19:03:19 +02:00
mnListDiffRet = BuildSimplifiedDiff ( baseDmnList , dmnList , extended ) ;
2018-04-09 14:49:34 +02:00
2019-07-09 07:59:57 +02:00
// We need to return the value that was provided by the other peer as it otherwise won't be able to recognize the
// response. This will usually be identical to the block found in baseBlockIndex. The only difference is when a
// null block hash was provided to get the diff from the genesis block.
mnListDiffRet . baseBlockHash = baseBlockHash ;
2024-06-25 00:57:00 +02:00
if ( ! mnListDiffRet . BuildQuorumsDiff ( baseBlockIndex , blockIndex , qblockman ) ) {
2019-04-04 10:27:17 +02:00
errorRet = strprintf ( " failed to build quorums diff " ) ;
return false ;
}
2023-12-04 19:04:51 +01:00
if ( DeploymentActiveAfter ( blockIndex , Params ( ) . GetConsensus ( ) , Consensus : : DEPLOYMENT_V20 ) ) {
2024-05-19 21:10:35 +02:00
mnListDiffRet . BuildQuorumChainlockInfo ( qman , blockIndex ) ;
2023-07-10 18:23:09 +02:00
}
2018-04-09 14:49:34 +02:00
// TODO store coinbase TX in CBlockIndex
CBlock block ;
2019-02-12 20:52:06 +01:00
if ( ! ReadBlockFromDisk ( block , blockIndex , Params ( ) . GetConsensus ( ) ) ) {
2018-04-09 14:49:34 +02:00
errorRet = strprintf ( " failed to read block %s from disk " , blockHash . ToString ( ) ) ;
return false ;
}
mnListDiffRet . cbTx = block . vtx [ 0 ] ;
std : : vector < uint256 > vHashes ;
std : : vector < bool > vMatch ( block . vtx . size ( ) , false ) ;
for ( const auto & tx : block . vtx ) {
vHashes . emplace_back ( tx - > GetHash ( ) ) ;
}
vMatch [ 0 ] = true ; // only coinbase matches
mnListDiffRet . cbTxMerkleTree = CPartialMerkleTree ( vHashes , vMatch ) ;
return true ;
}