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

wasm: add example passing tx into state_transition()

x 3 лет назад
Родитель
Сommit
87be69f103

+ 7 - 3
example/smart-contract/src/lib.rs

@@ -6,9 +6,10 @@ use darkfi_sdk::{
     initialize, msg,
     pasta::pallas,
     state::{nullifier_exists, set_update},
+    tx::Transaction,
     update_state,
 };
-use darkfi_serial::{deserialize, serialize, SerialDecodable, SerialEncodable};
+use darkfi_serial::{deserialize, serialize, SerialDecodable, SerialEncodable, ReadExt, Decodable};
 
 /// Available functions for this contract.
 /// We identify them with the first byte passed in through the payload.
@@ -30,7 +31,7 @@ impl From<u8> for Function {
 
 // An example of deserializing the payload into a struct
 #[derive(SerialEncodable, SerialDecodable)]
-pub struct FooArgs {
+pub struct FooCallData {
     pub a: u64,
     pub b: u64,
 }
@@ -71,7 +72,9 @@ fn process_instruction(ix: &[u8]) -> ContractResult {
         Function::Foo => {
             let tx_data = &ix[1..];
             // ...
-            let args: FooArgs = deserialize(tx_data)?;
+            let (func_call_index, tx): (u32, Transaction) = deserialize(tx_data)?;
+            let call_data: FooCallData = deserialize(&tx.func_calls[func_call_index as usize].call_data)?;
+            msg!("call_data {{ a: {}, b: {} }}", call_data.a, call_data.b);
             // ...
             let update = FooUpdate { name: "john_doe".to_string(), age: 110 };
 
@@ -82,6 +85,7 @@ fn process_instruction(ix: &[u8]) -> ContractResult {
 
             // Example: try to get a value from the db
             let db_handle = db_lookup("wagies")?;
+            // FIXME: this is just empty right now
             let age_data = db_get(db_handle, "jason_gulag".as_bytes())?;
             msg!("wagie age data: {:?}", age_data);
         }

+ 23 - 7
example/smart-contract/tests/runtime.rs

@@ -21,10 +21,10 @@ use darkfi::{
     runtime::{util::serialize_payload, vm_runtime::Runtime},
     Result,
 };
-use darkfi_sdk::{crypto::nullifier::Nullifier, pasta::pallas};
-use darkfi_serial::serialize;
+use darkfi_sdk::{crypto::nullifier::Nullifier, pasta::pallas, tx::{Transaction, FuncCall}};
+use darkfi_serial::{serialize, Encodable, WriteExt};
 
-use smart_contract::FooArgs;
+use smart_contract::FooCallData;
 
 #[test]
 fn run_contract() -> Result<()> {
@@ -57,10 +57,26 @@ fn run_contract() -> Result<()> {
     // =============================================
     // Build some kind of payload to show an example
     // =============================================
-    let args = FooArgs { a: 777, b: 666 };
-    // Prepend the func id
-    let mut payload = vec![0x00];
-    payload.extend_from_slice(&serialize(&args));
+    let tx = Transaction {
+        func_calls: vec![
+            FuncCall {
+                contract_id: pallas::Base::from(110),
+                func_id: pallas::Base::from(4),
+                call_data: serialize(&FooCallData { a: 777, b: 666 }),
+                proofs: Vec::new()
+            }
+        ],
+        signatures: Vec::new()
+    };
+    let func_call_index: u32 = 0;
+
+    let mut payload = Vec::new();
+    // Prepend the func id = 0x00
+    // Selects which path executes in the contract.
+    payload.write_u8(0x00);
+    // Write the actual payload data
+    payload.write_u32(func_call_index);
+    tx.encode(&mut payload)?;
 
     // ============================================================
     // Serialize the payload into the runtime format and execute it

+ 3 - 3
src/runtime/import/db.rs

@@ -31,7 +31,7 @@ pub(crate) fn db_init(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32)
                 }
                 Err(_) => {
                     error!(target: "wasm_runtime::drk_log", "Failed to read UTF-8 string from VM memory");
-                    return -2;
+                    return -2
                 }
             }
             0
@@ -56,11 +56,11 @@ pub(crate) fn db_lookup(mut ctx: FunctionEnvMut<Env>, ptr: WasmPtr<u8>, len: u32
             match ptr.read_utf8_string(&memory_view, len) {
                 Ok(db_name) => {
                     // db_name = blake3_hash(contract_id, db_name)
-                    return 110;
+                    return 110
                 }
                 Err(_) => {
                     error!(target: "wasm_runtime::drk_log", "Failed to read UTF-8 string from VM memory");
-                    return -2;
+                    return -2
                 }
             }
             0

+ 62 - 62
src/runtime/vm_runtime.rs

@@ -141,68 +141,68 @@ impl Runtime {
         );
 
         let imports = imports! {
-                "env" => {
-                    "drk_log_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::util::drk_log,
-                    ),
-
-                    "nullifier_exists_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::chain_state::nullifier_exists,
-                    ),
-
-                    "is_valid_merkle_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::chain_state::is_valid_merkle,
-                    ),
-
-                    "set_update_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::chain_state::set_update,
-                    ),
-
-                    "db_init_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::db::db_init,
-                    ),
-
-                    "db_lookup_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::db::db_lookup,
-                    ),
-
-                    "db_get_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::db::db_get,
-                    ),
-
-                    "db_begin_tx_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::db::db_begin_tx,
-                    ),
-
-                    "db_set_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::db::db_set,
-                    ),
-
-                    "db_end_tx_" => Function::new_typed_with_env(
-                        &mut store,
-                        &ctx,
-                        import::db::db_end_tx,
-                    ),
-                }
-            };
+            "env" => {
+                "drk_log_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::util::drk_log,
+                ),
+
+                "nullifier_exists_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::chain_state::nullifier_exists,
+                ),
+
+                "is_valid_merkle_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::chain_state::is_valid_merkle,
+                ),
+
+                "set_update_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::chain_state::set_update,
+                ),
+
+                "db_init_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::db::db_init,
+                ),
+
+                "db_lookup_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::db::db_lookup,
+                ),
+
+                "db_get_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::db::db_get,
+                ),
+
+                "db_begin_tx_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::db::db_begin_tx,
+                ),
+
+                "db_set_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::db::db_set,
+                ),
+
+                "db_end_tx_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::db::db_end_tx,
+                ),
+            }
+        };
 
         debug!(target: "wasm_runtime::new", "Instantiating module");
         let instance = Instance::new(&mut store, &module, &imports)?;

