Skip to content

Commit ac579ad

Browse files
author
MarcoFalke
committed
Merge bitcoin#18278: interfaces: Describe and follow some code conventions
3dc27a1 doc: Add internal interface conventions to developer notes (Russell Yanofsky) 1dca9dc refactor: Change createWallet, fillPSBT argument order (Russell Yanofsky) 96dfe5c refactor: Change Chain::broadcastTransaction param order (Russell Yanofsky) 6ceb219 refactor: Rename Chain::Notifications methods to be consistent with other interfaces methods (Russell Yanofsky) 1c2ab1a refactor: Rename Node::disconnect methods (Russell Yanofsky) 77e4b06 refactor: Get rid of Wallet::IsWalletFlagSet method (Russell Yanofsky) Pull request description: This PR is part of the [process separation project](https://github.com/bitcoin/bitcoin/projects/10). This PR doesn't change behavior at all, it just cleans up code in [`src/interfaces`](https://github.com/bitcoin/bitcoin/tree/master/src/interfaces) to simplify bitcoin#10102, and [documents](https://github.com/ryanofsky/bitcoin/blob/pr/ipc-conv/doc/developer-notes.md#internal-interface-guidelines) coding conventions there better ACKs for top commit: hebasto: re-ACK 3dc27a1, the only change since the [previous](bitcoin#18278 (review)) review is rebasing. MarcoFalke: ACK 3dc27a1 🕍 Tree-SHA512: 62e6a0f2488e3924e559d2074ed460b92e7a0a5d98eab492221cb20d59d04bbe32aef2a8aeba5e4ea9168cfa91acd5bc973dce6677be0180bd7a919354df53ed
2 parents 97b0687 + 3dc27a1 commit ac579ad

17 files changed

+208
-93
lines changed

doc/developer-notes.md

+122
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Developer Notes
4343
- [Suggestions and examples](#suggestions-and-examples)
4444
- [Release notes](#release-notes)
4545
- [RPC interface guidelines](#rpc-interface-guidelines)
46+
- [Internal interface guidelines](#internal-interface-guidelines)
4647

4748
<!-- markdown-toc end -->
4849

@@ -1100,3 +1101,124 @@ A few guidelines for introducing and reviewing new RPC interfaces:
11001101
timestamps in the documentation.
11011102

11021103
- *Rationale*: User-facing consistency.
1104+
1105+
Internal interface guidelines
1106+
-----------------------------
1107+
1108+
Internal interfaces between parts of the codebase that are meant to be
1109+
independent (node, wallet, GUI), are defined in
1110+
[`src/interfaces/`](../src/interfaces/). The main interface classes defined
1111+
there are [`interfaces::Chain`](../src/interfaces/chain.h), used by wallet to
1112+
access the node's latest chain state,
1113+
[`interfaces::Node`](../src/interfaces/node.h), used by the GUI to control the
1114+
node, and [`interfaces::Wallet`](../src/interfaces/wallet.h), used by the GUI
1115+
to control an individual wallet. There are also more specialized interface
1116+
types like [`interfaces::Handler`](../src/interfaces/handler.h)
1117+
[`interfaces::ChainClient`](../src/interfaces/chain.h) passed to and from
1118+
various interface methods.
1119+
1120+
Interface classes are written in a particular style so node, wallet, and GUI
1121+
code doesn't need to run in the same process, and so the class declarations
1122+
work more easily with tools and libraries supporting interprocess
1123+
communication:
1124+
1125+
- Interface classes should be abstract and have methods that are [pure
1126+
virtual](https://en.cppreference.com/w/cpp/language/abstract_class). This
1127+
allows multiple implementations to inherit from the same interface class,
1128+
particularly so one implementation can execute functionality in the local
1129+
process, and other implementations can forward calls to remote processes.
1130+
1131+
- Interface method definitions should wrap existing functionality instead of
1132+
implementing new functionality. Any substantial new node or wallet
1133+
functionality should be implemented in [`src/node/`](../src/node/) or
1134+
[`src/wallet/`](../src/wallet/) and just exposed in
1135+
[`src/interfaces/`](../src/interfaces/) instead of being implemented there,
1136+
so it can be more modular and accessible to unit tests.
1137+
1138+
- Interface method parameter and return types should either be serializable or
1139+
be other interface classes. Interface methods shouldn't pass references to
1140+
objects that can't be serialized or accessed from another process.
1141+
1142+
Examples:
1143+
1144+
```c++
1145+
// Good: takes string argument and returns interface class pointer
1146+
virtual unique_ptr<interfaces::Wallet> loadWallet(std::string filename) = 0;
1147+
1148+
// Bad: returns CWallet reference that can't be used from another process
1149+
virtual CWallet& loadWallet(std::string filename) = 0;
1150+
```
1151+
1152+
```c++
1153+
// Good: accepts and returns primitive types
1154+
virtual bool findBlock(const uint256& hash, int& out_height, int64_t& out_time) = 0;
1155+
1156+
// Bad: returns pointer to internal node in a linked list inaccessible to
1157+
// other processes
1158+
virtual const CBlockIndex* findBlock(const uint256& hash) = 0;
1159+
```
1160+
1161+
```c++
1162+
// Good: takes plain callback type and returns interface pointer
1163+
using TipChangedFn = std::function<void(int block_height, int64_t block_time)>;
1164+
virtual std::unique_ptr<interfaces::Handler> handleTipChanged(TipChangedFn fn) = 0;
1165+
1166+
// Bad: returns boost connection specific to local process
1167+
using TipChangedFn = std::function<void(int block_height, int64_t block_time)>;
1168+
virtual boost::signals2::scoped_connection connectTipChanged(TipChangedFn fn) = 0;
1169+
```
1170+
1171+
- For consistency and friendliness to code generation tools, interface method
1172+
input and inout parameters should be ordered first and output parameters
1173+
should come last.
1174+
1175+
Example:
1176+
1177+
```c++
1178+
// Good: error output param is last
1179+
virtual bool broadcastTransaction(const CTransactionRef& tx, CAmount max_fee, std::string& error) = 0;
1180+
1181+
// Bad: error output param is between input params
1182+
virtual bool broadcastTransaction(const CTransactionRef& tx, std::string& error, CAmount max_fee) = 0;
1183+
```
1184+
1185+
- For friendliness to code generation tools, interface methods should not be
1186+
overloaded:
1187+
1188+
Example:
1189+
1190+
```c++
1191+
// Good: method names are unique
1192+
virtual bool disconnectByAddress(const CNetAddr& net_addr) = 0;
1193+
virtual bool disconnectById(NodeId id) = 0;
1194+
1195+
// Bad: methods are overloaded by type
1196+
virtual bool disconnect(const CNetAddr& net_addr) = 0;
1197+
virtual bool disconnect(NodeId id) = 0;
1198+
```
1199+
1200+
- For consistency and friendliness to code generation tools, interface method
1201+
names should be `lowerCamelCase` and standalone function names should be
1202+
`UpperCamelCase`.
1203+
1204+
Examples:
1205+
1206+
```c++
1207+
// Good: lowerCamelCase method name
1208+
virtual void blockConnected(const CBlock& block, int height) = 0;
1209+
1210+
// Bad: uppercase class method
1211+
virtual void BlockConnected(const CBlock& block, int height) = 0;
1212+
```
1213+
1214+
```c++
1215+
// Good: UpperCamelCase standalone function name
1216+
std::unique_ptr<Node> MakeNode(LocalInit& init);
1217+
1218+
// Bad: lowercase standalone function
1219+
std::unique_ptr<Node> makeNode(LocalInit& init);
1220+
```
1221+
1222+
Note: This last convention isn't generally followed outside of
1223+
[`src/interfaces/`](../src/interfaces/), though it did come up for discussion
1224+
before in [#14635](https://github.com/bitcoin/bitcoin/pull/14635).

src/interfaces/chain.cpp

+11-8
Original file line numberDiff line numberDiff line change
@@ -166,25 +166,25 @@ class NotificationsHandlerImpl : public Handler, CValidationInterface
166166
}
167167
void TransactionAddedToMempool(const CTransactionRef& tx) override
168168
{
169-
m_notifications->TransactionAddedToMempool(tx);
169+
m_notifications->transactionAddedToMempool(tx);
170170
}
171171
void TransactionRemovedFromMempool(const CTransactionRef& tx) override
172172
{
173-
m_notifications->TransactionRemovedFromMempool(tx);
173+
m_notifications->transactionRemovedFromMempool(tx);
174174
}
175175
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
176176
{
177-
m_notifications->BlockConnected(*block, index->nHeight);
177+
m_notifications->blockConnected(*block, index->nHeight);
178178
}
179179
void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
180180
{
181-
m_notifications->BlockDisconnected(*block, index->nHeight);
181+
m_notifications->blockDisconnected(*block, index->nHeight);
182182
}
183183
void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override
184184
{
185-
m_notifications->UpdatedBlockTip();
185+
m_notifications->updatedBlockTip();
186186
}
187-
void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->ChainStateFlushed(locator); }
187+
void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->chainStateFlushed(locator); }
188188
Chain& m_chain;
189189
Chain::Notifications* m_notifications;
190190
};
@@ -278,7 +278,10 @@ class ChainImpl : public Chain
278278
auto it = ::mempool.GetIter(txid);
279279
return it && (*it)->GetCountWithDescendants() > 1;
280280
}
281-
bool broadcastTransaction(const CTransactionRef& tx, std::string& err_string, const CAmount& max_tx_fee, bool relay) override
281+
bool broadcastTransaction(const CTransactionRef& tx,
282+
const CAmount& max_tx_fee,
283+
bool relay,
284+
std::string& err_string) override
282285
{
283286
const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, relay, /*wait_callback*/ false);
284287
// Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures.
@@ -366,7 +369,7 @@ class ChainImpl : public Chain
366369
{
367370
LOCK2(::cs_main, ::mempool.cs);
368371
for (const CTxMemPoolEntry& entry : ::mempool.mapTx) {
369-
notifications.TransactionAddedToMempool(entry.GetSharedTx());
372+
notifications.transactionAddedToMempool(entry.GetSharedTx());
370373
}
371374
}
372375
NodeContext& m_node;

src/interfaces/chain.h

+11-8
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,10 @@ class Chain
154154
//! Transaction is added to memory pool, if the transaction fee is below the
155155
//! amount specified by max_tx_fee, and broadcast to all peers if relay is set to true.
156156
//! Return false if the transaction could not be added due to the fee or for another reason.
157-
virtual bool broadcastTransaction(const CTransactionRef& tx, std::string& err_string, const CAmount& max_tx_fee, bool relay) = 0;
157+
virtual bool broadcastTransaction(const CTransactionRef& tx,
158+
const CAmount& max_tx_fee,
159+
bool relay,
160+
std::string& err_string) = 0;
158161

159162
//! Calculate mempool ancestor and descendant counts for the given transaction.
160163
virtual void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants) = 0;
@@ -217,12 +220,12 @@ class Chain
217220
{
218221
public:
219222
virtual ~Notifications() {}
220-
virtual void TransactionAddedToMempool(const CTransactionRef& tx) {}
221-
virtual void TransactionRemovedFromMempool(const CTransactionRef& ptx) {}
222-
virtual void BlockConnected(const CBlock& block, int height) {}
223-
virtual void BlockDisconnected(const CBlock& block, int height) {}
224-
virtual void UpdatedBlockTip() {}
225-
virtual void ChainStateFlushed(const CBlockLocator& locator) {}
223+
virtual void transactionAddedToMempool(const CTransactionRef& tx) {}
224+
virtual void transactionRemovedFromMempool(const CTransactionRef& ptx) {}
225+
virtual void blockConnected(const CBlock& block, int height) {}
226+
virtual void blockDisconnected(const CBlock& block, int height) {}
227+
virtual void updatedBlockTip() {}
228+
virtual void chainStateFlushed(const CBlockLocator& locator) {}
226229
};
227230

228231
//! Register handler for notifications.
@@ -245,7 +248,7 @@ class Chain
245248
//! Current RPC serialization flags.
246249
virtual int rpcSerializationFlags() = 0;
247250

248-
//! Synchronously send TransactionAddedToMempool notifications about all
251+
//! Synchronously send transactionAddedToMempool notifications about all
249252
//! current mempool transactions to the specified handler and return after
250253
//! the last one is sent. These notifications aren't coordinated with async
251254
//! notifications sent by handleNotifications, so out of date async

src/interfaces/node.cpp

+5-6
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,14 @@ class NodeImpl : public Node
152152
}
153153
return false;
154154
}
155-
bool disconnect(const CNetAddr& net_addr) override
155+
bool disconnectByAddress(const CNetAddr& net_addr) override
156156
{
157157
if (m_context.connman) {
158158
return m_context.connman->DisconnectNode(net_addr);
159159
}
160160
return false;
161161
}
162-
bool disconnect(NodeId id) override
162+
bool disconnectById(NodeId id) override
163163
{
164164
if (m_context.connman) {
165165
return m_context.connman->DisconnectNode(id);
@@ -262,12 +262,11 @@ class NodeImpl : public Node
262262
{
263263
return MakeWallet(LoadWallet(*m_context.chain, name, error, warnings));
264264
}
265-
WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::unique_ptr<Wallet>& result) override
265+
std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, WalletCreationStatus& status) override
266266
{
267267
std::shared_ptr<CWallet> wallet;
268-
WalletCreationStatus status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
269-
result = MakeWallet(wallet);
270-
return status;
268+
status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
269+
return MakeWallet(wallet);
271270
}
272271
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
273272
{

src/interfaces/node.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,10 @@ class Node
124124
virtual bool unban(const CSubNet& ip) = 0;
125125

126126
//! Disconnect node by address.
127-
virtual bool disconnect(const CNetAddr& net_addr) = 0;
127+
virtual bool disconnectByAddress(const CNetAddr& net_addr) = 0;
128128

129129
//! Disconnect node by id.
130-
virtual bool disconnect(NodeId id) = 0;
130+
virtual bool disconnectById(NodeId id) = 0;
131131

132132
//! Get total bytes recv.
133133
virtual int64_t getTotalBytesRecv() = 0;
@@ -204,7 +204,7 @@ class Node
204204
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::vector<std::string>& warnings) = 0;
205205

