From 4a02be4798604630699507c7b80016d6dfde6712 Mon Sep 17 00:00:00 2001 From: Hoon <48665813+sh-cha@users.noreply.github.com> Date: Tue, 14 May 2024 16:19:36 +0900 Subject: [PATCH] add keccak (#47) * add keccak * rollback dylibs --- Cargo.toml | 1 + crates/gas/src/gas_params/keccak.rs | 12 ++++ crates/gas/src/gas_params/mod.rs | 1 + crates/gas/src/initia.rs | 10 ++++ crates/natives/Cargo.toml | 1 + crates/natives/src/keccak.rs | 56 ++++++++++++++++++ crates/natives/src/lib.rs | 2 + crates/types/src/module.rs | 8 ++- precompile/binaries/minlib/keccak.mv | Bin 0 -> 91 bytes precompile/binaries/stdlib/keccak.mv | Bin 0 -> 91 bytes .../modules/initia_stdlib/sources/keccak.move | 36 +++++++++++ .../minitia_stdlib/sources/keccak.move | 36 +++++++++++ 12 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 crates/gas/src/gas_params/keccak.rs create mode 100644 crates/natives/src/keccak.rs create mode 100644 precompile/binaries/minlib/keccak.mv create mode 100644 precompile/binaries/stdlib/keccak.mv create mode 100644 precompile/modules/initia_stdlib/sources/keccak.move create mode 100644 precompile/modules/minitia_stdlib/sources/keccak.move diff --git a/Cargo.toml b/Cargo.toml index 5517c982..4483298b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,6 +102,7 @@ base64 = "0.21.7" bigdecimal = "0.4" bech32 = "0.11" triomphe = "0.1.9" +tiny-keccak = { version = "2.0.2", features = ["keccak", "sha3"] } # Note: the BEGIN and END comments below are required for external tooling. Do not remove. # BEGIN MOVE DEPENDENCIES diff --git a/crates/gas/src/gas_params/keccak.rs b/crates/gas/src/gas_params/keccak.rs new file mode 100644 index 00000000..e45787b2 --- /dev/null +++ b/crates/gas/src/gas_params/keccak.rs @@ -0,0 +1,12 @@ +use move_core_types::gas_algebra::{InternalGas, InternalGasPerByte}; + +#[derive(Debug, Clone)] +pub struct Keccak256GasParameters { + pub base: InternalGas, + pub per_byte: InternalGasPerByte, +} + +#[derive(Debug, Clone)] +pub struct GasParameters { + pub keccak256: Keccak256GasParameters, +} diff --git a/crates/gas/src/gas_params/mod.rs b/crates/gas/src/gas_params/mod.rs index 149ffbc3..d2730534 100644 --- a/crates/gas/src/gas_params/mod.rs +++ b/crates/gas/src/gas_params/mod.rs @@ -8,6 +8,7 @@ pub mod crypto; pub mod event; pub mod from_bcs; pub mod json; +pub mod keccak; pub mod object; pub mod oracle; pub mod query; diff --git a/crates/gas/src/initia.rs b/crates/gas/src/initia.rs index 66c4ad72..ca843bb5 100644 --- a/crates/gas/src/initia.rs +++ b/crates/gas/src/initia.rs @@ -69,6 +69,9 @@ crate::natives::define_gas_parameters_for_natives!(GasParameters, "initia", [ // TODO(Gas): the on-chain name is wrong... [.event.write_module_event_to_store.per_abstract_value_unit, "event.write_module_event_to_store.per_abstract_memory_unit", 61], + [.keccak.keccak256.base, "keccak.keccak256.base", 14704], + [.keccak.keccak256.per_byte, "keccak.keccak256.per_byte", 165], + [.object.exists_at.base, "object.exists_at.base", 919], [.object.exists_at.per_byte_loaded, "object.exists_at.per_byte_loaded", 183], [.object.exists_at.per_item_loaded, "object.exists_at.per_item_loaded", 1470], @@ -134,6 +137,7 @@ pub struct GasParameters { pub base64: base64::GasParameters, pub crypto: crypto::GasParameters, pub event: event::GasParameters, + pub keccak: keccak::GasParameters, pub object: object::GasParameters, pub transaction_context: transaction_context::GasParameters, pub staking: staking::GasParameters, @@ -329,6 +333,12 @@ impl GasParameters { per_byte: 0.into(), }, }, + keccak: keccak::GasParameters { + keccak256: keccak::Keccak256GasParameters { + base: 0.into(), + per_byte: 0.into(), + }, + }, object: object::GasParameters { exists_at: object::ExistsAtGasParameters { base: 0.into(), diff --git a/crates/natives/Cargo.toml b/crates/natives/Cargo.toml index fa2bc242..7a19b0a0 100644 --- a/crates/natives/Cargo.toml +++ b/crates/natives/Cargo.toml @@ -34,6 +34,7 @@ move-stdlib = { workspace = true } bigdecimal = { workspace = true } base64 = { workspace = true } +tiny-keccak = { workspace = true } [dev-dependencies] serial_test = { workspace = true } diff --git a/crates/natives/src/keccak.rs b/crates/natives/src/keccak.rs new file mode 100644 index 00000000..418a2a04 --- /dev/null +++ b/crates/natives/src/keccak.rs @@ -0,0 +1,56 @@ +// Copyright © Aptos Foundation + +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use move_core_types::gas_algebra::NumBytes; +use move_vm_runtime::native_functions::NativeFunction; +use move_vm_types::{loaded_data::runtime_types::Type, values::Value}; +use smallvec::{smallvec, SmallVec}; +use std::collections::VecDeque; +use tiny_keccak::{Hasher as KeccakHasher, Keccak}; + +use crate::{ + interface::{RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeResult}, + safely_pop_arg, +}; + +/*************************************************************************************************** + * native fun keccak256 + * + * gas cost: base_cost + unit_cost * input_length + * + **************************************************************************************************/ + +fn native_keccak256( + context: &mut SafeNativeContext, + mut _ty_args: Vec, + mut args: VecDeque, +) -> SafeNativeResult> { + debug_assert!(_ty_args.is_empty()); + debug_assert!(args.len() == 1); + + let gas_params = &context.native_gas_params.initia_stdlib.keccak.keccak256; + + let bytes = safely_pop_arg!(args, Vec); + + context.charge(gas_params.base + gas_params.per_byte * NumBytes::new(bytes.len() as u64))?; + + let mut hasher = Keccak::v256(); + hasher.update(&bytes); + let mut output = [0u8; 32]; + hasher.finalize(&mut output); + + Ok(smallvec![Value::vector_u8(output)]) +} +/*************************************************************************************************** + * module + **************************************************************************************************/ +pub fn make_all( + builder: &SafeNativeBuilder, +) -> impl Iterator + '_ { + let natives = [("keccak256", native_keccak256 as RawSafeNative)]; + + builder.make_named_natives(natives) +} diff --git a/crates/natives/src/lib.rs b/crates/natives/src/lib.rs index ab9fdc94..ba0a8762 100644 --- a/crates/natives/src/lib.rs +++ b/crates/natives/src/lib.rs @@ -16,6 +16,7 @@ pub mod debug; pub mod event; pub mod from_bcs; pub mod json; +pub mod keccak; pub mod move_stdlib; pub mod object; pub mod oracle; @@ -58,6 +59,7 @@ pub fn initia_move_natives( add_natives_from_module!("type_info", type_info::make_all(builder)); add_natives_from_module!("from_bcs", from_bcs::make_all(builder)); add_natives_from_module!("base64", base64::make_all(builder)); + add_natives_from_module!("keccak", keccak::make_all(builder)); add_natives_from_module!("staking", staking::make_all(builder)); add_natives_from_module!("cosmos", cosmos::make_all(builder)); add_natives_from_module!("object", object::make_all(builder)); diff --git a/crates/types/src/module.rs b/crates/types/src/module.rs index 3cad5eb1..465ac98b 100644 --- a/crates/types/src/module.rs +++ b/crates/types/src/module.rs @@ -87,7 +87,13 @@ impl ModuleBundle { let mut order = vec![]; let mut order_set = BTreeSet::new(); for id in map.keys() { - sort_by_deps(&map, &mut order, &mut order_set, &mut BTreeSet::new(), id.clone())?; + sort_by_deps( + &map, + &mut order, + &mut order_set, + &mut BTreeSet::new(), + id.clone(), + )?; } let mut codes = vec![]; diff --git a/precompile/binaries/minlib/keccak.mv b/precompile/binaries/minlib/keccak.mv new file mode 100644 index 0000000000000000000000000000000000000000..79ec8e0d5d2111d6e839d887618f1b0344add328 GIT binary patch literal 91 zcmZ1|^O~EDfq{XIk%5VsiItU|nVn0JLt25ynguAz2*O-UY}u*F$%)yV5X#8Z3@D5b LFfuSQF)#oC(l7`P literal 0 HcmV?d00001 diff --git a/precompile/binaries/stdlib/keccak.mv b/precompile/binaries/stdlib/keccak.mv new file mode 100644 index 0000000000000000000000000000000000000000..79ec8e0d5d2111d6e839d887618f1b0344add328 GIT binary patch literal 91 zcmZ1|^O~EDfq{XIk%5VsiItU|nVn0JLt25ynguAz2*O-UY}u*F$%)yV5X#8Z3@D5b LFfuSQF)#oC(l7`P literal 0 HcmV?d00001 diff --git a/precompile/modules/initia_stdlib/sources/keccak.move b/precompile/modules/initia_stdlib/sources/keccak.move new file mode 100644 index 00000000..3f808a45 --- /dev/null +++ b/precompile/modules/initia_stdlib/sources/keccak.move @@ -0,0 +1,36 @@ +/// Cryptographic hashes: +/// - Keccak-256: see https://keccak.team/keccak.html +/// +/// In addition, SHA2-256 and SHA3-256 are available in `std::hash`. Note that SHA3-256 is a variant of Keccak: it is +/// NOT the same as Keccak-256. +module initia_std::keccak { + /// Returns the Keccak-256 hash of `bytes`. + native public fun keccak256(byte: vector): vector; + // + // Testing + // + + #[test] + fun keccak256_test() { + let inputs = vector[ + b"testing", + b"", + ]; + + let outputs = vector[ + x"5f16f4c7f149ac4f9510d9cf8cf384038ad348b3bcdc01915f95de12df9d1b02", + x"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + ]; + + let i = 0; + while (i < std::vector::length(&inputs)) { + let input = *std::vector::borrow(&inputs, i); + let hash_expected = *std::vector::borrow(&outputs, i); + let hash = keccak256(input); + + assert!(hash_expected == hash, 1); + + i = i + 1; + }; + } +} \ No newline at end of file diff --git a/precompile/modules/minitia_stdlib/sources/keccak.move b/precompile/modules/minitia_stdlib/sources/keccak.move new file mode 100644 index 00000000..d10fb80c --- /dev/null +++ b/precompile/modules/minitia_stdlib/sources/keccak.move @@ -0,0 +1,36 @@ +/// Cryptographic hashes: +/// - Keccak-256: see https://keccak.team/keccak.html +/// +/// In addition, SHA2-256 and SHA3-256 are available in `std::hash`. Note that SHA3-256 is a variant of Keccak: it is +/// NOT the same as Keccak-256. +module minitia_std::keccak { + /// Returns the Keccak-256 hash of `bytes`. + native public fun keccak256(byte: vector): vector; + // + // Testing + // + + #[test] + fun keccak256_test() { + let inputs = vector[ + b"testing", + b"", + ]; + + let outputs = vector[ + x"5f16f4c7f149ac4f9510d9cf8cf384038ad348b3bcdc01915f95de12df9d1b02", + x"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + ]; + + let i = 0; + while (i < std::vector::length(&inputs)) { + let input = *std::vector::borrow(&inputs, i); + let hash_expected = *std::vector::borrow(&outputs, i); + let hash = keccak256(input); + + assert!(hash_expected == hash, 1); + + i = i + 1; + }; + } +} \ No newline at end of file