|
@ -56,6 +56,11 @@ impl Stack { |
|
|
s.opcodes = new_opcodes();
|
|
|
s.opcodes = new_opcodes();
|
|
|
s
|
|
|
s
|
|
|
}
|
|
|
}
|
|
|
|
|
|
fn print_stack(&self) {
|
|
|
|
|
|
for i in (0..self.stack.len()).rev() {
|
|
|
|
|
|
println!("{:x?}", &self.stack[i][28..]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
fn push(&mut self, b: [u8; 32]) {
|
|
|
fn push(&mut self, b: [u8; 32]) {
|
|
|
self.stack.push(b);
|
|
|
self.stack.push(b);
|
|
|
}
|
|
|
}
|
|
@ -67,6 +72,14 @@ impl Stack { |
|
|
d[32 - b.len()..].copy_from_slice(&b[..]);
|
|
|
d[32 - b.len()..].copy_from_slice(&b[..]);
|
|
|
self.stack.push(d);
|
|
|
self.stack.push(d);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// put_arbitrary puts in the last element of the stack the value
|
|
|
|
|
|
fn put_arbitrary(&mut self, b: &[u8]) {
|
|
|
|
|
|
// TODO if b.len()>32 return error
|
|
|
|
|
|
let mut d: [u8; 32] = [0; 32];
|
|
|
|
|
|
d[32 - b.len()..].copy_from_slice(&b[..]);
|
|
|
|
|
|
let l = self.stack.len();
|
|
|
|
|
|
self.stack[l - 1] = d;
|
|
|
|
|
|
}
|
|
|
fn pop(&mut self) -> [u8; 32] {
|
|
|
fn pop(&mut self) -> [u8; 32] {
|
|
|
match self.stack.pop() {
|
|
|
match self.stack.pop() {
|
|
|
Some(x) => return x,
|
|
|
Some(x) => return x,
|
|
@ -84,6 +97,17 @@ impl Stack { |
|
|
panic!("invalid opcode {:x}", opcode);
|
|
|
panic!("invalid opcode {:x}", opcode);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if debug {
|
|
|
|
|
|
println!(
|
|
|
|
|
|
"{:?} (0x{:x}): pc={:?} gas={:?}\nstack:",
|
|
|
|
|
|
self.opcodes.get(&opcode).unwrap().name,
|
|
|
|
|
|
opcode,
|
|
|
|
|
|
self.pc,
|
|
|
|
|
|
self.gas,
|
|
|
|
|
|
);
|
|
|
|
|
|
self.print_stack();
|
|
|
|
|
|
println!("");
|
|
|
|
|
|
}
|
|
|
match opcode & 0xf0 {
|
|
|
match opcode & 0xf0 {
|
|
|
0x00 => {
|
|
|
0x00 => {
|
|
|
// arithmetic
|
|
|
// arithmetic
|
|
@ -106,6 +130,15 @@ impl Stack { |
|
|
}
|
|
|
}
|
|
|
self.pc += 1;
|
|
|
self.pc += 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
0x30 => {
|
|
|
|
|
|
match opcode {
|
|
|
|
|
|
0x35 => {
|
|
|
|
|
|
self.calldata_load(&calldata);
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => panic!("unimplemented {:x}", opcode),
|
|
|
|
|
|
}
|
|
|
|
|
|
self.pc += 1;
|
|
|
|
|
|
}
|
|
|
0x50 => {
|
|
|
0x50 => {
|
|
|
self.pc += 1;
|
|
|
self.pc += 1;
|
|
|
match opcode {
|
|
|
match opcode {
|
|
@ -201,7 +234,10 @@ impl Stack { |
|
|
// crypto
|
|
|
// crypto
|
|
|
|
|
|
|
|
|
// contract context
|
|
|
// contract context
|
|
|
fn calldata_load(&mut self, calldata: &[u8]) {}
|
|
|
|
|
|
|
|
|
fn calldata_load(&mut self, calldata: &[u8]) {
|
|
|
|
|
|
self.put_arbitrary(&calldata[self.calldata_i..self.calldata_i + 32]);
|
|
|
|
|
|
self.calldata_i += 32;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
// blockchain context
|
|
|
// blockchain context
|
|
|
|
|
|
|
|
@ -415,4 +451,18 @@ mod tests { |
|
|
assert_eq!(s.pc, 7);
|
|
|
assert_eq!(s.pc, 7);
|
|
|
assert_eq!(s.pop(), str_to_u256("515"));
|
|
|
assert_eq!(s.pop(), str_to_u256("515"));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn execute_opcodes_3() {
|
|
|
|
|
|
// contains calldata
|
|
|
|
|
|
let code = hex::decode("60003560203501").unwrap();
|
|
|
|
|
|
let calldata = hex::decode("00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000004").unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let mut s = Stack::new();
|
|
|
|
|
|
s.execute(&code, &calldata, false);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(s.gas, 9999999985);
|
|
|
|
|
|
assert_eq!(s.pc, 7);
|
|
|
|
|
|
assert_eq!(s.pop(), str_to_u256("9"));
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|