Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 31 additions & 1 deletion light-client-lib/src/storage/db/browser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use ckb_types::{
pub use idb::CursorDirection;
use light_client_db_common::{
idb_cursor_direction_to_ckb, read_command_payload, write_command_with_payload,
DbCommandRequest, DbCommandResponse, InputCommand, OutputCommand, KV,
DbCommandRequest, DbCommandResponse, GetRecordCountType, InputCommand, OutputCommand, KV,
};

use log::debug;
Expand Down Expand Up @@ -68,6 +68,9 @@ enum CommandRequestWithTakeWhile {
limit: usize,
skip: usize,
},
GetRecordCount {
prefix: Vec<u8>,
},
}

thread_local! {
Expand Down Expand Up @@ -194,6 +197,9 @@ impl CommunicationChannel {
},
Some(take_while),
),
CommandRequestWithTakeWhile::GetRecordCount { prefix } => {
(DbCommandRequest::GetRecordCount { prefix }, None)
}
};
debug!("Dispatching database command: {:?}", new_cmd);
let CommunicationChannel {
Expand Down Expand Up @@ -284,6 +290,30 @@ impl Storage {
Self { channel: chan }
}

pub fn get_store_record_count(&self, record_type: GetRecordCountType) -> usize {
let prefix = match record_type {
GetRecordCountType::All => vec![],
GetRecordCountType::Transaction => vec![KeyPrefix::TxHash as u8],
GetRecordCountType::CellLockScript => vec![KeyPrefix::CellLockScript as u8],
GetRecordCountType::CellTypeScript => vec![KeyPrefix::CellTypeScript as u8],
GetRecordCountType::TxLockScript => vec![KeyPrefix::TxLockScript as u8],
GetRecordCountType::TxTypeScript => vec![KeyPrefix::TxTypeScript as u8],
GetRecordCountType::BlockByHash => vec![KeyPrefix::BlockHash as u8],
GetRecordCountType::BlockByNumber => vec![KeyPrefix::BlockNumber as u8],
GetRecordCountType::CheckPointIndex => vec![KeyPrefix::CheckPointIndex as u8],
GetRecordCountType::Meta => vec![KeyPrefix::Meta as u8],
};
let result = self
.channel
.dispatch_database_command(CommandRequestWithTakeWhile::GetRecordCount { prefix })
.map_err(|e| Error::Indexdb(format!("{:?}", e)))
.unwrap();
match result {
DbCommandResponse::GetRecordCount { count } => count,
_ => unreachable!(),
}
}

fn batch(&self) -> Batch {
Batch {
add: vec![],
Expand Down
18 changes: 18 additions & 0 deletions wasm/light-client-db-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub enum DbCommandResponse {
Delete,
Iterator { kvs: Vec<KV> },
IteratorKey { keys: Vec<Vec<u8>> },
GetRecordCount { count: usize },
}

#[derive(Deserialize, Serialize, Debug)]
Expand Down Expand Up @@ -61,7 +62,24 @@ pub enum DbCommandRequest {
limit: usize,
skip: usize,
},
/// Count how many records statisfies the specified prefix
GetRecordCount { prefix: Vec<u8> },
}
#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "snake_case")]
pub enum GetRecordCountType {
All,
Transaction,
CellLockScript,
CellTypeScript,
TxLockScript,
TxTypeScript,
BlockByHash,
BlockByNumber,
CheckPointIndex,
Meta,
}

#[repr(i32)]
/// Represent a 4-byte command which will be put in input buffer
pub enum InputCommand {
Expand Down
25 changes: 22 additions & 3 deletions wasm/light-client-db-worker/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,9 @@ where
{
debug!("Handle command: {:?}", cmd);
let tx_mode = match cmd {
DbCommandRequest::Iterator { .. } | DbCommandRequest::IteratorKey { .. } => {
TransactionMode::ReadOnly
}
DbCommandRequest::Iterator { .. }
| DbCommandRequest::IteratorKey { .. }
| DbCommandRequest::GetRecordCount { .. } => TransactionMode::ReadOnly,
DbCommandRequest::Read { .. } => TransactionMode::ReadOnly,
DbCommandRequest::Put { .. } | DbCommandRequest::Delete { .. } => {
TransactionMode::ReadWrite
Expand All @@ -204,6 +204,25 @@ where
.map_err(|e| anyhow!("Unable to find store {}: {}", store_name, e))?;

let result = match cmd {
DbCommandRequest::GetRecordCount { prefix } => {
let lower_bound = serde_wasm_bindgen::to_value(&prefix).unwrap();
let upper_bound = {
let mut upper_bound = prefix.clone();
upper_bound.push(255);
serde_wasm_bindgen::to_value(&upper_bound).unwrap()
};
let count = store
.count(Some(idb::Query::KeyRange(
KeyRange::bound(&lower_bound, &upper_bound, Some(false), Some(false)).unwrap(),
)))
.map_err(|e| anyhow!("Unable to create query store size request: {}", e))?
.await
.map_err(|e| anyhow!("Unable to get store size: {}", e))?;

DbCommandResponse::GetRecordCount {
count: count as usize,
}
}
DbCommandRequest::Read { keys } => {
let mut res = Vec::new();
for key in keys {
Expand Down
11 changes: 9 additions & 2 deletions wasm/light-client-js/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ClientIndexerSearchKeyLike, ClientIndexerSearchKeyTransactionLike, ClientTransactionResponse } from "@ckb-ccc/core";
import { FetchResponse, LocalNode, localNodeTo, RemoteNode, remoteNodeTo, ScriptStatus, scriptStatusFrom, scriptStatusTo, LightClientSetScriptsCommand, transformFetchResponse, cccOrderToLightClientWasmOrder, GetTransactionsResponse, TxWithCell, TxWithCells, lightClientGetTransactionsResultTo, LightClientLocalNode, LightClientRemoteNode, LightClientScriptStatus, NetworkSetting, GetCellsResponse, getCellsResponseFrom, LightClientWorkerInitializeOptions, TraceRecord } from "./types.ts";
import { FetchResponse, LocalNode, localNodeTo, RemoteNode, remoteNodeTo, ScriptStatus, scriptStatusFrom, scriptStatusTo, LightClientSetScriptsCommand, transformFetchResponse, cccOrderToLightClientWasmOrder, GetTransactionsResponse, TxWithCell, TxWithCells, lightClientGetTransactionsResultTo, LightClientLocalNode, LightClientRemoteNode, LightClientScriptStatus, NetworkSetting, GetCellsResponse, getCellsResponseFrom, LightClientWorkerInitializeOptions, TraceRecord, RecordType } from "./types.ts";
import { ClientBlock, ClientBlockHeader, Hex, hexFrom, HexLike, Num, numFrom, NumLike, numToHex, TransactionLike } from "@ckb-ccc/core/barrel";
import { JsonRpcBlockHeader, JsonRpcTransformers } from "@ckb-ccc/core/advancedBarrel";
import { Mutex } from "async-mutex";
Expand Down Expand Up @@ -289,7 +289,14 @@ class LightClient {
async fetchTransaction(txHash: HexLike): Promise<FetchResponse<ClientTransactionResponse>> {
return transformFetchResponse<any, ClientTransactionResponse>(await this.invokeLightClientCommand("fetch_transaction", [hexFrom(txHash)]), JsonRpcTransformers.transactionResponseTo);
}

/**
* Count how many records are in the IndexedDB store
* @param RecordType to filter
* @returns The count.
*/
async getStoreRecordCount(recordType: RecordType): Promise<number> {
return await this.invokeLightClientCommand("get_store_record_count", [recordType]);
}
}

export { LightClient };
Expand Down
5 changes: 4 additions & 1 deletion wasm/light-client-js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ type TraceRecord = {
stop_at: number;
};

type RecordType = "all" | "transaction" | "cell_lock_script" | "cell_type_script" | "tx_lock_script" | "tx_type_script" | "block_by_hash" | "block_by_number" | "check_point_index" | "meta";

export {
LightClientFunctionCall,
WorkerInitializeOptions,
Expand All @@ -341,5 +343,6 @@ export {
GetCellsResponse,
TraceRecord,
Num,
Transaction
Transaction,
RecordType
}
2 changes: 1 addition & 1 deletion wasm/light-client-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "0.2.63"
ckb-light-client-lib = { path = "../../light-client-lib" }

light-client-db-common = { path = "../light-client-db-common" }
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
Expand Down
10 changes: 10 additions & 0 deletions wasm/light-client-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use ckb_light_client_lib::{
types::RunEnv,
verify::verify_tx,
};
use light_client_db_common::GetRecordCountType;
use log::debug;
use serde::{Deserialize, Serialize};
use serde_wasm_bindgen::Serializer;
Expand Down Expand Up @@ -1265,6 +1266,15 @@ pub fn fetch_transaction(tx_hash: &str) -> Result<JsValue, JsValue> {
.serialize(&SERIALIZER)?)
}

#[wasm_bindgen]
pub fn get_store_record_count(record_type: JsValue) -> Result<usize, JsValue> {
let record_type: GetRecordCountType = serde_wasm_bindgen::from_value(record_type)
.map_err(|e| format!("Invalid record type: {}", e))?;

let swc = STORAGE_WITH_DATA.get().unwrap();
Ok(swc.storage().get_store_record_count(record_type))
}

const MAX_PREFIX_SEARCH_SIZE: usize = u16::MAX as usize;

// a helper fn to build query options from search paramters, returns prefix, from_key, direction and skip offset
Expand Down