فهرست منبع

Remove usage of `seal_random` in favor of `instantiation_nonce` (#1199)

Cyrill Leutwiler 2 سال پیش
والد
کامیت
d2729bc877
4فایلهای تغییر یافته به همراه23 افزوده شده و 90 حذف شده
  1. 4 33
      src/emit/substrate/mod.rs
  2. 13 14
      src/emit/substrate/target.rs
  3. 2 1
      src/linker/wasm.rs
  4. 4 42
      tests/substrate.rs

+ 4 - 33
src/emit/substrate/mod.rs

@@ -9,7 +9,6 @@ use inkwell::AddressSpace;
 use inkwell::IntPredicate;
 use num_traits::ToPrimitive;
 use solang_parser::pt;
-use std::collections::HashMap;
 
 use crate::emit::functions::{abort_if_value_transfer, emit_functions, emit_initializer};
 use crate::emit::{Binary, TargetRuntime};
@@ -101,9 +100,7 @@ macro_rules! emit_context {
     };
 }
 
-pub struct SubstrateTarget {
-    unique_strings: HashMap<usize, usize>,
-}
+pub struct SubstrateTarget;
 
 impl SubstrateTarget {
     pub fn build<'a>(
@@ -145,9 +142,7 @@ impl SubstrateTarget {
         scratch.set_initializer(&context.i8_type().array_type(SCRATCH_SIZE).get_undef());
         binary.scratch = Some(scratch);
 
-        let mut target = SubstrateTarget {
-            unique_strings: HashMap::new(),
-        };
+        let mut target = SubstrateTarget;
 
         target.declare_externals(&binary);
 
@@ -174,7 +169,7 @@ impl SubstrateTarget {
             "seal_value_transferred",
             "seal_minimum_balance",
             "seal_weight_to_fee",
-            "seal_random",
+            "instantiation_nonce",
             "seal_address",
             "seal_balance",
             "seal_block_number",
@@ -266,7 +261,7 @@ impl SubstrateTarget {
         external!("seal_hash_sha2_256", void_type, u8_ptr, u32_val, u8_ptr);
         external!("seal_hash_blake2_128", void_type, u8_ptr, u32_val, u8_ptr);
         external!("seal_hash_blake2_256", void_type, u8_ptr, u32_val, u8_ptr);
-        external!("seal_random", void_type, u8_ptr, u32_val, u8_ptr, u32_ptr);
+        external!("instantiation_nonce", i64_type,);
         external!(
             "seal_set_storage",
             i32_type,
@@ -1795,30 +1790,6 @@ impl SubstrateTarget {
             _ => unreachable!(),
         }
     }
-
-    /// Create a unique salt each time this function is called.
-    fn contract_unique_salt<'x>(
-        &mut self,
-        binary: &'x Binary,
-        binary_no: usize,
-        ns: &ast::Namespace,
-    ) -> (PointerValue<'x>, IntValue<'x>) {
-        let counter = *self.unique_strings.get(&binary_no).unwrap_or(&0);
-
-        let binary_name = &ns.contracts[binary_no].name;
-
-        let unique = format!("{binary_name}-{counter}");
-
-        let salt = binary.emit_global_string(
-            &format!("salt_{binary_name}_{counter}"),
-            blake2_rfc::blake2b::blake2b(32, &[], unique.as_bytes()).as_bytes(),
-            true,
-        );
-
-        self.unique_strings.insert(binary_no, counter + 1);
-
-        (salt, binary.context.i32_type().const_int(32, false))
-    }
 }
 
 /// Print the return code of API calls to the debug buffer.

+ 13 - 14
src/emit/substrate/target.rs

@@ -1089,22 +1089,21 @@ impl<'a> TargetRuntime<'a> for SubstrateTarget {
 
         // salt
         let salt_buf =
-            binary.build_alloca(function, binary.context.i8_type().array_type(36), "salt");
+            binary.build_alloca(function, binary.context.i8_type().array_type(32), "salt");
         let salt_len = i32_const!(32);
 
-        if let Some(salt) = contract_args.salt {
-            binary.builder.build_store(salt_buf, salt);
-        } else {
-            let (ptr, len) = self.contract_unique_salt(binary, contract_no, ns);
-
-            binary.builder.build_store(scratch_len, i32_const!(36));
-
-            call!(
-                "seal_random",
-                &[ptr.into(), len.into(), salt_buf.into(), scratch_len.into()],
-                "random"
-            );
-        }
+        let salt = contract_args.salt.unwrap_or_else(|| {
+            let nonce = call!("instantiation_nonce", &[], "instantiation_nonce_ext")
+                .try_as_basic_value()
+                .left()
+                .unwrap()
+                .into_int_value();
+            let i256_t = binary.context.custom_width_int_type(256);
+            binary
+                .builder
+                .build_int_z_extend_or_bit_cast(nonce, i256_t, "instantiation_nonce")
+        });
+        binary.builder.build_store(salt_buf, salt);
 
         let encoded_args = binary.vector_bytes(encoded_args);
 

+ 2 - 1
src/linker/wasm.rs

@@ -76,11 +76,12 @@ pub fn link(input: &[u8], name: &str) -> Vec<u8> {
                     | "seal_get_storage"
                     | "seal_instantiate"
                     | "seal_terminate"
-                    | "seal_random"
                     | "seal_call" => "seal1",
                     _ => "seal0",
                 };
                 *imports[ind].module_mut() = module_name.to_owned();
+            } else if imports[ind].field() == "instantiation_nonce" {
+                *imports[ind].module_mut() = "seal0".to_owned();
             }
 
             ind += 1;

+ 4 - 42
tests/substrate.rs

@@ -69,7 +69,7 @@ enum SubstrateExternal {
     seal_instantiate,
     seal_value_transferred,
     seal_minimum_balance,
-    seal_random,
+    instantiation_nonce,
     seal_address,
     seal_balance,
     seal_terminate,
@@ -435,46 +435,8 @@ impl Externals for MockSubstrate {
 
                 Ok(Some(RuntimeValue::I32(0)))
             }
-            Some(SubstrateExternal::seal_random) => {
-                let data_ptr: u32 = args.nth_checked(0)?;
-                let len: u32 = args.nth_checked(1)?;
-                let dest_ptr: u32 = args.nth_checked(2)?;
-                let len_ptr: u32 = args.nth_checked(3)?;
-
-                let mut buf = Vec::new();
-                buf.resize(len as usize, 0u8);
-
-                if let Err(e) = self.vm.memory.get_into(data_ptr, &mut buf) {
-                    panic!("seal_random: {e}");
-                }
-
-                let mut hash = [0u8; 32];
-
-                hash.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], &buf).as_bytes());
-
-                println!("seal_random: {} {}", hex::encode(buf), hex::encode(hash));
-
-                let len = self
-                    .vm
-                    .memory
-                    .get_value::<u32>(len_ptr)
-                    .expect("seal_random len_ptr should be valid");
-
-                assert!(
-                    (len as usize) >= hash.len(),
-                    "seal_random dest buffer is too small"
-                );
-
-                if let Err(e) = self.vm.memory.set(dest_ptr, &hash) {
-                    panic!("seal_random: {e}");
-                }
-
-                self.vm
-                    .memory
-                    .set_value(len_ptr, hash.len() as u32)
-                    .expect("seal_random len_ptr should be valid");
-
-                Ok(None)
+            Some(SubstrateExternal::instantiation_nonce) => {
+                Ok(Some(RuntimeValue::I64(self.accounts.len() as i64)))
             }
             Some(SubstrateExternal::seal_call) => {
                 let flags: u32 = args.nth_checked(0)?;
@@ -910,7 +872,7 @@ impl ModuleImportResolver for MockSubstrate {
             "seal_instantiate" => SubstrateExternal::seal_instantiate,
             "seal_value_transferred" => SubstrateExternal::seal_value_transferred,
             "seal_minimum_balance" => SubstrateExternal::seal_minimum_balance,
-            "seal_random" => SubstrateExternal::seal_random,
+            "instantiation_nonce" => SubstrateExternal::instantiation_nonce,
             "seal_address" => SubstrateExternal::seal_address,
             "seal_balance" => SubstrateExternal::seal_balance,
             "seal_terminate" => SubstrateExternal::seal_terminate,