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/engine): add more engine primitives and add template context #4388

Merged
merged 6 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions Cargo.lock

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

2 changes: 0 additions & 2 deletions dan_layer/common_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
pub mod proto;
pub mod storage;

mod hash;
mod template_id;

pub use hash::Hash;
pub use template_id::TemplateId;
7 changes: 4 additions & 3 deletions dan_layer/engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tari_common_types = { path = "../../base_layer/common_types" }
tari_common = { path = "../../common" }
tari_common_types = { path = "../../base_layer/common_types" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.4" }
tari_dan_common_types = { path = "../common_types" }
tari_mmr = { path = "../../base_layer/mmr" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag = "v0.4.5" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.4" }
tari_template_abi = { path = "../template_abi" }
tari_template_lib = { path = "../template_lib", features = ["serde"] }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag = "v0.4.5" }

anyhow = "1.0.53"
borsh = "0.9.3"
Expand Down
11 changes: 7 additions & 4 deletions dan_layer/engine/src/flow/workers/create_bucket_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker};
use tari_common_types::types::PublicKey;
use tari_utilities::{hex::Hex, ByteArray};

use crate::{models::Bucket, state::StateDbUnitOfWork};
use crate::{
models::{Bucket, ResourceAddress},
state::StateDbUnitOfWork,
};

pub struct CreateBucketWorker<TUnitOfWork: StateDbUnitOfWork> {
pub state_db: Arc<RwLock<TUnitOfWork>>,
Expand All @@ -24,19 +27,19 @@ impl<TUnitOfWork: StateDbUnitOfWork> Worker for CreateBucketWorker<TUnitOfWork>
fn work(&self, node: &Node, input_data: InputData) -> anyhow::Result<OutputData> {
// TODO: return proper errors....
let amount = u64::try_from(node.get_number_field("amount", &input_data)?)?;
let vault_id = ResourceAddress::from_hex(&node.get_string_field("vault_id", &input_data)?)?;
let token_id = u64::try_from(node.get_number_field("token_id", &input_data)?)?;
let asset_id = u64::try_from(node.get_number_field("asset_id", &input_data)?)?;
let from = PublicKey::from_hex(&node.get_string_field("from", &input_data)?).expect("Not a valid pub key");
let mut state = self.state_db.write().unwrap();
let balance_key = format!("token_id-{}-{}", asset_id, token_id);
let balance_key = format!("token_id-{}-{}", vault_id, token_id);
let balance = state.get_u64(&balance_key, from.as_bytes())?.unwrap_or(0);
let new_balance = balance.checked_sub(amount).expect("Not enough funds to create bucket");
state
.set_u64(&balance_key, from.as_bytes(), new_balance)
.expect("Could not save state");
let output = OutputDataBuilder::new()
.data("default", Box::new(()))
.data("bucket", Box::new(Bucket::new(amount, token_id, asset_id)))
.data("bucket", Box::new(Bucket::for_token(vault_id, vec![token_id])))
.build();
Ok(output)
}
Expand Down
8 changes: 4 additions & 4 deletions dan_layer/engine/src/flow/workers/mint_bucket_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::convert::TryFrom;

use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker};

use crate::models::Bucket;
use crate::models::{Bucket, ResourceAddress};

pub struct MintBucketWorker {}

Expand Down Expand Up @@ -48,10 +48,10 @@ impl Worker for MintBucketWorker {
}