206206
//! Create a wallet from file
207-
virtual WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::unique_ptr<Wallet>& result) = 0;
207+
virtual std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, WalletCreationStatus& status) = 0;
208208

209209
//! Register handler for init messages.
210210
using InitMessageFn = std::function<void(const std::string& message)>;

src/interfaces/wallet.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,11 @@ class WalletImpl : public Wallet
352352
}
353353
return {};
354354
}
355-
TransactionError fillPSBT(PartiallySignedTransaction& psbtx,
356-
bool& complete,
357-
int sighash_type = 1 /* SIGHASH_ALL */,
358-
bool sign = true,
359-
bool bip32derivs = false) const override
355+
TransactionError fillPSBT(int sighash_type,
356+
bool sign,
357+
bool bip32derivs,
358+
PartiallySignedTransaction& psbtx,
359+
bool& complete) override
360360
{
361361
return m_wallet->FillPSBT(psbtx, complete, sighash_type, sign, bip32derivs);
362362
}
@@ -463,8 +463,8 @@ class WalletImpl : public Wallet
463463
}
464464
unsigned int getConfirmTarget() override { return m_wallet->m_confirm_target; }
465465
bool hdEnabled() override { return m_wallet->IsHDEnabled(); }
466-
bool canGetAddresses() const override { return m_wallet->CanGetAddresses(); }
467-
bool IsWalletFlagSet(uint64_t flag) override { return m_wallet->IsWalletFlagSet(flag); }
466+
bool canGetAddresses() override { return m_wallet->CanGetAddresses(); }
467+
bool privateKeysDisabled() override { return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS); }
468468
OutputType getDefaultAddressType() override { return m_wallet->m_default_address_type; }
469469
OutputType getDefaultChangeType() override { return m_wallet->m_default_change_type; }
470470
CAmount getDefaultMaxTxFee() override { return m_wallet->m_default_max_tx_fee; }

src/interfaces/wallet.h

+8-8
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,11 @@ class Wallet
193193
int& num_blocks) = 0;
194194

195195
//! Fill PSBT.
196-
virtual TransactionError fillPSBT(PartiallySignedTransaction& psbtx,
197-
bool& complete,
198-
int sighash_type = 1 /* SIGHASH_ALL */,
199-
bool sign = true,
200-
bool bip32derivs = false) const = 0;
196+
virtual TransactionError fillPSBT(int sighash_type,
197+
bool sign,
198+
bool bip32derivs,
199+
PartiallySignedTransaction& psbtx,
200+
bool& complete) = 0;
201201

202202
//! Get balances.
203203
virtual WalletBalances getBalances() = 0;
@@ -247,10 +247,10 @@ class Wallet
247247
virtual bool hdEnabled() = 0;
248248

249249
// Return whether the wallet is blank.
250-
virtual bool canGetAddresses() const = 0;
250+
virtual bool canGetAddresses() = 0;
251251

252-
// check if a certain wallet flag is set.
253-
virtual bool IsWalletFlagSet(uint64_t flag) = 0;
252+
// Return whether private keys enabled.
253+
virtual bool privateKeysDisabled() = 0;
254254

255255
// Get default address type.
256256
virtual OutputType getDefaultAddressType() = 0;

src/qt/bitcoingui.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ void BitcoinGUI::updateWalletStatus()
12581258
}
12591259
WalletModel * const walletModel = walletView->getWalletModel();
12601260
setEncryptionStatus(walletModel->getEncryptionStatus());
1261-
setHDStatus(walletModel->privateKeysDisabled(), walletModel->wallet().hdEnabled());
1261+
setHDStatus(walletModel->wallet().privateKeysDisabled(), walletModel->wallet().hdEnabled());
12621262
}
12631263
#endif // ENABLE_WALLET
12641264

src/qt/overviewpage.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
161161
{
162162
int unit = walletModel->getOptionsModel()->getDisplayUnit();
163163
m_balances = balances;
164-
if (walletModel->privateKeysDisabled()) {
164+
if (walletModel->wallet().privateKeysDisabled()) {
165165
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balances.watch_only_balance, false, BitcoinUnits::separatorAlways));
166166
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, balances.unconfirmed_watch_only_balance, false, BitcoinUnits::separatorAlways));
167167
ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, balances.immature_watch_only_balance, false, BitcoinUnits::separatorAlways));
@@ -184,7 +184,7 @@ void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
184184
// for symmetry reasons also show immature label when the watch-only one is shown
185185
ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
186186
ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
187-
ui->labelWatchImmature->setVisible(!walletModel->privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
187+
ui->labelWatchImmature->setVisible(!walletModel->wallet().privateKeysDisabled() && showWatchOnlyImmature); // show watch-only immature balance
188188
}
189189

190190
// show/hide watch-only labels
@@ -236,9 +236,9 @@ void OverviewPage::setWalletModel(WalletModel *model)
236236

237237
connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit);
238238

239-
updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->privateKeysDisabled());
239+
updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->wallet().privateKeysDisabled());
240240
connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
241-
updateWatchOnlyLabels(showWatchOnly && !walletModel->privateKeysDisabled());
241+
updateWatchOnlyLabels(showWatchOnly && !walletModel->wallet().privateKeysDisabled());
242242
});
243243
}
244244

src/qt/receivecoinsdialog.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model)
9999
}
100100

101101
// Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
102-
ui->receiveButton->setEnabled(model->canGetAddresses());
102+
ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
103103

104104
// Enable/disable the receive button if the wallet is now able/unable to give out new addresses.
105105
connect(model, &WalletModel::canGetAddressesChanged, [this] {
106-
ui->receiveButton->setEnabled(model->canGetAddresses());
106+
ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
107107
});
108108
}
109109
}

0 commit comments

Comments
 (0)