biter: fix ?

This commit is contained in:
nym21
2024-12-14 17:39:42 +01:00
parent 0b3329ca35
commit e0a378cb81
36 changed files with 96 additions and 116 deletions

6
.gitignore vendored
View File

@@ -4,9 +4,6 @@
# Builds # Builds
target target
# Sync
.stfolder
# Copies # Copies
*\ copy* *\ copy*
@@ -32,6 +29,3 @@ docker/kibo
# Types # Types
paths.d.ts paths.d.ts
# Git
.git-*

4
Cargo.lock generated
View File

@@ -481,7 +481,7 @@ dependencies = [
[[package]] [[package]]
name = "biter" name = "biter"
version = "0.2.1" version = "0.2.2"
dependencies = [ dependencies = [
"bitcoin", "bitcoin",
"bitcoincore-rpc", "bitcoincore-rpc",
@@ -2623,7 +2623,7 @@ dependencies = [
[[package]] [[package]]
name = "snkrj" name = "snkrj"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"sanakirja", "sanakirja",
] ]

View File

@@ -12,7 +12,7 @@ bincode = { git = "https://github.com/bincode-org/bincode.git", features = [
"serde", "serde",
] } ] }
bitcoin_hashes = { version = "0.15.0" } bitcoin_hashes = { version = "0.15.0" }
biter = { path = "./crates/biter" } biter = { path = "./src/crates/biter" }
chrono = { version = "0.4.39", features = ["serde"] } chrono = { version = "0.4.39", features = ["serde"] }
clap = { version = "4.5.23", features = ["derive"] } clap = { version = "4.5.23", features = ["derive"] }
color-eyre = "0.6.3" color-eyre = "0.6.3"
@@ -27,10 +27,10 @@ rayon = "1.10.0"
regex = "1.11.1" regex = "1.11.1"
reqwest = { version = "0.12.9", features = ["blocking", "json"] } reqwest = { version = "0.12.9", features = ["blocking", "json"] }
rlimit = "0.10.2" rlimit = "0.10.2"
snkrj = { path = "./crates/snkrj" } snkrj = { path = "./src/crates/snkrj" }
serde = { version = "1.0.216", features = ["derive"] } serde = { version = "1.0.216", features = ["derive"] }
serde_json = "1.0.133" serde_json = "1.0.133"
struct_iterable = { path = "./crates/iterable" } struct_iterable = { path = "./src/crates/iterable" }
swc = "9.0.0" swc = "9.0.0"
swc_common = "5.0.0" swc_common = "5.0.0"
tokio = { version = "1.42.0", features = ["full"] } tokio = { version = "1.42.0", features = ["full"] }

View File

