Skip to content

Commit

Permalink
Merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
b-j-roberts committed Jul 29, 2024
2 parents baf76cd + 950d8cd commit 2ba8177
Show file tree
Hide file tree
Showing 8 changed files with 409 additions and 40 deletions.
8 changes: 6 additions & 2 deletions src/compiler.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,16 @@ pub impl CompilerTraitImpl of CompilerTrait {
opcodes.insert('OP_14', Opcode::OP_14);
opcodes.insert('OP_15', Opcode::OP_15);
opcodes.insert('OP_16', Opcode::OP_16);
opcodes.insert('OP_IF', Opcode::OP_IF);
opcodes.insert('OP_NOTIF', Opcode::OP_NOTIF);
opcodes.insert('OP_ELSE', Opcode::OP_ELSE);
opcodes.insert('OP_ENDIF', Opcode::OP_ENDIF);
opcodes.insert('OP_DEPTH', Opcode::OP_DEPTH);
opcodes.insert('OP_1ADD', Opcode::OP_1ADD);
opcodes.insert('OP_NOT', Opcode::OP_NOT);
opcodes.insert('OP_ADD', Opcode::OP_ADD);

opcodes.insert('OP_SUB', Opcode::OP_SUB);
opcodes.insert('OP_MAX', Opcode::OP_MAX);
opcodes.insert('OP_NOT', Opcode::OP_NOT);
Compiler { opcodes }
}

Expand Down
43 changes: 43 additions & 0 deletions src/cond_stack.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#[derive(Destruct)]
pub struct ConditionalStack {
stack: Felt252Dict<u8>,
len: usize,
}

#[generate_trait()]
pub impl ConditionalStackImpl of ConditionalStackTrait {
fn new() -> ConditionalStack {
ConditionalStack { stack: Default::default(), len: 0, }
}

fn push(ref self: ConditionalStack, value: u8) {
self.stack.insert(self.len.into(), value);
self.len += 1;
}

fn pop(ref self: ConditionalStack) {
self.len -= 1;
}

fn branch_executing(ref self: ConditionalStack) -> bool {
if self.len == 0 {
return true;
} else {
return self.stack[self.len.into() - 1] == 1;
}
}

fn len(ref self: ConditionalStack) -> usize {
self.len
}

fn swap_condition(ref self: ConditionalStack) {
let cond_idx = self.len() - 1;
match self.stack.get(cond_idx.into()) {
0 => self.stack.insert(cond_idx.into(), 1),
1 => self.stack.insert(cond_idx.into(), 0),
2 => self.stack.insert(cond_idx.into(), 2),
_ => panic!("Invalid condition")
}
}
}
17 changes: 16 additions & 1 deletion src/engine.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use shinigami::stack::{ScriptStack, ScriptStackImpl};
use shinigami::opcodes::opcodes::Opcode::execute;
use shinigami::cond_stack::{ConditionalStack, ConditionalStackImpl};
use shinigami::opcodes::opcodes::Opcode::{execute, is_branching_opcode};

// Represents the VM that executes Bitcoin scripts
#[derive(Destruct)]
Expand All @@ -12,6 +13,8 @@ pub struct Engine {
pub dstack: ScriptStack,
// Alternate data stack
pub astack: ScriptStack,
// Tracks conditonal execution state supporting nested conditionals
pub cond_stack: ConditionalStack,
// TODO
// ...
}
Expand All @@ -34,6 +37,7 @@ pub impl EngineTraitImpl of EngineTrait {
opcode_idx: 0,
dstack: ScriptStackImpl::new(),
astack: ScriptStackImpl::new(),
cond_stack: ConditionalStackImpl::new(),
}
}

Expand All @@ -50,6 +54,12 @@ pub impl EngineTraitImpl of EngineTrait {
return false;
}

if !self.cond_stack.branch_executing()
&& !is_branching_opcode(self.script[self.opcode_idx]) {
self.opcode_idx += 1;
return true;
}

