parazyd 3 лет назад
Родитель
Сommit
96b159c00c

+ 1 - 1
example/smart-contract/Makefile

@@ -36,4 +36,4 @@ test: all
 clean:
 	rm -f $(PROOF_BIN) $(WASM_BIN)
 
-.PHONY: all test clean
+.PHONY: $(WASM_BIN) all test clean

+ 3 - 3
src/blockchain/contractstore.rs

@@ -17,7 +17,7 @@
  */
 
 use darkfi_sdk::crypto::ContractId;
-use darkfi_serial::deserialize;
+use darkfi_serial::{deserialize, serialize};
 
 use crate::{
     Error::{ContractAlreadyInitialized, ContractNotFound, ContractStateNotFound},
@@ -41,7 +41,7 @@ impl ContractStore {
         contract_id: &ContractId,
         tree_name: &str,
     ) -> Result<sled::Tree> {
-        let contract_id_bytes = contract_id.to_bytes();
+        let contract_id_bytes = serialize(contract_id);
 
         // If the db was never initialized, it should not be in here.
         if self.0.contains_key(&contract_id_bytes)? {
@@ -67,7 +67,7 @@ impl ContractStore {
         contract_id: &ContractId,
         tree_name: &str,
     ) -> Result<sled::Tree> {
-        let contract_id_bytes = contract_id.to_bytes();
+        let contract_id_bytes = serialize(contract_id);
 
         // A guard to make sure we went through init()
         if !self.0.contains_key(&contract_id_bytes)? {

+ 30 - 19
src/runtime/import/db.rs

@@ -17,7 +17,9 @@
  */
 
 use darkfi_sdk::crypto::ContractId;
+use darkfi_serial::{deserialize, Decodable};
 use log::error;
+use std::io::Cursor;
 use wasmer::{FunctionEnvMut, WasmPtr};
 
 use crate::runtime::vm_runtime::{ContractSection, Env};
@@ -49,30 +51,39 @@ pub(crate) fn db_init(ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32) -> i
             let contracts = &env.blockchain.contracts;
             let contract_id = &env.contract_id;
 
-            /*
-            let Ok(cid_slice) = cid_ptr.slice(&memory_view, 32) else {
-                error!(target: "wasm_runtime::db_init", "Failed to read contract id from ptr");
+            let Ok(mem_slice) = ptr.slice(&memory_view, len) else {
+                error!(target: "wasm_runtime::db_init", "Failed to make slice from ptr");
                 return -2
             };
 
-            let Ok(cid_bytes) = cid_slice.read_to_vec() else {
-                error!(target: "wasm_runtime::db_init", "Failed to read slice to vec in db_init");
+            let mut buf = vec![0_u8; len as usize];
+            if let Err(e) = mem_slice.read_slice(&mut buf) {
+                error!(target: "wasm_runtime::db_init", "Failed to read from memory slice");
                 return -2
             };
 
-            // FIXME: Could panic
-            let cid = ContractId::from_bytes(cid_bytes.try_into().unwrap());
+            let mut buf_reader = Cursor::new(buf);
+
+            let cid: ContractId = match Decodable::decode(&mut buf_reader) {
+                Ok(v) => v,
+                Err(e) => {
+                    error!(target: "wasm_runtime::db_init", "Failed to decode ContractId: {}", e);
+                    return -2
+                }
+            };
+
+            let db_name: String = match Decodable::decode(&mut buf_reader) {
+                Ok(v) => v,
+                Err(e) => {
+                    error!(target: "wasm_runtime::db_init", "Failed to decode db_name: {}", e);
+                    return -2
+                }
+            };
 
             if &cid != contract_id {
                 error!(target: "wasm_runtime::db_init", "Unauthorized ContractId for db_init");
                 return -1
             }
-            */
-
-            let Ok(db_name) = ptr.read_utf8_string(&memory_view, len) else {
-                error!(target: "wasm_runtime::db_init", "Failed to read string from VM memory");
-                return -2
-            };
 
             let tree_handle = match contracts.init(db, contract_id, &db_name) {
                 Ok(v) => v,
@@ -134,12 +145,12 @@ pub(crate) fn db_get(ctx: FunctionEnvMut<Env>) -> i32 {
     }
 }
 
-/// Only update() can call this. Starts an atomic transaction.
+/// Only update() can call this. Set a value within the transaction.
 ///
 /// ```
-///     tx_handle = db_begin_tx();
+///     db_set(tx_handle, key, value);
 /// ```
-pub(crate) fn db_begin_tx(ctx: FunctionEnvMut<Env>) -> i32 {
+pub(crate) fn db_set(ctx: FunctionEnvMut<Env>) -> i32 {
     let env = ctx.data();
     match env.contract_section {
         ContractSection::Deploy | ContractSection::Update => 0,
@@ -147,12 +158,12 @@ pub(crate) fn db_begin_tx(ctx: FunctionEnvMut<Env>) -> i32 {
     }
 }
 
-/// Only update() can call this. Set a value within the transaction.
+/// Only update() can call this. Starts an atomic transaction.
 ///
 /// ```
-///     db_set(tx_handle, key, value);
+///     tx_handle = db_begin_tx();
 /// ```
-pub(crate) fn db_set(ctx: FunctionEnvMut<Env>) -> i32 {
+pub(crate) fn db_begin_tx(ctx: FunctionEnvMut<Env>) -> i32 {
     let env = ctx.data();
     match env.contract_section {
         ContractSection::Deploy | ContractSection::Update => 0,

+ 3 - 2
src/runtime/vm_runtime.rs

@@ -22,6 +22,7 @@ use std::{
 };
 
 use darkfi_sdk::{crypto::ContractId, entrypoint};
+use darkfi_serial::serialize;
 use log::{debug, info};
 use wasmer::{
     imports, wasmparser::Operator, AsStoreRef, CompilerConfig, Function, FunctionEnv, Instance,
@@ -257,7 +258,7 @@ impl Runtime {
         env_mut.contract_section = ContractSection::Null;
         let retdata = match env_mut.contract_return_data.take() {
             Some(retdata) => retdata,
-            None => Vec::new()
+            None => Vec::new(),
         };
 
         let retval = match ret[0] {
@@ -355,7 +356,7 @@ impl Runtime {
     /// We keep the same payload as a slice of bytes, and prepend it with a
     /// little-endian u64 to tell the payload's length.
     fn serialize_payload(cid: &ContractId, payload: &[u8]) -> Vec<u8> {
-        let ser_cid = cid.to_bytes();
+        let ser_cid = serialize(cid);
         let payload_len = payload.len();
         let mut out = Vec::with_capacity(ser_cid.len() + 8 + payload_len);
         out.extend_from_slice(&ser_cid);

+ 2 - 5
src/sdk/src/crypto/contract_id.rs

@@ -16,9 +16,10 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use darkfi_serial::{SerialDecodable, SerialEncodable};
 use pasta_curves::{group::ff::PrimeField, pallas};
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, SerialEncodable, SerialDecodable)]
 pub struct ContractId(pallas::Base);
 
 impl ContractId {
@@ -30,10 +31,6 @@ impl ContractId {
         self.0
     }
 
-    pub fn to_bytes(&self) -> [u8; 32] {
-        self.0.to_repr()
-    }
-
     pub fn from_bytes(x: [u8; 32]) -> Self {
         // FIXME: Handle Option
         Self(pallas::Base::from_repr(x).unwrap())

+ 8 - 7
src/sdk/src/db.rs

@@ -1,3 +1,5 @@
+use darkfi_serial::Encodable;
+
 use super::{
     crypto::ContractId,
     error::{ContractError, GenericResult},
@@ -15,13 +17,12 @@ type TxHandle = u32;
 pub fn db_init(contract_id: ContractId, db_name: &str) -> GenericResult<DbHandle> {
     #[cfg(target_arch = "wasm32")]
     unsafe {
-        println!("sdk/src/db.rs:db_init() BEGIN");
-        let ret = db_init_(
-            //contract_id.to_bytes().as_ptr(),
-            //32_u32,
-            db_name.as_ptr(),
-            db_name.len() as u32,
-        );
+        let mut len = 0;
+        let mut buf = vec![];
+        len += contract_id.encode(&mut buf)?;
+        len += db_name.to_string().encode(&mut buf)?;
+
+        let ret = db_init_(buf.as_ptr(), len as u32);
 
         if ret < 0 {
             match ret {

+ 3 - 0
src/sdk/src/entrypoint.rs

@@ -84,5 +84,8 @@ pub unsafe fn deserialize<'a>(input: *mut u8) -> (ContractId, &'a [u8]) {
     offset += size_of::<u64>();
     let instruction_data = { from_raw_parts(input.add(offset), instruction_data_len) };
 
+    // FIXME: ContractId recovery should use proper serialization, and also
+    //        there should be a Result<>; we can match on it in the macros
+    //        above and return errors if needed.
     (ContractId::from_bytes(contract_id_slice.try_into().unwrap()), instruction_data)
 }