mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-01 09:59:59 -07:00
parser: switch to biter
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
pub const BYTES_IN_MB: usize = 1_000_000;
|
||||
@@ -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;
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
57
parser/src/utils/multisig.rs
Normal file
57
parser/src/utils/multisig.rs
Normal 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
13
parser/src/utils/rpc.rs
Normal 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(),
|
||||
),
|
||||
)?)
|
||||
}
|
||||
Reference in New Issue
Block a user