diff --git a/contracts/soroban/libs/soroban-rlp/src/decoder.rs b/contracts/soroban/libs/soroban-rlp/src/decoder.rs index 9d05760d..7c74f411 100644 --- a/contracts/soroban/libs/soroban-rlp/src/decoder.rs +++ b/contracts/soroban/libs/soroban-rlp/src/decoder.rs @@ -116,6 +116,14 @@ pub fn decode_length(env: &Env, bytes: Bytes, offset: u8) -> u64 { len } +pub fn decode_bool(bytes: Bytes) -> bool { + if bytes.len() > 0 && bytes.get(0).unwrap() == 1 { + return true; + } + + false +} + pub fn decode_u8(env: &Env, bytes: Bytes) -> u8 { decode(&env, bytes).get(0).unwrap_or(0) } diff --git a/contracts/soroban/libs/soroban-rlp/src/encoder.rs b/contracts/soroban/libs/soroban-rlp/src/encoder.rs index 3b55bf7c..4c37a384 100644 --- a/contracts/soroban/libs/soroban-rlp/src/encoder.rs +++ b/contracts/soroban/libs/soroban-rlp/src/encoder.rs @@ -45,7 +45,7 @@ pub fn encode_length(env: &Env, len: u64, offset: u8) -> Bytes { let len_u8 = len as u8; len_info.push_back(len_u8 + offset) } else { - let mut bytes_length = u64_to_bytes(&env, len); + let mut bytes_length = u64_to_bytes(&env, len, false); let rlp_bytes_len = bytes_length.len() as u8; len_info.push_back(rlp_bytes_len + offset + 55); len_info.append(&mut bytes_length); @@ -54,6 +54,14 @@ pub fn encode_length(env: &Env, len: u64, offset: u8) -> Bytes { len_info } +pub fn encode_bool(env: &Env, value: bool) -> Bytes { + if value == true { + return bytes!(env, 0x01); + } + + bytes!(env, 0x00) +} + pub fn encode_u8(env: &Env, num: u8) -> Bytes { let mut bytes = Bytes::new(&env); bytes.push_back(num); @@ -62,17 +70,17 @@ pub fn encode_u8(env: &Env, num: u8) -> Bytes { } pub fn encode_u32(env: &Env, num: u32) -> Bytes { - let bytes = u32_to_bytes(&env, num); + let bytes = u32_to_bytes(&env, num, true); encode(&env, bytes) } pub fn encode_u64(env: &Env, num: u64) -> Bytes { - let bytes = u64_to_bytes(&env, num); + let bytes = u64_to_bytes(&env, num, true); encode(&env, bytes) } pub fn encode_u128(env: &Env, num: u128) -> Bytes { - let bytes = u128_to_bytes(&env, num); + let bytes = u128_to_bytes(&env, num, true); encode(&env, bytes) } diff --git a/contracts/soroban/libs/soroban-rlp/src/test/encoder.rs b/contracts/soroban/libs/soroban-rlp/src/test/encoder.rs index 1bef6239..2ecb5269 100644 --- a/contracts/soroban/libs/soroban-rlp/src/test/encoder.rs +++ b/contracts/soroban/libs/soroban-rlp/src/test/encoder.rs @@ -16,7 +16,7 @@ fn test_encode_u32() { let env = Env::default(); let encoded = encode_u32(&env, 2000022458); - assert_eq!(encoded, bytes!(&env, 0x85007735EBBA)); + assert_eq!(encoded, bytes!(&env, 0x847735EBBA)); } #[test] @@ -24,10 +24,10 @@ fn test_encode_u64() { let env = Env::default(); let encoded = encode_u64(&env, 1999999999999999999); - assert_eq!(encoded, bytes!(&env, 0x89001BC16D674EC7FFFF)); + assert_eq!(encoded, bytes!(&env, 0x881BC16D674EC7FFFF)); let encoded = encode_u64(&env, 199999999); - assert_eq!(encoded, bytes!(&env, 0x85000BEBC1FF)) + assert_eq!(encoded, bytes!(&env, 0x840BEBC1FF)) } #[test] @@ -63,11 +63,10 @@ fn test_encode_string_with_larger_bytes_length() { let encoded = encode_string(&env, String::from_str(&env, "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s")); - let expected_rlp_byte = 185; + let expected_rlp_byte = 184; let str_bytes_slice = b"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s"; let mut expected_bytes = Bytes::new(&env); expected_bytes.push_back(expected_rlp_byte); - expected_bytes.push_back(0); expected_bytes.push_back(0x97); expected_bytes.extend_from_slice(str_bytes_slice); @@ -108,29 +107,29 @@ fn test_encode_strings_with_longer_bytes() { let encoded = encode_strings(&env, strings); - let rlp_byte = 0xf7 + 3; + let rlp_byte = 0xf7 + 2; let mut expected_encode = Bytes::new(&env); // rlp byte and data length bytes expected_encode.push_back(rlp_byte); - expected_encode.extend_from_array(&[0x00, 0x01, 0x74]); + expected_encode.extend_from_array(&[0x01, 0x71]); // strings - let string_rlp_byte = 0xb7 + 2; + let string_rlp_byte = 0xb7 + 1; let string_len_byte = 0x7c; - expected_encode.extend_from_array(&[string_rlp_byte, 0, string_len_byte]); + expected_encode.extend_from_array(&[string_rlp_byte, string_len_byte]); expected_encode.extend_from_slice(b"It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout."); let string_len_byte = 0x7b; - expected_encode.extend_from_array(&[string_rlp_byte, 0, string_len_byte]); + expected_encode.extend_from_array(&[string_rlp_byte, string_len_byte]); expected_encode.extend_from_slice(b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); let string_len_byte = 0x74; - expected_encode.extend_from_array(&[string_rlp_byte, 0, string_len_byte]); + expected_encode.extend_from_array(&[string_rlp_byte, string_len_byte]); expected_encode.extend_from_slice(b"Egestas maecenas pharetra convallis posuere morbi. Velit laoreet id donec ultrices tincidunt arcu non sodales neque."); assert_eq!(encoded, expected_encode); - assert_eq!(encoded.len(), 376); + // assert_eq!(encoded.len(), 376); } #[test] @@ -149,7 +148,7 @@ fn test_encode_list_with_smaller_bytes() { let mut list: Vec = vec![&env]; let short_str = String::from_str(&env, "soroban-rlp"); - list.push_back(u32_to_bytes(&env, 4294967295)); + list.push_back(u32_to_bytes(&env, 4294967295, true)); list.push_back(string_to_bytes(&env, short_str.clone())); let encoded = encode_list(&env, list, true); @@ -184,18 +183,18 @@ fn test_encode_list_with_longer_bytes() { let mut expected_bytes = Bytes::new(&env); // rlp and data len bytes - let rlp_byte = 0xf7 + 2; - let data_len_byte = 0xAA + 4; - expected_bytes.extend_from_array(&[rlp_byte, 0, data_len_byte]); + let rlp_byte = 0xf7 + 1; + let data_len_byte = 0xAA + 1; + expected_bytes.extend_from_array(&[rlp_byte, data_len_byte]); // u8 expected_bytes.extend_from_array(&[0x81, 0xF5]); // u32 - expected_bytes.extend_from_array(&[0x85, 0x00, 0x01, 0x71, 0x34, 0x67]); + expected_bytes.extend_from_array(&[0x84, 0x01, 0x71, 0x34, 0x67]); // u64 - expected_bytes.extend_from_array(&[0x89, 0x00, 0x01, 0x71, 0x34, 0x67, 0xff, 0xff, 0xff, 0xff]); + expected_bytes.extend_from_array(&[0x88, 0x01, 0x71, 0x34, 0x67, 0xff, 0xff, 0xff, 0xff]); // u128 expected_bytes.extend_from_array(&[ @@ -204,10 +203,10 @@ fn test_encode_list_with_longer_bytes() { ]); // strings - let array_rlp_byte = 0xf7 + 2; + let array_rlp_byte = 0xf7 + 1; let total_rlp_bytes_in_array = 2; let strings_len_byte = 0x56 + total_rlp_bytes_in_array; - expected_bytes.extend_from_array(&[array_rlp_byte, 0, strings_len_byte]); + expected_bytes.extend_from_array(&[array_rlp_byte, strings_len_byte]); let rlp_byte = 0x80 + 46; expected_bytes.push_back(rlp_byte); diff --git a/contracts/soroban/libs/soroban-rlp/src/test/utils.rs b/contracts/soroban/libs/soroban-rlp/src/test/utils.rs index a7ebf346..fdf0a173 100644 --- a/contracts/soroban/libs/soroban-rlp/src/test/utils.rs +++ b/contracts/soroban/libs/soroban-rlp/src/test/utils.rs @@ -6,7 +6,7 @@ fn test_u32_to_bytes() { let env = Env::default(); let num = 0x12345678; - let bytes = u32_to_bytes(&env, num); + let bytes = u32_to_bytes(&env, num, true); let expected_num = bytes_to_u32(bytes); assert_eq!(num, expected_num) @@ -17,7 +17,7 @@ fn test_u64_to_bytes() { let env = Env::default(); let num: u64 = 18446744073709551615; - let bytes = u64_to_bytes(&env, num); + let bytes = u64_to_bytes(&env, num, true); let expected_num = bytes_to_u64(bytes); assert_eq!(num, expected_num) @@ -28,7 +28,7 @@ fn test_u128_to_bytes() { let env = Env::default(); let num: u128 = 340282366920938463463374607431768211455; - let bytes = u128_to_bytes(&env, num); + let bytes = u128_to_bytes(&env, num, true); let expected_num = bytes_to_u128(bytes); assert_eq!(num, expected_num) @@ -38,8 +38,8 @@ fn test_u128_to_bytes() { fn test_slice_vector() { let env = Env::default(); - let bytes = u128_to_bytes(&env, 1844674407); + let bytes = u128_to_bytes(&env, 1844674407, true); let slice = slice_vector(&env, bytes.clone(), 1, 2); - assert_eq!(slice, bytes!(&env, 0x6DF3)); + assert_eq!(slice, bytes!(&env, 0xF37F)); } diff --git a/contracts/soroban/libs/soroban-rlp/src/utils.rs b/contracts/soroban/libs/soroban-rlp/src/utils.rs index 403cac52..57da3199 100644 --- a/contracts/soroban/libs/soroban-rlp/src/utils.rs +++ b/contracts/soroban/libs/soroban-rlp/src/utils.rs @@ -4,20 +4,53 @@ use soroban_sdk::{ Bytes, Env, String, }; -pub fn u32_to_bytes(env: &Env, number: u32) -> Bytes { - let mut bytes = bytes!(&env, 0x00); - let mut i = 3; - let mut leading_zero = true; - while i >= 0 { - let val = (number >> (i * 8) & 0xff) as u8; - if val > 0 || !leading_zero { - leading_zero = false; - bytes.push_back(val); - } +pub fn u32_to_bytes(env: &Env, number: u32, signed: bool) -> Bytes { + let bytes = Bytes::from_slice(&env, &number.to_be_bytes()); + to_signed_bytes(&env, bytes, signed) +} + +pub fn u64_to_bytes(env: &Env, number: u64, signed: bool) -> Bytes { + let bytes = Bytes::from_slice(&env, &number.to_be_bytes()); + to_signed_bytes(&env, bytes, signed) +} - i -= 1; +pub fn u128_to_bytes(env: &Env, number: u128, signed: bool) -> Bytes { + let bytes = Bytes::from_slice(&env, &number.to_be_bytes()); + to_signed_bytes(&env, bytes, signed) +} + +pub fn to_signed_bytes(env: &Env, bytes: Bytes, signed: bool) -> Bytes { + let truncated = truncate_zeros(&env, bytes); + if signed == false { + return truncated; + } + + let first_byte = truncated.get(0).unwrap_or(0); + + if first_byte >= 128 { + let mut prefix = bytes!(&env, 0x00); + prefix.append(&truncated); + prefix + } else { + truncated } - bytes +} + +pub fn truncate_zeros(env: &Env, bytes: Bytes) -> Bytes { + let mut i = 0; + let mut started = false; + let mut result = Bytes::new(&env); + + while i < bytes.len() { + let val = bytes.get(i).unwrap(); + if val > 0 || started { + started = true; + result.push_back(val); + } + i = i + 1; + } + + result } pub fn bytes_to_u32(bytes: Bytes) -> u32 { @@ -28,22 +61,6 @@ pub fn bytes_to_u32(bytes: Bytes) -> u32 { num } -pub fn u64_to_bytes(env: &Env, number: u64) -> Bytes { - let mut bytes = bytes!(&env, 0x00); - let mut i = 7; - let mut leading_zero = true; - while i >= 0 { - let val = (number >> (i * 8) & 0xff) as u8; - if val > 0 || !leading_zero { - leading_zero = false; - bytes.push_back(val); - } - - i -= 1; - } - bytes -} - pub fn bytes_to_u64(bytes: Bytes) -> u64 { let mut num = 0; for byte in bytes.iter() { @@ -52,23 +69,6 @@ pub fn bytes_to_u64(bytes: Bytes) -> u64 { num } -pub fn u128_to_bytes(env: &Env, number: u128) -> Bytes { - let mut bytes = bytes!(&env, 0x00); - let mut i = 15; - let mut leading_zero = true; - while i >= 0 { - let val = (number >> (i * 8) & 0xff) as u8; - if val > 0 || !leading_zero { - leading_zero = false; - bytes.push_back(val); - } - - i -= 1; - } - - bytes -} - pub fn bytes_to_u128(bytes: Bytes) -> u128 { let mut num = 0; for byte in bytes.iter() {