mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-16 13:38:12 -07:00
global: snapshot
This commit is contained in:
@@ -39,7 +39,8 @@ impl Vecs {
|
||||
|
||||
Ok(Self {
|
||||
height_to_interval: EagerVec::forced_import(
|
||||
&path.join("height_to_interval"),
|
||||
path,
|
||||
"interval",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -85,11 +86,7 @@ impl Vecs {
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_sum().add_total(),
|
||||
)?,
|
||||
height_to_vbytes: EagerVec::forced_import(
|
||||
&path.join("height_to_vbytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_vbytes: EagerVec::forced_import(path, "vbytes", Version::ZERO, compressed)?,
|
||||
indexes_to_block_vbytes: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"block_vbytes",
|
||||
@@ -99,12 +96,14 @@ impl Vecs {
|
||||
StorableVecGeneatorOptions::default().add_sum().add_total(),
|
||||
)?,
|
||||
difficultyepoch_to_timestamp: EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_timestamp"),
|
||||
path,
|
||||
"timestamp",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
halvingepoch_to_timestamp: EagerVec::forced_import(
|
||||
&path.join("halvingepoch_to_timestamp"),
|
||||
path,
|
||||
"timestamp",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
|
||||
@@ -82,72 +82,76 @@ impl Vecs {
|
||||
|
||||
Ok(Self {
|
||||
dateindex_to_ohlc_in_cents: EagerVec::forced_import(
|
||||
&fetched_path.join("dateindex_to_ohlc_in_cents"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_ohlc"),
|
||||
&fetched_path,
|
||||
"ohlc_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
dateindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_close_in_cents: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_close_in_cents"),
|
||||
path,
|
||||
"close_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_high_in_cents: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_high_in_cents"),
|
||||
path,
|
||||
"high_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_low_in_cents: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_low_in_cents"),
|
||||
path,
|
||||
"low_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_open_in_cents: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_open_in_cents"),
|
||||
path,
|
||||
"open_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_ohlc_in_cents: EagerVec::forced_import(
|
||||
&fetched_path.join("height_to_ohlc_in_cents"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("height_to_ohlc"),
|
||||
&fetched_path,
|
||||
"ohlc_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
height_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("height_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_close_in_cents: EagerVec::forced_import(
|
||||
&path.join("height_to_close_in_cents"),
|
||||
path,
|
||||
"close_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_high_in_cents: EagerVec::forced_import(
|
||||
&path.join("height_to_high_in_cents"),
|
||||
path,
|
||||
"high_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_low_in_cents: EagerVec::forced_import(
|
||||
&path.join("height_to_low_in_cents"),
|
||||
path,
|
||||
"low_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_open_in_cents: EagerVec::forced_import(
|
||||
&path.join("height_to_open_in_cents"),
|
||||
path,
|
||||
"open_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -263,64 +267,52 @@ impl Vecs {
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
weekindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("weekindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
weekindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
weekindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("weekindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
difficultyepoch_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_ohlc"),
|
||||
path,
|
||||
"ohlc",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
difficultyepoch_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
monthindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("monthindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
monthindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
monthindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("monthindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
quarterindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("quarterindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
quarterindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
quarterindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("quarterindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
yearindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("yearindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
yearindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
yearindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("yearindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
// halvingepoch_to_ohlc: StorableVec::forced_import(&path.join("halvingepoch_to_ohlc"), Version::ZERO, compressed)?,
|
||||
decadeindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("decadeindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
// halvingepoch_to_ohlc: StorableVec::forced_import(path,
|
||||
// "halvingepoch_to_ohlc"), Version::ZERO, compressed)?,
|
||||
decadeindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
decadeindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("decadeindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
|
||||
@@ -46,27 +46,23 @@ where
|
||||
compressed: Compressed,
|
||||
options: StorableVecGeneatorOptions,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let key = I::to_string().split("::").last().unwrap().to_lowercase();
|
||||
|
||||
let only_one_active = options.is_only_one_active();
|
||||
|
||||
let default = || path.join(format!("{key}_to_{name}"));
|
||||
|
||||
let prefix = |s: &str| path.join(format!("{key}_to_{s}_{name}"));
|
||||
let prefix = |s: &str| format!("{s}_{name}");
|
||||
|
||||
let maybe_prefix = |s: &str| {
|
||||
if only_one_active {
|
||||
default()
|
||||
name.to_string()
|
||||
} else {
|
||||
prefix(s)
|
||||
}
|
||||
};
|
||||
|
||||
let suffix = |s: &str| path.join(format!("{key}_to_{name}_{s}"));
|
||||
let suffix = |s: &str| format!("{name}_{s}");
|
||||
|
||||
let maybe_suffix = |s: &str| {
|
||||
if only_one_active {
|
||||
default()
|
||||
name.to_string()
|
||||
} else {
|
||||
suffix(s)
|
||||
}
|
||||
@@ -78,6 +74,7 @@ where
|
||||
first: options.first.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_prefix("first"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -87,17 +84,14 @@ where
|
||||
}),
|
||||
last: options.last.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
&path.join(format!("{key}_to_{name}")),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
EagerVec::forced_import(path, name, version + Version::ZERO, compressed)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
min: options.min.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("min"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -108,6 +102,7 @@ where
|
||||
max: options.max.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("max"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -118,6 +113,7 @@ where
|
||||
median: options.median.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("median"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -128,6 +124,7 @@ where
|
||||
average: options.average.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("average"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -138,6 +135,7 @@ where
|
||||
sum: options.sum.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("sum"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -147,13 +145,19 @@ where
|
||||
}),
|
||||
total: options.total.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(&prefix("total"), version + Version::ZERO, compressed)
|
||||
.unwrap(),
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&prefix("total"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
_90p: options._90p.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("90p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -164,6 +168,7 @@ where
|
||||
_75p: options._75p.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("75p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -174,6 +179,7 @@ where
|
||||
_25p: options._25p.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("25p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
@@ -184,6 +190,7 @@ where
|
||||
_10p: options._10p.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("10p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
|
||||
@@ -49,11 +49,7 @@ where
|
||||
let options = options.remove_percentiles();
|
||||
|
||||
Ok(Self {
|
||||
dateindex: EagerVec::forced_import(
|
||||
&path.join(format!("dateindex_to_{name}")),
|
||||
version,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex: EagerVec::forced_import(path, name, version, compressed)?,
|
||||
dateindex_extra,
|
||||
weekindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
|
||||
monthindex: ComputedVecBuilder::forced_import(
|
||||
|
||||
@@ -45,16 +45,8 @@ where
|
||||
) -> color_eyre::Result<Self> {
|
||||
let version = VERSION + version;
|
||||
|
||||
let height = compute_source.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
&path.join(format!("height_to_{name}")),
|
||||
version,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
});
|
||||
let height = compute_source
|
||||
.then(|| Box::new(EagerVec::forced_import(path, name, version, compressed).unwrap()));
|
||||
|
||||
let height_extra = ComputedVecBuilder::forced_import(
|
||||
path,
|
||||
|
||||
@@ -36,8 +36,7 @@ where
|
||||
) -> color_eyre::Result<Self> {
|
||||
let version = VERSION + version;
|
||||
|
||||
let height =
|
||||
EagerVec::forced_import(&path.join(format!("height_to_{name}")), version, compressed)?;
|
||||
let height = EagerVec::forced_import(path, name, version, compressed)?;
|
||||
|
||||
let height_extra = ComputedVecBuilder::forced_import(
|
||||
path,
|
||||
|
||||
@@ -48,16 +48,8 @@ where
|
||||
) -> color_eyre::Result<Self> {
|
||||
let version = VERSION + version;
|
||||
|
||||
let txindex = compute_source.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
&path.join(format!("txindex_to_{name}")),
|
||||
version,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
});
|
||||
let txindex = compute_source
|
||||
.then(|| Box::new(EagerVec::forced_import(path, name, version, compressed).unwrap()));
|
||||
|
||||
let height = ComputedVecBuilder::forced_import(path, name, version, compressed, options)?;
|
||||
|
||||
|
||||
@@ -51,6 +51,9 @@ impl ComputedValueVecsFromTxindex {
|
||||
let compute_source = source.is_none();
|
||||
let compute_dollars = fetched.is_some();
|
||||
|
||||
let name_in_btc = format!("{name}_in_btc");
|
||||
let name_in_usd = format!("{name}_in_usd");
|
||||
|
||||
let sats = ComputedVecsFromTxindex::forced_import(
|
||||
path,
|
||||
name,
|
||||
@@ -61,7 +64,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
)?;
|
||||
|
||||
let bitcoin_txindex = LazyVecFrom1::init(
|
||||
"txindex_to_{name}_in_btc",
|
||||
&name_in_btc,
|
||||
VERSION + version,
|
||||
source.map_or_else(|| sats.txindex.as_ref().unwrap().boxed_clone(), |s| s),
|
||||
|txindex: TxIndex, iter| {
|
||||
@@ -74,7 +77,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
|
||||
let bitcoin = ComputedVecsFromTxindex::forced_import(
|
||||
path,
|
||||
&format!("{name}_in_btc"),
|
||||
&name_in_btc,
|
||||
false,
|
||||
VERSION + version,
|
||||
compressed,
|
||||
@@ -85,7 +88,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
ComputedVecFrom3::forced_import_or_init_from_3(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_{name}_in_usd",
|
||||
&name_in_usd,
|
||||
VERSION + version,
|
||||
compressed,
|
||||
bitcoin_txindex.boxed_clone(),
|
||||
@@ -120,7 +123,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
dollars: compute_dollars.then(|| {
|
||||
ComputedVecsFromTxindex::forced_import(
|
||||
path,
|
||||
&format!("{name}_in_usd"),
|
||||
&name_in_usd,
|
||||
false,
|
||||
VERSION + version,
|
||||
compressed,
|
||||
|
||||
@@ -99,7 +99,7 @@ impl Vecs {
|
||||
let outputindex_to_outputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"outputindex_to_outputindex",
|
||||
"outputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().outputindex_to_value.boxed_clone(),
|
||||
@@ -109,7 +109,7 @@ impl Vecs {
|
||||
let inputindex_to_inputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"inputindex_to_inputindex",
|
||||
"inputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().inputindex_to_outputindex.boxed_clone(),
|
||||
@@ -119,7 +119,7 @@ impl Vecs {
|
||||
let txindex_to_txindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_txindex",
|
||||
"txindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_txid.boxed_clone(),
|
||||
@@ -129,7 +129,7 @@ impl Vecs {
|
||||
let txindex_to_input_count = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_input_count",
|
||||
"input_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_inputindex.boxed_clone(),
|
||||
@@ -152,7 +152,7 @@ impl Vecs {
|
||||
let txindex_to_output_count = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_output_count",
|
||||
"output_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_outputindex.boxed_clone(),
|
||||
@@ -175,7 +175,7 @@ impl Vecs {
|
||||
let p2pk33index_to_p2pk33index = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2pk33index_to_p2pk33index",
|
||||
"p2pk33index",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2pk33index_to_p2pk33bytes.boxed_clone(),
|
||||
@@ -184,7 +184,7 @@ impl Vecs {
|
||||
let p2pk65index_to_p2pk65index = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2pk65index_to_p2pk65index",
|
||||
"p2pk65index",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2pk65index_to_p2pk65bytes.boxed_clone(),
|
||||
@@ -193,7 +193,7 @@ impl Vecs {
|
||||
let p2pkhindex_to_p2pkhindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2pkhindex_to_p2pkhindex",
|
||||
"p2pkhindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2pkhindex_to_p2pkhbytes.boxed_clone(),
|
||||
@@ -202,7 +202,7 @@ impl Vecs {
|
||||
let p2shindex_to_p2shindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2shindex_to_p2shindex",
|
||||
"p2shindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2shindex_to_p2shbytes.boxed_clone(),
|
||||
@@ -211,7 +211,7 @@ impl Vecs {
|
||||
let p2trindex_to_p2trindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2trindex_to_p2trindex",
|
||||
"p2trindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2trindex_to_p2trbytes.boxed_clone(),
|
||||
@@ -220,7 +220,7 @@ impl Vecs {
|
||||
let p2wpkhindex_to_p2wpkhindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2wpkhindex_to_p2wpkhindex",
|
||||
"p2wpkhindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2wpkhindex_to_p2wpkhbytes.boxed_clone(),
|
||||
@@ -229,7 +229,7 @@ impl Vecs {
|
||||
let p2wshindex_to_p2wshindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2wshindex_to_p2wshindex",
|
||||
"p2wshindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2wshindex_to_p2wshbytes.boxed_clone(),
|
||||
@@ -238,7 +238,7 @@ impl Vecs {
|
||||
let p2aindex_to_p2aindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2aindex_to_p2aindex",
|
||||
"p2aindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2aindex_to_p2abytes.boxed_clone(),
|
||||
@@ -247,7 +247,7 @@ impl Vecs {
|
||||
let p2msindex_to_p2msindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2msindex_to_p2msindex",
|
||||
"p2msindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2msindex_to_txindex.boxed_clone(),
|
||||
@@ -256,7 +256,7 @@ impl Vecs {
|
||||
let emptyoutputindex_to_emptyoutputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"emptyoutputindex_to_emptyoutputindex",
|
||||
"emptyoutputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().emptyoutputindex_to_txindex.boxed_clone(),
|
||||
@@ -265,7 +265,7 @@ impl Vecs {
|
||||
let unknownoutputindex_to_unknownoutputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"unknownoutputindex_to_unknownoutputindex",
|
||||
"unknownoutputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().unknownoutputindex_to_txindex.boxed_clone(),
|
||||
@@ -274,23 +274,20 @@ impl Vecs {
|
||||
let opreturnindex_to_opreturnindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"opreturnindex_to_opreturnindex",
|
||||
"opreturnindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().opreturnindex_to_txindex.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
let dateindex_to_first_height = EagerVec::forced_import(
|
||||
&path.join("dateindex_to_first_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let dateindex_to_first_height =
|
||||
EagerVec::forced_import(path, "first_height", Version::ZERO, compressed)?;
|
||||
|
||||
let dateindex_to_dateindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"dateindex_to_dateindex",
|
||||
"dateindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
dateindex_to_first_height.boxed_clone(),
|
||||
@@ -300,20 +297,19 @@ impl Vecs {
|
||||
let dateindex_to_date = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"dateindex_to_date",
|
||||
"date",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
dateindex_to_dateindex.boxed_clone(),
|
||||
|index, _| Some(Date::from(index)),
|
||||
)?;
|
||||
|
||||
let height_to_date =
|
||||
EagerVec::forced_import(&path.join("height_to_date"), Version::ZERO, compressed)?;
|
||||
let height_to_date = EagerVec::forced_import(path, "date", Version::ZERO, compressed)?;
|
||||
|
||||
let height_to_height = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"height_to_height",
|
||||
"height",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
height_to_date.boxed_clone(),
|
||||
@@ -323,23 +319,20 @@ impl Vecs {
|
||||
let height_to_difficultyepoch = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"height_to_difficultyepoch",
|
||||
"difficultyepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
height_to_height.boxed_clone(),
|
||||
|index, _| Some(DifficultyEpoch::from(index)),
|
||||
)?;
|
||||
|
||||
let difficultyepoch_to_first_height = EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_first_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let difficultyepoch_to_first_height =
|
||||
EagerVec::forced_import(path, "first_height", Version::ZERO, compressed)?;
|
||||
|
||||
let difficultyepoch_to_difficultyepoch = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"difficultyepoch_to_difficultyepoch",
|
||||
"difficultyepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
difficultyepoch_to_first_height.boxed_clone(),
|
||||
@@ -349,67 +342,52 @@ impl Vecs {
|
||||
let height_to_halvingepoch = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"height_to_halvingepoch",
|
||||
"halvingepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
height_to_height.boxed_clone(),
|
||||
|index, _| Some(HalvingEpoch::from(index)),
|
||||
)?;
|
||||
|
||||
let halvingepoch_to_first_height = EagerVec::forced_import(
|
||||
&path.join("halvingepoch_to_first_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let halvingepoch_to_first_height =
|
||||
EagerVec::forced_import(path, "first_height", Version::ZERO, compressed)?;
|
||||
|
||||
let halvingepoch_to_halvingepoch = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"halvingepoch_to_halvingepoch",
|
||||
"halvingepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
halvingepoch_to_first_height.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
let dateindex_to_weekindex = EagerVec::forced_import(
|
||||
&path.join("dateindex_to_weekindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let dateindex_to_weekindex =
|
||||
EagerVec::forced_import(path, "weekindex", Version::ZERO, compressed)?;
|
||||
|
||||
let weekindex_to_first_dateindex = EagerVec::forced_import(
|
||||
&path.join("weekindex_to_first_dateindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let weekindex_to_first_dateindex =
|
||||
EagerVec::forced_import(path, "first_dateindex", Version::ZERO, compressed)?;
|
||||
|
||||
let weekindex_to_weekindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"weekindex_to_weekindex",
|
||||
"weekindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
weekindex_to_first_dateindex.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
let dateindex_to_monthindex = EagerVec::forced_import(
|
||||
&path.join("dateindex_to_monthindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let dateindex_to_monthindex =
|
||||
EagerVec::forced_import(path, "monthindex", Version::ZERO, compressed)?;
|
||||
|
||||
let monthindex_to_first_dateindex = EagerVec::forced_import(
|
||||
&path.join("monthindex_to_first_dateindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let monthindex_to_first_dateindex =
|
||||
EagerVec::forced_import(path, "first_dateindex", Version::ZERO, compressed)?;
|
||||
|
||||
let monthindex_to_monthindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"monthindex_to_monthindex",
|
||||
"monthindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
monthindex_to_first_dateindex.boxed_clone(),
|
||||
@@ -419,23 +397,20 @@ impl Vecs {
|
||||
let monthindex_to_quarterindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"monthindex_to_quarterindex",
|
||||
"quarterindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
monthindex_to_monthindex.boxed_clone(),
|
||||
|index, _| Some(QuarterIndex::from(index)),
|
||||
)?;
|
||||
|
||||
let quarterindex_to_first_monthindex = EagerVec::forced_import(
|
||||
&path.join("quarterindex_to_first_monthindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let quarterindex_to_first_monthindex =
|
||||
EagerVec::forced_import(path, "first_monthindex", Version::ZERO, compressed)?;
|
||||
|
||||
let quarterindex_to_quarterindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"quarterindex_to_quarterindex",
|
||||
"quarterindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
quarterindex_to_first_monthindex.boxed_clone(),
|
||||
@@ -445,23 +420,20 @@ impl Vecs {
|
||||
let monthindex_to_yearindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"monthindex_to_yearindex",
|
||||
"yearindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
monthindex_to_monthindex.boxed_clone(),
|
||||
|index, _| Some(YearIndex::from(index)),
|
||||
)?;
|
||||
|
||||
let yearindex_to_first_monthindex = EagerVec::forced_import(
|
||||
&path.join("yearindex_to_first_monthindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let yearindex_to_first_monthindex =
|
||||
EagerVec::forced_import(path, "first_monthindex", Version::ZERO, compressed)?;
|
||||
|
||||
let yearindex_to_yearindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"yearindex_to_yearindex",
|
||||
"yearindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
yearindex_to_first_monthindex.boxed_clone(),
|
||||
@@ -471,23 +443,20 @@ impl Vecs {
|
||||
let yearindex_to_decadeindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"yearindex_to_decadeindex",
|
||||
"decadeindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
yearindex_to_yearindex.boxed_clone(),
|
||||
|index, _| Some(DecadeIndex::from(index)),
|
||||
)?;
|
||||
|
||||
let decadeindex_to_first_yearindex = EagerVec::forced_import(
|
||||
&path.join("decadeindex_to_first_yearindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let decadeindex_to_first_yearindex =
|
||||
EagerVec::forced_import(path, "first_yearindex", Version::ZERO, compressed)?;
|
||||
|
||||
let decadeindex_to_decadeindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"decadeindex_to_decadeindex",
|
||||
"decadeindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
decadeindex_to_first_yearindex.boxed_clone(),
|
||||
@@ -539,67 +508,75 @@ impl Vecs {
|
||||
yearindex_to_first_monthindex,
|
||||
yearindex_to_yearindex,
|
||||
height_to_date_fixed: EagerVec::forced_import(
|
||||
&path.join("height_to_date_fixed"),
|
||||
path,
|
||||
"date_fixed",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_dateindex: EagerVec::forced_import(
|
||||
&path.join("height_to_dateindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_height: EagerVec::forced_import(
|
||||
&path.join("txindex_to_height"),
|
||||
path,
|
||||
"dateindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_height: EagerVec::forced_import(path, "height", Version::ZERO, compressed)?,
|
||||
height_to_timestamp_fixed: EagerVec::forced_import(
|
||||
&path.join("height_to_timestamp_fixed"),
|
||||
path,
|
||||
"timestamp_fixed",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_txindex_count: EagerVec::forced_import(
|
||||
&path.join("height_to_txindex_count"),
|
||||
path,
|
||||
"txindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_height_count: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_height_count"),
|
||||
path,
|
||||
"height_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
weekindex_to_dateindex_count: EagerVec::forced_import(
|
||||
&path.join("weekindex_to_dateindex_count"),
|
||||
path,
|
||||
"dateindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
difficultyepoch_to_height_count: EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_height_count"),
|
||||
path,
|
||||
"height_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
monthindex_to_dateindex_count: EagerVec::forced_import(
|
||||
&path.join("monthindex_to_dateindex_count"),
|
||||
path,
|
||||
"dateindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
quarterindex_to_monthindex_count: EagerVec::forced_import(
|
||||
&path.join("quarterindex_to_monthindex_count"),
|
||||
path,
|
||||
"monthindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
yearindex_to_monthindex_count: EagerVec::forced_import(
|
||||
&path.join("yearindex_to_monthindex_count"),
|
||||
path,
|
||||
"monthindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
decadeindex_to_yearindex_count: EagerVec::forced_import(
|
||||
&path.join("decadeindex_to_yearindex_count"),
|
||||
path,
|
||||
"yearindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
outputindex_to_txindex: EagerVec::forced_import(
|
||||
&path.join("outputindex_to_txindex"),
|
||||
path,
|
||||
"txindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
|
||||
@@ -102,7 +102,7 @@ impl Vecs {
|
||||
let inputindex_to_value = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"inputindex_to_value",
|
||||
"value",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().inputindex_to_outputindex.boxed_clone(),
|
||||
@@ -129,7 +129,7 @@ impl Vecs {
|
||||
let txindex_to_weight = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_weight",
|
||||
"weight",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_base_size.boxed_clone(),
|
||||
@@ -157,7 +157,7 @@ impl Vecs {
|
||||
let txindex_to_vsize = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_vsize",
|
||||
"vsize",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
txindex_to_weight.boxed_clone(),
|
||||
@@ -174,7 +174,7 @@ impl Vecs {
|
||||
let txindex_to_is_coinbase = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_is_coinbase",
|
||||
"is_coinbase",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexes.txindex_to_height.boxed_clone(),
|
||||
@@ -198,7 +198,7 @@ impl Vecs {
|
||||
let txindex_to_input_value = ComputedVec::forced_import_or_init_from_3(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_input_value",
|
||||
"input_value",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_inputindex.boxed_clone(),
|
||||
@@ -247,7 +247,7 @@ impl Vecs {
|
||||
let txindex_to_output_value = ComputedVec::forced_import_or_init_from_3(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_output_value",
|
||||
"output_value",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_outputindex.boxed_clone(),
|
||||
@@ -296,7 +296,7 @@ impl Vecs {
|
||||
let txindex_to_fee = ComputedVecFrom2::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_fee",
|
||||
"fee",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
txindex_to_input_value.boxed_clone(),
|
||||
@@ -319,7 +319,7 @@ impl Vecs {
|
||||
let txindex_to_feerate = ComputedVecFrom2::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_feerate",
|
||||
"feerate",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
txindex_to_fee.boxed_clone(),
|
||||
|
||||
@@ -12,7 +12,7 @@ use brk_vec::{
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::states::{CohortState, Outputs, RealizedState, ReceivedState, SentState};
|
||||
use crate::states::{CohortState, Outputs, OutputsByTerm, RealizedState, ReceivedState, SentState};
|
||||
|
||||
use super::{
|
||||
Indexes, fetched,
|
||||
@@ -33,7 +33,11 @@ impl Vecs {
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
) -> color_eyre::Result<Self> {
|
||||
Ok(Self(Outputs {
|
||||
all: Vecs_::forced_import(path, _computation, compressed, fetched)?,
|
||||
all: Vecs_::forced_import(path, None, _computation, compressed, fetched)?,
|
||||
// by_term: OutputsByTerm {
|
||||
// short: Vecs_::forced_import(path, Some("sth"), _computation, compressed, fetched)?,
|
||||
// long: Vecs_::forced_import(path, Some("lth"), _computation, compressed, fetched)?,
|
||||
// },
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -373,6 +377,7 @@ pub struct Vecs_ {
|
||||
impl Vecs_ {
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
cohort_name: Option<&str>,
|
||||
_computation: Computation,
|
||||
compressed: Compressed,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
@@ -381,10 +386,15 @@ impl Vecs_ {
|
||||
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
// let prefix = |s: &str| cohort_name.map_or(s.to_string(), |name| format!("{s}_{name}"));
|
||||
|
||||
let suffix = |s: &str| cohort_name.map_or(s.to_string(), |name| format!("{name}_{s}"));
|
||||
|
||||
Ok(Self {
|
||||
height_to_realized_cap: compute_dollars.then(|| {
|
||||
EagerVec::forced_import(
|
||||
&path.join("height_to_realized_cap"),
|
||||
path,
|
||||
&suffix("realized_cap"),
|
||||
VERSION + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
@@ -393,7 +403,7 @@ impl Vecs_ {
|
||||
indexes_to_realized_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"realized_cap",
|
||||
&suffix("realized_cap"),
|
||||
false,
|
||||
VERSION + Version::ZERO,
|
||||
compressed,
|
||||
@@ -402,13 +412,14 @@ impl Vecs_ {
|
||||
.unwrap()
|
||||
}),
|
||||
height_to_supply: EagerVec::forced_import(
|
||||
&path.join("height_to_supply"),
|
||||
path,
|
||||
&suffix("supply"),
|
||||
VERSION + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
indexes_to_supply: ComputedValueVecsFromHeight::forced_import(
|
||||
path,
|
||||
"supply",
|
||||
&suffix("supply"),
|
||||
false,
|
||||
VERSION + Version::ZERO,
|
||||
compressed,
|
||||
@@ -416,13 +427,14 @@ impl Vecs_ {
|
||||
compute_dollars,
|
||||
)?,
|
||||
height_to_unspendable_supply: EagerVec::forced_import(
|
||||
&path.join("height_to_unspendable_supply"),
|
||||
path,
|
||||
&suffix("unspendable_supply"),
|
||||
VERSION + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
indexes_to_unspendable_supply: ComputedValueVecsFromHeight::forced_import(
|
||||
path,
|
||||
"unspendable_supply",
|
||||
&suffix("unspendable_supply"),
|
||||
false,
|
||||
VERSION + Version::ZERO,
|
||||
compressed,
|
||||
@@ -430,13 +442,14 @@ impl Vecs_ {
|
||||
compute_dollars,
|
||||
)?,
|
||||
height_to_utxo_count: EagerVec::forced_import(
|
||||
&path.join("height_to_utxo_count"),
|
||||
path,
|
||||
&suffix("utxo_count"),
|
||||
VERSION + Version::new(111),
|
||||
compressed,
|
||||
)?,
|
||||
indexes_to_utxo_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"utxo_count",
|
||||
&suffix("utxo_count"),
|
||||
false,
|
||||
VERSION + Version::ZERO,
|
||||
compressed,
|
||||
|
||||
Reference in New Issue
Block a user