From ac93872b2c3ab156b19a2f6a258d95004a8eb12e Mon Sep 17 00:00:00 2001 From: Benjamin Canou Date: Thu, 14 Dec 2017 18:40:30 +0100 Subject: [PATCH] Alpha: allow no commas in tez litterals --- CHANGES.alphanet | 6 +++-- lib_embedded_protocol_alpha/src/qty_repr.ml | 16 ++++++++++-- test/proto_alpha/test_michelson_parser.ml | 29 ++++++++++++++++----- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/CHANGES.alphanet b/CHANGES.alphanet index 0cba28284..b308b0fa5 100644 --- a/CHANGES.alphanet +++ b/CHANGES.alphanet @@ -6,9 +6,11 @@ For the next reset - Do not allow revealing the same endorsement twice. - Tez values now have 6 decimals instead of two. The syntax used by - the client and Michelson requires comma separators every three + the client and Michelson use comma separators every three digits, before and after the dot. For instance, 3 million tez and 10 - µtez is written `3,000,000.000,01`. + µtez is written `3,000,000.000,01`. The syntax in JSON is the raw + amount in µtez, either as a number without decimals or as a decimal + string, for the same example we would get `"3000000000010"`. [Node] diff --git a/lib_embedded_protocol_alpha/src/qty_repr.ml b/lib_embedded_protocol_alpha/src/qty_repr.ml index 2686f66df..ffabb363f 100644 --- a/lib_embedded_protocol_alpha/src/qty_repr.ml +++ b/lib_embedded_protocol_alpha/src/qty_repr.ml @@ -107,8 +107,20 @@ module Make (T: QTY) : S = struct Some (Int64.of_string (remove_commas left ^ pad_to_six (remove_commas right))) with _ -> None in match String.split_on_char '.' s with - | [ left ; right ] when (integers left && decimals right) -> parse left right - | [ left ] when integers left -> parse left "" + | [ left ; right ] -> + if String.contains s ',' then + if integers left && decimals right then + parse left right + else + None + else if Compare.Int.(String.length right > 0) + && Compare.Int.(String.length right <= 6) then + parse left right + else None + | [ left ] -> + if not (String.contains s ',') || integers left then + parse left "" + else None | _ -> None let pp ppf amount = diff --git a/test/proto_alpha/test_michelson_parser.ml b/test/proto_alpha/test_michelson_parser.ml index 33213b9ff..7823e259b 100644 --- a/test/proto_alpha/test_michelson_parser.ml +++ b/test/proto_alpha/test_michelson_parser.ml @@ -34,14 +34,16 @@ let known_ok_tez_litterals = 999_999_999_999_999_999L, "999,999,999,999.999,999" ] let known_bad_tez_litterals = - [ "10000" ; + [ "10000." ; + "100,." ; + "100," ; "1,0000" ; "0.0000,1" ; "0.00,1" ; "0,1" ; - "0.0001" ; "HAHA" ; "0.000,000,1" ; + "0.0000000" ; "9,999,999,999,999.999,999"] let test_known_tez_litterals () = @@ -49,9 +51,12 @@ let test_known_tez_litterals () = (fun (v, s) -> let vv = Tez_repr.of_mutez v in let vs = Tez_repr.of_string s in + let vs' = Tez_repr.of_string (String.concat "" (String.split_on_char ',' s)) in let vv = match vv with None -> Assert.fail_msg "could not unopt %Ld" v | Some vv -> vv in let vs = match vs with None -> Assert.fail_msg "could not unopt %s" s | Some vs -> vs in + let vs' = match vs' with None -> Assert.fail_msg "could not unopt %s" s | Some vs' -> vs' in Assert.equal ~prn:Tez_repr.to_string vv vs ; + Assert.equal ~prn:Tez_repr.to_string vv vs' ; Assert.equal ~prn:(fun s -> s) (Tez_repr.to_string vv) s) known_ok_tez_litterals ; List.iter @@ -68,12 +73,22 @@ let test_random_tez_litterals () = let vv = match vv with None -> Assert.fail_msg "could not unopt %Ld" v | Some vv -> vv in let s = Tez_repr.to_string vv in let vs = Tez_repr.of_string s in + let s' = String.concat "" (String.split_on_char ',' s) in + let vs' = Tez_repr.of_string s' in Assert.is_some ~msg:("Could not parse " ^ s ^ " back") vs ; - match vs with - | None -> assert false - | Some vs -> - let rev = Tez_repr.to_int64 vs in - Assert.equal ~prn:Int64.to_string ~msg:(Tez_repr.to_string vv) v rev + Assert.is_some ~msg:("Could not parse " ^ s ^ " back") vs' ; + begin match vs with + | None -> assert false + | Some vs -> + let rev = Tez_repr.to_int64 vs in + Assert.equal ~prn:Int64.to_string ~msg:(Tez_repr.to_string vv) v rev + end ; + begin match vs' with + | None -> assert false + | Some vs' -> + let rev = Tez_repr.to_int64 vs' in + Assert.equal ~prn:Int64.to_string ~msg:(Tez_repr.to_string vv) v rev + end done ; return ()