MCPcopy Create free account
hub / github.com/ElementsProject/elements / DisconnectBlock

Method DisconnectBlock

src/validation.cpp:1901–1960  ·  view source on GitHub ↗

Undo the effects of this block (with given index) on the UTXO set represented by coins. * When FAILED is returned, view is left in an indeterminate state. */

Source from the content-addressed store, hash-verified

1899/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
1900 * When FAILED is returned, view is left in an indeterminate state. */
1901DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
1902{
1903 AssertLockHeld(::cs_main);
1904 bool fClean = true;
1905
1906 CBlockUndo blockUndo;
1907 if (!UndoReadFromDisk(blockUndo, pindex)) {
1908 error("DisconnectBlock(): failure reading undo data");
1909 return DISCONNECT_FAILED;
1910 }
1911
1912 if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) {
1913 error("DisconnectBlock(): block and undo data inconsistent");
1914 return DISCONNECT_FAILED;
1915 }
1916
1917 // undo transactions in reverse order
1918 for (int i = block.vtx.size() - 1; i >= 0; i--) {
1919 const CTransaction &tx = *(block.vtx[i]);
1920 uint256 hash = tx.GetHash();
1921 bool is_coinbase = tx.IsCoinBase();
1922
1923 // Check that all outputs are available and match the outputs in the block itself
1924 // exactly.
1925 for (size_t o = 0; o < tx.vout.size(); o++) {
1926 if (!tx.vout[o].scriptPubKey.IsUnspendable()) {
1927 COutPoint out(hash, o);
1928 Coin coin;
1929 bool is_spent = view.SpendCoin(out, &coin);
1930 if (!is_spent || !TxOutDBEntryIsSame(tx.vout[o], coin.out) || pindex->nHeight != coin.nHeight || is_coinbase != coin.fCoinBase) {
1931 fClean = false; // transaction output mismatch
1932 }
1933 }
1934 }
1935
1936 // restore inputs
1937 const auto& fedpegscripts = GetValidFedpegScripts(pindex, Params().GetConsensus(), false /* nextblock_validation */);
1938 if (i > 0) { // not coinbases
1939 CTxUndo &txundo = blockUndo.vtxundo[i-1];
1940 if (txundo.vprevout.size() != tx.vin.size()) {
1941 error("DisconnectBlock(): transaction and undo data inconsistent");
1942 return DISCONNECT_FAILED;
1943 }
1944 for (unsigned int j = tx.vin.size(); j > 0;) {
1945 --j;
1946 const COutPoint& out = tx.vin[j].prevout;
1947 const CScriptWitness& pegin_wit = tx.witness.vtxinwit.size() > j ? tx.witness.vtxinwit[j].m_pegin_witness : CScriptWitness();
1948 int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), view, out, tx.vin[j], pegin_wit, fedpegscripts);
1949 if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED;
1950 fClean = fClean && res != DISCONNECT_UNCLEAN;
1951 }
1952 // At this point, all of txundo.vprevout should have been moved out.
1953 }
1954 }
1955
1956 // move best block pointer to prevout block
1957 view.SetBestBlock(pindex->pprev->GetBlockHash());
1958

Callers 1

VerifyDBMethod · 0.80

Calls 14

UndoReadFromDiskFunction · 0.85
errorFunction · 0.85
TxOutDBEntryIsSameFunction · 0.85
GetValidFedpegScriptsFunction · 0.85
ApplyTxInUndoFunction · 0.85
IsUnspendableMethod · 0.80
SpendCoinMethod · 0.80
SetBestBlockMethod · 0.80
ParamsClass · 0.70
CScriptWitnessClass · 0.70
sizeMethod · 0.45
GetHashMethod · 0.45

Tested by

no test coverage detected