let opcode = self.script[self.opcode_idx];
execute(opcode, ref self);
self.opcode_idx += 1;
Expand All @@ -61,6 +71,11 @@ pub impl EngineTraitImpl of EngineTrait {
.opcode_idx < self
.script
.len() {
if !self.cond_stack.branch_executing()
&& !is_branching_opcode(self.script[self.opcode_idx]) {
self.opcode_idx += 1;
continue;
}
let opcode = self.script[self.opcode_idx];
execute(opcode, ref self);
self.opcode_idx += 1;
Expand Down
2 changes: 2 additions & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod compiler;
pub mod cond_stack;
pub mod opcodes {
pub mod opcodes;
mod tests {
Expand All @@ -9,5 +10,6 @@ pub mod opcodes {
}
pub mod engine;
pub mod stack;
pub mod utils;

mod main;
82 changes: 73 additions & 9 deletions src/opcodes/opcodes.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@ pub mod Opcode {
pub const OP_14: u8 = 94;
pub const OP_15: u8 = 95;
pub const OP_16: u8 = 96;
pub const OP_IF: u8 = 99;
pub const OP_NOTIF: u8 = 100;
pub const OP_ELSE: u8 = 103;
pub const OP_ENDIF: u8 = 104;
pub const OP_DEPTH: u8 = 116;
pub const OP_1ADD: u8 = 139;
pub const OP_NOT: u8 = 145;
pub const OP_ADD: u8 = 147;
pub const OP_SUB: u8 = 148;
pub const OP_MAX: u8 = 164;

pub const OP_NOT: u8 = 145;


use shinigami::engine::Engine;
use shinigami::engine::{Engine, EngineTrait};
use shinigami::stack::ScriptStackTrait;
use shinigami::cond_stack::ConditionalStackTrait;
pub fn execute(opcode: u8, ref engine: Engine) {
match opcode {
0 => opcode_false(ref engine),
Expand Down Expand Up @@ -128,12 +132,12 @@ pub mod Opcode {
96 => opcode_n(16, ref engine),
97 => not_implemented(ref engine),
98 => not_implemented(ref engine),
99 => not_implemented(ref engine),
100 => not_implemented(ref engine),
99 => opcode_if(ref engine),
100 => opcode_notif(ref engine),
101 => not_implemented(ref engine),
102 => not_implemented(ref engine),
103 => not_implemented(ref engine),
104 => not_implemented(ref engine),
103 => opcode_else(ref engine),
104 => opcode_endif(ref engine),
105 => not_implemented(ref engine),
106 => not_implemented(ref engine),
107 => not_implemented(ref engine),
Expand Down Expand Up @@ -177,7 +181,7 @@ pub mod Opcode {
145 => opcode_not(ref engine),
146 => not_implemented(ref engine),
147 => opcode_add(ref engine),
148 => not_implemented(ref engine),
148 => opcode_sub(ref engine),
149 => not_implemented(ref engine),
150 => not_implemented(ref engine),
151 => not_implemented(ref engine),
Expand All @@ -198,6 +202,13 @@ pub mod Opcode {
}
}

pub fn is_branching_opcode(opcode: u8) -> bool {
if opcode == OP_IF || opcode == OP_NOTIF || opcode == OP_ELSE || opcode == OP_ENDIF {
return true;
}
return false;
}

fn opcode_false(ref engine: Engine) {
engine.dstack.push_byte_array("");
}
Expand All @@ -206,13 +217,66 @@ pub mod Opcode {
engine.dstack.push_int(n);
}

// TODO: MOve to cond_stack
const op_cond_false: u8 = 0;
const op_cond_true: u8 = 1;
const op_cond_skip: u8 = 2;
fn opcode_if(ref engine: Engine) {
let mut cond = op_cond_false;
// TODO: Pop if bool
if engine.cond_stack.branch_executing() {
let ok = engine.dstack.pop_bool();
if ok {
cond = op_cond_true;
}
} else {
cond = op_cond_skip;
}
engine.cond_stack.push(cond);
}

fn opcode_notif(ref engine: Engine) {
let mut cond = op_cond_false;
if engine.cond_stack.branch_executing() {
let ok = engine.dstack.pop_bool();
if !ok {
cond = op_cond_true;
}
} else {
cond = op_cond_skip;
}
engine.cond_stack.push(cond);
}

fn opcode_else(ref engine: Engine) {
if engine.cond_stack.len() == 0 {
panic!("No matching if");
}

engine.cond_stack.swap_condition();
}

fn opcode_endif(ref engine: Engine) {
if engine.cond_stack.len() == 0 {
panic!("No matching if");
}

engine.cond_stack.pop();
}

fn opcode_add(ref engine: Engine) {
// TODO: Error handling
let a = engine.dstack.pop_int();
let b = engine.dstack.pop_int();
engine.dstack.push_int(a + b);
}

fn opcode_sub(ref engine: Engine) {
// TODO: Error handling
let a = engine.dstack.pop_int();
let b = engine.dstack.pop_int();
engine.dstack.push_int(b - a);
}

fn opcode_depth(ref engine: Engine) {
let depth: i64 = engine.dstack.len().into();
Expand Down
Loading

0 comments on commit 2ba8177

Please sign in to comment.