瀏覽代碼

Fixing precision

Cesar Rodas 1 年之前
父節點
當前提交
25734b90cf
共有 3 個文件被更改,包括 39 次插入8 次删除
  1. 33 7
      utxo/src/amount.rs
  2. 4 0
      utxo/src/error.rs
  3. 2 1
      utxo/src/ledger.rs

+ 33 - 7
utxo/src/amount.rs

@@ -9,6 +9,9 @@ pub enum Error {
     #[error("{0} is not a valid number")]
     NoANumber(String),
 
+    #[error("Overflow")]
+    Overflow,
+
     #[error("Invalid asset name: {0}")]
     InvalidAssetName(String),
 }
@@ -161,16 +164,39 @@ impl Amount {
 
 impl ToString for Amount {
     fn to_string(&self) -> String {
+        self.try_into().unwrap()
+    }
+}
+
+impl TryInto<String> for &Amount {
+    type Error = Error;
+
+    fn try_into(self) -> Result<String, Error> {
         let str = self.cents.abs().to_string();
-        let precision: usize = self.asset.precision.into();
-        let str = if str.len() < precision + 1 {
-            format!("{}{}", "0".repeat(precision - str.len() + 1), str)
+        let precision = self.asset.precision;
+        let len = u8::try_from(str.len()).map_err(|_| Error::Overflow)?;
+
+        let (str, len) = if len < precision.checked_add(1).ok_or(Error::Overflow)? {
+            (
+                format!(
+                    "{}{}",
+                    "0".repeat(
+                        precision
+                            .checked_sub(len)
+                            .and_then(|x| x.checked_add(1))
+                            .ok_or(Error::Overflow)?
+                            .into()
+                    ),
+                    str
+                ),
+                precision.checked_add(1).ok_or(Error::Overflow)?,
+            )
         } else {
-            str
+            (str, len)
         };
 
-        let (left, right) = str.split_at(str.len() - precision);
-        format!(
+        let (left, right) = str.split_at(len.checked_sub(precision).ok_or(Error::Overflow)?.into());
+        Ok(format!(
             "{}{}.{}",
             if self.cents.is_negative() { "-" } else { "" },
             left,
@@ -178,7 +204,7 @@ impl ToString for Amount {
         )
         .trim_end_matches('0')
         .trim_end_matches('.')
-        .to_owned()
+        .to_owned())
     }
 }
 

+ 4 - 0
utxo/src/error.rs

@@ -8,6 +8,10 @@ pub enum Error {
     #[error("Transaction: {0}")]
     Transaction(#[from] transaction::Error),
 
+    /// An internal conversion error
+    #[error("Conversion overflow: {0}")]
+    Overflow(String),
+
     /// A storage error
     #[error("Storage: {0}")]
     Storage(#[from] storage::Error),

+ 2 - 1
utxo/src/ledger.rs

@@ -113,7 +113,8 @@ where
         let exchange_tx = if change_input.is_empty() {
             None
         } else {
-            let total = change_input.len() as u16;
+            let total =
+                u16::try_from(change_input.len()).map_err(|e| Error::Overflow(e.to_string()))?;
             let split_input = Transaction::new(
                 "Exchange transaction".to_owned(),
                 // Set the change transaction as settled. This is an