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 <node/ui_interface.h>
17 #include <policy/fees.h>
18 #include <policy/policy.h>
19 #include <policy/rbf.h>
20 #include <policy/settings.h>
21 #include <primitives/block.h>
22 #include <primitives/transaction.h>
23 #include <rpc/protocol.h>
24 #include <rpc/server.h>
25 #include <shutdown.h>
26 #include <sync.h>
27 #include <timedata.h>
28 #include <txmempool.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 
FillBlock(const CBlockIndex * index,const FoundBlock & block,UniqueLock<RecursiveMutex> & lock)41 bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock)
42 {
43     if (!index) return false;
44     if (block.m_hash) *block.m_hash = index->GetBlockHash();
45     if (block.m_height) *block.m_height = index->nHeight;
46     if (block.m_time) *block.m_time = index->GetBlockTime();
47     if (block.m_max_time) *block.m_max_time = index->GetBlockTimeMax();
48     if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast();
49     if (block.m_data) {
50         REVERSE_LOCK(lock);
51         if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull();
52     }
53     return true;
54 }
55 
56 class NotificationsProxy : public CValidationInterface
57 {
58 public:
NotificationsProxy(std::shared_ptr<Chain::Notifications> notifications)59     explicit NotificationsProxy(std::shared_ptr<Chain::Notifications> notifications)
60         : m_notifications(std::move(notifications)) {}
61     virtual ~NotificationsProxy() = default;
TransactionAddedToMempool(const CTransactionRef & tx,uint64_t mempool_sequence)62     void TransactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override
63     {
64         m_notifications->transactionAddedToMempool(tx, mempool_sequence);
65     }
TransactionRemovedFromMempool(const CTransactionRef & tx,MemPoolRemovalReason reason,uint64_t mempool_sequence)66     void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
67     {
68         m_notifications->transactionRemovedFromMempool(tx, reason, mempool_sequence);
69     }
BlockConnected(const std::shared_ptr<const CBlock> & block,const CBlockIndex * index)70     void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
71     {
72         m_notifications->blockConnected(*block, index->nHeight);
73     }
BlockDisconnected(const std::shared_ptr<const CBlock> & block,const CBlockIndex * index)74     void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
75     {
76         m_notifications->blockDisconnected(*block, index->nHeight);
77     }
UpdatedBlockTip(const CBlockIndex * index,const CBlockIndex * fork_index,bool is_ibd)78     void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override
79     {
80         m_notifications->updatedBlockTip();
81     }
ChainStateFlushed(const CBlockLocator & locator)82     void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->chainStateFlushed(locator); }
83     std::shared_ptr<Chain::Notifications> m_notifications;
84 };
85 
86 class NotificationsHandlerImpl : public Handler
87 {
88 public:
NotificationsHandlerImpl(std::shared_ptr<Chain::Notifications> notifications)89     explicit NotificationsHandlerImpl(std::shared_ptr<Chain::Notifications> notifications)
90         : m_proxy(std::make_shared<NotificationsProxy>(std::move(notifications)))
91     {
92         RegisterSharedValidationInterface(m_proxy);
93     }
~NotificationsHandlerImpl()94     ~NotificationsHandlerImpl() override { disconnect(); }
disconnect()95     void disconnect() override
96     {
97         if (m_proxy) {
98             UnregisterSharedValidationInterface(m_proxy);
99             m_proxy.reset();
100         }
101     }
102     std::shared_ptr<NotificationsProxy> m_proxy;
103 };
104 
105 class RpcHandlerImpl : public Handler
106 {
107 public:
RpcHandlerImpl(const CRPCCommand & command)108     explicit RpcHandlerImpl(const CRPCCommand& command) : m_command(command), m_wrapped_command(&command)
109     {
110         m_command.actor = [this](const JSONRPCRequest& request, UniValue& result, bool last_handler) {
111             if (!m_wrapped_command) return false;
112             try {
113                 return m_wrapped_command->actor(request, result, last_handler);
114             } catch (const UniValue& e) {
115                 // If this is not the last handler and a wallet not found
116                 // exception was thrown, return false so the next handler can
117                 // try to handle the request. Otherwise, reraise the exception.
118                 if (!last_handler) {
119                     const UniValue& code = e["code"];
120                     if (code.isNum() && code.get_int() == RPC_WALLET_NOT_FOUND) {
121                         return false;
122                     }
123                 }
124                 throw;
125             }
126         };
127         ::tableRPC.appendCommand(m_command.name, &m_command);
128     }
129 
disconnect()130     void disconnect() final
131     {
132         if (m_wrapped_command) {
133             m_wrapped_command = nullptr;
134             ::tableRPC.removeCommand(m_command.name, &m_command);
135         }
136     }
137 
~RpcHandlerImpl()138     ~RpcHandlerImpl() override { disconnect(); }
139 
140     CRPCCommand m_command;
141     const CRPCCommand* m_wrapped_command;
142 };
143 
144 class ChainImpl : public Chain
145 {
146 public:
ChainImpl(NodeContext & node)147     explicit ChainImpl(NodeContext& node) : m_node(node) {}
getHeight()148     Optional<int> getHeight() override
149     {
150         LOCK(::cs_main);
151         int height = ::ChainActive().Height();
152         if (height >= 0) {
153             return height;
154         }
155         return nullopt;
156     }
getBlockHeight(const uint256 & hash)157     Optional<int> getBlockHeight(const uint256& hash) override
158     {
159         LOCK(::cs_main);
160         CBlockIndex* block = LookupBlockIndex(hash);
161         if (block && ::ChainActive().Contains(block)) {
162             return block->nHeight;
163         }
164         return nullopt;
165     }
getBlockHash(int height)166     uint256 getBlockHash(int height) override
167     {
168         LOCK(::cs_main);
169         CBlockIndex* block = ::ChainActive()[height];
170         assert(block);
171         return block->GetBlockHash();
172     }
haveBlockOnDisk(int height)173     bool haveBlockOnDisk(int height) override
174     {
175         LOCK(cs_main);
176         CBlockIndex* block = ::ChainActive()[height];
177         return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
178     }
findFirstBlockWithTimeAndHeight(int64_t time,int height,uint256 * hash)179     Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
180     {
181         LOCK(cs_main);
182         CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height);
183         if (block) {
184             if (hash) *hash = block->GetBlockHash();
185             return block->nHeight;
186         }
187         return nullopt;
188     }
getTipLocator()189     CBlockLocator getTipLocator() override
190     {
191         LOCK(cs_main);
192         return ::ChainActive().GetLocator();
193     }
checkFinalTx(const CTransaction & tx)194     bool checkFinalTx(const CTransaction& tx) override
195     {
196         LOCK(cs_main);
197         return CheckFinalTx(tx);
198     }
findLocatorFork(const CBlockLocator & locator)199     Optional<int> findLocatorFork(const CBlockLocator& locator) override
200     {
201         LOCK(cs_main);
202         if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) {
203             return fork->nHeight;
204         }
205         return nullopt;
206     }
findBlock(const uint256 & hash,const FoundBlock & block)207     bool findBlock(const uint256& hash, const FoundBlock& block) override
208     {
209         WAIT_LOCK(cs_main, lock);
210         return FillBlock(LookupBlockIndex(hash), block, lock);
211     }
findFirstBlockWithTimeAndHeight(int64_t min_time,int min_height,const FoundBlock & block)212     bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
213     {
214         WAIT_LOCK(cs_main, lock);
215         return FillBlock(ChainActive().FindEarliestAtLeast(min_time, min_height), block, lock);
216     }
findNextBlock(const uint256 & block_hash,int block_height,const FoundBlock & next,bool * reorg)217     bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next, bool* reorg) override {
218         WAIT_LOCK(cs_main, lock);
219         CBlockIndex* block = ChainActive()[block_height];
220         if (block && block->GetBlockHash() != block_hash) block = nullptr;
221         if (reorg) *reorg = !block;
222         return FillBlock(block ? ChainActive()[block_height + 1] : nullptr, next, lock);
223     }
findAncestorByHeight(const uint256 & block_hash,int ancestor_height,const FoundBlock & ancestor_out)224     bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
225     {
226         WAIT_LOCK(cs_main, lock);
227         if (const CBlockIndex* block = LookupBlockIndex(block_hash)) {
228             if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
229                 return FillBlock(ancestor, ancestor_out, lock);
230             }
231         }
232         return FillBlock(nullptr, ancestor_out, lock);
233     }
findAncestorByHash(const uint256 & block_hash,const uint256 & ancestor_hash,const FoundBlock & ancestor_out)234     bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
235     {
236         WAIT_LOCK(cs_main, lock);
237         const CBlockIndex* block = LookupBlockIndex(block_hash);
238         const CBlockIndex* ancestor = LookupBlockIndex(ancestor_hash);
239         if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
240         return FillBlock(ancestor, ancestor_out, lock);
241     }
findCommonAncestor(const uint256 & block_hash1,const uint256 & block_hash2,const FoundBlock & ancestor_out,const FoundBlock & block1_out,const FoundBlock & block2_out)242     bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override
243     {
244         WAIT_LOCK(cs_main, lock);
245         const CBlockIndex* block1 = LookupBlockIndex(block_hash1);
246         const CBlockIndex* block2 = LookupBlockIndex(block_hash2);
247         const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
248         // Using & instead of && below to avoid short circuiting and leaving
249         // output uninitialized.
250         return FillBlock(ancestor, ancestor_out, lock) & FillBlock(block1, block1_out, lock) & FillBlock(block2, block2_out, lock);
251     }
findCoins(std::map<COutPoint,Coin> & coins)252     void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
guessVerificationProgress(const uint256 & block_hash)253     double guessVerificationProgress(const uint256& block_hash) override
254     {
255         LOCK(cs_main);
256         return GuessVerificationProgress(Params().TxData(), LookupBlockIndex(block_hash));
257     }
hasBlocks(const uint256 & block_hash,int min_height,Optional<int> max_height)258     bool hasBlocks(const uint256& block_hash, int min_height, Optional<int> max_height) override
259     {
260         // hasBlocks returns true if all ancestors of block_hash in specified
261         // range have block data (are not pruned), false if any ancestors in
262         // specified range are missing data.
263         //
264         // For simplicity and robustness, min_height and max_height are only
265         // used to limit the range, and passing min_height that's too low or
266         // max_height that's too high will not crash or change the result.
267         LOCK(::cs_main);
268         if (CBlockIndex* block = LookupBlockIndex(block_hash)) {
269             if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height);
270             for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) {
271                 // Check pprev to not segfault if min_height is too low
272                 if (block->nHeight <= min_height || !block->pprev) return true;
273             }
274         }
275         return false;
276     }
isRBFOptIn(const CTransaction & tx)277     RBFTransactionState isRBFOptIn(const CTransaction& tx) override
278     {
279         if (!m_node.mempool) return IsRBFOptInEmptyMempool(tx);
280         LOCK(m_node.mempool->cs);
281         return IsRBFOptIn(tx, *m_node.mempool);
282     }
hasDescendantsInMempool(const uint256 & txid)283     bool hasDescendantsInMempool(const uint256& txid) override
284     {
285         if (!m_node.mempool) return false;
286         LOCK(m_node.mempool->cs);
287         auto it = m_node.mempool->GetIter(txid);
288         return it && (*it)->GetCountWithDescendants() > 1;
289     }
broadcastTransaction(const CTransactionRef & tx,const CAmount & max_tx_fee,bool relay,std::string & err_string)290     bool broadcastTransaction(const CTransactionRef& tx,
291         const CAmount& max_tx_fee,
292         bool relay,
293         std::string& err_string) override
294     {
295         const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, relay, /*wait_callback*/ false);
296         // Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures.
297         // Note: this will need to be updated if BroadcastTransactions() is updated to return other non-mempool failures
298         // that Chain clients do not need to know about.
299         return TransactionError::OK == err;
300     }
getTransactionAncestry(const uint256 & txid,size_t & ancestors,size_t & descendants)301     void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) override
302     {
303         ancestors = descendants = 0;
304         if (!m_node.mempool) return;
305         m_node.mempool->GetTransactionAncestry(txid, ancestors, descendants);
306     }
getPackageLimits(unsigned int & limit_ancestor_count,unsigned int & limit_descendant_count)307     void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) override
308     {
309         limit_ancestor_count = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
310         limit_descendant_count = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
311     }
checkChainLimits(const CTransactionRef & tx)312     bool checkChainLimits(const CTransactionRef& tx) override
313     {
314         if (!m_node.mempool) return true;
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(m_node.mempool->cs);
324         return m_node.mempool->CalculateMemPoolAncestors(
325             entry, ancestors, limit_ancestor_count, limit_ancestor_size,
326             limit_descendant_count, limit_descendant_size, unused_error_string);
327     }
estimateSmartFee(int num_blocks,bool conservative,FeeCalculation * calc)328     CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
329     {
330         return ::feeEstimator.estimateSmartFee(num_blocks, calc, conservative);
331     }
estimateMaxBlocks()332     unsigned int estimateMaxBlocks() override
333     {
334         return ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
335     }
mempoolMinFee()336     CFeeRate mempoolMinFee() override
337     {
338         if (!m_node.mempool) return {};
339         return m_node.mempool->GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
340     }
relayMinFee()341     CFeeRate relayMinFee() override { return ::minRelayTxFee; }
relayIncrementalFee()342     CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; }
relayDustFee()343     CFeeRate relayDustFee() override { return ::dustRelayFee; }
havePruned()344     bool havePruned() override
345     {
346         LOCK(cs_main);
347         return ::fHavePruned;
348     }
isReadyToBroadcast()349     bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); }
isInitialBlockDownload()350     bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
shutdownRequested()351     bool shutdownRequested() override { return ShutdownRequested(); }
getAdjustedTime()352     int64_t getAdjustedTime() override { return GetAdjustedTime(); }
initMessage(const std::string & message)353     void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
initWarning(const bilingual_str & message)354     void initWarning(const bilingual_str& message) override { InitWarning(message); }
initError(const bilingual_str & message)355     void initError(const bilingual_str& message) override { InitError(message); }
showProgress(const std::string & title,int progress,bool resume_possible)356     void showProgress(const std::string& title, int progress, bool resume_possible) override
357     {
358         ::uiInterface.ShowProgress(title, progress, resume_possible);
359     }
handleNotifications(std::shared_ptr<Notifications> notifications)360     std::unique_ptr<Handler> handleNotifications(std::shared_ptr<Notifications> notifications) override
361     {
362         return MakeUnique<NotificationsHandlerImpl>(std::move(notifications));
363     }
waitForNotificationsIfTipChanged(const uint256 & old_tip)364     void waitForNotificationsIfTipChanged(const uint256& old_tip) override
365     {
366         if (!old_tip.IsNull()) {
367             LOCK(::cs_main);
368             if (old_tip == ::ChainActive().Tip()->GetBlockHash()) return;
369         }
370         SyncWithValidationInterfaceQueue();
371     }
handleRpc(const CRPCCommand & command)372     std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override
373     {
374         return MakeUnique<RpcHandlerImpl>(command);
375     }
rpcEnableDeprecated(const std::string & method)376     bool rpcEnableDeprecated(const std::string& method) override { return IsDeprecatedRPCEnabled(method); }
rpcRunLater(const std::string & name,std::function<void ()> fn,int64_t seconds)377     void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) override
378     {
379         RPCRunLater(name, std::move(fn), seconds);
380     }
rpcSerializationFlags()381     int rpcSerializationFlags() override { return RPCSerializationFlags(); }
getRwSetting(const std::string & name)382     util::SettingsValue getRwSetting(const std::string& name) override
383     {
384         util::SettingsValue result;
385         gArgs.LockSettings([&](const util::Settings& settings) {
386             if (const util::SettingsValue* value = util::FindKey(settings.rw_settings, name)) {
387                 result = *value;
388             }
389         });
390         return result;
391     }
updateRwSetting(const std::string & name,const util::SettingsValue & value)392     bool updateRwSetting(const std::string& name, const util::SettingsValue& value) override
393     {
394         gArgs.LockSettings([&](util::Settings& settings) {
395             if (value.isNull()) {
396                 settings.rw_settings.erase(name);
397             } else {
398                 settings.rw_settings[name] = value;
399             }
400         });
401         return gArgs.WriteSettingsFile();
402     }
requestMempoolTransactions(Notifications & notifications)403     void requestMempoolTransactions(Notifications& notifications) override
404     {
405         if (!m_node.mempool) return;
406         LOCK2(::cs_main, m_node.mempool->cs);
407         for (const CTxMemPoolEntry& entry : m_node.mempool->mapTx) {
408             notifications.transactionAddedToMempool(entry.GetSharedTx(), 0 /* mempool_sequence */);
409         }
410     }
411     NodeContext& m_node;
412 };
413 } // namespace
414 
MakeChain(NodeContext & node)415 std::unique_ptr<Chain> MakeChain(NodeContext& node) { return MakeUnique<ChainImpl>(node); }
416 
417 } // namespace interfaces
418