Skip to content

Commit

Permalink
fix: rlp signed bytes prefix (#422)
Browse files Browse the repository at this point in the history
  • Loading branch information
bishalbikram authored Dec 13, 2024
1 parent 106a5f3 commit a81c141
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 74 deletions.
8 changes: 8 additions & 0 deletions contracts/soroban/libs/soroban-rlp/src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
16 changes: 12 additions & 4 deletions contracts/soroban/libs/soroban-rlp/src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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)
}

Expand Down
39 changes: 19 additions & 20 deletions contracts/soroban/libs/soroban-rlp/src/test/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ 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]
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]
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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]
Expand All @@ -149,7 +148,7 @@ fn test_encode_list_with_smaller_bytes() {

let mut list: Vec<Bytes> = 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);
Expand Down Expand Up @@ -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(&[
Expand All @@ -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);
Expand Down
10 changes: 5 additions & 5 deletions contracts/soroban/libs/soroban-rlp/src/test/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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));
}
90 changes: 45 additions & 45 deletions contracts/soroban/libs/soroban-rlp/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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() {
Expand All @@ -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() {
Expand Down

0 comments on commit a81c141

Please sign in to comment.