1 // Copyright (c) 2018-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <interfaces/chain.h>
6 
7 #include <chain.h>
8 #include <chainparams.h>
9 #include <interfaces/handler.h>
10 #include <interfaces/wallet.h>
11 #include <net.h>
12 #include <net_processing.h>
13 #include <node/coin.h>
14 #include <node/context.h>
15 #include <node/transaction.h>
16 #include <policy/fees.h>
17 #include <policy/policy.h>
18 #include <policy/rbf.h>
19 #include <policy/settings.h>
20 #include <primitives/block.h>
21 #include <primitives/transaction.h>
22 #include <rpc/protocol.h>
23 #include <rpc/server.h>
24 #include <shutdown.h>
25 #include <sync.h>
26 #include <timedata.h>
27 #include <txmempool.h>
28 #include <ui_interface.h>
29 #include <uint256.h>
30 #include <univalue.h>
31 #include <util/system.h>
32 #include <validation.h>
33 #include <validationinterface.h>
34 
35 #include <memory>
36 #include <utility>
37 
38 namespace interfaces {
39 namespace {
40 
41 class LockImpl : public Chain::Lock, public UniqueLock<RecursiveMutex>
42 {
getHeight()43     Optional<int> getHeight() override
44     {
45         LockAssertion lock(::cs_main);
46         int height = ::ChainActive().Height();
47         if (height >= 0) {
48             return height;
49         }
50         return nullopt;
51     }
getBlockHeight(const uint256 & hash)52     Optional<int> getBlockHeight(const uint256& hash) override
53     {
54         LockAssertion lock(::cs_main);
55         CBlockIndex* block = LookupBlockIndex(hash);
56         if (block && ::ChainActive().Contains(block)) {
57             return block->nHeight;
58         }
59         return nullopt;
60     }
getBlockHash(int height)61     uint256 getBlockHash(int height) override
62     {
63         LockAssertion lock(::cs_main);
64         CBlockIndex* block = ::ChainActive()[height];
65         assert(block != nullptr);
66         return block->GetBlockHash();
67     }
getBlockTime(int height)68     int64_t getBlockTime(int height) override
69     {
70         LockAssertion lock(::cs_main);
71         CBlockIndex* block = ::ChainActive()[height];
72         assert(block != nullptr);
73         return block->GetBlockTime();
74     }
getBlockMedianTimePast(int height)75     int64_t getBlockMedianTimePast(int height) override
76     {
77         LockAssertion lock(::cs_main);
78         CBlockIndex* block = ::ChainActive()[height];
79         assert(block != nullptr);
80         return block->GetMedianTimePast();
81     }
haveBlockOnDisk(int height)82     bool haveBlockOnDisk(int height) override
83     {
84         LockAssertion lock(::cs_main);
85         CBlockIndex* block = ::ChainActive()[height];
86         return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
87     }
findFirstBlockWithTimeAndHeight(int64_t time,int height,uint256 * hash)88     Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
89     {
90         LockAssertion lock(::cs_main);
91         CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height);
92         if (block) {
93             if (hash) *hash = block->GetBlockHash();
94             return block->nHeight;
95         }
96         return nullopt;
97     }
findPruned(int start_height,Optional<int> stop_height)98     Optional<int> findPruned(int start_height, Optional<int> stop_height) override
99     {
100         LockAssertion lock(::cs_main);
101         if (::fPruneMode) {
102             CBlockIndex* block = stop_height ? ::ChainActive()[*stop_height] : ::ChainActive().Tip();
103             while (block && block->nHeight >= start_height) {
104                 if ((block->nStatus & BLOCK_HAVE_DATA) == 0) {
105                     return block->nHeight;
106                 }
107                 block = block->pprev;
108             }
109         }
110         return nullopt;
111     }
findFork(const uint256 & hash,Optional<int> * height)112     Optional<int> findFork(const uint256& hash, Optional<int>* height) override
113     {
114         LockAssertion lock(::cs_main);
115         const CBlockIndex* block = LookupBlockIndex(hash);
116         const CBlockIndex* fork = block ? ::ChainActive().FindFork(block) : nullptr;
117         if (height) {
118             if (block) {
119                 *height = block->nHeight;
120             } else {
121                 height->reset();
122             }
123         }
124         if (fork) {
125             return fork->nHeight;
126         }
127         return nullopt;
128     }
getTipLocator()129     CBlockLocator getTipLocator() override
130     {
131         LockAssertion lock(::cs_main);
132         return ::ChainActive().GetLocator();
133     }
findLocatorFork(const CBlockLocator & locator)134     Optional<int> findLocatorFork(const CBlockLocator& locator) override
135     {
136         LockAssertion lock(::cs_main);
137         if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) {
138             return fork->nHeight;
139         }
140         return nullopt;
141     }
checkFinalTx(const CTransaction & tx)142     bool checkFinalTx(const CTransaction& tx) override
143     {
144         LockAssertion lock(::cs_main);
145         return CheckFinalTx(tx);
146     }
getImmatureStakes()147     std::map<COutPoint, uint32_t> getImmatureStakes() override
148     {
149         LockAssertion lock(::cs_main);
150         return GetImmatureStakes();
151     }
152 
153     using UniqueLock::UniqueLock;
154 };
155 
156 class NotificationsProxy : public CValidationInterface
157 {
158 public:
NotificationsProxy(std::shared_ptr<Chain::Notifications> notifications)159     explicit NotificationsProxy(std::shared_ptr<Chain::Notifications> notifications)
160         : m_notifications(std::move(notifications)) {}
161     virtual ~NotificationsProxy() = default;
TransactionAddedToMempool(const CTransactionRef & tx)162     void TransactionAddedToMempool(const CTransactionRef& tx) override
163     {
164         m_notifications->transactionAddedToMempool(tx);
165     }
TransactionRemovedFromMempool(const CTransactionRef & tx,MemPoolRemovalReason reason)166     void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason) override
167     {
168         m_notifications->transactionRemovedFromMempool(tx, reason);
169     }
BlockConnected(const std::shared_ptr<const CBlock> & block,const CBlockIndex * index)170     void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
171     {
172         m_notifications->blockConnected(*block, index->nHeight);
173     }
BlockDisconnected(const std::shared_ptr<const CBlock> & block,const CBlockIndex * index)174     void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
175     {
176         m_notifications->blockDisconnected(*block, index->nHeight);
177     }
UpdatedBlockTip(const CBlockIndex * index,const CBlockIndex * fork_index,bool is_ibd)178     void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override
179     {
180         m_notifications->updatedBlockTip();
181     }
ChainStateFlushed(const CBlockLocator & locator)182     void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->chainStateFlushed(locator); }
183     std::shared_ptr<Chain::Notifications> m_notifications;
184 };
185 
186 class NotificationsHandlerImpl : public Handler
187 {
188 public:
NotificationsHandlerImpl(std::shared_ptr<Chain::Notifications> notifications)189     explicit NotificationsHandlerImpl(std::shared_ptr<Chain::Notifications> notifications)
190         : m_proxy(std::make_shared<NotificationsProxy>(std::move(notifications)))
191     {
192         RegisterSharedValidationInterface(m_proxy);
193     }
~NotificationsHandlerImpl()194     ~NotificationsHandlerImpl() override { disconnect(); }
disconnect()195     void disconnect() override
196     {
197         if (m_proxy) {
198             UnregisterSharedValidationInterface(m_proxy);
199             m_proxy.reset();
200         }
201     }
202     std::shared_ptr<NotificationsProxy> m_proxy;
203 };
204 
205 class RpcHandlerImpl : public Handler
206 {
207 public:
RpcHandlerImpl(const CRPCCommand & command)208     explicit RpcHandlerImpl(const CRPCCommand& command) : m_command(command), m_wrapped_command(&command)
209     {
210         m_command.actor = [this](const JSONRPCRequest& request, UniValue& result, bool last_handler) {
211             if (!m_wrapped_command) return false;
212             try {
213                 return m_wrapped_command->actor(request, result, last_handler);
214             } catch (const UniValue& e) {
215                 // If this is not the last handler and a wallet not found
216                 // exception was thrown, return false so the next handler can
217                 // try to handle the request. Otherwise, reraise the exception.
218                 if (!last_handler) {
219                     const UniValue& code = e["code"];
220                     if (code.isNum() && code.get_int() == RPC_WALLET_NOT_FOUND) {
221                         return false;
222                     }
223                 }
224                 throw;
225             }
226         };
227         ::tableRPC.appendCommand(m_command.name, &m_command);
228     }
229 
disconnect()230     void disconnect() override final
231     {
232         if (m_wrapped_command) {
233             m_wrapped_command = nullptr;
234             ::tableRPC.removeCommand(m_command.name, &m_command);
235         }
236     }
237 
~RpcHandlerImpl()238     ~RpcHandlerImpl() override { disconnect(); }
239 
240     CRPCCommand m_command;
241     const CRPCCommand* m_wrapped_command;
242 };
243 
244 class ChainImpl : public Chain
245 {
246 public:
ChainImpl(NodeContext & node)247     explicit ChainImpl(NodeContext& node) : m_node(node) {}
lock(bool try_lock)248     std::unique_ptr<Chain::Lock> lock(bool try_lock) override
249     {
250         auto lock = MakeUnique<LockImpl>(::cs_main, "cs_main", __FILE__, __LINE__, try_lock);
251         if (try_lock && lock && !*lock) return {};
252         std::unique_ptr<Chain::Lock> result = std::move(lock); // Temporary to avoid CWG 1579
253         return result;
254     }
findBlock(const uint256 & hash,CBlock * block,int64_t * time,int64_t * time_max)255     bool findBlock(const uint256& hash, CBlock* block, int64_t* time, int64_t* time_max) override
256     {
257         CBlockIndex* index;
258         {
259             LOCK(cs_main);
260             index = LookupBlockIndex(hash);
261             if (!index) {
262                 return false;
263             }
264             if (time) {
265                 *time = index->GetBlockTime();
266             }
267             if (time_max) {
268                 *time_max = index->GetBlockTimeMax();
269             }
270         }
271         if (block && !ReadBlockFromDisk(*block, index, Params().GetConsensus())) {
272             block->SetNull();
273         }
274         return true;
275     }
findCoins(std::map<COutPoint,Coin> & coins)276     void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
guessVerificationProgress(const uint256 & block_hash)277     double guessVerificationProgress(const uint256& block_hash) override
278     {
279         LOCK(cs_main);
280         return GuessVerificationProgress(Params().TxData(), LookupBlockIndex(block_hash));
281     }
isRBFOptIn(const CTransaction & tx)282     RBFTransactionState isRBFOptIn(const CTransaction& tx) override
283     {
284         LOCK(::mempool.cs);
285         return IsRBFOptIn(tx, ::mempool);
286     }
hasDescendantsInMempool(const uint256 & txid)287     bool hasDescendantsInMempool(const uint256& txid) override
288     {
289         LOCK(::mempool.cs);
290         auto it = ::mempool.GetIter(txid);
291         return it && (*it)->GetCountWithDescendants() > 1;
292     }
broadcastTransaction(const CTransactionRef & tx,const CAmount & max_tx_fee,bool relay,std::string & err_string)293     bool broadcastTransaction(const CTransactionRef& tx,
294         const CAmount& max_tx_fee,
295         bool relay,
296         std::string& err_string) override
297     {
298         const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, relay, /*wait_callback*/ false);
299         // Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures.
300         // Note: this will need to be updated if BroadcastTransactions() is updated to return other non-mempool failures
301         // that Chain clients do not need to know about.
302         return TransactionError::OK == err;
303     }
getTransactionAncestry(const uint256 & txid,size_t & ancestors,size_t & descendants)304     void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) override
305     {
306         ::mempool.GetTransactionAncestry(txid, ancestors, descendants);
307     }
getPackageLimits(unsigned int & limit_ancestor_count,unsigned int & limit_descendant_count)308     void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) override
309     {
310         limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
311         limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
312     }
checkChainLimits(const CTransactionRef & tx)313     bool checkChainLimits(const CTransactionRef& tx) override
314     {
315         LockPoints lp;
316         CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp);
317         CTxMemPool::setEntries ancestors;
318         auto limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
319         auto limit_ancestor_size = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000;
320         auto limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
321         auto limit_descendant_size = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000;
322         std::string unused_error_string;
323         LOCK(::mempool.cs);
324         return ::mempool.CalculateMemPoolAncestors(entry, ancestors, limit_ancestor_count, limit_ancestor_size,
325             limit_descendant_count, limit_descendant_size, unused_error_string);
326     }
estimateSmartFee(int num_blocks,bool conservative,FeeCalculation * calc)327     CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
328     {
329         return ::feeEstimator.estimateSmartFee(num_blocks, calc, conservative);
330     }
estimateMaxBlocks()331     unsigned int estimateMaxBlocks() override
332     {
333         return ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
334     }
mempoolMinFee()335     CFeeRate mempoolMinFee() override
336     {
337         return ::mempool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
338     }
relayMinFee()339     CFeeRate relayMinFee() override { return ::minRelayTxFee; }
relayIncrementalFee()340     CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; }
relayDustFee()341     CFeeRate relayDustFee() override { return ::dustRelayFee; }
havePruned()342     bool havePruned() override
343     {
344         LOCK(cs_main);
345         return ::fHavePruned;
346     }
isReadyToBroadcast()347     bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
isInitialBlockDownload()348     bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
shutdownRequested()349     bool shutdownRequested() override { return ShutdownRequested(); }
getAdjustedTime()350     int64_t getAdjustedTime() override { return GetAdjustedTime(); }
initMessage(const std::string & message)351     void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
initWarning(const std::string & message)352     void initWarning(const std::string& message) override { InitWarning(message); }
initError(const std::string & message)353     void initError(const std::string& message) override { InitError(message); }
showProgress(const std::string & title,int progress,bool resume_possible)354     void showProgress(const std::string& title, int progress, bool resume_possible) override
355     {
356         ::uiInterface.ShowProgress(title, progress, resume_possible);
357     }
handleNotifications(std::shared_ptr<Notifications> notifications)358     std::unique_ptr<Handler> handleNotifications(std::shared_ptr<Notifications> notifications) override
359     {
360         return MakeUnique<NotificationsHandlerImpl>(std::move(notifications));
361     }
waitForNotificationsIfTipChanged(const uint256 & old_tip)362     void waitForNotificationsIfTipChanged(const uint256& old_tip) override
363     {
364         if (!old_tip.IsNull()) {
365             LOCK(::cs_main);
366             if (old_tip == ::ChainActive().Tip()->GetBlockHash()) return;
367         }
368         SyncWithValidationInterfaceQueue();
369     }
handleRpc(const CRPCCommand & command)370     std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override
371     {
372         return MakeUnique<RpcHandlerImpl>(command);
373     }
rpcEnableDeprecated(const std::string & method)374     bool rpcEnableDeprecated(const std::string& method) override { return IsDeprecatedRPCEnabled(method); }
rpcRunLater(const std::string & name,std::function<void ()> fn,int64_t seconds)375     void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) override
376     {
377         RPCRunLater(name, std::move(fn), seconds);
378     }
rpcSerializationFlags()379     int rpcSerializationFlags() override { return RPCSerializationFlags(); }
requestMempoolTransactions(Notifications & notifications)380     void requestMempoolTransactions(Notifications& notifications) override
381     {
382         LOCK2(::cs_main, ::mempool.cs);
383         for (const CTxMemPoolEntry& entry : ::mempool.mapTx) {
384             notifications.transactionAddedToMempool(entry.GetSharedTx());
385         }
386     }
387     NodeContext& m_node;
388 };
389 } // namespace
390 
MakeChain(NodeContext & node)391 std::unique_ptr<Chain> MakeChain(NodeContext& node) { return MakeUnique<ChainImpl>(node); }
392 
393 } // namespace interfaces
394