parser: switch to biter

This commit is contained in:
k
2024-08-03 15:17:57 +02:00
parent afacea3fbb
commit 9067c28d24
35 changed files with 494 additions and 1589 deletions

View File

@@ -1,219 +0,0 @@
use std::{
iter::Sum,
ops::{Add, AddAssign, Div, Mul, Sub, SubAssign},
};
use itertools::Itertools;
use ordered_float::{FloatCore, OrderedFloat};
use super::ToF32;
pub trait ArrayOperations<T> {
fn transform<F>(&self, transform: F) -> Vec<T>
where
T: Copy + Default,
F: Fn((usize, &T, &[T])) -> T;
fn add(&self, other: &[T]) -> Vec<T>
where
T: Add<Output = T> + Copy + Default;
fn subtract(&self, other: &[T]) -> Vec<T>
where
T: Sub<Output = T> + Copy + Default;
fn multiply(&self, other: &[T]) -> Vec<T>
where
T: Mul<Output = T> + Copy + Default;
fn divide(&self, other: &[T]) -> Vec<T>
where
T: Div<Output = T> + Copy + Default;
fn match_size<'a>(&'a self, other: &'a [T]) -> &'a [T];
fn cumulate(&self) -> Vec<T>
where
T: Sum + Copy + Default + AddAssign;
fn last_x_sum(&self, x: usize) -> Vec<T>
where
T: Sum + Copy + Default + AddAssign + SubAssign;
fn moving_average(&self, x: usize) -> Vec<f32>
where
T: Sum + Copy + Default + AddAssign + SubAssign + ToF32;
fn net_change(&self, offset: usize) -> Vec<T>
where
T: Copy + Default + Sub<Output = T>;
fn median(&self, size: usize) -> Vec<Option<T>>
where
T: FloatCore;
}
impl<T> ArrayOperations<T> for &[T] {
fn transform<F>(&self, transform: F) -> Vec<T>
where
T: Copy + Default,
F: Fn((usize, &T, &[T])) -> T,
{
self.iter()
.enumerate()
.map(|(index, value)| transform((index, value, self)))
.collect_vec()
}
fn add(&self, other: &[T]) -> Vec<T>
where
T: Add<Output = T> + Copy + Default,
{
self.match_size(other)
.transform(|(index, value, _)| *value + *other.get(index).unwrap())
}
fn subtract(&self, other: &[T]) -> Vec<T>
where
T: Sub<Output = T> + Copy + Default,
{
self.match_size(other)
.transform(|(index, value, _)| *value - *other.get(index).unwrap())
}
fn multiply(&self, other: &[T]) -> Vec<T>
where
T: Mul<Output = T> + Copy + Default,
{
self.match_size(other)
.transform(|(index, value, _)| *value * *other.get(index).unwrap())
}
fn divide(&self, other: &[T]) -> Vec<T>
where
T: Div<Output = T> + Copy + Default,
{
self.match_size(other)
.transform(|(index, value, _)| *value / *other.get(index).unwrap())
}
fn match_size(&self, other: &[T]) -> &[T] {
let len = other.len();
if self.len() > len {
&self[..len]
} else {
self
}
}
fn cumulate(&self) -> Vec<T>
where
T: Sum + Copy + Default + AddAssign,
{
let mut sum = T::default();
self.iter()
.map(|value| {
sum += *value;
sum
})
.collect_vec()
}
fn last_x_sum(&self, x: usize) -> Vec<T>
where
T: Sum + Copy + Default + AddAssign + SubAssign,
{
let mut sum = T::default();
self.iter()
.enumerate()
.map(|(index, value)| {
sum += *value;
if index >= x - 1 {
let previous_index = index + 1 - x;
sum -= *self.get(previous_index).unwrap()
}
sum
})
.collect_vec()
}
fn moving_average(&self, x: usize) -> Vec<f32>
where
T: Sum + Copy + Default + AddAssign + SubAssign + ToF32,
{
let mut sum = T::default();
self.iter()
.enumerate()
.map(|(index, value)| {
sum += *value;
if index >= x - 1 {
sum -= *self.get(index + 1 - x).unwrap()
}
sum.to_f32() / x as f32
})
.collect_vec()
}
fn net_change(&self, offset: usize) -> Vec<T>
where
T: Copy + Default + Sub<Output = T>,
{
self.transform(|(index, value, arr)| {
let previous = {
if let Some(previous_index) = index.checked_sub(offset) {
*arr.get(previous_index).unwrap()
} else {
T::default()
}
};
*value - previous
})
}
fn median(&self, size: usize) -> Vec<Option<T>>
where
T: FloatCore,
{
let even = size % 2 == 0;
let median_index = size / 2;
if size < 3 {
panic!("Computing a median for a size lower than 3 is useless");
}
self.iter()
.enumerate()
.map(|(index, _)| {
if index >= size - 1 {
let mut arr = self[index - (size - 1)..index + 1]
.iter()
.map(|value| OrderedFloat(*value))
.collect_vec();
arr.sort_unstable();
if even {
Some(
(**arr.get(median_index).unwrap()
+ **arr.get(median_index - 1).unwrap())
/ T::from(2.0).unwrap(),
)
} else {
Some(**arr.get(median_index).unwrap())
}
} else {
None
}
})
.collect()
}
}

View File

@@ -1 +0,0 @@
pub const BYTES_IN_MB: usize = 1_000_000;

View File

@@ -1,3 +1,7 @@
pub const BYTES_IN_MB: usize = 1_000_000;
pub const TARGET_BLOCKS_PER_DAY: usize = 144;
pub const ONE_DAY_IN_DAYS: usize = 1;
pub const ONE_WEEK_IN_DAYS: usize = 7;
pub const TWO_WEEK_IN_DAYS: usize = 2 * ONE_WEEK_IN_DAYS;

View File

@@ -1,4 +1,4 @@
use std::{fs::OpenOptions, io::Write, process::Output};
use std::{fs::OpenOptions, io::Write};
use chrono::Local;
use color_eyre::owo_colors::OwoColorize;
@@ -23,13 +23,3 @@ pub fn log(str: &str) {
println!("{} {}", date_time.bright_black(), line);
});
}
pub fn log_output(output: &Output) {
if !output.stdout.is_empty() {
log(&String::from_utf8_lossy(&output.stdout));
}
if !output.stderr.is_empty() {
log(&String::from_utf8_lossy(&output.stderr));
}
}

View File

@@ -1,17 +1,19 @@
mod bytes;
mod date;
mod consts;
mod flamegraph;
mod log;
mod lossy;
mod multisig;
mod percentile;
mod retry;
mod rpc;
mod time;
pub use bytes::*;
pub use date::*;
pub use consts::*;
pub use flamegraph::*;
pub use log::*;
pub use lossy::*;
pub use multisig::*;
pub use percentile::*;
pub use retry::*;
pub use rpc::*;
pub use time::*;

View File

@@ -0,0 +1,57 @@
//
// Code from bitcoin-explorer now deprecated
//
use biter::bitcoin::{
blockdata::{
opcodes::all,
script::Instruction::{self, Op, PushBytes},
},
Opcode, Script,
};
///
/// Obtain addresses for multisig transactions.
///
pub fn multisig_addresses(script: &Script) -> Vec<Vec<u8>> {
let ops: Vec<Instruction> = script.instructions().filter_map(|o| o.ok()).collect();
// obtain number of keys
let num_keys = {
if let Some(Op(op)) = ops.get(ops.len() - 2) {
decode_from_op_n(op)
} else {
unreachable!()
}
};
// read public keys
let mut public_keys = Vec::with_capacity(num_keys as usize);
for op in ops.iter().skip(1).take(num_keys as usize) {
if let PushBytes(data) = op {
public_keys.push(data.as_bytes().to_vec());
} else {
unreachable!()
}
}
public_keys
}
///
/// Decode OP_N
///
/// translated from BitcoinJ:
/// [decodeFromOpN()](https://github.com/bitcoinj/bitcoinj/blob/d3d5edbcbdb91b25de4df3b6ed6740d7e2329efc/core/src/main/java/org/bitcoinj/script/Script.java#L515:L524)
///
#[inline]
fn decode_from_op_n(op: &Opcode) -> i32 {
if op.eq(&all::OP_PUSHBYTES_0) {
0
} else if op.eq(&all::OP_PUSHNUM_NEG1) {
-1
} else {
op.to_u8() as i32 + 1 - all::OP_PUSHNUM_1.to_u8() as i32
}
}

13
parser/src/utils/rpc.rs Normal file
View File

@@ -0,0 +1,13 @@
use biter::bitcoincore_rpc::{Auth, Client};
use crate::Config;
pub fn create_rpc(config: &Config) -> color_eyre::Result<Client> {
Ok(Client::new(
&format!("http://localhost:{}", config.rpcport.unwrap()),
Auth::UserPass(
config.rpcuser.clone().unwrap(),
config.rpcpassword.clone().unwrap(),
),
)?)
}