@@ -63,17 +63,19 @@ Please open an issue if you want to add another instance
### Requirements ### Requirements
- At least 16 GB of RAM - At least 16 GB of RAM
- 1 TB of free space (will use 70% of that without defragmentation and 40% after) - Recommended: 32 GB
- A disk with 1 TB of free space (will use between 40% to 80% depending on several things)
- Recommended: Rated at 3 GB/s (Thunderbolt 4 speed)
- A running instance of bitcoin-core with: - A running instance of bitcoin-core with:
- `-txindex=1` - `-txindex=1`
- `-blocksxor=0` - `-blocksxor=0`
- RPC credentials - RPC credentials
- Example: `bitcoind -datadir="$HOME/.bitcoin" -blocksonly -txindex=1 -blocksxor=0` - Example: `bitcoind -datadir="$HOME/.bitcoin" -blocksonly -txindex=1 -blocksxor=0`
- Git - Git
- Unix based operating system (Mac OS or Linux)
- Ubuntu users need to install `open-ssl` via `sudo apt install libssl-dev pkg-config`
### Manual ### Build
_Mac OS and Linux only, Windows is unsupported_
First we need to install Rust (https://www.rust-lang.org/tools/install) First we need to install Rust (https://www.rust-lang.org/tools/install)
@@ -81,75 +83,33 @@ First we need to install Rust (https://www.rust-lang.org/tools/install)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
``` ```
If you already had Rust installed you could update it just in case If you already had Rust installed you could update it
```bash ```bash
rustup update rustup update
``` ```
> If you're on Ubuntu you'll probably also need to install `open-ssl` with Then you need to choose a path where the project will reside and then clone it
>
> ```bash
> sudo apt install libssl-dev pkg-config
> ```
Optionally, you can also install `cargo-watch` for the server to automatically restart it on file change, which will be triggered by new code and new datasets from the parser (https://github.com/watchexec/cargo-watch?tab=readme-ov-file#install)
```bash
cargo install cargo-watch --locked
```
Then you need to choose a path where all files related to **kibō** will live
```bash ```bash
cd ??? cd ???
```
We can now clone the repository
```bash
git clone https://github.com/kibo-money/kibo.git git clone https://github.com/kibo-money/kibo.git
cd kibo
``` ```
In a new terminal, go to the `parser`'s folder of the repository If it's your first time running kibo, it will need several information such as:
```bash - `--bitcoindir PATH`: path to bitcoin core data directory, `???/bitcoin`
cd ???/kibo/parser - `--kibodir PATH`: path to kibo outputs, if you have enough space on your main disk `~/.kibo` is fine
```
Now we can finally start by running the parser, you need to use the `./run.sh` script instead of `cargo run -r` as we need to set various system variables for the program to run smoothly Everything will be saved at `~/.kibo/config.toml`, which will allow you to simply run `cargo run -r` next time
For the first launch, the parser will need several information such as: If you need more options please run `cargo run -r --help` to see what parameters are available.
- `--datadir`: which is bitcoin data directory path, prefer `$HOME` to `~` as the latter might not work
- `--outdir`: where all outputs will be saved, prefer `$HOME` to `~` as the latter might not work
Optionally you can also specify:
- `--rpccookiefile`: the path to the cookie file if not default
- `--rpcuser`: the username of the RPC credentials to talk to the bitcoin server if set
- `--rpcpassword`: the password of the RPC credentials if set
- `--rpcconnect`: if the bitcoin core server's IP is different than `localhost`
- `--rpcport`: if the port is different than `8332`
Everything will be saved in a `config.toml` file, which will allow you to simply run `./run.sh` next time
Here's an example Here's an example
```bash ```bash
./run.sh --datadir=$HOME/Developer/bitcoin --outdir=$HOME/.kibo/out cargo run -r -- --bitcoindir=~/Developer/bitcoin --kibodir=~/.kibo
```
In a **new** terminal, go to the `server`'s folder of the repository
```bash
cd ???/kibo/server
```
And start it also with the `run.sh` script instead of `cargo run -r`
```bash
./run.sh
``` ```
Then the easiest to let others access your server is to use `cloudflared` which will also cache requests. For more information go to: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/ Then the easiest to let others access your server is to use `cloudflared` which will also cache requests. For more information go to: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/

View File

@@ -1,12 +0,0 @@
[package]
name = "snkrj"
description = "A simple wrapper around Sanakirja aatabase that acts as a very fast on disk BTreeMap"
version = "0.1.0"
license = "MIT"
repository = "https://github.com/kibo-money/kibo/tree/main/crates/snkrj"
keywords = ["database", "sanakirja", "btreemap"]
categories = ["database"]
edition = "2021"
[dependencies]
sanakirja = "1.4.3"

View File

@@ -1,9 +1,9 @@
[package] [package]
name = "biter" name = "biter"
description = "A very fast Bitcoin block iterator" description = "A very fast Bitcoin block iterator"
version = "0.2.1" version = "0.2.2"
license = "MIT" license = "MIT"
repository = "https://github.com/kibo-money/kibo/tree/main/crates/biter" repository = "https://github.com/kibo-money/kibo/tree/main/src/crates/biter"
keywords = ["bitcoin", "block", "iterator"] keywords = ["bitcoin", "block", "iterator"]
categories = ["cryptography::cryptocurrencies", "encoding"] categories = ["cryptography::cryptocurrencies", "encoding"]
edition = "2021" edition = "2021"

View File

@@ -17,7 +17,7 @@ pub struct BlkIndexToBlkRecap {
path: PathBuf, path: PathBuf,
#[target] #[target]
tree: BTreeMap<usize, BlkRecap>, tree: BTreeMap<usize, BlkRecap>,
last_safe_recap: Option<BlkRecap>, last_safe_height: Option<usize>,
} }
impl BlkIndexToBlkRecap { impl BlkIndexToBlkRecap {
@@ -38,7 +38,7 @@ impl BlkIndexToBlkRecap {
let mut this = Self { let mut this = Self {
path, path,
tree, tree,
last_safe_recap: None, last_safe_height: None,
}; };
this.clean_outdated(blocks_dir); this.clean_outdated(blocks_dir);
@@ -58,11 +58,11 @@ impl BlkIndexToBlkRecap {
} }
}); });
unprocessed_keys.iter().for_each(|blk_index| { unprocessed_keys.into_iter().for_each(|blk_index| {
self.remove(blk_index); self.remove(&blk_index);
}); });
self.last_safe_recap = self.last_entry().map(|e| e.get().clone()); self.last_safe_height = self.iter().map(|(_, recap)| recap.height()).max();
} }
pub fn get_start_recap(&self, start: Option<usize>) -> Option<(usize, BlkRecap)> { pub fn get_start_recap(&self, start: Option<usize>) -> Option<(usize, BlkRecap)> {
@@ -108,8 +108,8 @@ impl BlkIndexToBlkRecap {
} }
if self if self
.last_safe_recap .last_safe_height
.map_or(true, |recap| recap.height() >= height) .map_or(true, |safe_height| height >= safe_height)
&& (height % TARGET_BLOCKS_PER_MONTH) == 0 && (height % TARGET_BLOCKS_PER_MONTH) == 0
{ {
self.export(); self.export();

View File

@@ -11,8 +11,8 @@ fn main() {
let auth = Auth::CookieFile(cookie); let auth = Auth::CookieFile(cookie);
let rpc = Client::new(url, auth).unwrap(); let rpc = Client::new(url, auth).unwrap();
let start = Some(800_000); let start = Some(810078);
let end = Some(855_000); let end = None;
biter::new(data_dir, start, end, rpc) biter::new(data_dir, start, end, rpc)
.iter() .iter()

View File

@@ -0,0 +1,12 @@
[package]
name = "snkrj"
description = "A simple wrapper around Sanakirja's database that acts as a very fast on disk BTreeMap"
version = "0.1.1"
license = "MIT"
repository = "https://github.com/kibo-money/kibo/tree/main/src/crates/snkrj"
keywords = ["database", "sanakirja", "btreemap"]
categories = ["database"]
edition = "2021"
[dependencies]
sanakirja = "1.4.3"

View File

@@ -37,7 +37,7 @@ pub fn main(
&mut datasets, &mut datasets,
)?; )?;
if let Some(delay) = config.delay { if let Some(delay) = config.delay() {
sleep(Duration::from_secs(delay)) sleep(Duration::from_secs(delay))
} }

View File

@@ -15,36 +15,36 @@ use super::MapPath;
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
pub struct Config { pub struct Config {
/// Bitcoin data directory path, saved /// Bitcoin data directory path, saved
#[arg(long, value_name = "DIR")] #[arg(long, value_name = "PATH")]
bitcoindir: Option<String>, bitcoindir: Option<String>,
/// Kibo data directory path, saved /// Kibo output directory path, saved
#[arg(long, value_name = "DIR")] #[arg(long, value_name = "PATH")]
kibodir: Option<String>, kibodir: Option<String>,
/// Bitcoin RPC ip, default: localhost, saved /// Bitcoin RPC ip, default: localhost, saved
#[arg(long, value_name = "IP")] #[arg(long, value_name = "IP")]
pub rpcconnect: Option<String>, rpcconnect: Option<String>,
/// Bitcoin RPC port, default: 8332, saved /// Bitcoin RPC port, default: 8332, saved
#[arg(long, value_name = "PORT")] #[arg(long, value_name = "PORT")]
pub rpcport: Option<u16>, rpcport: Option<u16>,
/// Bitcoin RPC cookie file, default: --bitcoindir/.cookie, saved /// Bitcoin RPC cookie file, default: --bitcoindir/.cookie, saved
#[arg(long, value_name = "PATH")] #[arg(long, value_name = "PATH")]
pub rpccookiefile: Option<String>, rpccookiefile: Option<String>,
/// Bitcoin RPC username, saved /// Bitcoin RPC username, saved
#[arg(long, value_name = "USERNAME")] #[arg(long, value_name = "USERNAME")]
pub rpcuser: Option<String>, rpcuser: Option<String>,
/// Bitcoin RPC password, saved /// Bitcoin RPC password, saved
#[arg(long, value_name = "PASSWORD")] #[arg(long, value_name = "PASSWORD")]
pub rpcpassword: Option<String>, rpcpassword: Option<String>,
/// Delay between runs, default: 0, saved /// Delay between runs, default: 0, saved
#[arg(long, value_name = "SECONDS")] #[arg(long, value_name = "SECONDS")]
pub delay: Option<u64>, delay: Option<u64>,
// Maximum ram you want the program to use in GB, default: 50% of total, not saved // Maximum ram you want the program to use in GB, default: 50% of total, not saved
// #[arg(long, value_name = "GB")] // #[arg(long, value_name = "GB")]
@@ -181,7 +181,7 @@ impl Config {
std::process::exit(1); std::process::exit(1);
} }
let path = Path::new(self.bitcoindir.as_ref().unwrap()); let path = self.path_bitcoindir();
if !path.is_dir() { if !path.is_dir() {
println!("Expect path '{:#?}' to be a directory.", path); println!("Expect path '{:#?}' to be a directory.", path);
std::process::exit(1); std::process::exit(1);
@@ -206,18 +206,10 @@ impl Config {
} }
pub fn to_rpc_auth(&self) -> color_eyre::Result<Auth> { pub fn to_rpc_auth(&self) -> color_eyre::Result<Auth> {
let cookie = Path::new(self.bitcoindir.as_ref().unwrap()).join(".cookie"); let cookie = self.path_cookiefile();
if cookie.is_file() { if cookie.is_file() {
Ok(Auth::CookieFile(cookie)) Ok(Auth::CookieFile(cookie))
} else if self
.rpccookiefile
.as_ref()
.is_some_and(|cookie| Path::new(cookie).is_file())
{
Ok(Auth::CookieFile(PathBuf::from(
self.rpccookiefile.as_ref().unwrap(),
)))
} else if self.rpcuser.is_some() && self.rpcpassword.is_some() { } else if self.rpcuser.is_some() && self.rpcpassword.is_some() {
Ok(Auth::UserPass( Ok(Auth::UserPass(
self.rpcuser.clone().unwrap(), self.rpcuser.clone().unwrap(),
@@ -228,6 +220,18 @@ impl Config {
} }
} }
pub fn rpcconnect(&self) -> Option<&String> {
self.rpcconnect.as_ref()
}
pub fn rpcport(&self) -> Option<u16> {
self.rpcport
}
pub fn delay(&self) -> Option<u64> {
self.delay
}
pub fn dry_run(&self) -> bool { pub fn dry_run(&self) -> bool {
self.dry_run.is_some_and(|b| b) self.dry_run.is_some_and(|b| b)
} }
@@ -241,11 +245,36 @@ impl Config {
} }
pub fn path_bitcoindir(&self) -> PathBuf { pub fn path_bitcoindir(&self) -> PathBuf {
PathBuf::from(self.bitcoindir.as_ref().unwrap()) Self::fix_user_path(self.bitcoindir.as_ref().unwrap().as_ref())
} }
fn path_kibodir(&self) -> PathBuf { fn path_kibodir(&self) -> PathBuf {
PathBuf::from(self.kibodir.as_ref().unwrap()) Self::fix_user_path(self.kibodir.as_ref().unwrap().as_ref())
}
fn path_cookiefile(&self) -> PathBuf {
self.rpccookiefile.as_ref().map_or_else(
|| self.path_bitcoindir().join(".cookie"),
|p| Self::fix_user_path(p.as_str()),
)
}
fn fix_user_path(path: &str) -> PathBuf {
let fix = move |pattern: &str| {
if path.starts_with(pattern) {
let path = &path
.replace(&format!("{pattern}/"), "")
.replace(pattern, "");
let home = std::env::var("HOME").unwrap();
Some(Path::new(&home).join(path))
} else {
None
}
};
fix("~").unwrap_or_else(|| fix("$HOME").unwrap_or_else(|| PathBuf::from(&path)))
} }
pub fn path_datasets(&self) -> MapPath { pub fn path_datasets(&self) -> MapPath {

View File

@@ -12,11 +12,8 @@ fn create_rpc(config: &Config) -> color_eyre::Result<Client> {
Ok(Client::new( Ok(Client::new(
&format!( &format!(
"http://{}:{}", "http://{}:{}",
config config.rpcconnect().unwrap_or(&"localhost".to_owned()),
.rpcconnect config.rpcport().unwrap_or(8332)
.as_ref()
.unwrap_or(&"localhost".to_owned()),
config.rpcport.unwrap_or(8332)
), ),
config.to_rpc_auth().unwrap(), config.to_rpc_auth().unwrap(),
)?) )?)