* Restore the UTXO in a Coin at a given COutPoint * @param undo The Coin to be restored. * @param view The coins view to which to apply the changes. * @param out The out point that corresponds to the tx input. * @return A DisconnectResult as an int */
| 1839 | * @return A DisconnectResult as an int |
| 1840 | */ |
| 1841 | int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector<std::pair<CScript, CScript>>& fedpegscripts) |
| 1842 | { |
| 1843 | bool fClean = true; |
| 1844 | |
| 1845 | if (!txin.m_is_pegin) { |
| 1846 | if (view.HaveCoin(out)) fClean = false; // overwriting transaction output |
| 1847 | |
| 1848 | if (undo.nHeight == 0) { |
| 1849 | // Missing undo metadata (height and coinbase). Older versions included this |
| 1850 | // information only in undo records for the last spend of a transactions' |
| 1851 | // outputs. This implies that it must be present for some other output of the same tx. |
| 1852 | const Coin& alternate = AccessByTxid(view, out.hash); |
| 1853 | if (!alternate.IsSpent()) { |
| 1854 | undo.nHeight = alternate.nHeight; |
| 1855 | undo.fCoinBase = alternate.fCoinBase; |
| 1856 | } else { |
| 1857 | // ELEMENTS: |
| 1858 | // If we're connecting genesis outputs, it's probably actually just |
| 1859 | // a genesis output, let it through. N.B. The case where it's a corrupted |
| 1860 | // txundo from per-tx db will not be caught! |
| 1861 | if (!Params().GetConsensus().connect_genesis_outputs) { |
| 1862 | return DISCONNECT_FAILED; // adding output for transaction without known metadata |
| 1863 | } |
| 1864 | } |
| 1865 | } |
| 1866 | // If the coin already exists as an unspent coin in the cache, then the |
| 1867 | // possible_overwrite parameter to AddCoin must be set to true. We have |
| 1868 | // already checked whether an unspent coin exists above using HaveCoin, so |
| 1869 | // we don't need to guess. When fClean is false, an unspent coin already |
| 1870 | // existed and it is an overwrite. |
| 1871 | view.AddCoin(out, std::move(undo), !fClean); |
| 1872 | } else { |
| 1873 | std::string err; |
| 1874 | if (!IsValidPeginWitness(pegin_witness, fedpegscripts, txin.prevout, err, false)) { |
| 1875 | fClean = fClean && error("%s: peg-in occurred without proof", __func__); |
| 1876 | } else { |
| 1877 | std::pair<uint256, COutPoint> outpoint = std::make_pair(uint256(pegin_witness.stack[2]), txin.prevout); |
| 1878 | bool fSpent = view.IsPeginSpent(outpoint); |
| 1879 | if (!fSpent) { |
| 1880 | fClean = fClean && error("%s: peg-in bitcoin txid not marked spent", __func__); |
| 1881 | } else { |
| 1882 | view.SetPeginSpent(outpoint, false); |
| 1883 | } |
| 1884 | } |
| 1885 | } |
| 1886 | |
| 1887 | return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; |
| 1888 | } |
| 1889 | |
| 1890 | // We don't want to compare things that are not stored in utxo db, specifically |
| 1891 | // the nonce commitment which has no consensus meaning for spending conditions |