-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
String encoding for return values #185
Changes from all commits
7a25875
bd3767d
28bf950
72dc6b6
f14a42c
384aef2
8254fa2
5f4b61d
65ac93e
d40e15d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#![no_std] | ||
|
||
#[allow(unused_imports)] | ||
use ulm::*; | ||
|
||
#[ulm::contract] | ||
pub trait Types { | ||
#[init] | ||
fn init(&self) {} | ||
|
||
#[endpoint(strEndpoint)] | ||
fn str_endpoint(&self) -> str { | ||
"Hello" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
push "strEndpoint"; | ||
hold_string_from_test_stack; | ||
hold_list_values_from_test_stack; | ||
hold_list_values_from_test_stack; | ||
encode_call_data; | ||
|
||
return_value; | ||
mock CallData; | ||
|
||
call_contract 12345; | ||
return_value; | ||
check_eq (); | ||
|
||
push_status; | ||
check_eq 2; | ||
|
||
check_raw_output | ||
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20" + | ||
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05" + | ||
b"Hello\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | ||
Comment on lines
+18
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on my understanding of how encoded values work, this seems like it has an extra value in it? I expect that the endpoint returns a string, where a str is encoded as follows:
where:
I don't understand where the initial value x20 is coming from. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See the answer here: #185 (comment) , but a single string is encoded like this (when part of a request, response, log entry, and probably other stuff):
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
push "strEndpoint"; | ||
hold_string_from_test_stack; | ||
hold_list_values_from_test_stack; | ||
hold_list_values_from_test_stack; | ||
encode_call_data; | ||
|
||
return_value; | ||
mock CallData; | ||
|
||
call_contract 12345; | ||
return_value; | ||
check_eq (); | ||
|
||
push_status; | ||
check_eq 2; | ||
output_to_arg; | ||
call :: test_helpers :: decode_single_str; | ||
return_value; | ||
check_eq "Hello" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, this prefix is supposed to be an integer equal to the length of the string. If so, is that a property worth validating?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's more complicated. See this for more details: https://docs.soliditylang.org/en/latest/abi-spec.html but, as I understand it, the summary is something like this:
First, values are encoded in two bytes objects (called the "prefix" and the "suffix"), which are concatenated at the end to produce the full encoding. Fixed length values (such as int256) are encoded fully in the prefix (their suffix part is empty). Variable length values (such as strings) have both prefix and suffix parts. The prefix part is equal to
the-final-length-of-the-prefix + the-length-of-the-suffix-before-the-current-value
(I assume that this makes it easy to find the start of the suffix part of the value). The suffix part contains the length of the value followed by the value bytes.So,
prefix_size
here is the prefix encoding of the string, which, for a single encoded string, should be the total length of the prefix. It can only be32
, i.e. the number of bytes needed for any fixed size int with at most 256 bytes.The
:: bytes_hooks :: decode_str
call below will receive the suffix, and it will read the length, then it will extract that many bytes, and so on.