Add updates mod
This commit is contained in:
parent
b52468e987
commit
b14a37a32a
@ -27,6 +27,7 @@ pub mod secrets;
|
|||||||
pub mod serialization;
|
pub mod serialization;
|
||||||
pub mod signature;
|
pub mod signature;
|
||||||
pub mod silentpayments;
|
pub mod silentpayments;
|
||||||
|
pub mod updates;
|
||||||
|
|
||||||
pub const MAX_PRD_PAYLOAD_SIZE: usize = u16::MAX as usize; // 64KiB sounds reasonable for now
|
pub const MAX_PRD_PAYLOAD_SIZE: usize = u16::MAX as usize; // 64KiB sounds reasonable for now
|
||||||
|
|
||||||
|
203
src/updates.rs
Normal file
203
src/updates.rs
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
use std::{mem, sync::{mpsc::{self, Receiver, Sender}, Arc, RwLock}};
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
// use wasm_bindgen::prelude::*;
|
||||||
|
// use sp_client::bitcoin::absolute::Height;
|
||||||
|
// use sp_client::bitcoin::BlockHash;
|
||||||
|
use sp_client::{bitcoin::{absolute::Height, BlockHash, OutPoint}, OwnedOutput, Updater};
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ScanProgress {
|
||||||
|
pub start: u32,
|
||||||
|
pub current: u32,
|
||||||
|
pub end: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum StateUpdate {
|
||||||
|
NoUpdate {
|
||||||
|
blkheight: Height,
|
||||||
|
},
|
||||||
|
Update {
|
||||||
|
blkheight: Height,
|
||||||
|
blkhash: BlockHash,
|
||||||
|
found_outputs: HashMap<OutPoint, OwnedOutput>,
|
||||||
|
found_inputs: HashSet<OutPoint>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[cfg(target_arch = "wasm32")]
|
||||||
|
// #[wasm_bindgen]
|
||||||
|
// extern "C" {
|
||||||
|
// #[wasm_bindgen(js_namespace = window)]
|
||||||
|
// fn sendScanProgress(progress: JsValue);
|
||||||
|
|
||||||
|
// #[wasm_bindgen(js_namespace = window)]
|
||||||
|
// fn sendStateUpdate(update: JsValue);
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub trait UpdateSink: Send + Sync {
|
||||||
|
fn send_scan_progress(&self, progress: ScanProgress) -> Result<()>;
|
||||||
|
fn send_state_update(&self, update: StateUpdate) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub struct NativeUpdateSink {
|
||||||
|
scan_tx: Sender<ScanProgress>,
|
||||||
|
state_tx: Sender<StateUpdate>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
impl NativeUpdateSink {
|
||||||
|
pub fn new() -> (Self, Receiver<ScanProgress>, Receiver<StateUpdate>) {
|
||||||
|
let (scan_tx, scan_rx) = mpsc::channel();
|
||||||
|
let (state_tx, state_rx) = mpsc::channel();
|
||||||
|
|
||||||
|
(Self { scan_tx, state_tx }, scan_rx, state_rx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
impl UpdateSink for NativeUpdateSink {
|
||||||
|
fn send_scan_progress(&self, progress: ScanProgress) -> Result<()> {
|
||||||
|
self.scan_tx.send(progress)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_state_update(&self, update: StateUpdate) -> Result<()> {
|
||||||
|
self.state_tx.send(update)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[cfg(target_arch = "wasm32")]
|
||||||
|
// pub struct WasmUpdateSink;
|
||||||
|
|
||||||
|
// #[cfg(target_arch = "wasm32")]
|
||||||
|
// impl UpdateSink for WasmUpdateSink {
|
||||||
|
// fn send_scan_progress(&self, progress: ScanProgress) -> Result<()> {
|
||||||
|
// let js_value = serde_wasm_bindgen::to_value(&progress)?;
|
||||||
|
// sendScanProgress(js_value);
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn send_state_update(&self, update: StateUpdate) -> Result<()> {
|
||||||
|
// let js_value = serde_wasm_bindgen::to_value(&update)?;
|
||||||
|
// sendStateUpdate(js_value);
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Global sink instance
|
||||||
|
static UPDATE_SINK: RwLock<Option<Arc<dyn UpdateSink>>> = RwLock::new(None);
|
||||||
|
|
||||||
|
pub fn init_update_sink(sink: Arc<dyn UpdateSink>) {
|
||||||
|
let mut sink_guard = UPDATE_SINK.write().unwrap();
|
||||||
|
*sink_guard = Some(sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_update_sink() -> Option<Arc<dyn UpdateSink>> {
|
||||||
|
UPDATE_SINK.read().unwrap().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StateUpdater {
|
||||||
|
update: bool,
|
||||||
|
blkhash: Option<BlockHash>,
|
||||||
|
blkheight: Option<Height>,
|
||||||
|
found_outputs: HashMap<OutPoint, OwnedOutput>,
|
||||||
|
found_inputs: HashSet<OutPoint>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StateUpdater {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
update: false,
|
||||||
|
blkheight: None,
|
||||||
|
blkhash: None,
|
||||||
|
found_outputs: HashMap::new(),
|
||||||
|
found_inputs: HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_update(&mut self) -> Result<StateUpdate> {
|
||||||
|
let blkheight = self
|
||||||
|
.blkheight
|
||||||
|
.ok_or(anyhow::Error::msg("blkheight not filled"))?;
|
||||||
|
|
||||||
|
if self.update {
|
||||||
|
self.update = false;
|
||||||
|
|
||||||
|
let blkhash = self.blkhash.ok_or(anyhow::Error::msg("blkhash not set"))?;
|
||||||
|
|
||||||
|
self.blkheight = None;
|
||||||
|
self.blkhash = None;
|
||||||
|
|
||||||
|
// take results, and insert new empty values
|
||||||
|
let found_inputs = mem::take(&mut self.found_inputs);
|
||||||
|
let found_outputs = mem::take(&mut self.found_outputs);
|
||||||
|
|
||||||
|
Ok(StateUpdate::Update {
|
||||||
|
blkheight,
|
||||||
|
blkhash,
|
||||||
|
found_outputs,
|
||||||
|
found_inputs,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(StateUpdate::NoUpdate { blkheight })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Updater for StateUpdater {
|
||||||
|
fn record_scan_progress(&mut self, start: Height, current: Height, end: Height) -> Result<()> {
|
||||||
|
self.blkheight = Some(current);
|
||||||
|
|
||||||
|
if let Some(sink) = get_update_sink() {
|
||||||
|
sink.send_scan_progress(ScanProgress {
|
||||||
|
start: start.to_consensus_u32(),
|
||||||
|
current: current.to_consensus_u32(),
|
||||||
|
end: end.to_consensus_u32(),
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record_block_outputs(
|
||||||
|
&mut self,
|
||||||
|
height: Height,
|
||||||
|
blkhash: BlockHash,
|
||||||
|
found_outputs: HashMap<OutPoint, OwnedOutput>,
|
||||||
|
) -> Result<()> {
|
||||||
|
// may have already been written by record_block_inputs
|
||||||
|
self.update = true;
|
||||||
|
self.found_outputs = found_outputs;
|
||||||
|
self.blkhash = Some(blkhash);
|
||||||
|
self.blkheight = Some(height);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record_block_inputs(
|
||||||
|
&mut self,
|
||||||
|
blkheight: Height,
|
||||||
|
blkhash: BlockHash,
|
||||||
|
found_inputs: HashSet<OutPoint>,
|
||||||
|
) -> Result<()> {
|
||||||
|
self.update = true;
|
||||||
|
self.blkheight = Some(blkheight);
|
||||||
|
self.blkhash = Some(blkhash);
|
||||||
|
self.found_inputs = found_inputs;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_to_persistent_storage(&mut self) -> Result<()> {
|
||||||
|
if let Some(sink) = get_update_sink() {
|
||||||
|
sink.send_state_update(self.to_update()?)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user