예제 #1
0
        public void RollbackBlock(ChainedHeader chainedHeader, IEnumerable <BlockTx> blockTxes)
        {
            using (var handle = storageManager.OpenChainStateCursor())
            {
                var chainStateCursor = handle.Item;

                chainStateCursor.BeginTransaction();

                // verify storage chain tip matches this chain state builder's chain tip
                CheckChainTip(chainStateCursor);

                var newChain = chain.Value.ToBuilder().RemoveBlock(chainedHeader).ToImmutable();

                // keep track of the previoux tx output information for all unminted transactions
                // the information is removed and will be needed to enable a replay of the rolled back block
                var unmintedTxes = ImmutableList.CreateBuilder <UnmintedTx>();

                // rollback the utxo
                utxoBuilder.RollbackUtxo(chainStateCursor, chain.Value, chainedHeader, blockTxes, unmintedTxes);

                // remove the block from the chain
                chainStateCursor.ChainTip = newChain.LastBlock;

                // remove the rollback information
                chainStateCursor.TryRemoveBlockSpentTxes(chainedHeader.Height);

                // store the replay information
                chainStateCursor.TryAddBlockUnmintedTxes(chainedHeader.Hash, unmintedTxes.ToImmutable());

                // commit the chain state
                commitLock.Do(() =>
                {
                    chainStateCursor.CommitTransaction();
                    chain = new Lazy <Chain>(() => newChain).Force();
                });
            }
        }