|
@@ -37,7 +37,7 @@ use darkfi_serial::{deserialize, serialize};
|
|
|
|
|
|
|
|
use crate::{
|
|
use crate::{
|
|
|
error::{WalletDbError, WalletDbResult},
|
|
error::{WalletDbError, WalletDbResult},
|
|
|
- money::{MONEY_INFO_COL_LAST_SCANNED_SLOT, MONEY_INFO_TABLE},
|
|
|
|
|
|
|
+ money::{MONEY_INFO_COL_LAST_SCANNED_BLOCK, MONEY_INFO_TABLE},
|
|
|
Drk,
|
|
Drk,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -52,20 +52,20 @@ impl Drk {
|
|
|
endpoint: Url,
|
|
endpoint: Url,
|
|
|
ex: Arc<smol::Executor<'static>>,
|
|
ex: Arc<smol::Executor<'static>>,
|
|
|
) -> Result<()> {
|
|
) -> Result<()> {
|
|
|
- let req = JsonRequest::new("blockchain.last_known_slot", JsonValue::Array(vec![]));
|
|
|
|
|
|
|
+ let req = JsonRequest::new("blockchain.last_known_block", JsonValue::Array(vec![]));
|
|
|
let rep = self.rpc_client.request(req).await?;
|
|
let rep = self.rpc_client.request(req).await?;
|
|
|
let last_known = *rep.get::<f64>().unwrap() as u64;
|
|
let last_known = *rep.get::<f64>().unwrap() as u64;
|
|
|
- let last_scanned = match self.last_scanned_slot().await {
|
|
|
|
|
|
|
+ let last_scanned = match self.last_scanned_block().await {
|
|
|
Ok(l) => l,
|
|
Ok(l) => l,
|
|
|
Err(e) => {
|
|
Err(e) => {
|
|
|
return Err(Error::RusqliteError(format!(
|
|
return Err(Error::RusqliteError(format!(
|
|
|
- "[subscribe_blocks] Retrieving last scanned slot failed: {e:?}"
|
|
|
|
|
|
|
+ "[subscribe_blocks] Retrieving last scanned block failed: {e:?}"
|
|
|
)))
|
|
)))
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
if last_known != last_scanned {
|
|
if last_known != last_scanned {
|
|
|
- eprintln!("Warning: Last scanned slot is not the last known slot.");
|
|
|
|
|
|
|
+ eprintln!("Warning: Last scanned block is not the last known block.");
|
|
|
eprintln!("You should first fully scan the blockchain, and then subscribe");
|
|
eprintln!("You should first fully scan the blockchain, and then subscribe");
|
|
|
return Err(Error::RusqliteError(
|
|
return Err(Error::RusqliteError(
|
|
|
"[subscribe_blocks] Blockchain not fully scanned".to_string(),
|
|
"[subscribe_blocks] Blockchain not fully scanned".to_string(),
|
|
@@ -177,12 +177,12 @@ impl Drk {
|
|
|
self.apply_tx_money_data(tx, true).await?;
|
|
self.apply_tx_money_data(tx, true).await?;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Write this slot into `last_scanned_slot`
|
|
|
|
|
|
|
+ // Write this block height into `last_scanned_block`
|
|
|
let query =
|
|
let query =
|
|
|
- format!("UPDATE {} SET {} = ?1;", *MONEY_INFO_TABLE, MONEY_INFO_COL_LAST_SCANNED_SLOT);
|
|
|
|
|
|
|
+ format!("UPDATE {} SET {} = ?1;", *MONEY_INFO_TABLE, MONEY_INFO_COL_LAST_SCANNED_BLOCK);
|
|
|
if let Err(e) = self.wallet.exec_sql(&query, rusqlite::params![block.header.height]).await {
|
|
if let Err(e) = self.wallet.exec_sql(&query, rusqlite::params![block.header.height]).await {
|
|
|
return Err(Error::RusqliteError(format!(
|
|
return Err(Error::RusqliteError(format!(
|
|
|
- "[scan_block_money] Update last scanned slot failed: {e:?}"
|
|
|
|
|
|
|
+ "[scan_block_money] Update last scanned block failed: {e:?}"
|
|
|
)))
|
|
)))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -202,12 +202,12 @@ impl Drk {
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Scans the blockchain starting from the last scanned slot, for relevant
|
|
|
|
|
|
|
+ /// Scans the blockchain starting from the last scanned block, for relevant
|
|
|
/// money transfer transactions. If reset flag is provided, Merkle tree state
|
|
/// money transfer transactions. If reset flag is provided, Merkle tree state
|
|
|
/// and coins are reset, and start scanning from beginning. Alternatively,
|
|
/// and coins are reset, and start scanning from beginning. Alternatively,
|
|
|
/// it looks for a checkpoint in the wallet to reset and start scanning from.
|
|
/// it looks for a checkpoint in the wallet to reset and start scanning from.
|
|
|
pub async fn scan_blocks(&self, reset: bool) -> WalletDbResult<()> {
|
|
pub async fn scan_blocks(&self, reset: bool) -> WalletDbResult<()> {
|
|
|
- let mut sl = if reset {
|
|
|
|
|
|
|
+ let mut height = if reset {
|
|
|
self.reset_money_tree().await?;
|
|
self.reset_money_tree().await?;
|
|
|
self.reset_money_coins().await?;
|
|
self.reset_money_coins().await?;
|
|
|
self.reset_dao_trees().await?;
|
|
self.reset_dao_trees().await?;
|
|
@@ -217,10 +217,10 @@ impl Drk {
|
|
|
self.update_all_tx_history_records_status("Rejected").await?;
|
|
self.update_all_tx_history_records_status("Rejected").await?;
|
|
|
0
|
|
0
|
|
|
} else {
|
|
} else {
|
|
|
- self.last_scanned_slot().await?
|
|
|
|
|
|
|
+ self.last_scanned_block().await?
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- let req = JsonRequest::new("blockchain.last_known_slot", JsonValue::Array(vec![]));
|
|
|
|
|
|
|
+ let req = JsonRequest::new("blockchain.last_known_block", JsonValue::Array(vec![]));
|
|
|
let rep = match self.rpc_client.request(req).await {
|
|
let rep = match self.rpc_client.request(req).await {
|
|
|
Ok(r) => r,
|
|
Ok(r) => r,
|
|
|
Err(e) => {
|
|
Err(e) => {
|
|
@@ -230,69 +230,50 @@ impl Drk {
|
|
|
};
|
|
};
|
|
|
let last = *rep.get::<f64>().unwrap() as u64;
|
|
let last = *rep.get::<f64>().unwrap() as u64;
|
|
|
|
|
|
|
|
- eprintln!("Requested to scan from slot number: {sl}");
|
|
|
|
|
- eprintln!("Last known slot number reported by darkfid: {last}");
|
|
|
|
|
|
|
+ eprintln!("Requested to scan from block number: {height}");
|
|
|
|
|
+ eprintln!("Last known block number reported by darkfid: {last}");
|
|
|
|
|
|
|
|
- // Already scanned last known slot
|
|
|
|
|
- if sl == last {
|
|
|
|
|
|
|
+ // Already scanned last known block
|
|
|
|
|
+ if height == last {
|
|
|
return Ok(())
|
|
return Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- while sl <= last {
|
|
|
|
|
- eprint!("Requesting slot {}... ", sl);
|
|
|
|
|
- let requested_block = match self.get_block_by_slot(sl).await {
|
|
|
|
|
|
|
+ while height <= last {
|
|
|
|
|
+ eprint!("Requesting block {}... ", height);
|
|
|
|
|
+ let block = match self.get_block_by_height(height).await {
|
|
|
Ok(r) => r,
|
|
Ok(r) => r,
|
|
|
Err(e) => {
|
|
Err(e) => {
|
|
|
eprintln!("[scan_blocks] RPC client request failed: {e:?}");
|
|
eprintln!("[scan_blocks] RPC client request failed: {e:?}");
|
|
|
return Err(WalletDbError::GenericError)
|
|
return Err(WalletDbError::GenericError)
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
- if let Some(block) = requested_block {
|
|
|
|
|
- eprintln!("Found");
|
|
|
|
|
- if let Err(e) = self.scan_block_money(&block).await {
|
|
|
|
|
- eprintln!("[scan_blocks] Scan block Money failed: {e:?}");
|
|
|
|
|
- return Err(WalletDbError::GenericError)
|
|
|
|
|
- };
|
|
|
|
|
- if let Err(e) = self.scan_block_dao(&block).await {
|
|
|
|
|
- eprintln!("[scan_blocks] Scan block DAO failed: {e:?}");
|
|
|
|
|
- return Err(WalletDbError::GenericError)
|
|
|
|
|
- };
|
|
|
|
|
- self.update_tx_history_records_status(&block.txs, "Finalized").await?;
|
|
|
|
|
- } else {
|
|
|
|
|
- eprintln!("Not found");
|
|
|
|
|
- // Write down the slot number into back to the wallet
|
|
|
|
|
- // This might be a bit intense, but we accept it for now.
|
|
|
|
|
- let query = format!(
|
|
|
|
|
- "UPDATE {} SET {} = ?1;",
|
|
|
|
|
- *MONEY_INFO_TABLE, MONEY_INFO_COL_LAST_SCANNED_SLOT
|
|
|
|
|
- );
|
|
|
|
|
- self.wallet.exec_sql(&query, rusqlite::params![sl]).await?;
|
|
|
|
|
- }
|
|
|
|
|
- sl += 1;
|
|
|
|
|
|
|
+ if let Err(e) = self.scan_block_money(&block).await {
|
|
|
|
|
+ eprintln!("[scan_blocks] Scan block Money failed: {e:?}");
|
|
|
|
|
+ return Err(WalletDbError::GenericError)
|
|
|
|
|
+ };
|
|
|
|
|
+ if let Err(e) = self.scan_block_dao(&block).await {
|
|
|
|
|
+ eprintln!("[scan_blocks] Scan block DAO failed: {e:?}");
|
|
|
|
|
+ return Err(WalletDbError::GenericError)
|
|
|
|
|
+ };
|
|
|
|
|
+ self.update_tx_history_records_status(&block.txs, "Finalized").await?;
|
|
|
|
|
+ height += 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Queries darkfid for a block with given slot
|
|
|
|
|
- async fn get_block_by_slot(&self, slot: u64) -> Result<Option<BlockInfo>> {
|
|
|
|
|
|
|
+ // Queries darkfid for a block with given height
|
|
|
|
|
+ async fn get_block_by_height(&self, height: u64) -> Result<BlockInfo> {
|
|
|
let req = JsonRequest::new(
|
|
let req = JsonRequest::new(
|
|
|
- "blockchain.get_slot",
|
|
|
|
|
- JsonValue::Array(vec![JsonValue::String(slot.to_string())]),
|
|
|
|
|
|
|
+ "blockchain.get_block",
|
|
|
|
|
+ JsonValue::Array(vec![JsonValue::String(height.to_string())]),
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
- // This API is weird, we need some way of telling it's an empty slot and
|
|
|
|
|
- // not an error
|
|
|
|
|
- match self.rpc_client.request(req).await {
|
|
|
|
|
- Ok(params) => {
|
|
|
|
|
- let param = params.get::<String>().unwrap();
|
|
|
|
|
- let bytes = bs58::decode(param).into_vec()?;
|
|
|
|
|
- let block = deserialize(&bytes)?;
|
|
|
|
|
- Ok(Some(block))
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- Err(_) => Ok(None),
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ let params = self.rpc_client.request(req).await?;
|
|
|
|
|
+ let param = params.get::<String>().unwrap();
|
|
|
|
|
+ let bytes = bs58::decode(param).into_vec()?;
|
|
|
|
|
+ let block = deserialize(&bytes)?;
|
|
|
|
|
+ Ok(block)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// Broadcast a given transaction to darkfid and forward onto the network.
|
|
/// Broadcast a given transaction to darkfid and forward onto the network.
|