Browse Source

Impl mload, jump, jump_i, jump_dest, swap, dup

master
arnaucube 2 years ago
parent
commit
dbd992138b
1 changed files with 110 additions and 0 deletions
  1. +110
    -0
      src/lib.rs

+ 110
- 0
src/lib.rs

@ -142,7 +142,15 @@ impl Stack {
0x50 => {
self.pc += 1;
match opcode {
0x51 => self.mload(),
0x52 => self.mstore(),
0x56 => self.jump(),
0x57 => {
self.jump_i();
}
0x5b => {
self.jump_dest();
}
_ => panic!("unimplemented {:x}", opcode),
}
}
@ -152,6 +160,30 @@ impl Stack {
self.push_arbitrary(&code[self.pc + 1..self.pc + 1 + n]);
self.pc += 1 + n;
}
0x80 => {
// 0x8x dup
let l = self.stack.len();
if opcode > 0x7f {
self.stack.push(self.stack[l - (opcode - 0x7f) as usize]);
} else {
self.stack.push(self.stack[(0x7f - opcode) as usize]);
}
self.pc += 1;
}
0x90 => {
// 0x9x swap
let l = self.stack.len();
let pos;
if opcode > 0x8e {
pos = l - (opcode - 0x8e) as usize;
} else {
pos = (0x8e - opcode) as usize;
}
let tmp = self.stack[pos];
self.stack[pos] = self.stack[l - 1];
self.stack[l - 1] = tmp;
self.pc += 1;
}
0xf0 => {
if opcode == 0xf3 {
let pos_to_return = u256_to_u64(self.pop()) as usize;
@ -255,6 +287,12 @@ impl Stack {
let mut new_bytes: Vec<u8> = vec![0; size];
self.mem.append(&mut new_bytes);
}
fn mload(&mut self) {
let pos = u256_to_u64(self.pop()) as usize;
self.extend_mem(pos as usize, 32);
let mem32 = self.mem[pos..pos + 32].to_vec();
self.push_arbitrary(&mem32);
}
fn mstore(&mut self) {
let pos = u256_to_u64(self.pop());
let val = self.pop();
@ -262,6 +300,24 @@ impl Stack {
self.mem[pos as usize..].copy_from_slice(&val);
}
fn jump(&mut self) {
// TODO that jump destination is valid
self.pc = u256_to_u64(self.pop()) as usize;
}
fn jump_i(&mut self) {
let new_pc = u256_to_u64(self.pop()) as usize;
if self.stack.len() > 0 {
let cond = u256_to_u64(self.pop()) as usize;
if cond != 0 {
self.pc = new_pc;
}
}
// let cont = self.pop();
// if cont {} // TODO depends on having impl Err in pop()
}
fn jump_dest(&mut self) {
// TODO
}
}
fn u256_to_u64(a: [u8; 32]) -> u64 {
@ -282,6 +338,7 @@ struct Opcode {
ins: u32,
outs: u32,
gas: u64,
// operation: fn(),
}
fn new_opcode(name: &str, ins: u32, outs: u32, gas: u64) -> Opcode {
@ -465,4 +522,57 @@ mod tests {
assert_eq!(s.pc, 7);
assert_eq!(s.pop(), str_to_u256("9"));
}
// storage and execution
#[test]
fn execute_opcodes_4() {
// contains loops
let code = hex::decode("6000356000525b600160005103600052600051600657").unwrap();
let calldata =
hex::decode("0000000000000000000000000000000000000000000000000000000000000005")
.unwrap();
let mut s = Stack::new();
s.execute(&code, &calldata, false);
assert_eq!(s.gas, 9999999795);
assert_eq!(s.pc, 22);
assert_eq!(s.stack.len(), 0);
}
#[test]
fn execute_opcodes_5() {
// contains loops, without using mem
let code = hex::decode("6000355b6001900380600357").unwrap();
let calldata =
hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
.unwrap();
let mut s = Stack::new();
s.execute(&code, &calldata, false);
assert_eq!(s.gas, 9999999968);
assert_eq!(s.pc, 12);
let code = hex::decode("6000355b6001900380600357").unwrap();
let calldata =
hex::decode("0000000000000000000000000000000000000000000000000000000000000002")
.unwrap();
let mut s = Stack::new();
s.execute(&code, &calldata, false);
assert_eq!(s.gas, 9999999942);
assert_eq!(s.pc, 12);
let code = hex::decode("6000355b6001900380600357").unwrap();
let calldata =
hex::decode("0000000000000000000000000000000000000000000000000000000000000005")
.unwrap();
let mut s = Stack::new();
s.execute(&code, &calldata, false);
assert_eq!(s.gas, 9999999864);
assert_eq!(s.pc, 12);
}
}

Loading…
Cancel
Save