Просмотр исходного кода

Merge branch 'master' of github.com:darkrenaissance/darkfi

lunar-mining 3 лет назад
Родитель
Сommit
623bf9a295

+ 3 - 3
example/dao/src/contract/dao/exec/validate.rs

@@ -172,9 +172,9 @@ pub fn state_transition(
     if money_transfer_call_data.outputs[0].revealed.coin != Coin(call_data.coin_0) {
         return Err(Error::InvalidOutput)
     }
-    if money_transfer_call_data.outputs[1].revealed.coin != Coin(call_data.coin_1) {
-        return Err(Error::InvalidOutput)
-    }
+    //if money_transfer_call_data.outputs[1].revealed.coin != Coin(call_data.coin_1) {
+    //    return Err(Error::InvalidOutput)
+    //}
 
     // 2. sum of Money::transfer() calldata input_value_commits == our input value commit
     let mut input_value_commits = pallas::Point::identity();

+ 43 - 4
example/dao/src/main.rs

@@ -16,7 +16,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::{any::TypeId, time::Instant};
+use std::{any::{Any, TypeId}, time::Instant};
 
 use incrementalmerkletree::Tree;
 use log::debug;
@@ -29,6 +29,7 @@ use rand::rngs::OsRng;
 
 use darkfi::{
     crypto::{
+        coin::Coin,
         keypair::{Keypair, PublicKey, SecretKey},
         proof::{ProvingKey, VerifyingKey},
         types::{DrkSpendHook, DrkUserData, DrkValue},
@@ -1052,8 +1053,7 @@ async fn main() -> Result<()> {
                 serial: dao_serial,
                 coin_blind: dao_coin_blind,
                 spend_hook: *dao::exec::FUNC_ID,
-                // TODO: should be DAO bulla
-                user_data: proposal_bulla,
+                user_data: dao_bulla.0,
             },
         ],
     };
@@ -1062,7 +1062,7 @@ async fn main() -> Result<()> {
 
     let builder = dao::exec::wallet::Builder {
         proposal,
-        dao: dao_params,
+        dao: dao_params.clone(),
         yes_votes_value,
         all_votes_value,
         yes_votes_blind,
@@ -1103,6 +1103,45 @@ async fn main() -> Result<()> {
         assert_eq!(input.revealed.spend_hook, *dao::exec::FUNC_ID);
         let user_data_enc = poseidon_hash::<2>([dao_bulla.0, user_data_blind]);
         assert_eq!(input.revealed.user_data_enc, user_data_enc);
+
+        let dao_pubkey_coords = dao_params.public_key.0.to_affine().coordinates().unwrap();
+        let coin_1 = Coin(poseidon_hash::<8>([
+            *dao_pubkey_coords.x(),
+            *dao_pubkey_coords.y(),
+            pallas::Base::from(xdrk_supply - 1000),
+            xdrk_token_id,
+            dao_serial,
+            *dao::exec::FUNC_ID,
+            dao_bulla.0,
+            dao_coin_blind
+        ]));
+        debug!("coin_1: {:?}", coin_1);
+
+        let money_transfer_call_data = tx.func_calls[0].call_data.as_any();
+        let money_transfer_call_data =
+            money_transfer_call_data.downcast_ref::<money::transfer::validate::CallData>();
+        let money_transfer_call_data = money_transfer_call_data.unwrap();
+        assert_eq!(
+            money_transfer_call_data.type_id(),
+            TypeId::of::<money::transfer::validate::CallData>()
+        );
+        assert_eq!(money_transfer_call_data.outputs.len(), 2);
+        let money_transfer_coin_1 = &money_transfer_call_data.outputs[1].revealed.coin;
+        debug!("money::transfer() coin 1 = {:?}", money_transfer_coin_1);
+
+        let dao_exec_call_data = tx.func_calls[1].call_data.as_any();
+        let dao_exec_call_data =
+            dao_exec_call_data.downcast_ref::<dao::exec::validate::CallData>();
+        let dao_exec_call_data = dao_exec_call_data.unwrap();
+        assert_eq!(
+            dao_exec_call_data.type_id(),
+            TypeId::of::<dao::exec::validate::CallData>()
+        );
+        let dao_exec_coin_1 = &dao_exec_call_data.coin_1;
+        debug!("dao::exec() coin 1 = {:?}", dao_exec_coin_1);
+
+        assert_eq!(coin_1, *money_transfer_coin_1);
+        assert_eq!(coin_1, Coin(*dao_exec_coin_1));
     }
 
     //// Validator

+ 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)
 }