@@ -43,11 +43,13 @@ pub enum ScriptResult {
4343#[ derive( Debug , PartialEq ) ]
4444pub enum RuntimeError {
4545 OutOfMemory ,
46+ IndexOutOfBound ,
4647 StackUnderflow ,
4748 TypeMismatch ,
4849 InvalidResult ,
4950}
5051
52+ #[ derive( Clone ) ]
5153struct Item ( Vec < u8 > ) ;
5254
5355impl 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
110126pub 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