implement U512 as [u128;4]
This commit is contained in:
parent
324ecce9e7
commit
ccdc03295c
11 changed files with 119 additions and 59 deletions
|
@ -2,14 +2,13 @@
|
||||||
name = "pathfinder2"
|
name = "pathfinder2"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run = "server"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eth_checksum = "0.1.2"
|
eth_checksum = {path = "../eth-checksum"}
|
||||||
json = "^0.12.4"
|
json = "^0.12.4"
|
||||||
num-bigint = "^0.4.3"
|
num-bigint = "^0.4.3"
|
||||||
serde = { version = "1.0.149", features = ["serde_derive"] }
|
serde = { version = "^1.0.149", features = ["derive"] }
|
||||||
serde_json = "1.0.89"
|
serde_json = "^1.0.89"
|
||||||
regex = "1.8.1"
|
regex = "1.8.1"
|
||||||
|
|
3
dotfile.dot
Normal file
3
dotfile.dot
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
digraph transfers {
|
||||||
|
"0x9ba1bc" -> "0x42cedd" [label="1.00 (0x9a0bbb)"];
|
||||||
|
}
|
BIN
edges.dat
Normal file
BIN
edges.dat
Normal file
Binary file not shown.
7
out.flow
Normal file
7
out.flow
Normal file
File diff suppressed because one or more lines are too long
1
safes.json
Normal file
1
safes.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"blockNumber": "0x1e080ec", "safes": []}
|
|
@ -4,6 +4,7 @@ use crate::types::{Edge, U256};
|
||||||
use std::cmp::{max, Reverse};
|
use std::cmp::{max, Reverse};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
|
||||||
pub struct Adjacencies<'a> {
|
pub struct Adjacencies<'a> {
|
||||||
edges: &'a EdgeDB,
|
edges: &'a EdgeDB,
|
||||||
lazy_adjacencies: HashMap<Node, HashMap<Node, U256>>,
|
lazy_adjacencies: HashMap<Node, HashMap<Node, U256>>,
|
||||||
|
|
|
@ -266,9 +266,11 @@ fn read_u256(file: &mut File) -> Result<U256, io::Error> {
|
||||||
let length = read_u8(file)? as usize;
|
let length = read_u8(file)? as usize;
|
||||||
let mut bytes = [0u8; 32];
|
let mut bytes = [0u8; 32];
|
||||||
file.read_exact(&mut bytes[32 - length..32])?;
|
file.read_exact(&mut bytes[32 - length..32])?;
|
||||||
let high = u128::from_be_bytes(*<&[u8; 16]>::try_from(&bytes[0..16]).unwrap());
|
let hh = u64::from_be_bytes(*<&[u8; 8]>::try_from(&bytes[0..8]).unwrap());
|
||||||
let low = u128::from_be_bytes(*<&[u8; 16]>::try_from(&bytes[16..32]).unwrap());
|
let hl = u64::from_be_bytes(*<&[u8; 8]>::try_from(&bytes[8..16]).unwrap());
|
||||||
Ok(U256::new(high, low))
|
let lh = u64::from_be_bytes(*<&[u8; 8]>::try_from(&bytes[16..24]).unwrap());
|
||||||
|
let ll = u64::from_be_bytes(*<&[u8; 8]>::try_from(&bytes[24..32]).unwrap());
|
||||||
|
Ok(U256::new(hh, hl, lh, ll))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_u256(file: &mut File, v: &U256) -> Result<(), io::Error> {
|
fn write_u256(file: &mut File, v: &U256) -> Result<(), io::Error> {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Default, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
pub struct Address([u8; 20]);
|
pub struct Address([u8; 20]);
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
use crate::types::{U256, Address};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::types::Address;
|
|
||||||
use crate::types::U256;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, Ord, PartialOrd)]
|
#[derive(
|
||||||
|
Clone, Copy, Debug, Default, Hash, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub struct Edge {
|
pub struct Edge {
|
||||||
pub from: Address,
|
pub from: Address,
|
||||||
pub to: Address,
|
pub to: Address,
|
||||||
|
@ -17,7 +19,7 @@ pub fn eq_up_to_capacity(e1: &Edge, e2: &Edge) -> bool {
|
||||||
e1.from == e2.from && e1.to == e2.to && e1.token == e2.token
|
e1.from == e2.from && e1.to == e2.to && e1.token == e2.token
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
pub struct EdgeDB {
|
pub struct EdgeDB {
|
||||||
edges: Vec<Edge>,
|
edges: Vec<Edge>,
|
||||||
outgoing: HashMap<Address, Vec<usize>>,
|
outgoing: HashMap<Address, Vec<usize>>,
|
||||||
|
@ -35,6 +37,16 @@ impl EdgeDB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn edge_capacity(&self, from: Address, to: Address) -> U256 {
|
||||||
|
let outgoing = self.outgoing(&from);
|
||||||
|
for edge in outgoing {
|
||||||
|
if edge.to == to {
|
||||||
|
return edge.capacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0.into()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn edge_count(&self) -> usize {
|
pub fn edge_count(&self) -> usize {
|
||||||
self.edges.len()
|
self.edges.len()
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ impl Safe {
|
||||||
let receiver_balance = receiver.balance(&self.token_address);
|
let receiver_balance = receiver.balance(&self.token_address);
|
||||||
|
|
||||||
let amount = (receiver.balance(&receiver.token_address)
|
let amount = (receiver.balance(&receiver.token_address)
|
||||||
* U256::from(trust_percentage as u128))
|
* U256::from(trust_percentage as u64))
|
||||||
/ U256::from(100);
|
/ U256::from(100);
|
||||||
let scaled_receiver_balance =
|
let scaled_receiver_balance =
|
||||||
receiver_balance * U256::from((100 - trust_percentage) as u128) / U256::from(100);
|
receiver_balance * U256::from((100 - trust_percentage) as u64) / U256::from(100);
|
||||||
if amount < receiver_balance {
|
if amount < receiver_balance {
|
||||||
U256::from(0)
|
U256::from(0)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,29 +4,30 @@ use std::fmt::Formatter;
|
||||||
use std::ops::Div;
|
use std::ops::Div;
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct U256([u128; 2]);
|
pub struct U256([u64; 4]);
|
||||||
|
|
||||||
impl U256 {
|
impl U256 {
|
||||||
pub const fn new(high: u128, low: u128) -> U256 {
|
pub const fn new(hh: u64, hl: u64, lh: u64, ll: u64) -> U256 {
|
||||||
U256([high, low])
|
U256([hh, hl, lh, ll])
|
||||||
}
|
}
|
||||||
pub const MAX: U256 = U256::new(u128::MAX, u128::MAX);
|
pub const MAX: U256 = U256::new(u64::MAX, u64::MAX, u64::MAX, u64::MAX);
|
||||||
pub fn from_bigint_truncating(input: BigUint) -> U256 {
|
pub fn from_bigint_truncating(input: BigUint) -> U256 {
|
||||||
let digits = input.to_u64_digits();
|
let digits = input.to_u64_digits();
|
||||||
U256([
|
U256([
|
||||||
u128::from(*digits.get(3).unwrap_or(&0)) << 64
|
u64::from(*digits.get(3).unwrap_or(&0)),
|
||||||
| u128::from(*digits.get(2).unwrap_or(&0)),
|
u64::from(*digits.get(2).unwrap_or(&0)),
|
||||||
u128::from(*digits.get(1).unwrap_or(&0)) << 64
|
u64::from(*digits.get(1).unwrap_or(&0)),
|
||||||
| u128::from(*digits.first().unwrap_or(&0)),
|
u64::from(*digits.first().unwrap_or(&0)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_decimal(self) -> String {
|
pub fn to_decimal(self) -> String {
|
||||||
let value = BigUint::from(self.0[0]) << 128 | BigUint::from(self.0[1]);
|
let value = BigUint::from(self.0[0]) << 192 | BigUint::from(self.0[1]) << 128 | BigUint::from(self.0[2]) << 64 | BigUint::from(self.0[3]);
|
||||||
format!("{value}")
|
format!("{value}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ impl U256 {
|
||||||
|
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
for i in 0..=1 {
|
for i in 0..=3 {
|
||||||
for j in (0..16).rev() {
|
for j in (0..16).rev() {
|
||||||
let b = ((self.0[i] >> (j * 8)) & 0xff) as u8;
|
let b = ((self.0[i] >> (j * 8)) & 0xff) as u8;
|
||||||
if b != 0 || !result.is_empty() {
|
if b != 0 || !result.is_empty() {
|
||||||
|
@ -62,50 +63,77 @@ impl U256 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u128> for U256 {
|
impl From<u64> for U256 {
|
||||||
fn from(item: u128) -> Self {
|
fn from(item: u64) -> Self {
|
||||||
U256([0, item])
|
U256([0, 0, 0, item])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO str is using unicode stuff - maybe we should use Vec<u8> for efficiency reasons?
|
// TODO str is using unicode stuff - maybe we should use Vec<u8> for efficiency reasons?
|
||||||
impl From<&str> for U256 {
|
impl From<&str> for U256 { // TODO: switch to u64 implementation
|
||||||
fn from(item: &str) -> Self {
|
fn from(item: &str) -> Self {
|
||||||
if item.starts_with("0x") {
|
if item.starts_with("0x") {
|
||||||
let len = item.len();
|
let len = item.len();
|
||||||
assert!(len <= 2 + 32 + 32, "{}", len);
|
assert!(len <= 2 + 16 + 16 + 16 + 16, "{}", len);
|
||||||
let low_start = if len >= 2 + 32 { len - 32 } else { 2 };
|
|
||||||
let low_hex = &item[low_start..];
|
|
||||||
|
let ll_start = if len >= 2 + 16 { len - 16 } else { 2 };
|
||||||
|
let ll_hex = &item[ll_start..];
|
||||||
// disallow + and - prefixes
|
// disallow + and - prefixes
|
||||||
assert!(
|
assert!(
|
||||||
low_hex.as_bytes().first() != Some(&54) && low_hex.as_bytes().first() != Some(&43)
|
ll_hex.as_bytes().first() != Some(&54) && ll_hex.as_bytes().first() != Some(&43)
|
||||||
);
|
);
|
||||||
let low = if low_hex.is_empty() {
|
let ll = if ll_hex.is_empty() {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
u128::from_str_radix(low_hex, 16).unwrap()
|
u64::from_str_radix(ll_hex, 16).unwrap()
|
||||||
};
|
};
|
||||||
let high_start = if len >= 2 + 32 + 32 { len - 64 } else { 2 };
|
|
||||||
let high_hex = &item[high_start..low_start];
|
let lh_start = if len >= 2 + 16 + 16 { len - 32 } else { 2 };
|
||||||
|
let lh_hex = &item[lh_start..ll_start];
|
||||||
// disallow + and - prefixes
|
// disallow + and - prefixes
|
||||||
assert!(
|
assert!(
|
||||||
high_hex.as_bytes().first() != Some(&45)
|
lh_hex.as_bytes().first() != Some(&54) && lh_hex.as_bytes().first() != Some(&43)
|
||||||
&& high_hex.as_bytes().first() != Some(&43)
|
|
||||||
);
|
);
|
||||||
let high = if high_hex.is_empty() {
|
let lh = if lh_hex.is_empty() {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
u128::from_str_radix(high_hex, 16).unwrap()
|
u64::from_str_radix(lh_hex, 16).unwrap()
|
||||||
};
|
};
|
||||||
U256([high, low])
|
|
||||||
|
let hl_start = if len >= 2 + 16 + 16 + 16 { len - 48 } else { 2 };
|
||||||
|
let hl_hex = &item[hl_start..lh_start];
|
||||||
|
// disallow + and - prefixes
|
||||||
|
assert!(
|
||||||
|
hl_hex.as_bytes().first() != Some(&54) && hl_hex.as_bytes().first() != Some(&43)
|
||||||
|
);
|
||||||
|
let hl = if hl_hex.is_empty() {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
u64::from_str_radix(hl_hex, 16).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let hh_start = if len >= 2 + 16 + 16 + 16 + 16 { len - 64 } else { 2 };
|
||||||
|
let hh_hex = &item[hh_start..hl_start];
|
||||||
|
// disallow + and - prefixes
|
||||||
|
assert!(
|
||||||
|
hh_hex.as_bytes().first() != Some(&45)
|
||||||
|
&& hh_hex.as_bytes().first() != Some(&43)
|
||||||
|
);
|
||||||
|
let hh = if hh_hex.is_empty() {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
u64::from_str_radix(hh_hex, 16).unwrap()
|
||||||
|
};
|
||||||
|
U256([hh, hl, lh, ll])
|
||||||
} else {
|
} else {
|
||||||
let digits = item.parse::<num_bigint::BigUint>().unwrap().to_u64_digits();
|
let digits = item.parse::<num_bigint::BigUint>().unwrap().to_u64_digits();
|
||||||
assert!(digits.len() <= 4);
|
assert!(digits.len() <= 4);
|
||||||
U256([
|
U256([
|
||||||
u128::from(*digits.get(3).unwrap_or(&0)) << 64
|
u64::from(*digits.get(3).unwrap_or(&0)),
|
||||||
| u128::from(*digits.get(2).unwrap_or(&0)),
|
u64::from(*digits.get(2).unwrap_or(&0)),
|
||||||
u128::from(*digits.get(1).unwrap_or(&0)) << 64
|
u64::from(*digits.get(1).unwrap_or(&0)),
|
||||||
| u128::from(*digits.first().unwrap_or(&0)),
|
u64::from(*digits.first().unwrap_or(&0)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,19 +141,25 @@ impl From<&str> for U256 {
|
||||||
|
|
||||||
impl From<U256> for BigUint {
|
impl From<U256> for BigUint {
|
||||||
fn from(value: U256) -> Self {
|
fn from(value: U256) -> Self {
|
||||||
BigUint::from(value.0[0]) << 128 | BigUint::from(value.0[1])
|
BigUint::from(value.0[0]) << 192 | BigUint::from(value.0[1]) << 128 | BigUint::from(value.0[2]) << 64 | BigUint::from(value.0[3])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add for U256 {
|
impl Add for U256 { // TODO: switch to u64
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn add(self, rhs: Self) -> Self {
|
fn add(self, rhs: Self) -> Self {
|
||||||
let (low, carry) = self.0[1].overflowing_add(rhs.0[1]);
|
let (ll, carry0) = self.0[3].overflowing_add(rhs.0[3]);
|
||||||
let mut high = self.0[0].wrapping_add(rhs.0[0]);
|
|
||||||
if carry {
|
let (mut lh, mut carry1) = self.0[2].overflowing_add(rhs.0[2]);
|
||||||
high = high.wrapping_add(1);
|
(lh, carry1) = lh.overflowing_add(carry0.into());
|
||||||
}
|
|
||||||
Self([high, low])
|
let (mut hl, mut carry2) = self.0[1].overflowing_add(rhs.0[1]);
|
||||||
|
(hl, carry2) = hl.overflowing_add(carry1.into());
|
||||||
|
|
||||||
|
let mut hh = self.0[0].wrapping_add(rhs.0[0]);
|
||||||
|
hh = hh.wrapping_add(carry2.into());
|
||||||
|
|
||||||
|
Self([hh, hl, lh, ll])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +172,7 @@ impl AddAssign for U256 {
|
||||||
impl Neg for U256 {
|
impl Neg for U256 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn neg(self) -> Self {
|
fn neg(self) -> Self {
|
||||||
let result = U256([!self.0[0], !self.0[1]]);
|
let result = U256([!self.0[0], !self.0[1], !self.0[2], !self.0[3]]);
|
||||||
result + U256::from(1)
|
result + U256::from(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,10 +212,10 @@ impl SubAssign for U256 {
|
||||||
|
|
||||||
impl Display for U256 {
|
impl Display for U256 {
|
||||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||||
if self.0[0] == 0 {
|
if self.0[0] == 0 && self.0[1] == 0 {
|
||||||
write!(f, "{:#x}", self.0[1])
|
write!(f, "{:#x}{:016x}", self.0[2], self.0[3])
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{:#x}{:032x}", self.0[0], self.0[1])
|
write!(f, "{:#x}{:016x}{:016x}{:016x}", self.0[0], self.0[1], self.0[2], self.0[3])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +233,7 @@ mod test {
|
||||||
fn to_string() {
|
fn to_string() {
|
||||||
assert_eq!(format!("{}", U256::from(0)), "0x0");
|
assert_eq!(format!("{}", U256::from(0)), "0x0");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
format!("{}", U256::from(u128::MAX)),
|
format!("{}", U256::from(u::MAX)),
|
||||||
"0xffffffffffffffffffffffffffffffff"
|
"0xffffffffffffffffffffffffffffffff"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue