This repository has been archived by the owner on Nov 9, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #118 from zeroqn/feat-change-ckb-decimal-to-18
BREAKING CHANGE: change ckb decimal to 18
- Loading branch information
Showing
33 changed files
with
1,173 additions
and
216 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
[workspace] | ||
members = [ | ||
"tests", | ||
"c-uint256-tests", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[package] | ||
name = "c-uint256-tests" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
cty = "0.2" | ||
|
||
[dev-dependencies] | ||
proptest = "1.0" | ||
primitive-types = { version = "0.10", default-features = false, features = [ "impl-serde", "impl-rlp" ] } | ||
|
||
[build-dependencies] | ||
cc = "1.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
fn main() { | ||
let mut build = cc::Build::new(); | ||
|
||
// building | ||
build | ||
.file("../c/rust-binding/uint256_wrapper.c") | ||
.static_flag(true) | ||
.flag("-O3") | ||
.flag("-Wl,-static") | ||
.flag("-Wl,--gc-sections") | ||
.include("../c/") | ||
.flag("-Wall") | ||
.flag("-Werror") | ||
.flag("-Wno-unused-parameter") | ||
.flag("-Wno-nonnull") | ||
.flag("-Wno-nonnull-compare") | ||
.flag("-Wno-unused-function") | ||
.define("__SHARED_LIBRARY__", None) | ||
.compile("c-uint256.a"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#!/bin/bash | ||
|
||
export PROPTEST_CASES=100000 | ||
|
||
counter=1 | ||
while : | ||
do | ||
echo "$counter round" | ||
cargo test | ||
((counter++)) | ||
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
/* automatically generated by rust-bindgen 0.59.2 */ | ||
|
||
pub const true_: u32 = 1; | ||
pub const false_: u32 = 0; | ||
pub const INT8_MIN: i32 = -128; | ||
pub const INT16_MIN: i32 = -32768; | ||
pub const INT32_MIN: i32 = -2147483648; | ||
pub const INT64_MIN: i64 = -9223372036854775808; | ||
pub const INT8_MAX: u32 = 127; | ||
pub const INT16_MAX: u32 = 32767; | ||
pub const INT32_MAX: u32 = 2147483647; | ||
pub const INT64_MAX: u64 = 9223372036854775807; | ||
pub const UINT8_MAX: u32 = 255; | ||
pub const UINT16_MAX: u32 = 65535; | ||
pub const UINT32_MAX: u32 = 4294967295; | ||
pub const UINT64_MAX: i32 = -1; | ||
pub const SIZE_MAX: i32 = -1; | ||
pub type size_t = ::std::os::raw::c_ulong; | ||
pub type ssize_t = ::std::os::raw::c_long; | ||
extern "C" { | ||
pub fn memset( | ||
dest: *mut ::std::os::raw::c_void, | ||
c: ::std::os::raw::c_int, | ||
n: ::std::os::raw::c_ulong, | ||
) -> *mut ::std::os::raw::c_void; | ||
} | ||
extern "C" { | ||
pub fn memcpy( | ||
dest: *mut ::std::os::raw::c_void, | ||
src: *const ::std::os::raw::c_void, | ||
n: ::std::os::raw::c_ulong, | ||
) -> *mut ::std::os::raw::c_void; | ||
} | ||
extern "C" { | ||
pub fn memcmp( | ||
vl: *const ::std::os::raw::c_void, | ||
vr: *const ::std::os::raw::c_void, | ||
n: ::std::os::raw::c_ulong, | ||
) -> ::std::os::raw::c_int; | ||
} | ||
pub type WT = size_t; | ||
extern "C" { | ||
pub fn memmove( | ||
dest: *mut ::std::os::raw::c_void, | ||
src: *const ::std::os::raw::c_void, | ||
n: ::std::os::raw::c_ulong, | ||
) -> *mut ::std::os::raw::c_void; | ||
} | ||
extern "C" { | ||
pub fn strcpy( | ||
d: *mut ::std::os::raw::c_char, | ||
s: *const ::std::os::raw::c_char, | ||
) -> *mut ::std::os::raw::c_char; | ||
} | ||
extern "C" { | ||
pub fn strlen(s: *const ::std::os::raw::c_char) -> ::std::os::raw::c_ulong; | ||
} | ||
extern "C" { | ||
pub fn strcmp( | ||
l: *const ::std::os::raw::c_char, | ||
r: *const ::std::os::raw::c_char, | ||
) -> ::std::os::raw::c_int; | ||
} | ||
extern "C" { | ||
pub fn malloc(size: ::std::os::raw::c_ulong) -> *mut ::std::os::raw::c_void; | ||
} | ||
extern "C" { | ||
pub fn free(ptr: *mut ::std::os::raw::c_void); | ||
} | ||
extern "C" { | ||
pub fn calloc( | ||
nmemb: ::std::os::raw::c_ulong, | ||
size: ::std::os::raw::c_ulong, | ||
) -> *mut ::std::os::raw::c_void; | ||
} | ||
extern "C" { | ||
pub fn realloc( | ||
ptr: *mut ::std::os::raw::c_void, | ||
size: ::std::os::raw::c_ulong, | ||
) -> *mut ::std::os::raw::c_void; | ||
} | ||
pub type cmpfun = ::std::option::Option< | ||
unsafe extern "C" fn( | ||
arg1: *const ::std::os::raw::c_void, | ||
arg2: *const ::std::os::raw::c_void, | ||
) -> ::std::os::raw::c_int, | ||
>; | ||
extern "C" { | ||
pub fn qsort(base: *mut ::std::os::raw::c_void, nel: size_t, width: size_t, cmp: cmpfun); | ||
} | ||
extern "C" { | ||
pub fn bsearch( | ||
key: *const ::std::os::raw::c_void, | ||
base: *const ::std::os::raw::c_void, | ||
nel: size_t, | ||
width: size_t, | ||
cmp: ::std::option::Option< | ||
unsafe extern "C" fn( | ||
arg1: *const ::std::os::raw::c_void, | ||
arg2: *const ::std::os::raw::c_void, | ||
) -> ::std::os::raw::c_int, | ||
>, | ||
) -> *mut ::std::os::raw::c_void; | ||
} | ||
extern "C" { | ||
pub fn printf(format: *const ::std::os::raw::c_char, ...) -> ::std::os::raw::c_int; | ||
} | ||
extern "C" { | ||
pub fn _start(); | ||
} | ||
#[repr(C)] | ||
#[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
pub struct uint256_t { | ||
pub array: [u32; 8usize], | ||
} | ||
#[test] | ||
fn bindgen_test_layout_uint256_t() { | ||
assert_eq!( | ||
::std::mem::size_of::<uint256_t>(), | ||
32usize, | ||
concat!("Size of: ", stringify!(uint256_t)) | ||
); | ||
assert_eq!( | ||
::std::mem::align_of::<uint256_t>(), | ||
4usize, | ||
concat!("Alignment of ", stringify!(uint256_t)) | ||
); | ||
assert_eq!( | ||
unsafe { &(*(::std::ptr::null::<uint256_t>())).array as *const _ as usize }, | ||
0usize, | ||
concat!( | ||
"Offset of field: ", | ||
stringify!(uint256_t), | ||
"::", | ||
stringify!(array) | ||
) | ||
); | ||
} | ||
extern "C" { | ||
pub fn gw_uint256_zero(num: *mut uint256_t); | ||
} | ||
extern "C" { | ||
pub fn gw_uint256_one(num: *mut uint256_t); | ||
} | ||
extern "C" { | ||
pub fn gw_uint256_max(num: *mut uint256_t); | ||
} | ||
extern "C" { | ||
pub fn gw_uint256_overflow_add( | ||
a: uint256_t, | ||
b: uint256_t, | ||
sum: *mut uint256_t, | ||
) -> ::std::os::raw::c_int; | ||
} | ||
extern "C" { | ||
pub fn gw_uint256_underflow_sub( | ||
a: uint256_t, | ||
b: uint256_t, | ||
rem: *mut uint256_t, | ||
) -> ::std::os::raw::c_int; | ||
} | ||
pub const GW_UINT256_SMALLER: ::std::os::raw::c_int = -1; | ||
pub const GW_UINT256_EQUAL: ::std::os::raw::c_int = 0; | ||
pub const GW_UINT256_LARGER: ::std::os::raw::c_int = 1; | ||
pub type _bindgen_ty_1 = ::std::os::raw::c_int; | ||
extern "C" { | ||
pub fn gw_uint256_cmp(a: uint256_t, b: uint256_t) -> ::std::os::raw::c_int; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
use std::cmp::Ordering; | ||
|
||
use self::bindings::{ | ||
gw_uint256_cmp, gw_uint256_one, gw_uint256_overflow_add, gw_uint256_underflow_sub, uint256_t, | ||
GW_UINT256_EQUAL, GW_UINT256_LARGER, GW_UINT256_SMALLER, | ||
}; | ||
|
||
// deref_nullptr in test code `fn bindgen_test_layout_uint256_t()`. | ||
#[allow(dead_code)] | ||
#[allow(non_camel_case_types)] | ||
#[allow(non_upper_case_globals)] | ||
#[allow(deref_nullptr)] | ||
mod bindings; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
pub struct U256(uint256_t); | ||
|
||
impl U256 { | ||
pub fn from_le_bytes(bytes: [u8; 32]) -> Self { | ||
let mut array = [0u32; 8]; | ||
for i in 0..8 { | ||
let start = i * 4; | ||
let end = i * 4 + 4; | ||
let u32_val = u32::from_le_bytes(bytes[start..end].try_into().unwrap()); | ||
array[i] = u32_val; | ||
} | ||
U256(uint256_t { array }) | ||
} | ||
|
||
pub fn to_le_bytes(&self) -> [u8; 32] { | ||
let mut bytes = [0u8; 32]; | ||
for i in 0..8 { | ||
let u32_val = self.0.array[i]; | ||
let start = i * 4; | ||
let end = i * 4 + 4; | ||
bytes[start..end].copy_from_slice(&u32_val.to_le_bytes()); | ||
} | ||
|
||
bytes | ||
} | ||
|
||
pub fn zero() -> Self { | ||
U256(uint256_t { array: [0u32; 8] }) | ||
} | ||
|
||
pub fn one() -> Self { | ||
let mut val = Self::zero(); | ||
unsafe { gw_uint256_one(&mut val.0) }; | ||
|
||
val | ||
} | ||
|
||
pub fn checked_add(&self, other: U256) -> Option<U256> { | ||
let mut sum = U256::zero(); | ||
match unsafe { gw_uint256_overflow_add(self.0, other.0, &mut sum.0) } { | ||
0 => Some(sum), | ||
_err => None, | ||
} | ||
} | ||
|
||
pub fn checked_sub(&self, other: U256) -> Option<U256> { | ||
let mut rem = U256::zero(); | ||
match unsafe { gw_uint256_underflow_sub(self.0, other.0, &mut rem.0) } { | ||
0 => Some(rem), | ||
_err => None, | ||
} | ||
} | ||
} | ||
|
||
impl PartialOrd for U256 { | ||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | ||
match unsafe { gw_uint256_cmp(self.0, other.0) } { | ||
GW_UINT256_SMALLER => Some(Ordering::Less), | ||
GW_UINT256_EQUAL => Some(Ordering::Equal), | ||
GW_UINT256_LARGER => Some(Ordering::Greater), | ||
_ => None, | ||
} | ||
} | ||
} | ||
|
||
impl Ord for U256 { | ||
fn cmp(&self, other: &Self) -> Ordering { | ||
self.partial_cmp(other).unwrap() | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::U256 as CU256; | ||
use primitive_types::U256 as PU256; | ||
use proptest::prelude::*; | ||
|
||
impl PartialEq<PU256> for CU256 { | ||
fn eq(&self, other: &PU256) -> bool { | ||
let mut other_le_bytes = [0u8; 32]; | ||
other.to_little_endian(&mut other_le_bytes); | ||
|
||
self.to_le_bytes() == other_le_bytes | ||
} | ||
} | ||
|
||
impl CU256 { | ||
fn into_pu256(self) -> PU256 { | ||
PU256::from_little_endian(&self.to_le_bytes()) | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_c_uint256_one() { | ||
let one = CU256::one(); | ||
assert_eq!(one.checked_sub(one), Some(CU256::zero())); | ||
|
||
let p_one = PU256::one(); | ||
assert_eq!(one, p_one); | ||
} | ||
|
||
proptest! { | ||
#[test] | ||
fn test_c_uint256_checked_add( | ||
a in prop::array::uniform32(any::<u8>()), | ||
b in prop::array::uniform32(any::<u8>()) | ||
) { | ||
let ca = CU256::from_le_bytes(a); | ||
let cb = CU256::from_le_bytes(b); | ||
let csum = ca.checked_add(cb); | ||
|
||
let pa = PU256::from_little_endian(&a); | ||
let pb = PU256::from_little_endian(&b); | ||
let psum = pa.checked_add(pb); | ||
prop_assert_eq!(csum.map(CU256::into_pu256), psum); | ||
} | ||
|
||
#[test] | ||
fn test_c_uint256_checked_sub( | ||
a in prop::array::uniform32(any::<u8>()), | ||
b in prop::array::uniform32(any::<u8>()) | ||
) { | ||
let ca = CU256::from_le_bytes(a); | ||
let cb = CU256::from_le_bytes(b); | ||
let crem = ca.checked_sub(cb); | ||
|
||
let pa = PU256::from_little_endian(&a); | ||
let pb = PU256::from_little_endian(&b); | ||
let prem = pa.checked_sub(pb); | ||
prop_assert_eq!(crem.map(CU256::into_pu256), prem); | ||
} | ||
|
||
#[test] | ||
fn test_c_uint256_cmp( | ||
a in prop::array::uniform32(any::<u8>()), | ||
b in prop::array::uniform32(any::<u8>()) | ||
) { | ||
let ca = CU256::from_le_bytes(a); | ||
let cb = CU256::from_le_bytes(b); | ||
|
||
let pa = PU256::from_little_endian(&a); | ||
let pb = PU256::from_little_endian(&b); | ||
|
||
prop_assert_eq!(ca > cb, pa > pb); | ||
} | ||
} | ||
} |
Oops, something went wrong.