@@ -2083,6 +2083,29 @@ static int64_t nTimeCallbacks = 0;
2083
2083
static int64_t nTimeTotal = 0 ;
2084
2084
static int64_t nBlocksTotal = 0 ;
2085
2085
2086
+ bool CheckPeginRipeness (const CBlock& block, const std::vector<std::pair<CScript, CScript>>& fedpegscripts) {
2087
+ for (unsigned int i = 0 ; i < block.vtx .size (); i++) {
2088
+ const CTransaction &tx = *(block.vtx [i]);
2089
+
2090
+ if (!tx.IsCoinBase ()) {
2091
+ for (unsigned int i = 0 ; i < tx.vin .size (); ++i) {
2092
+ if (tx.vin [i].m_is_pegin ) {
2093
+ std::string err;
2094
+ bool depth_failed = false ;
2095
+ if ((tx.witness .vtxinwit .size () <= i) || !IsValidPeginWitness (tx.witness .vtxinwit [i].m_pegin_witness , fedpegscripts, tx.vin [i].prevout , err, true , &depth_failed)) {
2096
+ if (depth_failed) {
2097
+ return false ; // Pegins not ripe.
2098
+ } else {
2099
+ return true ; // Some other failure; details later.
2100
+ }
2101
+ }
2102
+ }
2103
+ }
2104
+ }
2105
+ }
2106
+ return true ;
2107
+ }
2108
+
2086
2109
/* * Apply the effects of this block (with given index) on the UTXO set represented by coins.
2087
2110
* Validity checks that depend on the UTXO set are also done; ConnectBlock()
2088
2111
* can fail if those validity checks fail (among other reasons). */
@@ -2820,7 +2843,7 @@ class ConnectTrace {
2820
2843
*
2821
2844
* The block is added to connectTrace if connection succeeds.
2822
2845
*/
2823
- bool CChainState::ConnectTip (BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool)
2846
+ bool CChainState::ConnectTip (BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool, bool & fStall )
2824
2847
{
2825
2848
AssertLockHeld (cs_main);
2826
2849
AssertLockHeld (m_mempool.cs );
@@ -2838,6 +2861,14 @@ bool CChainState::ConnectTip(BlockValidationState& state, const CChainParams& ch
2838
2861
pthisBlock = pblock;
2839
2862
}
2840
2863
const CBlock& blockConnecting = *pthisBlock;
2864
+
2865
+ const auto & fedpegscripts = GetValidFedpegScripts (pindexNew, chainparams.GetConsensus (), false /* nextblock_validation */ );
2866
+ if (!CheckPeginRipeness (blockConnecting, fedpegscripts)) {
2867
+ LogPrintf (" STALLING further progress in ConnectTip while waiting for parent chain daemon to catch up! Chain will not grow until this is remedied!\n " );
2868
+ fStall = true ;
2869
+ return true ;
2870
+ }
2871
+
2841
2872
// Apply the block atomically to the chain state.
2842
2873
int64_t nTime2 = GetTimeMicros (); nTimeReadFromDisk += nTime2 - nTime1;
2843
2874
int64_t nTime3;
@@ -2854,29 +2885,6 @@ bool CChainState::ConnectTip(BlockValidationState& state, const CChainParams& ch
2854
2885
if (!rv) {
2855
2886
if (state.IsInvalid ()) {
2856
2887
InvalidBlockFound (pindexNew, state);
2857
-
2858
- // ELEMENTS:
2859
- // Possibly result of RPC to mainchain bitcoind failure
2860
- // or unseen Bitcoin blocks.
2861
- // These blocks are later re-evaluated at an interval
2862
- // set by `-recheckpeginblockinterval`.
2863
- if (state.GetRejectReason () == " bad-pegin-witness" ) {
2864
- // Write queue of invalid blocks that
2865
- // must be cleared to continue operation
2866
- std::vector<uint256> vinvalidBlocks;
2867
- pblocktree->ReadInvalidBlockQueue (vinvalidBlocks);
2868
- bool blockAlreadyInvalid = false ;
2869
- for (uint256& hash : vinvalidBlocks) {
2870
- if (hash == blockConnecting.GetHash ()) {
2871
- blockAlreadyInvalid = true ;
2872
- break ;
2873
- }
2874
- }
2875
- if (!blockAlreadyInvalid) {
2876
- vinvalidBlocks.push_back (blockConnecting.GetHash ());
2877
- pblocktree->WriteInvalidBlockQueue (vinvalidBlocks);
2878
- }
2879
- }
2880
2888
}
2881
2889
return error (" %s: ConnectBlock %s failed, %s" , __func__, pindexNew->GetBlockHash ().ToString (), state.ToString ());
2882
2890
}
@@ -2988,7 +2996,7 @@ void CChainState::PruneBlockIndexCandidates() {
2988
2996
*
2989
2997
* @returns true unless a system error occurred
2990
2998
*/
2991
- bool CChainState::ActivateBestChainStep (BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool & fInvalidFound , ConnectTrace& connectTrace)
2999
+ bool CChainState::ActivateBestChainStep (BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool & fInvalidFound , ConnectTrace& connectTrace, bool & fStall )
2992
3000
{
2993
3001
AssertLockHeld (cs_main);
2994
3002
AssertLockHeld (m_mempool.cs );
@@ -3033,7 +3041,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
3033
3041
3034
3042
// Connect new blocks.
3035
3043
for (CBlockIndex *pindexConnect : reverse_iterate (vpindexToConnect)) {
3036
- if (!ConnectTip (state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
3044
+ if (!ConnectTip (state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool, fStall )) {
3037
3045
if (state.IsInvalid ()) {
3038
3046
// The block violates a consensus rule.
3039
3047
if (state.GetResult () != BlockValidationResult::BLOCK_MUTATED) {
@@ -3051,6 +3059,12 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
3051
3059
return false ;
3052
3060
}
3053
3061
} else {
3062
+ if (fStall ) {
3063
+ // We didn't make progress because the parent chain is not
3064
+ // synced enough to check pegins. Try again later.
3065
+ fContinue = false ;
3066
+ break ;
3067
+ }
3054
3068
PruneBlockIndexCandidates ();
3055
3069
if (!pindexOldTip || m_chain.Tip ()->nChainWork > pindexOldTip->nChainWork ) {
3056
3070
// We're in a better position than we were. Return temporarily to release the lock.
@@ -3130,6 +3144,8 @@ bool CChainState::ActivateBestChain(BlockValidationState &state, const CChainPar
3130
3144
CBlockIndex *pindexMostWork = nullptr ;
3131
3145
CBlockIndex *pindexNewTip = nullptr ;
3132
3146
int nStopAtHeight = gArgs .GetArg (" -stopatheight" , DEFAULT_STOPATHEIGHT);
3147
+ bool fStall = false ;
3148
+
3133
3149
do {
3134
3150
// Block until the validation queue drains. This should largely
3135
3151
// never happen in normal operation, however may happen during
@@ -3160,7 +3176,7 @@ bool CChainState::ActivateBestChain(BlockValidationState &state, const CChainPar
3160
3176
3161
3177
bool fInvalidFound = false ;
3162
3178
std::shared_ptr<const CBlock> nullBlockPtr;
3163
- if (!ActivateBestChainStep (state, chainparams, pindexMostWork, pblock && pblock->GetHash () == pindexMostWork->GetBlockHash () ? pblock : nullBlockPtr, fInvalidFound , connectTrace)) {
3179
+ if (!ActivateBestChainStep (state, chainparams, pindexMostWork, pblock && pblock->GetHash () == pindexMostWork->GetBlockHash () ? pblock : nullBlockPtr, fInvalidFound , connectTrace, fStall )) {
3164
3180
// A system error occurred
3165
3181
return false ;
3166
3182
}
@@ -3176,6 +3192,11 @@ bool CChainState::ActivateBestChain(BlockValidationState &state, const CChainPar
3176
3192
assert (trace.pblock && trace.pindex );
3177
3193
GetMainSignals ().BlockConnected (trace.pblock , trace.pindex );
3178
3194
}
3195
+
3196
+ if (fStall ) {
3197
+ // Stuck waiting for parent chain daemon, twiddle our thumbs for awhile.
3198
+ break ;
3199
+ }
3179
3200
} while (!m_chain.Tip () || (starting_tip && CBlockIndexWorkComparator ()(m_chain.Tip (), starting_tip)));
3180
3201
if (!blocks_connected) return true ;
3181
3202
@@ -3194,6 +3215,11 @@ bool CChainState::ActivateBestChain(BlockValidationState &state, const CChainPar
3194
3215
}
3195
3216
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
3196
3217
3218
+ if (fStall ) {
3219
+ // Stuck waiting for parent chain daemon, twiddle our thumbs for awhile.
3220
+ break ;
3221
+ }
3222
+
3197
3223
if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown ();
3198
3224
3199
3225
// We check shutdown only after giving ActivateBestChainStep a chance to run once so that we
@@ -5711,35 +5737,12 @@ void ChainstateManager::MaybeRebalanceCaches()
5711
5737
}
5712
5738
5713
5739
// ELEMENTS:
5714
- /* This function has two major purposes:
5715
- * 1) Checks that the RPC connection to the parent chain node
5740
+ /* This function checks that the RPC connection to the parent chain node
5716
5741
* can be attained, and is returning back reasonable answers.
5717
- * 2) Re-evaluates a list of blocks that have been deemed "bad"
5718
- * from the perspective of peg-in witness validation. Blocks are
5719
- * added to this queue in ConnectTip based on the error code returned.
5720
5742
*/
5721
5743
bool MainchainRPCCheck (const bool init)
5722
5744
{
5723
- // First, we can clear out any blocks thatsomehow are now deemed valid
5724
- // eg reconsiderblock rpc call manually
5725
- std::vector<uint256> vblocksToReconsider;
5726
- pblocktree->ReadInvalidBlockQueue (vblocksToReconsider);
5727
- std::vector<uint256> vblocksToReconsiderAgain;
5728
- for (uint256& blockhash : vblocksToReconsider) {
5729
- LOCK (cs_main);
5730
- ChainstateManager& chainman = g_chainman;
5731
- if (chainman.BlockIndex ().count (blockhash)) {
5732
- CBlockIndex* pblockindex = chainman.BlockIndex ()[blockhash];
5733
- if ((pblockindex->nStatus & BLOCK_FAILED_MASK)) {
5734
- vblocksToReconsiderAgain.push_back (blockhash);
5735
- }
5736
- }
5737
- }
5738
- vblocksToReconsider = vblocksToReconsiderAgain;
5739
- vblocksToReconsiderAgain.clear ();
5740
- pblocktree->WriteInvalidBlockQueue (vblocksToReconsider);
5741
-
5742
- // Next, check for working and valid rpc
5745
+ // Check for working and valid rpc
5743
5746
if (gArgs .GetBoolArg (" -validatepegin" , Params ().GetConsensus ().has_parent_chain )) {
5744
5747
// During init try until a non-RPC_IN_WARMUP result
5745
5748
while (true ) {
@@ -5790,50 +5793,5 @@ bool MainchainRPCCheck(const bool init)
5790
5793
}
5791
5794
}
5792
5795
5793
- // Sanity startup check won't reconsider queued blocks
5794
- if (init) {
5795
- return true ;
5796
- }
5797
-
5798
- // Getting this far means we either aren't validating pegins(so let's make sure that's why
5799
- // it failed previously) or we successfully connected to bitcoind
5800
- // Time to reconsider blocks
5801
- if (vblocksToReconsider.size () > 0 ) {
5802
- BlockValidationState state;
5803
- for (const uint256& blockhash : vblocksToReconsider) {
5804
- {
5805
- LOCK (cs_main);
5806
- ChainstateManager& chainman = g_chainman;
5807
- if (chainman.BlockIndex ().count (blockhash) == 0 )
5808
- continue ;
5809
- CBlockIndex* pblockindex = chainman.BlockIndex ()[blockhash];
5810
- ResetBlockFailureFlags (pblockindex);
5811
- }
5812
- }
5813
-
5814
- // All blocks are now being reconsidered
5815
- ActivateBestChain (state, Params ());
5816
- // This simply checks for DB errors
5817
- if (!state.IsValid ()) {
5818
- // Something scary?
5819
- }
5820
-
5821
- // Now to clear out now-valid blocks
5822
- for (const uint256& blockhash : vblocksToReconsider) {
5823
- LOCK (cs_main);
5824
- ChainstateManager& chainman = g_chainman;
5825
- if (chainman.BlockIndex ().count (blockhash)) {
5826
- CBlockIndex* pblockindex = chainman.BlockIndex ()[blockhash];
5827
-
5828
- // Marked as invalid still, put back into queue
5829
- if ((pblockindex->nStatus & BLOCK_FAILED_MASK)) {
5830
- vblocksToReconsiderAgain.push_back (blockhash);
5831
- }
5832
- }
5833
- }
5834
-
5835
- // Write back remaining blocks
5836
- pblocktree->WriteInvalidBlockQueue (vblocksToReconsiderAgain);
5837
- }
5838
5796
return true ;
5839
5797
}
0 commit comments