+ 1 - 1
src/sdk/src/db.rs

@@ -36,7 +36,7 @@ pub fn db_lookup(db_name: &str) -> GenericResult<DbHandle> {
                     unreachable!();
                 }
                 Ok(handle as u32)
-            },
+            }
             -1 => Err(ContractError::CallerAccessDenied),
             -2 => Err(ContractError::DbNotFound),
         }

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

@@ -36,3 +36,6 @@ pub mod crypto;
 
 /// Functions for state queries
 pub mod state;
+
+/// Transaction structure
+pub mod tx;

+ 26 - 0
src/sdk/src/tx.rs

@@ -0,0 +1,26 @@
+use darkfi_serial::{SerialDecodable, SerialEncodable};
+use pasta_curves::{
+    group::ff::{Field, PrimeField},
+    pallas,
+};
+
+type ContractId = pallas::Base;
+type FuncId = pallas::Base;
+
+#[derive(SerialEncodable, SerialDecodable)]
+pub struct Transaction {
+    pub func_calls: Vec<FuncCall>,
+    // This should also be bytes?
+    //pub signatures: Vec<Signature>,
+    pub signatures: Vec<Vec<u8>>,
+}
+
+#[derive(SerialEncodable, SerialDecodable)]
+pub struct FuncCall {
+    pub contract_id: ContractId,
+    pub func_id: FuncId,
+    pub call_data: Vec<u8>,
+    // This should also be bytes?
+    //pub proofs: Vec<Proof>,
+    pub proofs: Vec<Vec<u8>>,
+}