From 34f2a2a5ef664e63a60fc438b645b6fc96f2c383 Mon Sep 17 00:00:00 2001 From: jun Date: Thu, 12 Jul 2018 16:12:24 +0900 Subject: [PATCH] Add SUCCESS, FAIL opcode --- spec/CodeChain-Virtual-Machine.md | 4 +++- vm/src/decoder.rs | 2 ++ vm/src/executor.rs | 2 ++ vm/src/instruction.rs | 2 ++ vm/src/opcode.rs | 2 ++ vm/src/tests/decoder.rs | 2 ++ vm/src/tests/executor.rs | 8 +++++++- 7 files changed, 20 insertions(+), 2 deletions(-) diff --git a/spec/CodeChain-Virtual-Machine.md b/spec/CodeChain-Virtual-Machine.md index 3745a3cfb2..e5f830f167 100644 --- a/spec/CodeChain-Virtual-Machine.md +++ b/spec/CodeChain-Virtual-Machine.md @@ -39,6 +39,8 @@ Leading zeros must be truncated. Note that it is allowed to decode value with le ## Special instructions * NOP(0x00): Do nothing * BURN(0x01): Stop script execution, and return `BURN` as result. +* SUCCESS(0x02): Stop script execution, and return `SUCCESS` as result. +* FAIL(0x03): Stop script execution, and return `FAIL` as result. ## Boolean computation * NOT(0x10): Pop one value from stack as boolean, and push negated value. @@ -84,4 +86,4 @@ Leading zeros must be truncated. Note that it is allowed to decode value with le * KECCAK256(0x93): Pop one value from stack, and push keccak-256 hash of it. ## Environment -* BLKNUM(0xa0): Push block number specified in parcel to stack as integer. If there's no specified block number, machine must fail immediately. \ No newline at end of file +* BLKNUM(0xa0): Push block number specified in parcel to stack as integer. If there's no specified block number, machine must fail immediately. diff --git a/vm/src/decoder.rs b/vm/src/decoder.rs index 5d7fff770f..b14c12e07c 100644 --- a/vm/src/decoder.rs +++ b/vm/src/decoder.rs @@ -30,6 +30,8 @@ pub fn decode(bytes: &[u8]) -> Result, DecoderError> { match *b { opcode::NOP => result.push(Instruction::Nop), opcode::BURN => result.push(Instruction::Burn), + opcode::SUCCESS => result.push(Instruction::Success), + opcode::FAIL => result.push(Instruction::Fail), opcode::NOT => result.push(Instruction::Not), opcode::EQ => result.push(Instruction::Eq), opcode::JMP => { diff --git a/vm/src/executor.rs b/vm/src/executor.rs index fe5dd2f49c..8e5480c2c4 100644 --- a/vm/src/executor.rs +++ b/vm/src/executor.rs @@ -161,6 +161,8 @@ pub fn execute( match &script[pc] { Instruction::Nop => {} Instruction::Burn => return Ok(ScriptResult::Burnt), + Instruction::Success => return Ok(ScriptResult::Unlocked), + Instruction::Fail => return Ok(ScriptResult::Fail), Instruction::Not => { let value: bool = stack.pop()?.into(); stack.push(Item::from(!value))?; diff --git a/vm/src/instruction.rs b/vm/src/instruction.rs index 751ba473fc..d2f1b36fde 100644 --- a/vm/src/instruction.rs +++ b/vm/src/instruction.rs @@ -18,6 +18,8 @@ pub enum Instruction { Nop, Burn, + Success, + Fail, Not, Eq, Jmp(u8), diff --git a/vm/src/opcode.rs b/vm/src/opcode.rs index 54b2c0c4d7..d990a6e722 100644 --- a/vm/src/opcode.rs +++ b/vm/src/opcode.rs @@ -16,6 +16,8 @@ pub const NOP: u8 = 0x00; pub const BURN: u8 = 0x01; +pub const SUCCESS: u8 = 0x02; +pub const FAIL: u8 = 0x03; pub const NOT: u8 = 0x10; pub const EQ: u8 = 0x11; pub const JMP: u8 = 0x20; diff --git a/vm/src/tests/decoder.rs b/vm/src/tests/decoder.rs index a7f2ff91d8..35981eb7cd 100644 --- a/vm/src/tests/decoder.rs +++ b/vm/src/tests/decoder.rs @@ -50,6 +50,8 @@ macro_rules! test_one_argument_opcode { test_no_argument_opcode!(NOP, Nop); test_no_argument_opcode!(BURN, Burn); +test_no_argument_opcode!(SUCCESS, Success); +test_no_argument_opcode!(FAIL, Fail); test_no_argument_opcode!(NOT, Not); test_no_argument_opcode!(EQ, Eq); test_one_argument_opcode!(JMP, Jmp); diff --git a/vm/src/tests/executor.rs b/vm/src/tests/executor.rs index f6fd6513f5..0d93f649f8 100644 --- a/vm/src/tests/executor.rs +++ b/vm/src/tests/executor.rs @@ -26,7 +26,12 @@ use instruction::Instruction; #[test] fn simple_success() { assert_eq!( - execute(&[Instruction::Push(1)], &[], &[], H256::default(), Config::default()), + execute(&[], &[], &[Instruction::Push(1)], H256::default(), Config::default()), + Ok(ScriptResult::Unlocked) + ); + + assert_eq!( + execute(&[], &[], &[Instruction::Success], H256::default(), Config::default()), Ok(ScriptResult::Unlocked) ); } @@ -34,6 +39,7 @@ fn simple_success() { #[test] fn simple_failure() { assert_eq!(execute(&[Instruction::Push(0)], &[], &[], H256::default(), Config::default()), Ok(ScriptResult::Fail)); + assert_eq!(execute(&[], &[], &[Instruction::Fail], H256::default(), Config::default()), Ok(ScriptResult::Fail)); } #[test]