Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dan/wasm): implement basic wasm module engine calls #4350

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion dan_layer/common_types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ license = "BSD-3-Clause"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tari_common = { path = "../../common", features = ["build"] }
tari_common_types = { path = "../../base_layer/common_types" }

borsh = "0.9.3"
prost = "0.9"
prost-types = "0.9"
tari_common = { path = "../../common", features = ["build"] }

[build-dependencies]
tari_common = { path = "../../common", features = ["build"] }
70 changes: 70 additions & 0 deletions dan_layer/common_types/src/hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2022. The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::{io, io::Write};

use borsh::{BorshDeserialize, BorshSerialize};
use tari_common_types::types::FixedHash;

// This is to avoid adding borsh as a dependency in common types (and therefore every application).
// TODO: Either this becomes the standard Hash type for the dan layer, or add borsh support to FixedHash.
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Hash(FixedHash);

impl Hash {
pub fn into_inner(self) -> FixedHash {
self.0
}
}

impl From<FixedHash> for Hash {
fn from(hash: FixedHash) -> Self {
Self(hash)
}
}

impl BorshSerialize for Hash {
fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
(*self.0).serialize(writer)
}
}

impl BorshDeserialize for Hash {
fn deserialize(buf: &mut &[u8]) -> io::Result<Self> {
let hash = <[u8; 32] as BorshDeserialize>::deserialize(buf)?;
Ok(Hash(hash.into()))
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn serialize_deserialize() {
let hash = Hash::default();
let mut buf = Vec::new();
hash.serialize(&mut buf).unwrap();
let hash2 = Hash::deserialize(&mut &buf[..]).unwrap();
assert_eq!(hash, hash2);
}
}
2 changes: 2 additions & 0 deletions dan_layer/common_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
pub mod proto;
pub mod storage;

mod hash;
mod template_id;

pub use hash::Hash;
use tari_common::hashing_domain::HashingDomain;
pub use template_id::TemplateId;

Expand Down
2 changes: 1 addition & 1 deletion dan_layer/engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ rand = "0.8.1"
serde = "1.0.126"
serde_json = "1.0.81"
thiserror = "^1.0.20"
wasmer = "2.2.1"
wasmer = "2.3.0"
27 changes: 8 additions & 19 deletions dan_layer/engine/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,19 @@
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use digest::Digest;
use rand::rngs::OsRng;
use tari_common_types::types::{PrivateKey, PublicKey};
use tari_crypto::{
hash::blake2::Blake256,
hashing::{DomainSeparatedHasher, DomainSeparation},
keys::PublicKey as PublicKeyT,
};
use tari_crypto::{hash::blake2::Blake256, hash_domain, hashing::DomainSeparatedHasher, keys::PublicKey as PublicKeyT};

pub fn create_key_pair() -> (PrivateKey, PublicKey) {
PublicKey::random_keypair(&mut OsRng)
}
hash_domain!(TariEngineHashDomain, "tari.dan.engine", 0);

pub struct TariEngineDomainSeparation;
pub type TariEngineHasher = DomainSeparatedHasher<Blake256, TariEngineHashDomain>;

impl DomainSeparation for TariEngineDomainSeparation {
fn version() -> u8 {
0
}

fn domain() -> &'static str {
"tari.dan.engine"
}
pub fn hasher(label: &'static str) -> impl Digest<OutputSize = digest::consts::U32> {
TariEngineHasher::new(label)
}

pub fn domain_separated_hasher(label: &'static str) -> DomainSeparatedHasher<Blake256, TariEngineDomainSeparation> {
DomainSeparatedHasher::new(label)
pub fn create_key_pair() -> (PrivateKey, PublicKey) {
PublicKey::random_keypair(&mut OsRng)
}
2 changes: 1 addition & 1 deletion dan_layer/engine/src/instruction/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use crate::{package::PackageId, wasm::WasmExecutionError};
use crate::{packager::PackageId, wasm::WasmExecutionError};

#[derive(Debug, thiserror::Error)]
pub enum InstructionError {
Expand Down
8 changes: 7 additions & 1 deletion dan_layer/engine/src/instruction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub use processor::InstructionProcessor;

mod signature;

use crate::{instruction::signature::InstructionSignature, package::PackageId};
use crate::{instruction::signature::InstructionSignature, packager::PackageId};

#[derive(Debug, Clone)]
pub enum Instruction {
Expand All @@ -40,6 +40,12 @@ pub enum Instruction {
function: String,
args: Vec<Vec<u8>>,
},
CallMethod {
package_id: PackageId,
component_id: String,
method: String,
args: Vec<Vec<u8>>,
},
}

#[derive(Debug, Clone)]
Expand Down
46 changes: 37 additions & 9 deletions dan_layer/engine/src/instruction/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,29 @@
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::collections::HashMap;
use std::{collections::HashMap, sync::Arc};

use crate::{
instruction::{error::InstructionError, Instruction, InstructionSet},
package::{Package, PackageId},
packager::{Package, PackageId},
runtime::{Runtime, RuntimeInterface},
traits::Invokable,
wasm::{ExecutionResult, Process, VmInstance},
wasm::{ExecutionResult, Process},
};

#[derive(Debug, Clone, Default)]
pub struct InstructionProcessor {
pub struct InstructionProcessor<TRuntimeInterface> {
packages: HashMap<PackageId, Package>,
runtime_interface: TRuntimeInterface,
}

impl InstructionProcessor {
pub fn new() -> Self {
impl<TRuntimeInterface> InstructionProcessor<TRuntimeInterface>
where TRuntimeInterface: RuntimeInterface + Clone + 'static
{
pub fn new(runtime_interface: TRuntimeInterface) -> Self {
Self {
packages: HashMap::new(),
runtime_interface,
}
}

Expand All @@ -47,7 +52,10 @@ impl InstructionProcessor {
}

pub fn execute(&self, instruction_set: InstructionSet) -> Result<Vec<ExecutionResult>, InstructionError> {
let mut results = vec![];
let mut results = Vec::with_capacity(instruction_set.instructions.len());

// TODO: implement engine
let state = Runtime::new(Arc::new(self.runtime_interface.clone()));
for instruction in instruction_set.instructions {
match instruction {
Instruction::CallFunction {
Expand All @@ -65,11 +73,31 @@ impl InstructionProcessor {
.ok_or(InstructionError::TemplateNameNotFound { name: template })?;

// TODO: implement intelligent instance caching
let vm = VmInstance::instantiate(module.wasm_module())?;
let process = Process::new(module.clone(), vm);
let process = Process::start(module.clone(), state.clone())?;
let result = process.invoke_by_name(&function, args)?;
results.push(result);
},
Instruction::CallMethod {
package_id,
component_id,
method,
args,
} => {
let package = self
.packages
.get(&package_id)
.ok_or(InstructionError::PackageNotFound { package_id })?;
// TODO: load component, not module - component_id is currently hard-coded as the template name in
// tests
let module = package
.get_module_by_name(&component_id)
.ok_or(InstructionError::TemplateNameNotFound { name: component_id })?;

// TODO: implement intelligent instance caching
let process = Process::start(module.clone(), state.clone())?;
let result = process.invoke_by_name(&method, args)?;
results.push(result);
},
}
}

Expand Down
5 changes: 2 additions & 3 deletions dan_layer/engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ pub mod models;
pub mod state;
pub mod wasm;

pub mod compile;
pub mod crypto;
pub mod env;
pub mod instruction;
pub mod package;
pub mod packager;
pub mod runtime;
pub mod traits;

/// The DAN layer engine domain separated hashing domain
Expand Down
46 changes: 46 additions & 0 deletions dan_layer/engine/src/models/component.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2022. The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::collections::HashMap;

use tari_dan_common_types::Hash;
use tari_template_abi::CreateComponentArg;

pub type ComponentId = (Hash, u32);

pub struct Component {
pub name: String,
pub quantity: u64,
pub metadata: HashMap<Vec<u8>, Vec<u8>>,
pub state: Vec<u8>,
}

impl From<CreateComponentArg> for Component {
fn from(arg: CreateComponentArg) -> Self {
Self {
name: arg.name,
quantity: arg.quantity,
metadata: arg.metadata,
state: arg.state,
}
}
}
7 changes: 6 additions & 1 deletion dan_layer/engine/src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@
// SPDX-License-Identifier: BSD-3-Clause

mod bucket;

pub use bucket::Bucket;

mod component;
pub use component::{Component, ComponentId};

mod vault;
pub use vault::{Vault, VaultId};
23 changes: 8 additions & 15 deletions dan_layer/engine/src/env.rs → dan_layer/engine/src/models/vault.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,16 @@
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use borsh::{BorshDeserialize, BorshSerialize};
use tari_common_types::types::FixedHash;

use std::sync::{Arc, Mutex};
pub type VaultId = FixedHash;

pub fn tari_engine(env: &EngineEnvironment, op: i32, _args_ptr: i32, args_len: i32) -> i32 {
println!("tari_engine CALLED: op: {}, args: {}", op, args_len);
// TODO:
env.inc_counter();
0
}

#[derive(wasmer::WasmerEnv, Clone, Default)]
pub struct EngineEnvironment {
counter: Arc<Mutex<i32>>,
}
#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
pub struct Vault {}

impl EngineEnvironment {
pub fn inc_counter(&self) {
*self.counter.lock().unwrap() += 1;
impl Vault {
pub fn empty() -> Self {
Self {}
}
}