Skip to content

Commit f0b12aa

Browse files
committed
Merge branch 'add-error'
2 parents 54aa100 + 54e444a commit f0b12aa

File tree

1 file changed

+67
-6
lines changed

1 file changed

+67
-6
lines changed

src/lib.rs

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ pub enum Error {
104104
EarlyExit(ExitStatus),
105105
/// Returned when both tmpdir and staticdir is specified in `Conf` options
106106
BothDirsSpecified,
107+
/// Returned when -rpcuser and/or -rpcpassword is used in `Conf` args
108+
/// It will soon be deprecated, please use -rpcauth instead
109+
RpcUserAndPasswordUsed,
107110
}
108111

109112
impl fmt::Debug for Error {
@@ -116,7 +119,8 @@ impl fmt::Debug for Error {
116119
Error::NoBitcoindExecutableFound => write!(f, "`bitcoind` executable is required, provide it with one of the following: set env var `BITCOIND_EXE` or use a feature like \"22_0\" or have `bitcoind` executable in the `PATH`"),
117120
Error::BothFeatureAndEnvVar => write!(f, "Called a method requiring env var `BITCOIND_EXE` or a feature to be set, but both are set"),
118121
Error::EarlyExit(e) => write!(f, "The bitcoind process terminated early with exit code {}", e),
119-
Error::BothDirsSpecified => write!(f, "tempdir and staticdir cannot be enabled at same time in configuration options")
122+
Error::BothDirsSpecified => write!(f, "tempdir and staticdir cannot be enabled at same time in configuration options"),
123+
Error::RpcUserAndPasswordUsed => write!(f, "`-rpcuser` and `-rpcpassword` cannot be used, it will be deprecated soon and it's recommended to use `-rpcauth` instead which works alongside with the default cookie authentication")
120124
}
121125
}
122126
}
@@ -131,6 +135,8 @@ impl std::error::Error for Error {}
131135

132136
const LOCAL_IP: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
133137

138+
const INVALID_ARGS: [&str; 2] = ["-rpcuser", "-rpcpassword"];
139+
134140
/// The node configuration parameters, implements a convenient [Default] for most common use.
135141
///
136142
/// `#[non_exhaustive]` allows adding new parameters without breaking downstream users.
@@ -268,17 +274,19 @@ impl BitcoinD {
268274
let datadir_arg = format!("-datadir={}", work_dir_path.display());
269275
let rpc_arg = format!("-rpcport={}", rpc_port);
270276
let default_args = [&datadir_arg, &rpc_arg];
277+
let conf_args = validate_args(conf.args.clone())?;
271278

272279
debug!(
273-
"launching {:?} with args: {:?} {:?} AND custom args",
280+
"launching {:?} with args: {:?} {:?} AND custom args: {:?}",
274281
exe.as_ref(),
275282
default_args,
276-
p2p_args
283+
p2p_args,
284+
conf_args
277285
);
278286
let mut process = Command::new(exe.as_ref())
279287
.args(&default_args)
280288
.args(&p2p_args)
281-
.args(&conf.args)
289+
.args(&conf_args)
282290
.stdout(stdout)
283291
.spawn()?;
284292

@@ -432,12 +440,25 @@ pub fn exe_path() -> Result<String, Error> {
432440
}
433441
}
434442

443+
/// Validate the specified arg if there is any unavailable or deprecated one
444+
pub fn validate_args(args: Vec<&str>) -> Result<Vec<&str>, Error> {
445+
args.iter().try_for_each(|arg| {
446+
// other kind of invalid arguments can be added into the list if needed
447+
if INVALID_ARGS.iter().any(|x| arg.starts_with(x)) {
448+
return Err(Error::RpcUserAndPasswordUsed);
449+
}
450+
Ok(())
451+
})?;
452+
453+
Ok(args)
454+
}
455+
435456
#[cfg(test)]
436457
mod test {
437458
use crate::bitcoincore_rpc::jsonrpc::serde_json::Value;
438-
use crate::bitcoincore_rpc::Client;
459+
use crate::bitcoincore_rpc::{Auth, Client};
439460
use crate::exe_path;
440-
use crate::{get_available_port, BitcoinD, Conf, LOCAL_IP, P2P};
461+
use crate::{get_available_port, BitcoinD, Conf, Error, LOCAL_IP, P2P};
441462
use bitcoincore_rpc::RpcApi;
442463
use std::net::SocketAddrV4;
443464
use tempfile::TempDir;
@@ -613,6 +634,46 @@ mod test {
613634
);
614635
}
615636

637+
#[test]
638+
fn test_bitcoind_rpcuser_and_rpcpassword() {
639+
let exe = init();
640+
641+
let mut conf = Conf::default();
642+
conf.args.push("-rpcuser=bitcoind");
643+
conf.args.push("-rpcpassword=bitcoind");
644+
645+
let bitcoind = BitcoinD::with_conf(exe, &conf);
646+
647+
assert!(bitcoind.is_err());
648+
assert!(matches!(bitcoind, Err(Error::RpcUserAndPasswordUsed)));
649+
}
650+
651+
#[test]
652+
fn test_bitcoind_rpcauth() {
653+
let exe = init();
654+
655+
let mut conf = Conf::default();
656+
// rpcauth generated with [rpcauth.py](https://github.com/bitcoin/bitcoin/blob/master/share/rpcauth/rpcauth.py)
657+
// this could be also added to bitcoind, example: [RpcAuth](https://github.com/testcontainers/testcontainers-rs/blob/dev/testcontainers/src/images/coblox_bitcoincore.rs#L39-L91)
658+
conf.args.push("-rpcauth=bitcoind:cccd5d7fd36e55c1b8576b8077dc1b83$60b5676a09f8518dcb4574838fb86f37700cd690d99bd2fdc2ea2bf2ab80ead6");
659+
660+
let bitcoind = BitcoinD::with_conf(exe, &conf).unwrap();
661+
662+
let client = Client::new(
663+
format!("{}/wallet/default", bitcoind.rpc_url().as_str()).as_str(),
664+
Auth::UserPass("bitcoind".to_string(), "bitcoind".to_string()),
665+
)
666+
.unwrap();
667+
668+
let info = client.get_blockchain_info().unwrap();
669+
assert_eq!(0, info.blocks);
670+
671+
let address = client.get_new_address(None, None).unwrap();
672+
let _ = client.generate_to_address(1, &address).unwrap();
673+
let info = bitcoind.client.get_blockchain_info().unwrap();
674+
assert_eq!(1, info.blocks);
675+
}
676+
616677
fn peers_connected(client: &Client) -> usize {
617678
let result: Vec<Value> = client.call("getpeerinfo", &[]).unwrap();
618679
result.len()

0 commit comments

Comments
 (0)