Uh oh!
There was an error while loading. Please reload this page.
Allow enabling at most one blockchain client feature - #38
Conversation
65729b9 to
47e0962Comparef9cd936 to
c81a99eCompareThere was a problem hiding this comment.
Thanks @notmandatory for the PR, we are close almost. I just have a few more comments.
Is there any specific use of Repl mode here?
Lines 258 to 262 in 378b33a
It just seems to be duplicating
WalletOpts and no commands. If not we can remove this, it seems redundant.One problem here is using --no-default-features will turn off repl too, which is required dep for the binary, so it will not compile any binary. This has been the crux of the problem because cargo doesn't let us selectively disable features. So if we disable default, it disables everything in default.
I think the only way to solve this problem is by having a very minimal default with only the stuffs that we need to create the minimal possible binary. And then add stuff to it with features flag. This will also remove the use of --no-default-feature if we only want esplora but not electrum.
So I propose something like this:
[features]
default = ["repl"]
repl = ["bdk/key-value-db", "clap", "dirs-next", "env_logger", "regex", "rustyline"]
electrum = ["bdk/electrum"]
esplora = ["bdk/esplora"]
compiler = ["bdk/compiler"]
async-interface = ["bdk/async-interface"]
compact_filters = ["bdk/compact_filters"]
[[bin]]
name = "bdk-cli"
path = "src/bdk_cli.rs"
required-features = ["repl"]
This will create the following builds
cargo build : build only repl stuffs, no backend
cargo build --features [backend] : build repl + [backend] blockchain.
I don't think there's any adverse effect of not having a blockchain by default. the only method we have with blockchain is sync and broadcast, everything else can be done without a blockchain. So it's safe to remove it in default.
Also, I am not sure if we should silently ignore "no binary built" scenarios in CI. with current changes for example you can check that locally with I am not sure how then it's passing the tests without a binary. |
I think tests were passing because they only needed a lib build to run. But I agree it would be nice to not have to use the
|
rajarshimaitra
left a comment
There was a problem hiding this comment.
Code review ACK. This simplifies the issue.
I had the following observation. It seems if we compile the library using cargo build --features cli --no-default-features, that produces a binary that is perfectly workable with non backend wallet. It has functionality like this
$ ./target/debug/bdk-cli wallet --help
bdk-cli-wallet 0.2.1-dev
Wallet mode
USAGE:
bdk-cli wallet [FLAGS] [OPTIONS] --descriptor <DESCRIPTOR> <SUBCOMMAND>
FLAGS:
-v, --verbose Adds verbosity, returns PSBT in JSON format alongside serialized
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-c, --change_descriptor <CHANGE_DESCRIPTOR> Sets the descriptor to use for internal addresses
-d, --descriptor <DESCRIPTOR> Sets the descriptor to use for the external addresses
-w, --wallet <WALLET_NAME> Selects the wallet to use [default: main]
SUBCOMMANDS:
bump_fee Bumps the fees of an RBF transaction
combine_psbt Combines multiple PSBTs into one
create_tx Creates a new unsigned transaction
extract_psbt Extracts a raw transaction from a PSBT
finalize_psbt Finalizes a PSBT
get_balance Returns the current wallet balance
get_new_address Generates a new external address
help Prints this message or the help of the given subcommand(s)
list_transactions Lists all the incoming and outgoing transactions of the wallet
list_unspent Lists the available spendable UTXOs
policies Returns the available spending policies for the descriptor
public_descriptor Returns the public version of the wallet's descriptor(s)
sign Signs and tries to finalize a PSBT
So that begs the question I had before, what do we need the repl thing for?
Also from here https://github.com/notmandatory/bdk-cli/blob/69b1d80bcd4715a3b78af4aafacebe2fc5ca2b88/src/bdk_cli.rs#L318-L331
it seems all a repl does is to perse existing commands and use them with either wallet or key functions. Maybe I am missing something, but I am not seeing any use of having the same methods called twice in different ways.
If two features cli and repl that does the same thing, it seems confusing to me.
| feature = "esplora", | ||
| any(feature = "electrum", feature = "compact_filters") | ||
| ))] | ||
| compile_error!("Only one blockchain client feature can be enabled at a time."); |
There was a problem hiding this comment.
It seems for every combination of electrum, esplora and compact_filters, this error is being duplicated with the one defined few lines below.
Instead, if we write it like this
#[cfg(all(
any( feature = "electrum", feature = "esplora", feature = "compact_filters"),
any( feature = "electrum", feature = "esplora", feature = "compact_filters")
))]
this will activate for any combination of the above three. And we won't need to specify compiler_error! multiple times.
Also for future extension, if we just add a new backend to the list above, that will taker care of multiple backend activation errors.
There was a problem hiding this comment.
Unfortunately the cfg all any any approach doesn't work, when I added this code:
#[cfg(all(any( feature = "electrum", feature = "esplora", feature = "compact_filters"),any( feature = "electrum", feature = "esplora", feature = "compact_filters")))]compile_error!("Only one blockchain client feature can be enabled at a time.");I get the error even with only one blockchain client feature enabled (ie. cargo build --features esplora).
Looks like other's have had this same problem and are proposing a Rust RFC to allow a set of features to provide another feature in a mutually exclusive way.
Until mutually exclusive features are possible I can fix this in a simplistic way in the build.rs file as below or just leave it as it.. What do you think?
fnmain(){let electrum = env::var_os("CARGO_FEATURE_ELECTRUM").map(|_| "electrum".to_string());let esplora = env::var_os("CARGO_FEATURE_ESPLORA").map(|_| "esplora".to_string());let compact_filters = env::var_os("CARGO_FEATURE_COMPACT_FILTERS").map(|_| "compact_filters".to_string());let blockchain_features :Vec<String> = vec!(electrum, esplora, compact_filters).iter().map(|f| f.to_owned()).flatten().collect();if blockchain_features.len() > 1{panic!("At most one blockchain client feature can be enabled but these features were enabled: {:?}", blockchain_features)}}There was a problem hiding this comment.
Ah ok.. I thought it would work because my analyzer didn't throw. Yes there should be a way to handle mutually exclusive features in cargo itself.
I like the build script approach. It's clear and concise. Till it's available in cargo we can use a guard like above.
rajarshimaitra
commented
Aug 6, 2021
The following structure and function call could use feature guard. They exist in binary compiled without a backend, but are never used. |
d3c0af3 to
9bb1c60Compare
rajarshimaitra
left a comment
There was a problem hiding this comment.
tACK 9bb1c60
With some minor nits.
Uh oh!
There was an error while loading. Please reload this page.
| name = "bdk-cli" | ||
| path = "src/bdk_cli.rs" | ||
| required-features = ["repl", "electrum"] | ||
| required-features = ["cli"] |
There was a problem hiding this comment.
Is this required-features value necessary? By putting cli in default we are ensuring that the build will always include cli. (we also removed any necessity of using --no-default-features).
There was a problem hiding this comment.
I think we still need cli as required to force anyone building the bin without repl (using --no-default-features) to still include cli.
Uh oh!
There was an error while loading. Please reload this page.
| ```shell | ||
| cargo run -- wallet --descriptor "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" sync | ||
| cargo run --features electrum -- wallet --descriptor "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" sync |
There was a problem hiding this comment.
Few lines ago we mentioned how to install bdk-cli with cargo.
Instructing to use cargo run here will build the local files instead of using the installed binary. So if someone is in their cloned repo, using cargo run they will actually build and then run the master branch instead of the release binary he just installed (this might be an unexpected behavior for the user, unless he knows cargo stuffs).
Even worse if someone didn't clone the repo, cargo run will not run anything, even if they have bdk-cli binary installed (and we don't have that instruction anywhere).
I think in the "bdk-cli bin usage examples" section, we should just instruct to use bdk-cli binary instead of crago run, which will make the instruction simpler also.
This doesn't have to be fixed here. Just mentioned as it occurred to me.
There was a problem hiding this comment.
I agree we should probably update the README to focus on installing with different features, and then usage with an installed version instead of using cargo run since anyone making local changes should already know how to use cargo. But let's do that cleanup in a different PR.
Uh oh!
There was an error while loading. Please reload this page.
rajarshimaitra
commented
Aug 11, 2021
ACK 062542a |
062542a to
7c4f5e7Compare
rajarshimaitra
left a comment
There was a problem hiding this comment.
Code review with testing ACK 4fd39b7
notmandatory
commented
Aug 13, 2021
Thanks for the suggestions and review on this @rajarshimaitra, all ready to rebase your #36 PR. |
Description
Allow at most one blockchain client feature be enabled at a time for builds. If no blockchain client feature is enabled then online wallet commands are disabled. This will simplify the options shown to the user and make adding new blockchain clients (such as #36) easier.
Electrum is still the default, to make a build with a different blockchain client theNo blockchain client is included in the--no-default-featuresbuild option will need to be used.defaultfeatures, so if one is needed it must be specified with--features. I also added a default esplora server url so the user doesn't need to specify one if selecting that client, which is how the electrum and compact_filters clients work.Notes to the reviewers
I changed the server option for both
electrumandesplorato --server or -s since that now won't cause a conflict. I also simplified the CHANGELOG to focus on what a user would see as a change while using the bin.I've also added a
build.rsfile to prevent more than one blockchain client feature from being enabled.Checklists
All Submissions:
cargo fmtandcargo clippybefore committingNew Features:
CHANGELOG.mdBugfixes: