Skip to content

Commit

Permalink
electrum: Implement --electrum-skip-merkle to avoid generating SPV …
Browse files Browse the repository at this point in the history
…proofs entirely, even when it's possible
  • Loading branch information
shesek committed Jun 6, 2020
1 parent d7f62e3 commit 2390f2d
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 14 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

- Electrum: Implement `--electrum-skip-merkle` to avoid generating SPV proofs entirely, even when it's possible.

## 0.1.3 - 2020-06-02

- Electrum: Use dummy SPV proofs to support pruning with the `--skipmerklecheck` option.
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ You can use bwt with pruning, but:

2. Electrum needs to be run with `--skipmerklecheck` to tolerate missing SPV proofs for transactions in pruned blocks.

If you're running Electrum with `--skipmerklecheck`, you may also configure bwt with `--electrum-skip-merkle` to save some resource by not generating SPV proofs even when it's possible.

### Real-time indexing

By default, bwt will query bitcoind for new blocks/transactions every 5 seconds.
Expand Down
6 changes: 5 additions & 1 deletion src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ impl App {
let sync_tx = debounce_sender(sync_tx, DEBOUNCE_SEC);

#[cfg(feature = "electrum")]
let electrum = ElectrumServer::start(config.electrum_rpc_addr(), query.clone());
let electrum = ElectrumServer::start(
config.electrum_rpc_addr(),
config.electrum_skip_merkle,
query.clone(),
);

#[cfg(feature = "http")]
let http = HttpServer::start(
Expand Down
14 changes: 12 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub struct Config {
)]
pub verbose: usize,

// XXX this is not settable as an env var due to https://github.com/TeXitoi/structopt/issues/305
#[structopt(
short = "t",
long,
Expand Down Expand Up @@ -155,6 +156,15 @@ pub struct Config {
)]
pub electrum_rpc_addr: Option<net::SocketAddr>,

// XXX this is not settable as an env var due to https://github.com/TeXitoi/structopt/issues/305
#[cfg(feature = "electrum")]
#[structopt(
long,
help = "Skip generating merkle proofs. Reduces resource usage, requires running Electrum with --skipmerklecheck",
display_order(41)
)]
pub electrum_skip_merkle: bool,

#[cfg(feature = "http")]
#[structopt(
short,
Expand All @@ -163,7 +173,7 @@ pub struct Config {
default_value = "127.0.0.1:3060",
env,
hide_env_values(true),
display_order(41)
display_order(45)
)]
pub http_server_addr: net::SocketAddr,

Expand All @@ -173,7 +183,7 @@ pub struct Config {
help = "Allowed cross-origins for http api server (Access-Control-Allow-Origin)",
env,
hide_env_values(true),
display_order(42)
display_order(46)
)]
pub http_cors: Option<String>,

Expand Down
30 changes: 19 additions & 11 deletions src/electrum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const MAX_HEADERS: u32 = 2016;

struct Connection {
query: Arc<Query>,
skip_merkle: bool,
stream: TcpStream,
addr: SocketAddr,
chan: SyncChannel<Message>,
Expand All @@ -35,6 +36,7 @@ struct Connection {
impl Connection {
pub fn new(
query: Arc<Query>,
skip_merkle: bool,
stream: TcpStream,
addr: SocketAddr,
subman: Arc<Mutex<SubscriptionManager>>,
Expand All @@ -43,6 +45,7 @@ impl Connection {
let subscriber_id = subman.lock().unwrap().register(chan.sender());
Connection {
query,
skip_merkle,
subman,
subscriber_id,
stream,
Expand Down Expand Up @@ -234,17 +237,22 @@ impl Connection {
fn blockchain_transaction_get_merkle(&self, params: Value) -> Result<Value> {
let (txid, height): (Txid, u32) = from_value(params)?;

let (merkle, pos) = match get_merkle_proof(&self.query, &txid, height) {
Ok(proof) => proof,
Err(e) => {
if let Some(BwtError::PrunedBlocks) = e.downcast_ref::<BwtError>() {
// if we can't generate the spv proof due to pruning, return a dummy proof instead of an
// error, which electrum will accept when run with --skipmerklecheck.
(vec![], 0)
} else {
bail!(e)
let (merkle, pos) = if !self.skip_merkle {
match get_merkle_proof(&self.query, &txid, height) {
Ok(proof) => proof,
Err(e) => {
if let Some(BwtError::PrunedBlocks) = e.downcast_ref::<BwtError>() {
// if we can't generate the spv proof due to pruning, return a dummy proof instead of an
// error, which electrum will accept when run with --skipmerklecheck.
(vec![], 0)
} else {
bail!(e)
}
}
}
} else {
// always return dummy SPV proofs when --electrum-skip-merkle is set
(vec![], 0)
};

Ok(json!({
Expand Down Expand Up @@ -507,7 +515,7 @@ impl ElectrumServer {
chan
}

pub fn start(addr: SocketAddr, query: Arc<Query>) -> Self {
pub fn start(addr: SocketAddr, skip_merkle: bool, query: Arc<Query>) -> Self {
let notification = Channel::unbounded();
Self {
notification: notification.sender(),
Expand All @@ -524,7 +532,7 @@ impl ElectrumServer {
let subman = subman.clone();
children.push(spawn_thread("peer", move || {
info!("[{}] connected peer", addr);
let conn = Connection::new(query, stream, addr, subman);
let conn = Connection::new(query, skip_merkle, stream, addr, subman);
conn.run();
info!("[{}] disconnected peer", addr);
}));
Expand Down

0 comments on commit 2390f2d

Please sign in to comment.