Skip to content

Commit fe34b92

Browse files
authored
Update hasher (#115)
* Add missing separator in MethodResolver * Add python script that implements the method hashing function This gives us a second implementation in another language to compare against * Use token actor method names as golden values for macro testing * Update method numbers in the token actor code * Bump frc42_dispatch version to 1.0.0
1 parent a58f063 commit fe34b92

File tree

10 files changed

+68
-26
lines changed

10 files changed

+68
-26
lines changed

frc42_dispatch/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "frc42_dispatch"
33
description = "Filecoin FRC-0042 calling convention/dispatch support library"
4-
version = "0.3.0"
4+
version = "1.0.0"
55
license = "MIT OR Apache-2.0"
66
keywords = ["filecoin", "dispatch", "frc-0042"]
77
repository = "https://github.com/helix-onchain/filecoin/"
@@ -12,8 +12,8 @@ edition = "2021"
1212
fvm_ipld_encoding = { version = "0.2.2" }
1313
fvm_sdk = { version = "2.0.0-alpha.2", optional = true }
1414
fvm_shared = { version = "2.0.0-alpha.2" }
15-
frc42_hasher = { version = "0.2.0", path = "hasher" }
16-
frc42_macros = { version = "0.2.0", path = "macros" }
15+
frc42_hasher = { version = "1.0.0", path = "hasher" }
16+
frc42_macros = { version = "1.0.0", path = "macros" }
1717
thiserror = { version = "1.0.31" }
1818

1919
[features]

frc42_dispatch/generate_hashes.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from hashlib import blake2b
2+
3+
# See https://github.com/filecoin-project/FIPs/blob/master/FRCs/frc-0042.md#method-number-computation
4+
def method_number(name):
5+
name = '1|' + name
6+
hash = blake2b(name.encode('ascii'), digest_size=64)
7+
#print('digest: ' + hash.hexdigest())
8+
#print(f'{len(hash.digest())} bytes long')
9+
10+
digest = hash.digest()
11+
while digest:
12+
chunk = digest[:4]
13+
num = int.from_bytes(chunk, byteorder='big')
14+
if num >= 1<<24:
15+
return num
16+
digest = digest[4:]
17+
raise Exception("Method ID could not be determined, please change it")
18+
19+
20+
# these are all the method names used in the example token actor
21+
methods = ['Name', 'Symbol', 'TotalSupply', 'BalanceOf', 'Allowance', 'IncreaseAllowance',
22+
'DecreaseAllowance', 'RevokeAllowance', 'Burn', 'TransferFrom', 'Transfer', 'Mint']
23+
for method in methods:
24+
num = method_number(method)
25+
#print(f'{num:08x}\t{method}')
26+
# print out Rust code for use in a test
27+
print(f'assert_eq!(method_hash!("{method}"), 0x{num:08x});')

frc42_dispatch/hasher/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "frc42_hasher"
3-
version = "0.2.0"
3+
version = "1.0.0"
44
license = "MIT OR Apache-2.0"
55
description = "Filecoin FRC-0042 calling convention method hashing"
66
repository = "https://github.com/helix-onchain/filecoin/"

frc42_dispatch/hasher/src/hash.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ impl<T: Hasher> MethodResolver<T> {
7979
return Ok(Self::CONSTRUCTOR_METHOD_NUMBER);
8080
}
8181

82+
let method_name = format!("1|{}", method_name);
8283
let digest = self.hasher.hash(method_name.as_bytes());
8384

8485
for chunk in digest.chunks(Self::DIGEST_CHUNK_LENGTH) {
@@ -88,7 +89,7 @@ impl<T: Hasher> MethodResolver<T> {
8889
}
8990

9091
let method_id = as_u32(chunk) as u64;
91-
// Method numbers below 256 are reserved for other use
92+
// Method numbers below FIRST_METHOD_NUMBER are reserved for other use
9293
if method_id >= Self::FIRST_METHOD_NUMBER {
9394
return Ok(method_id);
9495
}
@@ -152,14 +153,15 @@ mod tests {
152153
fn normal_method_is_hashed() {
153154
let fake_hasher = FakeHasher {};
154155
let method_hasher = MethodResolver::new(fake_hasher);
156+
// note that the method hashing prepends each name with "1|" as a domain separator
155157
assert_eq!(
156158
method_hasher.method_number("NormalMethod").unwrap(),
157-
super::as_u32(&fake_hasher.hash(b"NormalMethod")) as u64
159+
super::as_u32(&fake_hasher.hash(b"1|NormalMethod")) as u64
158160
);
159161

160162
assert_eq!(
161163
method_hasher.method_number("NormalMethod2").unwrap(),
162-
super::as_u32(&fake_hasher.hash(b"NormalMethod2")) as u64
164+
super::as_u32(&fake_hasher.hash(b"1|NormalMethod2")) as u64
163165
);
164166
}
165167

frc42_dispatch/macros/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "frc42_macros"
3-
version = "0.2.0"
3+
version = "1.0.0"
44
license = "MIT OR Apache-2.0"
55
description = "Filecoin FRC-0042 calling convention procedural macros"
66
repository = "https://github.com/helix-onchain/filecoin/"
@@ -11,7 +11,7 @@ proc-macro = true
1111

1212
[dependencies]
1313
blake2b_simd = { version = "1.0.0" }
14-
frc42_hasher = { version = "0.2.0", path = "../hasher", features = ["no_sdk"] }
14+
frc42_hasher = { version = "1.0.0", path = "../hasher", features = ["no_sdk"] }
1515
proc-macro2 = "1.0"
1616
quote = "1.0"
1717
syn = { version = "1.0", features = ["full"] }

frc42_dispatch/macros/example/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies]
7-
frc42_macros = { version = "0.2.0", path = ".." }
7+
frc42_macros = { version = "1.0.0", path = ".." }
Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
use frc42_macros::method_hash;
22

33
fn main() {
4-
let str_hash = method_hash!("Method");
4+
assert_eq!(method_hash!("Method"), 0xa20642fc);
55

6-
assert_eq!(str_hash, 1253606847);
6+
// method names from the example token actor
7+
// numbers are hashed by the python script included in the main dispatch crate
8+
assert_eq!(method_hash!("Name"), 0x02ea015c);
9+
assert_eq!(method_hash!("Symbol"), 0x7adab63e);
10+
assert_eq!(method_hash!("TotalSupply"), 0x06da7a35);
11+
assert_eq!(method_hash!("BalanceOf"), 0x8710e1ac);
12+
assert_eq!(method_hash!("Allowance"), 0xfaa45236);
13+
assert_eq!(method_hash!("IncreaseAllowance"), 0x69ecb918);
14+
assert_eq!(method_hash!("DecreaseAllowance"), 0x5b286f21);
15+
assert_eq!(method_hash!("RevokeAllowance"), 0xa4d840b1);
16+
assert_eq!(method_hash!("Burn"), 0x5584159a);
17+
assert_eq!(method_hash!("TransferFrom"), 0xd7d4deed);
18+
assert_eq!(method_hash!("Transfer"), 0x04cbf732);
19+
assert_eq!(method_hash!("Mint"), 0x06f84ab2);
720
}

frc46_token/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ edition = "2021"
1010
[dependencies]
1111
anyhow = "1.0.56"
1212
cid = { version = "0.8.3", default-features = false, features = ["serde-codec"] }
13-
frc42_dispatch = { version = "0.3.0", path = "../frc42_dispatch" }
13+
frc42_dispatch = { version = "1.0.0", path = "../frc42_dispatch" }
1414
fvm_actor_utils = { version = "0.1.0", path = "../fvm_actor_utils" }
1515
fvm_ipld_blockstore = "0.1.1"
1616
fvm_ipld_hamt = "0.5.1"

fvm_actor_utils/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ edition = "2021"
1010
[dependencies]
1111
anyhow = "1.0.56"
1212
cid = { version = "0.8.3", default-features = false, features = ["serde-codec"] }
13-
frc42_dispatch = { version = "0.3.0", path = "../frc42_dispatch" }
13+
frc42_dispatch = { version = "1.0.0", path = "../frc42_dispatch" }
1414
fvm_ipld_blockstore = "0.1.1"
1515
fvm_ipld_encoding = "0.2.2"
1616
fvm_shared = "2.0.0-alpha.2"

testing/fil_token_integration/actors/basic_token_actor/src/lib.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -226,72 +226,72 @@ pub fn invoke(params: u32) -> u32 {
226226
// Method numbers calculated via fvm_dispatch_tools using CamelCase names derived from
227227
// the corresponding FRC46Token trait methods.
228228
match rest {
229-
4244593718 => {
229+
0x02ea015c => {
230230
// Name
231231
let name = token_actor.name();
232232
return_ipld(&name).unwrap()
233233
}
234-
3551111368 => {
234+
0x7adab63e => {
235235
// Symbol
236236
let symbol = token_actor.symbol();
237237
return_ipld(&symbol).unwrap()
238238
}
239-
2511420746 => {
239+
0x06da7a35 => {
240240
// TotalSupply
241241
let total_supply = token_actor.total_supply();
242242
return_ipld(&total_supply).unwrap()
243243
}
244-
1568445334 => {
244+
0x8710e1ac => {
245245
//BalanceOf
246246
let params = deserialize_params(params);
247247
let res = token_actor.balance_of(params).unwrap();
248248
return_ipld(&res).unwrap()
249249
}
250-
2804639308 => {
250+
0xfaa45236 => {
251251
// Allowance
252252
let params = deserialize_params(params);
253253
let res = token_actor.allowance(params).unwrap();
254254
return_ipld(&res).unwrap()
255255
}
256-
991449938 => {
256+
0x69ecb918 => {
257257
// IncreaseAllowance
258258
let params = deserialize_params(params);
259259
let res = token_actor.increase_allowance(params).unwrap();
260260
let cid = token_actor.util.flush().unwrap();
261261
sdk::sself::set_root(&cid).unwrap();
262262
return_ipld(&res).unwrap()
263263
}
264-
4218751446 => {
264+
0x5b286f21 => {
265265
// DecreaseAllowance
266266
let params = deserialize_params(params);
267267
let res = token_actor.decrease_allowance(params).unwrap();
268268
let cid = token_actor.util.flush().unwrap();
269269
sdk::sself::set_root(&cid).unwrap();
270270
return_ipld(&res).unwrap()
271271
}
272-
1691518633 => {
272+
0xa4d840b1 => {
273273
// RevokeAllowance
274274
let params = deserialize_params(params);
275275
token_actor.revoke_allowance(params).unwrap();
276276
let cid = token_actor.util.flush().unwrap();
277277
sdk::sself::set_root(&cid).unwrap();
278278
NO_DATA_BLOCK_ID
279279
}
280-
1924391931 => {
280+
0x5584159a => {
281281
// Burn
282282
let params = deserialize_params(params);
283283
let res = token_actor.burn(params).unwrap();
284284
let cid = token_actor.util.flush().unwrap();
285285
sdk::sself::set_root(&cid).unwrap();
286286
return_ipld(&res).unwrap()
287287
}
288-
401872942 => {
288+
0xd7d4deed => {
289289
// TransferFrom
290290
let params = deserialize_params(params);
291291
let res = token_actor.transfer_from(params).unwrap();
292292
return_ipld(&res).unwrap()
293293
}
294-
1303003700 => {
294+
0x04cbf732 => {
295295
// Transfer
296296
let params = deserialize_params(params);
297297
let res = token_actor.transfer(params).unwrap();
@@ -300,7 +300,7 @@ pub fn invoke(params: u32) -> u32 {
300300

301301
// Custom actor interface, these are author-defined methods that extend beyond the
302302
// FRC46 Token standard
303-
3839021839 => {
303+
0x06f84ab2 => {
304304
// Mint
305305
let params: MintParams = deserialize_params(params);
306306
let res = token_actor.mint(params).unwrap();

0 commit comments

Comments
 (0)