@@ -601,15 +601,15 @@ impl Script {
601
601
/// To force minimal pushes, use [`Self::instructions_minimal`].
602
602
pub fn instructions ( & self ) -> Instructions {
603
603
Instructions {
604
- data : & self . 0 [ .. ] ,
604
+ data : self . 0 . iter ( ) ,
605
605
enforce_minimal : false ,
606
606
}
607
607
}
608
608
609
609
/// Iterates over the script in the form of `Instruction`s while enforcing minimal pushes.
610
610
pub fn instructions_minimal ( & self ) -> Instructions {
611
611
Instructions {
612
- data : & self . 0 [ .. ] ,
612
+ data : self . 0 . iter ( ) ,
613
613
enforce_minimal : true ,
614
614
}
615
615
}
@@ -748,114 +748,97 @@ pub enum Instruction<'a> {
748
748
749
749
/// Iterator over a script returning parsed opcodes.
750
750
pub struct Instructions < ' a > {
751
- data : & ' a [ u8 ] ,
751
+ data : :: core :: slice :: Iter < ' a , u8 > ,
752
752
enforce_minimal : bool ,
753
753
}
754
754
755
+ impl < ' a > Instructions < ' a > {
756
+ /// Set the iterator to end so that it won't iterate any longer
757
+ fn kill ( & mut self ) {
758
+ let len = self . data . len ( ) ;
759
+ self . data . nth ( len. max ( 1 ) - 1 ) ;
760
+ }
761
+
762
+ /// takes `len` bytes long slice from iterator and returns it advancing iterator
763
+ /// if the iterator is not long enough [`Error::EarlyEndOfScript`] is returned and the iterator is killed
764
+ /// to avoid returning an infinite stream of errors.
765
+ fn take_slice_or_kill ( & mut self , len : usize ) -> Result < & ' a [ u8 ] , Error > {
766
+ if self . data . len ( ) >= len {
767
+ let slice = & self . data . as_slice ( ) [ ..len] ;
768
+ if len > 0 {
769
+ self . data . nth ( len - 1 ) ;
770
+ }
771
+
772
+ Ok ( slice)
773
+ } else {
774
+ self . kill ( ) ;
775
+ Err ( Error :: EarlyEndOfScript )
776
+ }
777
+ }
778
+
779
+ fn next_push_data_len ( & mut self , len : usize , min_push_len : usize ) -> Option < Result < Instruction < ' a > , Error > > {
780
+ let n = match read_uint_iter ( & mut self . data , len) {
781
+ Ok ( n) => n,
782
+ // We do exhaustive matching to not forget to handle new variants if we extend
783
+ // `UintError` type.
784
+ // Overflow actually means early end of script (script is definitely shorter
785
+ // than `usize::max_value()`)
786
+ Err ( UintError :: EarlyEndOfScript ) | Err ( UintError :: NumericOverflow ) => {
787
+ self . kill ( ) ;
788
+ return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
789
+ } ,
790
+ } ;
791
+ if self . enforce_minimal && n < min_push_len {
792
+ self . kill ( ) ;
793
+ return Some ( Err ( Error :: NonMinimalPush ) ) ;
794
+ }
795
+ Some ( self . take_slice_or_kill ( n) . map ( Instruction :: PushBytes ) )
796
+ }
797
+ }
798
+
755
799
impl < ' a > Iterator for Instructions < ' a > {
756
800
type Item = Result < Instruction < ' a > , Error > ;
757
801
758
802
fn next ( & mut self ) -> Option < Result < Instruction < ' a > , Error > > {
759
- if self . data . is_empty ( ) {
760
- return None ;
761
- }
803
+ let & byte = self . data . next ( ) ?;
762
804
763
805
// classify parameter does not really matter here since we are only using
764
806
// it for pushes and nums
765
- match opcodes:: All :: from ( self . data [ 0 ] ) . classify ( opcodes:: ClassifyContext :: Legacy ) {
807
+ match opcodes:: All :: from ( byte ) . classify ( opcodes:: ClassifyContext :: Legacy ) {
766
808
opcodes:: Class :: PushBytes ( n) => {
809
+ // make sure safety argument holds across refactorings
810
+ let n: u32 = n;
811
+ // casting is safe because we don't support 16-bit architectures
767
812
let n = n as usize ;
768
- if self . data . len ( ) < n + 1 {
769
- self . data = & [ ] ; // Kill iterator so that it does not return an infinite stream of errors
770
- return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
771
- }
772
- if self . enforce_minimal {
773
- if n == 1 && ( self . data [ 1 ] == 0x81 || ( self . data [ 1 ] > 0 && self . data [ 1 ] <= 16 ) ) {
774
- self . data = & [ ] ;
775
- return Some ( Err ( Error :: NonMinimalPush ) ) ;
813
+
814
+ let op_byte = self . data . as_slice ( ) . first ( ) ;
815
+ match ( self . enforce_minimal , op_byte, n) {
816
+ ( true , Some ( & op_byte) , 1 ) if op_byte == 0x81 || ( op_byte > 0 && op_byte <= 16 ) => {
817
+ self . kill ( ) ;
818
+ Some ( Err ( Error :: NonMinimalPush ) )
819
+ } ,
820
+ ( _, None , 0 ) => {
821
+ // the iterator is already empty, may as well use this information to avoid
822
+ // whole take_slice_or_kill function
823
+ Some ( Ok ( Instruction :: PushBytes ( & [ ] ) ) )
824
+ } ,
825
+ _ => {
826
+ Some ( self . take_slice_or_kill ( n) . map ( Instruction :: PushBytes ) )
776
827
}
777
828
}
778
- let ret = Some ( Ok ( Instruction :: PushBytes ( & self . data [ 1 ..n+1 ] ) ) ) ;
779
- self . data = & self . data [ n + 1 ..] ;
780
- ret
781
829
}
782
830
opcodes:: Class :: Ordinary ( opcodes:: Ordinary :: OP_PUSHDATA1 ) => {
783
- if self . data . len ( ) < 2 {
784
- self . data = & [ ] ;
785
- return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
786
- }
787
- let n = match read_uint ( & self . data [ 1 ..] , 1 ) {
788
- Ok ( n) => n,
789
- Err ( e) => {
790
- self . data = & [ ] ;
791
- return Some ( Err ( e) ) ;
792
- }
793
- } ;
794
- if self . data . len ( ) < n + 2 {
795
- self . data = & [ ] ;
796
- return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
797
- }
798
- if self . enforce_minimal && n < 76 {
799
- self . data = & [ ] ;
800
- return Some ( Err ( Error :: NonMinimalPush ) ) ;
801
- }
802
- let ret = Some ( Ok ( Instruction :: PushBytes ( & self . data [ 2 ..n+2 ] ) ) ) ;
803
- self . data = & self . data [ n + 2 ..] ;
804
- ret
831
+ self . next_push_data_len ( 1 , 76 )
805
832
}
806
833
opcodes:: Class :: Ordinary ( opcodes:: Ordinary :: OP_PUSHDATA2 ) => {
807
- if self . data . len ( ) < 3 {
808
- self . data = & [ ] ;
809
- return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
810
- }
811
- let n = match read_uint ( & self . data [ 1 ..] , 2 ) {
812
- Ok ( n) => n,
813
- Err ( e) => {
814
- self . data = & [ ] ;
815
- return Some ( Err ( e) ) ;
816
- }
817
- } ;
818
- if self . enforce_minimal && n < 0x100 {
819
- self . data = & [ ] ;
820
- return Some ( Err ( Error :: NonMinimalPush ) ) ;
821
- }
822
- if self . data . len ( ) < n + 3 {
823
- self . data = & [ ] ;
824
- return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
825
- }
826
- let ret = Some ( Ok ( Instruction :: PushBytes ( & self . data [ 3 ..n + 3 ] ) ) ) ;
827
- self . data = & self . data [ n + 3 ..] ;
828
- ret
834
+ self . next_push_data_len ( 2 , 0x100 )
829
835
}
830
836
opcodes:: Class :: Ordinary ( opcodes:: Ordinary :: OP_PUSHDATA4 ) => {
831
- if self . data . len ( ) < 5 {
832
- self . data = & [ ] ;
833
- return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
834
- }
835
- let n = match read_uint ( & self . data [ 1 ..] , 4 ) {
836
- Ok ( n) => n,
837
- Err ( e) => {
838
- self . data = & [ ] ;
839
- return Some ( Err ( e) ) ;
840
- }
841
- } ;
842
- if self . enforce_minimal && n < 0x10000 {
843
- self . data = & [ ] ;
844
- return Some ( Err ( Error :: NonMinimalPush ) ) ;
845
- }
846
- if self . data . len ( ) < n + 5 {
847
- self . data = & [ ] ;
848
- return Some ( Err ( Error :: EarlyEndOfScript ) ) ;
849
- }
850
- let ret = Some ( Ok ( Instruction :: PushBytes ( & self . data [ 5 ..n + 5 ] ) ) ) ;
851
- self . data = & self . data [ n + 5 ..] ;
852
- ret
837
+ self . next_push_data_len ( 4 , 0x10000 )
853
838
}
854
839
// Everything else we can push right through
855
840
_ => {
856
- let ret = Some ( Ok ( Instruction :: Op ( opcodes:: All :: from ( self . data [ 0 ] ) ) ) ) ;
857
- self . data = & self . data [ 1 ..] ;
858
- ret
841
+ Some ( Ok ( Instruction :: Op ( opcodes:: All :: from ( byte) ) ) )
859
842
}
860
843
}
861
844
}
0 commit comments