-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow enabling at most one blockchain client feature #38
Allow enabling at most one blockchain client feature #38
Conversation
65729b9
to
47e0962
Compare
f9cd936
to
c81a99e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
#[structopt(long_about = "REPL command loop mode")] | |
Repl { | |
#[structopt(flatten)] | |
wallet_opts: WalletOpts, | |
}, |
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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
src/bdk_cli.rs
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
fn main() {
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
The following structure and function call could use feature guard. They exist in binary compiled without a backend, but are never used. |
d3c0af3
to
9bb1c60
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tACK 9bb1c60
With some minor nits.
@@ -38,7 +40,7 @@ compact_filters = ["bdk/compact_filters"] | |||
[[bin]] | |||
name = "bdk-cli" | |||
path = "src/bdk_cli.rs" | |||
required-features = ["repl", "electrum"] | |||
required-features = ["cli"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we still need cli
as required to force anyone building the bin without repl
(using --no-default-features) to still include cli
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ya makes sense.
@@ -42,7 +49,7 @@ cargo run | |||
To sync a wallet to the default electrum server: | |||
|
|||
```shell | |||
cargo run -- wallet --descriptor "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" sync | |||
cargo run --features electrum -- wallet --descriptor "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)" sync |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
ACK 062542a |
062542a
to
7c4f5e7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review with testing ACK 4fd39b7
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-features
build option will need to be used.default
features, 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
electrum
andesplora
to --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.rs
file to prevent more than one blockchain client feature from being enabled.Checklists
All Submissions:
cargo fmt
andcargo clippy
before committingNew Features:
CHANGELOG.md
Bugfixes: