Skip to content

Commit

Permalink
Improves performance of VM
Browse files Browse the repository at this point in the history
  • Loading branch information
Ashy5000 committed Jul 27, 2024
1 parent 4a92df2 commit b3f6d6f
Show file tree
Hide file tree
Showing 12 changed files with 9,136 additions and 121 deletions.
70 changes: 70 additions & 0 deletions contracts/Cargo.lock

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

10 changes: 9 additions & 1 deletion contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,12 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
hex = "0.4.3"
hex = "0.4.3"
tikv-jemallocator = "0.6.0"
rustc-hash = "2.0.0"
smartstring = "1.0.1"

[profile.release]
panic = "abort"
strip = "symbols"
lto = "fat"
36 changes: 21 additions & 15 deletions contracts/src/blockutil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,44 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::sanitization::sanitize_node_console_command;
use smartstring::alias::String;

pub struct BlockUtilInterface {
node_executable_path: String,
}

impl Default for BlockUtilInterface {
fn default() -> Self {
Self::new()
}
}

impl BlockUtilInterface {
pub fn new() -> Self {
Self {
node_executable_path: "builds/node/node".to_owned(),
node_executable_path: "builds/node/node".into(),
}
}
pub fn get_nth_block_property(&self, n: i64, property: String) -> (String, bool) {
// Run the node script to get a property of the nth block
let command = format!("sync;getNthBlock {} {}", n, property);
if !sanitize_node_console_command(&command) {
println!("Forbidden command");
return ("".to_string(), false);
return ("".into(), false);
}
let output = Command::new(self.node_executable_path.clone())
let output = Command::new(&*self.node_executable_path.clone())
.arg("--command")
.arg(command)
.output();
let output = output.expect("Failed to execute node script");
let output = String::from_utf8(output.stdout).expect("Failed to convert output to string");
let output = std::string::String::from_utf8(output.stdout).expect("Failed to convert output to string");
// Remove the newline character
let output = output.trim().to_string();
// Split the output by the newline character
let output = output.split("\n").collect::<Vec<&str>>();
// Get the last element of the output
// This is neccessary because the previous lines contain logs
let output = output[output.len() - 1].to_string();
let output = output[output.len() - 1].into();
(output, true)
}
pub fn get_nth_transaction_property(
Expand All @@ -54,21 +61,21 @@ impl BlockUtilInterface {
);
if !sanitize_node_console_command(&command) {
println!("Forbidden command");
return ("".to_string(), false);
return ("".into(), false);
}
let output = Command::new(self.node_executable_path.clone())
let output = Command::new(&*self.node_executable_path.clone())
.arg("--command")
.arg(command)
.output();
let output =
String::from_utf8(output.unwrap().stdout).expect("Failed to convert output to string");
std::string::String::from_utf8(output.unwrap().stdout).expect("Failed to convert output to string");
// Remove the newline character
let output = output.trim().to_string();
// Split the output by the newline character
let output = output.split("\n").collect::<Vec<&str>>();
// Get the last element of the output
// This is neccessary because the previous lines contain logs
let output = output[output.len() - 1].to_string();
let output = output[output.len() - 1].into();
(output, true)
}
pub fn get_from_state(&self, property: String) -> (Vec<u8>, bool) {
Expand All @@ -77,12 +84,12 @@ impl BlockUtilInterface {
println!("Forbidden command");
return (vec![], false);
}
let output = Command::new(self.node_executable_path.clone())
let output = Command::new(&*self.node_executable_path.clone())
.arg("--command")
.arg(command)
.output();
let output =
String::from_utf8(output.unwrap().stdout).expect("Failed to convert output to string");
std::string::String::from_utf8(output.unwrap().stdout).expect("Failed to convert output to string");
let output = output.trim().to_string();
let output = output.split("\n").collect::<Vec<&str>>();
let output = output[output.len() - 1].to_string();
Expand All @@ -94,16 +101,15 @@ impl BlockUtilInterface {
}
pub fn get_blockchain_len(&self) -> u64 {
let command = "sync;getBlockchainLen";
let output = Command::new(self.node_executable_path.clone())
let output = Command::new(&*self.node_executable_path.clone())
.arg("--command")
.arg(command)
.output();
let output =
String::from_utf8(output.unwrap().stdout).expect("Failed to convert output to string");
std::string::String::from_utf8(output.unwrap().stdout).expect("Failed to convert output to string");
let output = output.trim().to_string();
let output = output.split("\n").collect::<Vec<&str>>();
let output = output[output.len() - 1].to_string();
let len = output.parse::<u64>().unwrap(); // Long Live the Turbofish.
len
output.parse::<u64>().unwrap() // Long Live the Turbofish.
}
}
6 changes: 3 additions & 3 deletions contracts/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ impl Buffer {
self.contents = Vec::new();
let mut shift_amount = 64 - 8;
while shift_amount >= 0 {
let mut piece_u64 = x.clone();
piece_u64 = piece_u64 >> shift_amount;
piece_u64 = piece_u64 % 256;
let mut piece_u64 = x;
piece_u64 >>= shift_amount;
piece_u64 %= 256;
let piece = piece_u64 as u8;
shift_amount -= 8;
self.contents.push(piece);
Expand Down
18 changes: 12 additions & 6 deletions contracts/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,31 @@ mod syntax_tree;
mod vm;
mod stack;

use std::env;
use std::process::ExitCode;
use crate::{buffer::Buffer, vm::run_vm};
use smartstring::alias::String;

use std::{collections::HashMap, env, process::ExitCode};
use rustc_hash::FxHashMap;

#[global_allocator]
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;

fn main() -> ExitCode {
let contract_contents = read_contract::read_contract();
let mut tree = syntax_tree::build_syntax_tree();
tree.create(contract_contents);
let mut buffers: HashMap<String, Buffer> = HashMap::new();
let mut buffers: FxHashMap<String, Buffer> = FxHashMap::default();
buffers.insert(
"00000000".to_owned(),
"00000000".into(),
Buffer {
contents: Vec::new(),
},
);
let blockutil_interface = blockutil::BlockUtilInterface::new();
let args: Vec<String> = env::args().collect();
let blockutil_interface = blockutil::BlockUtilInterface::default();
let args: Vec<std::string::String> = env::args().collect();
let contract_hash = &args[2];
let (exit_code, gas_used) = run_vm(tree, &mut buffers, blockutil_interface, contract_hash.clone());
let (exit_code, gas_used) = run_vm(tree, &mut buffers, blockutil_interface, contract_hash.parse().unwrap());
println!("Gas used: {}", gas_used);
ExitCode::from(exit_code as u8)
}
17 changes: 8 additions & 9 deletions contracts/src/math.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustc_hash::FxHashMap;
// Copyright 2024, Asher Wrobel
/*
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Expand All @@ -7,8 +8,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::{buffer::Buffer, vm};

use std::collections::HashMap;
use smartstring::alias::String;

pub(crate) trait MathOperation {
fn execute(&self, a: u64, b: u64) -> Result<u64, String>;
Expand Down Expand Up @@ -43,7 +43,7 @@ pub(crate) struct Divide {}
impl MathOperation for Divide {
fn execute(&self, a: u64, b: u64) -> Result<u64, String> {
if b == 0 {
return Err("Division by zero".to_string());
return Err("Division by zero".into());
}
Ok(a.overflowing_div(b).0)
}
Expand Down Expand Up @@ -122,7 +122,7 @@ impl MathOperation for Less {

pub(crate) fn execute_math_operation(
operation: impl MathOperation,
buffers: &mut HashMap<String, Buffer>,
buffers: &mut FxHashMap<String, Buffer>,
a: String,
b: String,
res: String,
Expand All @@ -148,13 +148,12 @@ pub(crate) fn execute_math_operation(
buffer_1 = buffers.get(&b).unwrap();
}
let buffer_0_u64 = buffer_0.as_u64().unwrap();
let result_u64;
if std::any::type_name_of_val(&operation) != "contracts::math::Not" {
let result_u64 = if std::any::type_name_of_val(&operation) != "contracts::math::Not" {
let buffer_1_u64 = buffer_1.as_u64().unwrap();
result_u64 = operation.execute(buffer_0_u64, buffer_1_u64);
operation.execute(buffer_0_u64, buffer_1_u64)
} else {
result_u64 = operation.execute(buffer_0_u64, 0);
}
operation.execute(buffer_0_u64, 0)
};
let buffer_result = buffers.get_mut(&res).unwrap();
buffer_result.load_u64(result_u64.expect("Error storing result in buffer"));
}
10 changes: 6 additions & 4 deletions contracts/src/read_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::{env, fs};
use smartstring::alias::String;

pub fn read_contract() -> String {
let args: Vec<String> = env::args().collect();
let args: Vec<std::string::String> = env::args().collect();
if args.len() != 3 {
panic!("Expected exactly 3 arguments, got {}", args.len())
}
let contract_path = &args[1];
let contents = fs::read_to_string(contract_path)
.expect("Should have been able to read smart contract file");
contents
fs::read_to_string(contract_path)
.expect("Should have been able to read smart contract file")
.parse()
.unwrap()
}
12 changes: 6 additions & 6 deletions contracts/src/stack.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashMap;
use rustc_hash::FxHashMap;
use crate::buffer::Buffer;
use smartstring::alias::String;

// Copyright 2024, Asher Wrobel
/*
Expand All @@ -10,22 +11,21 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
pub struct StackFrame {
pub buffers: HashMap<String, Buffer>
pub buffers: FxHashMap<String, Buffer>
}

pub struct Stack {
pub frames: Vec<StackFrame>
}

impl Stack {
pub fn push(&mut self, buffers_param: &HashMap<String, Buffer>) {
let buffers = buffers_param;
pub fn push(&mut self, buffers_param: &FxHashMap<String, Buffer>) {
let frame = StackFrame {
buffers: buffers.clone()
buffers: buffers_param.clone()
};
self.frames.push(frame);
}
pub fn pop(&mut self) -> HashMap<String, Buffer> {
pub fn pop(&mut self) -> FxHashMap<String, Buffer> {
self.frames.pop().unwrap().buffers
}
}
Loading

0 comments on commit b3f6d6f

Please sign in to comment.