Skip to content

Commit b70a8e8

Browse files
author
Joon-Mo Yang
committed
Implement execution for stack manipulating opcodes
1 parent d35ea9c commit b70a8e8

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

vm/src/executor.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ pub enum ScriptResult {
4343
#[derive(Debug, PartialEq)]
4444
pub enum RuntimeError {
4545
OutOfMemory,
46+
IndexOutOfBound,
4647
StackUnderflow,
4748
TypeMismatch,
4849
InvalidResult,
4950
}
5051

52+
#[derive(Clone)]
5153
struct Item(Vec<u8>);
5254

5355
impl Item {
@@ -105,6 +107,20 @@ impl Stack {
105107
fn len(&self) -> usize {
106108
self.stack.len()
107109
}
110+
111+
fn get(&self, index: usize) -> Result<Item, RuntimeError> {
112+
self.stack.get(index).cloned().ok_or(RuntimeError::IndexOutOfBound)
113+
}
114+
115+
fn remove(&mut self, index: usize) -> Result<Item, RuntimeError> {
116+
if index < self.stack.len() {
117+
let item = self.stack.remove(index);
118+
self.memory_usage -= item.len();
119+
Ok(item)
120+
} else {
121+
Err(RuntimeError::IndexOutOfBound)
122+
}
123+
}
108124
}
109125

110126
pub fn execute(
@@ -135,10 +151,24 @@ pub fn execute(
135151
stack.pop()?;
136152
}
137153
Instruction::PushB(blob) => stack.push(Item(blob.clone()))?,
138-
Instruction::Dup => unimplemented!(),
139-
Instruction::Swap => unimplemented!(),
140-
Instruction::Copy(..) => unimplemented!(),
141-
Instruction::Drop(..) => unimplemented!(),
154+
Instruction::Dup => {
155+
let top = stack.pop()?;
156+
stack.push(top.clone())?;
157+
stack.push(top)?;
158+
}
159+
Instruction::Swap => {
160+
let first = stack.pop()?;
161+
let second = stack.pop()?;
162+
stack.push(first)?;
163+
stack.push(second)?;
164+
}
165+
Instruction::Copy(index) => {
166+
let item = stack.get(*index as usize)?;
167+
stack.push(item)?
168+
}
169+
Instruction::Drop(index) => {
170+
stack.remove(*index as usize)?;
171+
}
142172
Instruction::ChkSig => {
143173
let pubkey = Public::from_slice(stack.pop()?.assert_len(64)?.as_ref());
144174
let signature = ECDSASignature::from(H520::from(stack.pop()?.assert_len(65)?.as_ref()));

0 commit comments

Comments
 (0)