fn work(&self, node: &Node, inputs: InputData) -> anyhow::Result<OutputData> {
let amount = u64::try_from(node.get_number_field("amount", &inputs)?)?;
let _amount = u64::try_from(node.get_number_field("amount", &inputs)?)?;
let token_id = u64::try_from(node.get_number_field("token_id", &inputs)?)?;
let asset_id = u64::try_from(node.get_number_field("asset_id", &inputs)?)?;
let bucket = Bucket::new(amount, token_id, asset_id);
let vault_id = ResourceAddress::from_hex(&node.get_string_field("vault_id", &inputs)?)?;
let bucket = Bucket::for_token(vault_id, vec![token_id]);
let output = OutputDataBuilder::new()
.data("default", Box::new(()))
.data("bucket", Box::new(bucket))
Expand Down
7 changes: 6 additions & 1 deletion dan_layer/engine/src/flow/workers/store_bucket_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,12 @@ impl<TUnitOfWork: StateDbUnitOfWork> Worker for StoreBucketWorker<TUnitOfWork> {
let bucket: Bucket = serde_json::from_str(&node.get_string_field("bucket", &inputs)?)?;
let to = PublicKey::from_hex(&node.get_string_field("to", &inputs)?)?;
let mut state = self.state_db.write().unwrap();
let balance_key = format!("token_id-{}-{}", bucket.asset_id(), bucket.token_id());
// TODO: handle panics
let balance_key = format!(
"token_id-{}-{}",
bucket.resource_address(),
bucket.token_ids().unwrap()[0]
);
let balance = state.get_u64(&balance_key, to.as_bytes())?.unwrap_or(0);
state.set_u64(
&balance_key,
Expand Down
6 changes: 5 additions & 1 deletion dan_layer/engine/src/instruction/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
// 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::{packager::PackageId, wasm::WasmExecutionError};
use tari_template_lib::models::PackageId;

use crate::{runtime::RuntimeError, wasm::WasmExecutionError};

#[derive(Debug, thiserror::Error)]
pub enum InstructionError {
Expand All @@ -30,4 +32,6 @@ pub enum InstructionError {
PackageNotFound { package_id: PackageId },
#[error("Invalid template")]
TemplateNameNotFound { name: String },
#[error(transparent)]
RuntimeError(#[from] RuntimeError),
}
6 changes: 3 additions & 3 deletions dan_layer/engine/src/instruction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ mod processor;
pub use processor::InstructionProcessor;

mod signature;

use crate::{instruction::signature::InstructionSignature, packager::PackageId};
pub use signature::InstructionSignature;
use tari_template_lib::models::{ComponentId, PackageId};

#[derive(Debug, Clone)]
pub enum Instruction {
Expand All @@ -42,7 +42,7 @@ pub enum Instruction {
},
CallMethod {
package_id: PackageId,
component_id: String,
component_id: ComponentId,
method: String,
args: Vec<Vec<u8>>,
},
Expand Down
68 changes: 35 additions & 33 deletions dan_layer/engine/src/instruction/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,85 +20,87 @@
// 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, sync::Arc};
use std::sync::Arc;

use tari_template_abi::encode;

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

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

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

pub fn load(&mut self, package: Package) -> &mut Self {
self.packages.insert(package.id(), package);
self
}

pub fn execute(&self, instruction_set: InstructionSet) -> Result<Vec<ExecutionResult>, InstructionError> {
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 {
let result = match instruction {
Instruction::CallFunction {
package_id,
template,
function,
args,
} => {
let package = self
.packages
.get(&package_id)
.ok_or(InstructionError::PackageNotFound { package_id })?;
let module = package
if package_id != self.package.id() {
return Err(InstructionError::PackageNotFound { package_id });
}

let module = self
.package
.get_module_by_name(&template)
.ok_or(InstructionError::TemplateNameNotFound { name: template })?;

// TODO: implement intelligent instance caching
let process = Process::start(module.clone(), state.clone())?;
let result = process.invoke_by_name(&function, args)?;
results.push(result);
let process = Process::start(module.clone(), state.clone(), package_id)?;
process.invoke_by_name(&function, args)?
},
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 })?;
if package_id != self.package.id() {
return Err(InstructionError::PackageNotFound { package_id });
}
let component = self.runtime_interface.get_component(&component_id)?;
let module = self.package.get_module_by_name(&component.module_name).ok_or_else(|| {
InstructionError::TemplateNameNotFound {
name: component.module_name.clone(),
}
})?;

let mut final_args = Vec::with_capacity(args.len() + 1);
final_args.push(encode(&component).unwrap());
final_args.extend(args);

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

results.push(result);
}

Ok(results)
Expand Down
40 changes: 27 additions & 13 deletions dan_layer/engine/src/models/bucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,46 @@
// SPDX-License-Identifier: BSD-3-Clause

use serde::Deserialize;
use tari_template_abi::{Decode, Encode};

#[derive(Debug, Default, Clone, Deserialize)]
use crate::models::resource::{Resource, ResourceAddress};

#[derive(Debug, Clone, Encode, Decode, Deserialize)]
pub struct Bucket {
amount: u64,
token_id: u64,
asset_id: u64,
resource: Resource,
}

impl Bucket {
pub fn new(amount: u64, token_id: u64, asset_id: u64) -> Self {
pub fn for_coin(address: ResourceAddress, amount: u64) -> Self {
Self {
resource: Resource::Coin { address, amount },
}
}

pub fn for_token(address: ResourceAddress, token_ids: Vec<u64>) -> Self {
Self {
amount,
token_id,
asset_id,
resource: Resource::Token { address, token_ids },
}
}

pub fn amount(&self) -> u64 {
self.amount
match self.resource {
Resource::Coin { ref amount, .. } => *amount,
Resource::Token { ref token_ids, .. } => token_ids.len() as u64,
}
}

pub fn token_id(&self) -> u64 {
self.token_id
pub fn resource_address(&self) -> ResourceAddress {
match self.resource {
Resource::Coin { address, .. } => address,
Resource::Token { address, .. } => address,
}
}

pub fn asset_id(&self) -> u64 {
self.asset_id
pub fn token_ids(&self) -> Option<&[u64]> {
match self.resource {
Resource::Coin { .. } => None,
Resource::Token { ref token_ids, .. } => Some(token_ids),
}
}
}
Loading