Add updates mod
This commit is contained in:
parent
5b454c8158
commit
9b5a67fc13
@ -27,6 +27,7 @@ pub mod secrets;
|
||||
pub mod serialization;
|
||||
pub mod signature;
|
||||
pub mod silentpayments;
|
||||
pub mod updates;
|
||||
|
||||
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