Crash fixes, reorg handling, and sync performance improvements
Some checks failed
Rust / Build on macOS-latest (push) Has been cancelled
Rust / Build on ubuntu-16.04 (push) Has been cancelled
Rust / Build on windows-latest (push) Has been cancelled
Rust / Linux ARMv7 (push) Has been cancelled
Rust / Linux ARM64 (push) Has been cancelled
Rust / Build on ubuntu-latest (push) Has been cancelled
Some checks failed
Rust / Build on macOS-latest (push) Has been cancelled
Rust / Build on ubuntu-16.04 (push) Has been cancelled
Rust / Build on windows-latest (push) Has been cancelled
Rust / Linux ARMv7 (push) Has been cancelled
Rust / Linux ARM64 (push) Has been cancelled
Rust / Build on ubuntu-latest (push) Has been cancelled
- Fix FFI panics with catch_unwind and safe CString construction - Handle poisoned mutex/RwLock after prior panics instead of crashing - Fix empty block list panics in clear_blocks and invalidate_block - Reuse Tokio runtime across block fetch batches to reduce overhead - Add fetch_blocks_with_runtime for caller-managed runtime lifecycle - Update branding, dependencies, and checkpoints for DragonX
This commit is contained in:
@@ -155,15 +155,12 @@ where F : Fn(&[u8], u64) {
|
||||
|
||||
pub fn fetch_blocks<F : 'static + std::marker::Send>(uri: &http::Uri, start_height: u64, end_height: u64, no_cert: bool, pool: ThreadPool, c: F) -> Result<(), String>
|
||||
where F : Fn(&[u8], u64) {
|
||||
let mut rt = tokio::runtime::Runtime::new().map_err(|e| format!("Error creating runtime {:?}", e))?;
|
||||
fetch_blocks_with_runtime(&mut rt, uri, start_height, end_height, no_cert, pool, c)
|
||||
}
|
||||
|
||||
let mut rt = match tokio::runtime::Runtime::new() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
let es = format!("Error creating runtime {:?}", e);
|
||||
error!("{}", es);
|
||||
return Err(es);
|
||||
}
|
||||
};
|
||||
pub fn fetch_blocks_with_runtime<F : 'static + std::marker::Send>(rt: &mut tokio::runtime::Runtime, uri: &http::Uri, start_height: u64, end_height: u64, no_cert: bool, pool: ThreadPool, c: F) -> Result<(), String>
|
||||
where F : Fn(&[u8], u64) {
|
||||
|
||||
match rt.block_on(get_block_range(uri, start_height, end_height, no_cert, pool, c)) {
|
||||
Ok(o) => Ok(o),
|
||||
|
||||
@@ -1323,6 +1323,10 @@ pub fn start_mempool_monitor(lc: Arc<LightClient>) -> Result<(), String> {
|
||||
// Create a new threadpool (upto 8, atleast 2 threads) to scan with
|
||||
let pool = ThreadPool::new(max(2, min(8, num_cpus::get())));
|
||||
|
||||
// Create a single Tokio runtime for all block fetches to avoid per-batch overhead
|
||||
let mut rt = tokio::runtime::Runtime::new()
|
||||
.map_err(|e| format!("Error creating runtime: {:?}", e))?;
|
||||
|
||||
// Fetch CompactBlocks in increments
|
||||
let mut pass = 0;
|
||||
loop {
|
||||
@@ -1359,7 +1363,7 @@ pub fn start_mempool_monitor(lc: Arc<LightClient>) -> Result<(), String> {
|
||||
let last_invalid_height = Arc::new(AtomicI32::new(0));
|
||||
let last_invalid_height_inner = last_invalid_height.clone();
|
||||
let tpool = pool.clone();
|
||||
fetch_blocks(&self.get_server_uri(), start_height, end_height, self.config.no_cert_verification, pool.clone(),
|
||||
fetch_blocks_with_runtime(&mut rt, &self.get_server_uri(), start_height, end_height, self.config.no_cert_verification, pool.clone(),
|
||||
move |encoded_block: &[u8], height: u64| {
|
||||
// Process the block only if there were no previous errors
|
||||
if last_invalid_height_inner.load(Ordering::SeqCst) > 0 {
|
||||
|
||||
@@ -746,14 +746,29 @@ impl LightWallet {
|
||||
/// After this, the wallet's initial state will need to be set
|
||||
/// and the wallet will need to be rescanned
|
||||
pub fn clear_blocks(&self) {
|
||||
self.blocks.write().unwrap().clear();
|
||||
self.txs.write().unwrap().clear();
|
||||
self.mempool_txs.write().unwrap().clear();
|
||||
self.incoming_mempool_txs.write().unwrap().clear();
|
||||
match self.blocks.write() {
|
||||
Ok(mut b) => b.clear(),
|
||||
Err(p) => p.into_inner().clear(),
|
||||
};
|
||||
match self.txs.write() {
|
||||
Ok(mut t) => t.clear(),
|
||||
Err(p) => p.into_inner().clear(),
|
||||
};
|
||||
match self.mempool_txs.write() {
|
||||
Ok(mut m) => m.clear(),
|
||||
Err(p) => p.into_inner().clear(),
|
||||
};
|
||||
match self.incoming_mempool_txs.write() {
|
||||
Ok(mut m) => m.clear(),
|
||||
Err(p) => p.into_inner().clear(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_initial_block(&self, height: i32, hash: &str, sapling_tree: &str) -> bool {
|
||||
let mut blocks = self.blocks.write().unwrap();
|
||||
let mut blocks = match self.blocks.write() {
|
||||
Ok(b) => b,
|
||||
Err(p) => p.into_inner(),
|
||||
};
|
||||
if !blocks.is_empty() {
|
||||
return false;
|
||||
}
|
||||
@@ -1677,9 +1692,15 @@ pub fn scan_full_mempool_tx(&self, tx: &Transaction, height: i32, _datetime: u64
|
||||
|
||||
// First remove the blocks
|
||||
{
|
||||
let mut blks = self.blocks.write().unwrap();
|
||||
let mut blks = match self.blocks.write() {
|
||||
Ok(b) => b,
|
||||
Err(p) => p.into_inner(),
|
||||
};
|
||||
|
||||
while blks.last().unwrap().height >= at_height {
|
||||
while let Some(last) = blks.last() {
|
||||
if last.height < at_height {
|
||||
break;
|
||||
}
|
||||
blks.pop();
|
||||
num_invalidated += 1;
|
||||
}
|
||||
@@ -1687,7 +1708,10 @@ pub fn scan_full_mempool_tx(&self, tx: &Transaction, height: i32, _datetime: u64
|
||||
|
||||
// Next, remove entire transactions
|
||||
{
|
||||
let mut txs = self.txs.write().unwrap();
|
||||
let mut txs = match self.txs.write() {
|
||||
Ok(t) => t,
|
||||
Err(p) => p.into_inner(),
|
||||
};
|
||||
let txids_to_remove = txs.values()
|
||||
.filter_map(|wtx| if wtx.block >= at_height {Some(wtx.txid.clone())} else {None})
|
||||
.collect::<HashSet<TxId>>();
|
||||
@@ -1716,7 +1740,10 @@ pub fn scan_full_mempool_tx(&self, tx: &Transaction, height: i32, _datetime: u64
|
||||
// Of the notes that still remain, unroll the witness.
|
||||
// Remove `num_invalidated` items from the witness
|
||||
{
|
||||
let mut txs = self.txs.write().unwrap();
|
||||
let mut txs = match self.txs.write() {
|
||||
Ok(t) => t,
|
||||
Err(p) => p.into_inner(),
|
||||
};
|
||||
|
||||
// Trim all witnesses for the invalidated blocks
|
||||
for tx in txs.values_mut() {
|
||||
|
||||
Reference in New Issue
Block a user