-
Notifications
You must be signed in to change notification settings - Fork 122
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
Runtime sha256
should work for arbitrary strings even with length >= 128
#1056
Comments
The statically known strings is one story, where we can accurately compute their hashes with Do you mean to check the length of the string at runtime somehow? |
the implementation should traverse all the chunks of the string |
related issue: #1085 |
Maybe we should implement This going solve all related issues. |
BTW writing such function in TACT which gonna support hashing of strings any length is not that hard, here is an example of a simple fift function, which computes sha256 hash of any string of any length: asm fun sha256(data: String): Int{
1 PUSHINT // pusing the counter of the references to the stack
// s0 - counter, s1 - slice
WHILE:<{
OVER // copying the last slice to the top of the stack
// s0 - slice (copy), s1 - counter, s2 - slice
SREFS // counting the refs in the slice s0 and putting it (the counter) to s0
// s0 - number (of refs), s1 - counter, s2 - slice
0 NEQINT // comparing the number or refs, if 0 then exit the loop
// s0 - bool, s1 - counter, s2 - slice
}>DO<{
// s0 - counter, s1 - slice
OVER // copying the slice from s1 to the top of the stack (to s0)
// s0 - slice, s1 - counter, s2 - slice
LDREF // loading the reference, from s0 (the original data variable/last stack element), not s0 - original, s1 - result
// s0 - slice, s1 - cell (ref), s2 - counter, s3 - slice
s0 POP // removing the original slice from the stack (we don't need it anymore, only ref needed)
// s0 - cell (ref), s1 - counter, s2 - slice
CTOS // convert s0 the cell to slice (still in s0)
// s0 - slice (ref), s1 - counter, s2 - slice
s0 s1 XCHG // putting to s1 the value of current slice (it was in s0 prev), and counter to s0
// s0 - counter, s1 - slice (ref), s2 - slice
INC // increment the counter (in s0)
}>
HASHEXT_SHA256 // call the sha256 function
}
P.S. I used FIFT because I don't know an easy way to do manual stack manipulation with tact/func |
Neat approach! However, the Fift-specific constructs like Option 1So, one option would be to move that function over to FunC and then bind to it from Tact:
import "./sha256.fc";
@name(sha256)
native onchainSha256(data: String): Int; Option 2Another approach would be to replace those /// Main function that combines it all together
fun onchainSha256(data: String): Int {
shaPush(data);
while (shaShallProceed()) {
shaOperate();
}
return shaHashExt();
}
/// Gets the data onto stack, then pushes the 1 there too
/// Since there's no return value bound, both will remain on stack
asm fun shaPush(data: String) { 1 PUSHINT }
/// The while loop clause, which captures the Bool from the top of the stack
asm fun shaShallProceed(): Bool { OVER SREFS 0 NEQINT }
/// The body of the while loop
asm fun shaOperate() {
OVER LDREF s0 POP CTOS s0 s1 XCHG INC
}
/// HASHEXT_SHA256
asm fun shaHashExt(): Int { HASHEXT_SHA256 } Conclusion of sortsIn any case, those or any other options won't appear in the user code directly, only in the emitted/generated code. That's because handling of P.S.: Didn't test either of those options yet, just quickly wrote them here directly as a showcase :) |
The |
But if we will use such a function (as |
sha256
at run-time uses theSHA256U
TVM instruction, which only works with data with up to 1023 bits, so strings of length 128 bytes basically get truncated. This is confusing for smart-contract authors because it breaks the abstraction of theString
type. Since we allow strings with more than 127 characters, thosesha256
should work on those.See also, #1085
The text was updated successfully, but these errors were encountered: