Skip to content

Commit

Permalink
Implement Hash trait for Bytes and String types (#5089)
Browse files Browse the repository at this point in the history
## Description

The current `Hasher` implementation uses the `sha256()` and
`keccak256()` functions provided in the `Bytes` type implementation.

This PR moves the assembly block that does the hashing into the
`Hasher`. This allows for the homogenous syntax of hashing any type and
moves all hashing into the `hash.sw` file.
This PR also implements the `Hash` trait for the `Bytes` and `String`
types.

Before:
```rust
assert(sha256(my_string) == my_bytes.sha256());
```
After:
```rust
assert(sha256(my_string) == sha256(my_bytes));
```

## Checklist

- [ ] I have linked to any relevant issues.
- [ ] I have commented my code, particularly in hard-to-understand
areas.
- [ ] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: bitzoic <[email protected]>
  • Loading branch information
bitzoic and bitzoic authored Sep 5, 2023
1 parent 36ccf52 commit 49ee268
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 68 deletions.
54 changes: 0 additions & 54 deletions sway-lib-std/src/bytes.sw
Original file line number Diff line number Diff line change
Expand Up @@ -537,60 +537,6 @@ impl Bytes {
pub fn is_empty(self) -> bool {
self.len == 0
}

/// Returns the `SHA-2-256` hash of the elements.
///
/// # Returns
///
/// * [b256] - The `SHA-2-256` hash of the elements.
///
/// # Examples
///
/// ```sway
/// use std:bytes::Bytes;
///
/// fn foo() {
/// let bytes = Bytes::new();
/// bytes.push(1);
/// bytes.push(2);
/// bytes.push(3);
/// let sha256_hash = bytes.sha256();
/// }
/// ```
pub fn sha256(self) -> b256 {
let mut result_buffer = b256::min();
asm(hash: result_buffer, ptr: self.buf.ptr, bytes: self.len) {
s256 hash ptr bytes;
hash: b256
}
}

/// Returns the `KECCAK-256` hash of the elements.
///
/// # Returns
///
/// * [b256] - The `KECCAK-256` hash of the elements.
///
/// # Examples
///
/// ```sway
/// use std:bytes::Bytes;
///
/// fn foo() {
/// let bytes = Bytes::new();
/// bytes.push(1);
/// bytes.push(2);
/// bytes.push(3);
/// let keccak256_hash = bytes.keccak256();
/// }
/// ```
pub fn keccak256(self) -> b256 {
let mut result_buffer = b256::min();
asm(hash: result_buffer, ptr: self.buf.ptr, bytes: self.len) {
k256 hash ptr bytes;
hash: b256
}
}
}

// Need to use seperate impl blocks for now: https://github.com/FuelLabs/sway/issues/1548
Expand Down
38 changes: 35 additions & 3 deletions sway-lib-std/src/hash.sw
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,19 @@ impl Hasher {
}

pub fn sha256(self) -> b256 {
self.bytes.sha256()
let mut result_buffer = b256::min();
asm(hash: result_buffer, ptr: self.bytes.buf.ptr, bytes: self.bytes.len) {
s256 hash ptr bytes;
hash: b256
}
}

pub fn keccak256(self) -> b256 {
self.bytes.keccak256()
let mut result_buffer = b256::min();
asm(hash: result_buffer, ptr: self.bytes.buf.ptr, bytes: self.bytes.len) {
k256 hash ptr bytes;
hash: b256
}
}
}

Expand Down Expand Up @@ -123,6 +131,12 @@ impl Hash for bool {
}
}

impl Hash for Bytes {
fn hash(self, ref mut state: Hasher) {
state.write(self);
}
}

impl<A, B> Hash for (A, B) where A: Hash, B: Hash {
#![inline(never)]
fn hash(self, ref mut state: Hasher) {
Expand Down Expand Up @@ -418,4 +432,22 @@ fn test_hasher_sha256_bool() {
true.hash(hasher);
let sha256 = hasher.sha256();
assert(sha256 == 0x4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a);
}
}

#[test]
fn test_hasher_sha256_bytes() {
use ::assert::assert;
let mut hasher = Hasher::new();
let mut bytes = Bytes::new();
bytes.push(0u8);
bytes.hash(hasher);
let sha256 = hasher.sha256();
assert(sha256 == 0x6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d);

let mut hasher = Hasher::new();
let mut bytes = Bytes::new();
bytes.push(1u8);
bytes.hash(hasher);
let sha256 = hasher.sha256();
assert(sha256 == 0x4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a);
}
21 changes: 20 additions & 1 deletion sway-lib-std/src/string.sw
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
library;

use ::assert::assert;
use ::bytes::Bytes;
use ::convert::From;
use ::hash::{Hash, Hasher};
use ::option::Option;
use ::assert::assert;


/// A UTF-8 encoded growable string.
Expand Down Expand Up @@ -265,6 +266,12 @@ impl Eq for String {
}
}

impl Hash for String {
fn hash(self, ref mut state: Hasher) {
state.write(self.bytes);
}
}

// Tests

#[test]
Expand Down Expand Up @@ -495,3 +502,15 @@ fn string_test_equal() {
assert(string1 == string2);
assert(string1 != string3);
}

#[test]
fn string_test_hash() {
use ::hash::sha256;

let mut bytes = Bytes::new();
bytes.push(0u8);

let string = String::from(bytes);

assert(sha256(string) == sha256(bytes));
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"typeArguments": null
},
"name": "C0",
"offset": 7564
"offset": 7372
},
{
"configurableType": {
Expand All @@ -16,7 +16,7 @@
"typeArguments": null
},
"name": "C1",
"offset": 7572
"offset": 7380
},
{
"configurableType": {
Expand All @@ -25,7 +25,7 @@
"typeArguments": null
},
"name": "C2",
"offset": 7588
"offset": 7396
},
{
"configurableType": {
Expand All @@ -34,7 +34,7 @@
"typeArguments": []
},
"name": "C3",
"offset": 7620
"offset": 7428
},
{
"configurableType": {
Expand All @@ -43,7 +43,7 @@
"typeArguments": []
},
"name": "C4",
"offset": 7636
"offset": 7444
},
{
"configurableType": {
Expand All @@ -52,7 +52,7 @@
"typeArguments": []
},
"name": "C5",
"offset": 7652
"offset": 7460
},
{
"configurableType": {
Expand All @@ -61,7 +61,7 @@
"typeArguments": null
},
"name": "C6",
"offset": 7668
"offset": 7476
},
{
"configurableType": {
Expand All @@ -70,7 +70,7 @@
"typeArguments": null
},
"name": "C7",
"offset": 7684
"offset": 7492
},
{
"configurableType": {
Expand All @@ -79,7 +79,7 @@
"typeArguments": null
},
"name": "C9",
"offset": 7732
"offset": 7540
}
],
"functions": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ script;
use basic_storage_abi::{BasicStorage, Quad};

fn main() -> u64 {
let addr = abi(BasicStorage, 0x576da79735d7fe54047bef8df46195e2c0978726f68f3c840902b75e77d99c96);
let addr = abi(BasicStorage, 0x21d0b9983dced02ae881b2936f20f69026963f6cc4eb0bfb4991e16b7f8c580f);
let key = 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
let value = 4242;

Expand Down

0 comments on commit 49ee268

Please sign in to comment.