Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/chain/bitcoind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,8 +1280,13 @@ impl BlockSource for BitcoindClient {
BitcoindClient::Rpc { rpc_client, .. } => {
rpc_client.get_header(header_hash, height_hint).await
},
BitcoindClient::Rest { rest_client, .. } => {
rest_client.get_header(header_hash, height_hint).await
BitcoindClient::Rest { rest_client, rpc_client, .. } => {
match rest_client.get_header(header_hash, height_hint).await {
Err(e) if e.kind() == BlockSourceErrorKind::Persistent => {
rpc_client.get_header(header_hash, height_hint).await

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks a bit weird that we have to fallback to the other interface. From history it seems we need rest because rpc is too slow for large sync ops?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REST was added both for its unauthenticated read-only interface and for more efficient/cacheable binary block retrieval; it isn’t simply that RPC is unusably slow.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the unauth interface an advantage if you also may need rpc?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is to enable easier caching, but see your point.

},
result => result,
}
},
}
}
Expand Down
59 changes: 58 additions & 1 deletion tests/reorg_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,74 @@ mod common;
use std::collections::HashMap;

use bitcoin::Amount;
use electrsd::corepc_node::mtype::ChainTipsStatus;
use ldk_node::payment::{PaymentDirection, PaymentKind};
use ldk_node::{Event, LightningBalance, PendingSweepBalance};
use proptest::prelude::prop;
use proptest::proptest;
use serde_json::json;

use crate::common::{
expect_event, exponential_backoff_poll, generate_blocks_and_wait, invalidate_blocks,
open_channel, premine_and_distribute_funds, random_chain_source, random_config,
setup_bitcoind_and_electrsd, setup_node, wait_for_outpoint_spend, wait_for_tx,
setup_bitcoind_and_electrsd, setup_node, wait_for_outpoint_spend, wait_for_tx, TestChainSource,
};

#[test]
fn bitcoind_rest_follows_valid_reorg() {
let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
rt.block_on(async {
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
let node = setup_node(&TestChainSource::BitcoindRestSync(&bitcoind), random_config());
let (bitcoind, electrs) = (&bitcoind.client, &electrsd.client);

generate_blocks_and_wait(bitcoind, electrs, 3).await;
node.sync_wallets().unwrap();
let original_tip = node.status().current_best_block;
let fork_block_hash = bitcoind
.get_block_hash((original_tip.height - 1) as u64)
.expect("failed to get fork block hash")
.block_hash()
.expect("fork block hash should be present");

invalidate_blocks(bitcoind, 2);
generate_blocks_and_wait(bitcoind, electrs, 3).await;
let replacement_tip_hash =
bitcoind.best_block_hash().expect("failed to get replacement tip");
let replacement_tip_height =
bitcoind.get_blockchain_info().expect("failed to get replacement tip height").blocks
as u32;

let _: serde_json::Value = bitcoind
.call("reconsiderblock", &[json!(fork_block_hash)])
.expect("failed to reconsider original branch");
let chain_tips = bitcoind
.get_chain_tips()
.expect("failed to get chain tips")
.into_model()
.expect("failed to parse chain tips")
.0;
assert!(chain_tips.iter().any(|tip| {
tip.hash == original_tip.block_hash && tip.status == ChainTipsStatus::ValidFork
}));
assert!(chain_tips.iter().any(|tip| {
tip.hash == replacement_tip_hash && tip.status == ChainTipsStatus::Active
}));

node.sync_wallets()
.expect("REST-backed node did not follow Bitcoin Core's replacement chain");
let synced_tip = node.status().current_best_block;
assert_eq!(
synced_tip.block_hash, replacement_tip_hash,
"REST-backed node did not follow Bitcoin Core's replacement chain"
);
assert_eq!(
synced_tip.height, replacement_tip_height,
"REST-backed node did not follow Bitcoin Core's replacement chain"
);
})
}

async fn wait_for_pending_sweep_balance<F>(
node: &ldk_node::Node, mut matches_balance: F,
) -> PendingSweepBalance
Expand Down
Loading