diff --git a/Cargo.toml b/Cargo.toml index e5758e011ce0..ed4e4de3211a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,5 +14,6 @@ members = [ "node", "node/clock", "crypto", - "encoding" + "encoding", + "math/bigint", ] diff --git a/Makefile b/Makefile index b5cb30308319..4c7880c3078d 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ clean: @cargo clean -p interpreter @cargo clean -p crypto @cargo clean -p encoding + @cargo clean -p bigint @echo "Done cleaning." lint: clean diff --git a/math/bigint/Cargo.toml b/math/bigint/Cargo.toml new file mode 100644 index 000000000000..10810d39727f --- /dev/null +++ b/math/bigint/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ferret_bigint" +version = "0.1.0" +authors = ["ChainSafe Systems "] +edition = "2018" + +[dependencies] +num-bigint = "0.2.3" diff --git a/math/bigint/src/big.rs b/math/bigint/src/big.rs new file mode 100644 index 000000000000..7921ec00c3ee --- /dev/null +++ b/math/bigint/src/big.rs @@ -0,0 +1,65 @@ +pub use num_bigint::BigInt as BaseBigInt; +use std::fmt; +use std::ops::{Deref, DerefMut}; + +/// Signed Big integer variable +#[derive(PartialEq, Eq, Clone, Debug, Hash, Default, Ord, PartialOrd)] +pub struct BigInt { + num: BaseBigInt, +} + +impl From for BigInt { + #[inline] + fn from(n: i64) -> Self { + BigInt::from(BaseBigInt::from(n)) + } +} + +impl From for BigInt { + fn from(num: BaseBigInt) -> Self { + Self { num } + } +} + +impl Deref for BigInt { + type Target = BaseBigInt; + fn deref(&self) -> &Self::Target { + &self.num + } +} + +impl DerefMut for BigInt { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.num + } +} + +impl fmt::Display for BigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} + +impl fmt::Binary for BigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} + +impl fmt::Octal for BigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} + +impl fmt::LowerHex for BigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} + +impl fmt::UpperHex for BigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} diff --git a/math/bigint/src/lib.rs b/math/bigint/src/lib.rs new file mode 100644 index 000000000000..992be59357be --- /dev/null +++ b/math/bigint/src/lib.rs @@ -0,0 +1,6 @@ +mod big; +mod ubig; + +pub use self::big::{BaseBigInt, BigInt}; +pub use self::ubig::{BaseUBigInt, UBigInt}; +pub use num_bigint as base_big; diff --git a/math/bigint/src/ubig.rs b/math/bigint/src/ubig.rs new file mode 100644 index 000000000000..852592bb1a44 --- /dev/null +++ b/math/bigint/src/ubig.rs @@ -0,0 +1,64 @@ +pub use num_bigint::BigUint as BaseUBigInt; +use std::fmt; +use std::ops::{Deref, DerefMut}; + +#[derive(PartialEq, Eq, Clone, Debug, Hash, Default)] +pub struct UBigInt { + num: BaseUBigInt, +} + +impl From for UBigInt { + #[inline] + fn from(n: u64) -> Self { + UBigInt::from(BaseUBigInt::from(n)) + } +} + +impl From for UBigInt { + fn from(num: BaseUBigInt) -> Self { + Self { num } + } +} + +impl Deref for UBigInt { + type Target = BaseUBigInt; + fn deref(&self) -> &Self::Target { + &self.num + } +} + +impl DerefMut for UBigInt { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.num + } +} + +impl fmt::Display for UBigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} + +impl fmt::Binary for UBigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} + +impl fmt::Octal for UBigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} + +impl fmt::LowerHex for UBigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} + +impl fmt::UpperHex for UBigInt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.deref().fmt(f) + } +} diff --git a/math/bigint/tests/big_test.rs b/math/bigint/tests/big_test.rs new file mode 100644 index 000000000000..efa377b4b674 --- /dev/null +++ b/math/bigint/tests/big_test.rs @@ -0,0 +1,62 @@ +use ferret_bigint::{BaseBigInt, BigInt}; + +#[test] +fn test_lower_hex() { + let a = BigInt::from(BaseBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = BigInt::from( + BaseBigInt::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(), + ); + + assert_eq!(format!("{:x}", a), "a"); + assert_eq!(format!("{:x}", hello), "48656c6c6f20776f726c6421"); + assert_eq!(format!("{:♥>+#8x}", a), "♥♥♥♥+0xa"); +} + +#[test] +fn test_upper_hex() { + let a = BigInt::from(BaseBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = BigInt::from( + BaseBigInt::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(), + ); + + assert_eq!(format!("{:X}", a), "A"); + assert_eq!(format!("{:X}", hello), "48656C6C6F20776F726C6421"); + assert_eq!(format!("{:♥>+#8X}", a), "♥♥♥♥+0xA"); +} + +#[test] +fn test_binary() { + let a = BigInt::from(BaseBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = BigInt::from(BaseBigInt::parse_bytes("224055342307539".as_bytes(), 10).unwrap()); + + assert_eq!(format!("{:b}", a), "1010"); + assert_eq!( + format!("{:b}", hello), + "110010111100011011110011000101101001100011010011" + ); + assert_eq!(format!("{:♥>+#8b}", a), "♥+0b1010"); +} + +#[test] +fn test_octal() { + let a = BigInt::from(BaseBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = BigInt::from( + BaseBigInt::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(), + ); + + assert_eq!(format!("{:o}", a), "12"); + assert_eq!(format!("{:o}", hello), "22062554330674403566756233062041"); + assert_eq!(format!("{:♥>+#8o}", a), "♥♥♥+0o12"); +} + +#[test] +fn test_display() { + let a = BigInt::from(BaseBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = BigInt::from( + BaseBigInt::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(), + ); + + assert_eq!(format!("{}", a), "10"); + assert_eq!(format!("{}", hello), "22405534230753963835153736737"); + assert_eq!(format!("{:♥>+#8}", a), "♥♥♥♥♥+10"); +} diff --git a/math/bigint/tests/ubig_test.rs b/math/bigint/tests/ubig_test.rs new file mode 100644 index 000000000000..9e7741e2624f --- /dev/null +++ b/math/bigint/tests/ubig_test.rs @@ -0,0 +1,62 @@ +use ferret_bigint::{BaseUBigInt, UBigInt}; + +#[test] +fn test_lower_hex() { + let a = UBigInt::from(BaseUBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = UBigInt::from( + BaseUBigInt::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(), + ); + + assert_eq!(format!("{:x}", a), "a"); + assert_eq!(format!("{:x}", hello), "48656c6c6f20776f726c6421"); + assert_eq!(format!("{:♥>+#8x}", a), "♥♥♥♥+0xa"); +} + +#[test] +fn test_upper_hex() { + let a = UBigInt::from(BaseUBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = UBigInt::from( + BaseUBigInt::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(), + ); + + assert_eq!(format!("{:X}", a), "A"); + assert_eq!(format!("{:X}", hello), "48656C6C6F20776F726C6421"); + assert_eq!(format!("{:♥>+#8X}", a), "♥♥♥♥+0xA"); +} + +#[test] +fn test_binary() { + let a = UBigInt::from(BaseUBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = UBigInt::from(BaseUBigInt::parse_bytes("224055342307539".as_bytes(), 10).unwrap()); + + assert_eq!(format!("{:b}", a), "1010"); + assert_eq!( + format!("{:b}", hello), + "110010111100011011110011000101101001100011010011" + ); + assert_eq!(format!("{:♥>+#8b}", a), "♥+0b1010"); +} + +#[test] +fn test_octal() { + let a = UBigInt::from(BaseUBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = UBigInt::from( + BaseUBigInt::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(), + ); + + assert_eq!(format!("{:o}", a), "12"); + assert_eq!(format!("{:o}", hello), "22062554330674403566756233062041"); + assert_eq!(format!("{:♥>+#8o}", a), "♥♥♥+0o12"); +} + +#[test] +fn test_display() { + let a = UBigInt::from(BaseUBigInt::parse_bytes(b"A", 16).unwrap()); + let hello = UBigInt::from( + BaseUBigInt::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(), + ); + + assert_eq!(format!("{}", a), "10"); + assert_eq!(format!("{}", hello), "22405534230753963835153736737"); + assert_eq!(format!("{:♥>+#8}", a), "♥♥♥♥♥+10"); +} diff --git a/vm/Cargo.toml b/vm/Cargo.toml index f5b6583f920f..fa1749358fab 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -5,6 +5,6 @@ authors = ["ChainSafe Systems "] edition = "2018" [dependencies] -num-bigint = "0.2.3" +ferret_bigint = {path = "../math/bigint"} address = {path = "./address"} encoding = {path = "../encoding"} diff --git a/vm/actor/Cargo.toml b/vm/actor/Cargo.toml index 62295ccb8b31..5a5dd30e88bd 100644 --- a/vm/actor/Cargo.toml +++ b/vm/actor/Cargo.toml @@ -9,7 +9,7 @@ vm = {path = "../../vm"} address = {path = "../address"} runtime = {path = "../runtime"} cid = "0.3.1" -num-bigint = "0.2.3" +ferret_bigint = {path = "../../math/bigint"} encoding = {path = "../../encoding"} num-traits = "0.2" num-derive = "0.2" diff --git a/vm/actor/src/lib.rs b/vm/actor/src/lib.rs index 29940037b7e4..81f5b4ce0c25 100644 --- a/vm/actor/src/lib.rs +++ b/vm/actor/src/lib.rs @@ -6,7 +6,7 @@ pub use self::code::*; use cid::Cid; use encoding::{Cbor, CodecProtocol, Error as EncodingError}; -use num_bigint::BigUint; +use ferret_bigint::UBigInt; #[derive(PartialEq, Eq, Copy, Clone, Debug, Default)] pub struct ActorID(u64); @@ -33,13 +33,13 @@ impl Cbor for ActorID { pub struct ActorState { code_id: CodeID, state: Cid, - balance: BigUint, + balance: UBigInt, sequence: u64, } impl ActorState { /// Constructor for actor state - pub fn new(code_id: CodeID, state: Cid, balance: BigUint, sequence: u64) -> Self { + pub fn new(code_id: CodeID, state: Cid, balance: UBigInt, sequence: u64) -> Self { Self { code_id, state, diff --git a/vm/message/Cargo.toml b/vm/message/Cargo.toml index 73600a785150..7eab3b915ec1 100644 --- a/vm/message/Cargo.toml +++ b/vm/message/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] vm = {path = "../../vm"} address = {path = "../address"} -num-bigint = "0.2.3" +ferret_bigint = {path = "../../math/bigint"} encoding = {path = "../../encoding"} crypto = {path = "../../crypto"} derive_builder = "0.9" diff --git a/vm/message/src/lib.rs b/vm/message/src/lib.rs index 68f730d85875..75a9d7b788e5 100644 --- a/vm/message/src/lib.rs +++ b/vm/message/src/lib.rs @@ -7,7 +7,7 @@ pub use signed_message::*; pub use unsigned_message::*; use address::Address; -use num_bigint::BigUint; +use ferret_bigint::UBigInt; use vm::{MethodNum, MethodParams, TokenAmount}; pub trait Message { @@ -24,7 +24,7 @@ pub trait Message { /// params returns the encoded parameters for the method call fn params(&self) -> MethodParams; /// gas_price returns gas price for the message - fn gas_price(&self) -> BigUint; + fn gas_price(&self) -> UBigInt; /// gas_limit returns the gas limit for the message - fn gas_limit(&self) -> BigUint; + fn gas_limit(&self) -> UBigInt; } diff --git a/vm/message/src/message_receipt.rs b/vm/message/src/message_receipt.rs index 324518666601..9342ef6a1a97 100644 --- a/vm/message/src/message_receipt.rs +++ b/vm/message/src/message_receipt.rs @@ -1,4 +1,4 @@ -use num_bigint::BigUint; +use ferret_bigint::UBigInt; use vm::ExitCode; /// MessageReceipt is the result of a state transition from a message @@ -7,5 +7,5 @@ pub struct MessageReceipt { // TODO: determine if this is necessary, code returned from cbor pub exit_code: ExitCode, pub return_data: Vec, - pub gas_used: BigUint, + pub gas_used: UBigInt, } diff --git a/vm/message/src/signed_message.rs b/vm/message/src/signed_message.rs index 6b47c32fde09..1f5375421dbe 100644 --- a/vm/message/src/signed_message.rs +++ b/vm/message/src/signed_message.rs @@ -4,7 +4,7 @@ use vm::{MethodNum, MethodParams, TokenAmount}; use address::Address; use crypto::{Error as CryptoError, Signature, Signer}; use encoding::{Cbor, CodecProtocol, Error as EncodingError}; -use num_bigint::BigUint; +use ferret_bigint::UBigInt; /// SignedMessage represents a wrapped message with signature bytes #[derive(PartialEq, Clone, Debug)] @@ -58,11 +58,11 @@ impl Message for SignedMessage { self.message.params() } /// gas_price returns gas price for the message - fn gas_price(&self) -> BigUint { + fn gas_price(&self) -> UBigInt { self.message.gas_price() } /// gas_limit returns the gas limit for the message - fn gas_limit(&self) -> BigUint { + fn gas_limit(&self) -> UBigInt { self.message.gas_limit() } } diff --git a/vm/message/src/unsigned_message.rs b/vm/message/src/unsigned_message.rs index ece338ab3e0a..8b5abcfb6fb6 100644 --- a/vm/message/src/unsigned_message.rs +++ b/vm/message/src/unsigned_message.rs @@ -5,7 +5,7 @@ use crate::{MethodNum, MethodParams}; use address::Address; use derive_builder::Builder; use encoding::{Cbor, CodecProtocol, Error as EncodingError}; -use num_bigint::BigUint; +use ferret_bigint::UBigInt; /// Default Unsigned VM message type which includes all data needed for a state transition /// @@ -13,7 +13,7 @@ use num_bigint::BigUint; /// ``` /// use message::{UnsignedMessage, Message}; /// use vm::{TokenAmount, MethodParams, MethodNum}; -/// use num_bigint::BigUint; +/// use ferret_bigint::UBigInt; /// use address::Address; /// /// // Use the builder pattern to generate a message @@ -24,8 +24,8 @@ use num_bigint::BigUint; /// .value(TokenAmount::new(0)) // optional /// .method_num(MethodNum::default()) // optional /// .params(MethodParams::default()) // optional -/// .gas_limit(BigUint::default()) // optional -/// .gas_price(BigUint::default()) // optional +/// .gas_limit(UBigInt::default()) // optional +/// .gas_price(UBigInt::default()) // optional /// .build() /// .unwrap(); /// @@ -51,9 +51,9 @@ pub struct UnsignedMessage { #[builder(default)] params: MethodParams, #[builder(default)] - gas_price: BigUint, + gas_price: UBigInt, #[builder(default)] - gas_limit: BigUint, + gas_limit: UBigInt, } impl UnsignedMessage { @@ -88,11 +88,11 @@ impl Message for UnsignedMessage { self.params.clone() } /// gas_price returns gas price for the message - fn gas_price(&self) -> BigUint { + fn gas_price(&self) -> UBigInt { self.gas_price.clone() } /// gas_limit returns the gas limit for the message - fn gas_limit(&self) -> BigUint { + fn gas_limit(&self) -> UBigInt { self.gas_limit.clone() } } diff --git a/vm/message/tests/builder_test.rs b/vm/message/tests/builder_test.rs index 5253dae6e607..0c76c51dff26 100644 --- a/vm/message/tests/builder_test.rs +++ b/vm/message/tests/builder_test.rs @@ -1,7 +1,7 @@ use address::Address; use crypto::{Signature, Signer}; +use ferret_bigint::UBigInt; use message::{Message, SignedMessage, UnsignedMessage}; -use num_bigint::BigUint; use std::error::Error; use vm::{MethodNum, MethodParams, TokenAmount}; @@ -26,8 +26,8 @@ fn unsigned_message_builder() { .value(TokenAmount::new(0)) .method_num(MethodNum::default()) .params(MethodParams::default()) - .gas_limit(BigUint::default()) - .gas_price(BigUint::default()) + .gas_limit(UBigInt::default()) + .gas_price(UBigInt::default()) .build() .unwrap(); assert_eq!(message.from(), from_addr.clone()); @@ -36,8 +36,8 @@ fn unsigned_message_builder() { assert_eq!(message.method_num(), MethodNum::default()); assert_eq!(message.params(), MethodParams::default()); assert_eq!(message.value(), TokenAmount::new(0)); - assert_eq!(message.gas_price(), BigUint::default()); - assert_eq!(message.gas_limit(), BigUint::default()); + assert_eq!(message.gas_price(), UBigInt::default()); + assert_eq!(message.gas_limit(), UBigInt::default()); let mut mb = UnsignedMessage::builder(); mb.to(to_addr.clone()); mb.from(from_addr.clone()); diff --git a/vm/src/token.rs b/vm/src/token.rs index 258c9ef1d67e..377d6930d76b 100644 --- a/vm/src/token.rs +++ b/vm/src/token.rs @@ -1,12 +1,12 @@ -use num_bigint::BigUint; +use ferret_bigint::UBigInt; /// Wrapper around a big int variable to handle token specific functionality // TODO verify on finished spec whether or not big int or uint #[derive(Default, Clone, PartialEq, Debug)] -pub struct TokenAmount(pub BigUint); +pub struct TokenAmount(pub UBigInt); impl TokenAmount { pub fn new(val: u64) -> Self { - TokenAmount(BigUint::from(val)) + TokenAmount(UBigInt::from(val)) } } diff --git a/vm/state_tree/Cargo.toml b/vm/state_tree/Cargo.toml index 8321e09e80a5..cf7a4f550c68 100644 --- a/vm/state_tree/Cargo.toml +++ b/vm/state_tree/Cargo.toml @@ -11,4 +11,4 @@ vm = {path = "../../vm"} cid = "0.3.1" [dev-dependencies] -num-bigint = "0.2.3" +ferret_bigint = {path = "../../math/bigint"} diff --git a/vm/state_tree/src/lib.rs b/vm/state_tree/src/lib.rs index 7741057dcfd0..798e146d60d3 100644 --- a/vm/state_tree/src/lib.rs +++ b/vm/state_tree/src/lib.rs @@ -65,13 +65,13 @@ mod tests { use super::*; use actor::{ActorState, CodeID}; use cid::{Cid, Codec, Version}; - use num_bigint::BigUint; + use ferret_bigint::UBigInt; #[test] fn get_set_cache() { let cid = Cid::new(Codec::DagProtobuf, Version::V1, &[0u8]); - let act_s = ActorState::new(CodeID::Account, cid.clone(), BigUint::default(), 1); - let act_a = ActorState::new(CodeID::Account, cid.clone(), BigUint::default(), 2); + let act_s = ActorState::new(CodeID::Account, cid.clone(), UBigInt::default(), 1); + let act_a = ActorState::new(CodeID::Account, cid.clone(), UBigInt::default(), 2); let addr = Address::new_id(1).unwrap(); let mut tree = HamtStateTree::default();