Skip to content

Commit

Permalink
Implement wallet overriding
Browse files Browse the repository at this point in the history
It is sometimes useful to override wallet name. This can improve
security and compatibility.

This change implements simple wallet override.
  • Loading branch information
Kixunil committed Mar 29, 2023
1 parent 25f20a4 commit 50280a4
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 2 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ Finer-grained permission management for bitcoind.

## About

This is a proxy made specifically for `bitcoind` to allow finer-grained control of permissions. It enables you to specify several users and for each user the list of RPC calls they are allowed to make. When run against a prunded node, the proxy will perform on-demand block fetching and verification, enabling features of a non-pruned node while still using a pruned node.
This is a proxy made specifically for `bitcoind` to allow finer-grained control of permissions. It enables you to specify several users and for each user the list of RPC calls they are allowed to make and optionally the name of the wallet they will operate on. When run against a prunded node, the proxy will perform on-demand block fetching and verification, enabling features of a non-pruned node while still using a pruned node.

### Fine-grained permission management

This is useful because `bitcoind` allows every application with password to make possibly harmful calls like stopping the daemon or spending from wallet (if enabled). If you have several applications, you can provide the less trusted ones a different password and permissions than the others using this project.

There's another interesting advantage: since this is written in Rust, it might serve as a filter for **some** malformed requests which might be exploits. But I don't recommend relying on it!

### Overriding wallet

For each user you can set a specific wallet name to be used by setting `override_wallet = "wallet_name_here"`.
When this is set the wallet sent in request is ignored and the specified wallet is used instead. Aside from obvious security benefits this can help workaround applications that are incapable of accessing specific wallet (e.g. btc-rpc-explorer at the time of writing).

### On-demand block fetching

By connecting to your pruned Bitcoin node through Bitcoin Proxy, your node will now behave as though it is not pruned. If a user or application requires a block that is not retained by your pruned node, Bitcoin Proxy will dynamically fetch the block over the P2P network, then verify its hash against your node to ensure validity.
Expand Down
1 change: 1 addition & 0 deletions btc_rpc_proxy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ bind_address = "127.0.0.1"

[user.public]
password = "public"
# override_wallet = "some_wallet_name_here"
allowed_calls = [
"getinfo",
"getblock",
Expand Down
6 changes: 5 additions & 1 deletion src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@ pub async fn proxy_request(
Ok(req) => {
let state_local = state.clone();
let name_local = Arc::new(name);
let path = user.override_wallet
.as_ref()
.map(AsRef::as_ref)
.unwrap_or(parts.uri.path());
let response = state
.rpc_client
.send(parts.uri.path(), &req, move |_path, req| {
.send(path, &req, move |_path, req| {
use futures::TryFutureExt;
let name_local_ok = name_local.clone();
let name_local_err = name_local.clone();
Expand Down
8 changes: 8 additions & 0 deletions src/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,21 @@ pub mod input {
pub allowed_calls: HashSet<String>,
#[serde(default)]
pub fetch_blocks: Option<bool>,
#[serde(default)]
pub override_wallet: Option<String>,
}

impl User {
fn map_default(self, default_fetch_blocks: bool) -> super::User {
let wallet = self.override_wallet.map(|mut wallet| {
wallet.insert_str(0, "/wallet/");
wallet
});
super::User {
password: self.password,
allowed_calls: self.allowed_calls,
fetch_blocks: self.fetch_blocks.unwrap_or(default_fetch_blocks),
override_wallet: wallet,
}
}
}
Expand Down Expand Up @@ -176,6 +183,7 @@ pub struct User {
pub allowed_calls: HashSet<String>,
#[serde(default)]
pub fetch_blocks: bool,
pub override_wallet: Option<String>,
}
impl User {
pub async fn intercept<'a>(
Expand Down

0 comments on commit 50280a4

Please sign in to comment.