implement U512 as [u128;4]

This commit is contained in:
Ajinkya Kulkarni 2024-03-11 15:37:53 +01:00
parent 324ecce9e7
commit ccdc03295c
11 changed files with 119 additions and 59 deletions

View file

@ -2,14 +2,13 @@
name = "pathfinder2"
version = "0.1.0"
edition = "2021"
default-run = "server"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
eth_checksum = "0.1.2"
eth_checksum = {path = "../eth-checksum"}
json = "^0.12.4"
num-bigint = "^0.4.3"
serde = { version = "1.0.149", features = ["serde_derive"] }
serde_json = "1.0.89"
serde = { version = "^1.0.149", features = ["derive"] }
serde_json = "^1.0.89"
regex = "1.8.1"

3
dotfile.dot Normal file
View file

@ -0,0 +1,3 @@
digraph transfers {
"0x9ba1bc" -> "0x42cedd" [label="1.00 (0x9a0bbb)"];
}

BIN
edges.dat Normal file

Binary file not shown.

7
out.flow Normal file

File diff suppressed because one or more lines are too long

1
safes.json Normal file
View file

@ -0,0 +1 @@
{"blockNumber": "0x1e080ec", "safes": []}

View file

@ -4,6 +4,7 @@ use crate::types::{Edge, U256};
use std::cmp::{max, Reverse};
use std::collections::HashMap;
pub struct Adjacencies<'a> {
edges: &'a EdgeDB,
lazy_adjacencies: HashMap<Node, HashMap<Node, U256>>,

View file

@ -266,9 +266,11 @@ fn read_u256(file: &mut File) -> Result<U256, io::Error> {
let length = read_u8(file)? as usize;
let mut bytes = [0u8; 32];
file.read_exact(&mut bytes[32 - length..32])?;
let high = u128::from_be_bytes(*<&[u8; 16]>::try_from(&bytes[0..16]).unwrap());
let low = u128::from_be_bytes(*<&[u8; 16]>::try_from(&bytes[16..32]).unwrap());
Ok(U256::new(high, low))
let hh = u64::from_be_bytes(*<&[u8; 8]>::try_from(&bytes[0..8]).unwrap());
let hl = u64::from_be_bytes(*<&[u8; 8]>::try_from(&bytes[8..16]).unwrap());
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> {

View file

@ -1,6 +1,7 @@
use serde::{Deserialize, Serialize};
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]);
impl Address {

View file

@ -1,9 +1,11 @@
use crate::types::{U256, Address};
use serde::{Deserialize, Serialize};
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 from: 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
}
#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct EdgeDB {
edges: Vec<Edge>,
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 {
self.edges.len()
}

View file

@ -27,10 +27,10 @@ impl Safe {
let receiver_balance = receiver.balance(&self.token_address);
let amount = (receiver.balance(&receiver.token_address)
* U256::from(trust_percentage as u128))
* U256::from(trust_percentage as u64))
/ U256::from(100);
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 {
U256::from(0)
} else {

View file

@ -4,29 +4,30 @@ use std::fmt::Formatter;
use std::ops::Div;
use std::ops::Mul;
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
use serde::{Deserialize, Serialize};
use num_bigint::BigUint;
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct U256([u128; 2]);
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct U256([u64; 4]);
impl U256 {
pub const fn new(high: u128, low: u128) -> U256 {
U256([high, low])
pub const fn new(hh: u64, hl: u64, lh: u64, ll: u64) -> U256 {
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 {
let digits = input.to_u64_digits();
U256([
u128::from(*digits.get(3).unwrap_or(&0)) << 64
| u128::from(*digits.get(2).unwrap_or(&0)),
u128::from(*digits.get(1).unwrap_or(&0)) << 64
| u128::from(*digits.first().unwrap_or(&0)),
u64::from(*digits.get(3).unwrap_or(&0)),
u64::from(*digits.get(2).unwrap_or(&0)),
u64::from(*digits.get(1).unwrap_or(&0)),
u64::from(*digits.first().unwrap_or(&0)),
])
}
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}")
}
@ -50,7 +51,7 @@ impl U256 {
pub fn to_bytes(&self) -> Vec<u8> {
let mut result = Vec::new();
for i in 0..=1 {
for i in 0..=3 {
for j in (0..16).rev() {
let b = ((self.0[i] >> (j * 8)) & 0xff) as u8;
if b != 0 || !result.is_empty() {
@ -62,50 +63,77 @@ impl U256 {
}
}
impl From<u128> for U256 {
fn from(item: u128) -> Self {
U256([0, item])
impl From<u64> for U256 {
fn from(item: u64) -> Self {
U256([0, 0, 0, item])
}
}
// 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 {
if item.starts_with("0x") {
let len = item.len();
assert!(len <= 2 + 32 + 32, "{}", len);
let low_start = if len >= 2 + 32 { len - 32 } else { 2 };
let low_hex = &item[low_start..];
assert!(len <= 2 + 16 + 16 + 16 + 16, "{}", len);
let ll_start = if len >= 2 + 16 { len - 16 } else { 2 };
let ll_hex = &item[ll_start..];
// disallow + and - prefixes
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
} 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
assert!(
high_hex.as_bytes().first() != Some(&45)
&& high_hex.as_bytes().first() != Some(&43)
lh_hex.as_bytes().first() != Some(&54) && lh_hex.as_bytes().first() != Some(&43)
);
let high = if high_hex.is_empty() {
let lh = if lh_hex.is_empty() {
0
} 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 {
let digits = item.parse::<num_bigint::BigUint>().unwrap().to_u64_digits();
assert!(digits.len() <= 4);
U256([
u128::from(*digits.get(3).unwrap_or(&0)) << 64
| u128::from(*digits.get(2).unwrap_or(&0)),
u128::from(*digits.get(1).unwrap_or(&0)) << 64
| u128::from(*digits.first().unwrap_or(&0)),
u64::from(*digits.get(3).unwrap_or(&0)),
u64::from(*digits.get(2).unwrap_or(&0)),
u64::from(*digits.get(1).unwrap_or(&0)),
u64::from(*digits.first().unwrap_or(&0)),
])
}
}
@ -113,19 +141,25 @@ impl From<&str> for U256 {
impl From<U256> for BigUint {
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;
fn add(self, rhs: Self) -> Self {
let (low, carry) = self.0[1].overflowing_add(rhs.0[1]);
let mut high = self.0[0].wrapping_add(rhs.0[0]);
if carry {
high = high.wrapping_add(1);
}
Self([high, low])
let (ll, carry0) = self.0[3].overflowing_add(rhs.0[3]);
let (mut lh, mut carry1) = self.0[2].overflowing_add(rhs.0[2]);
(lh, carry1) = lh.overflowing_add(carry0.into());
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 {
type Output = 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)
}
}
@ -178,10 +212,10 @@ impl SubAssign for U256 {
impl Display for U256 {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
if self.0[0] == 0 {
write!(f, "{:#x}", self.0[1])
if self.0[0] == 0 && self.0[1] == 0 {
write!(f, "{:#x}{:016x}", self.0[2], self.0[3])
} 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() {
assert_eq!(format!("{}", U256::from(0)), "0x0");
assert_eq!(
format!("{}", U256::from(u128::MAX)),
format!("{}", U256::from(u::MAX)),
"0xffffffffffffffffffffffffffffffff"
);
}