@@ -6,11 +6,25 @@ use crate::serialization::{read_n, read_u16, read_u32, write_bytes, write_u16, w
66use crate :: BlackBoxFunc ;
77use serde:: { Deserialize , Serialize } ;
88
9+ #[ derive( Clone , PartialEq , Eq , Serialize , Deserialize , Hash , Copy , Default ) ]
10+ pub struct BlockId ( u32 ) ;
11+
12+ /// Operation on a block
13+ /// We can either write or read at a block index
14+ #[ derive( Clone , PartialEq , Eq , Serialize , Deserialize ) ]
15+ pub struct MemOp {
16+ pub operation : Expression ,
17+ pub index : Expression ,
18+ pub value : Expression ,
19+ }
20+
921#[ derive( Clone , PartialEq , Eq , Serialize , Deserialize ) ]
1022pub enum Opcode {
1123 Arithmetic ( Expression ) ,
1224 BlackBoxFuncCall ( BlackBoxFuncCall ) ,
1325 Directive ( Directive ) ,
26+ // Abstract read/write operations on a block of data
27+ Block ( BlockId , Vec < MemOp > ) ,
1428}
1529
1630impl Opcode {
@@ -21,17 +35,18 @@ impl Opcode {
2135 Opcode :: Arithmetic ( _) => "arithmetic" ,
2236 Opcode :: Directive ( directive) => directive. name ( ) ,
2337 Opcode :: BlackBoxFuncCall ( g) => g. name . name ( ) ,
38+ Opcode :: Block ( _, _) => "block" ,
2439 }
2540 }
26- // We have three types of opcodes allowed in the IR
27- // Expression, BlackBoxFuncCall and Directives
28- // When we serialize these opcodes, we use the index
41+
42+ // When we serialize the opcodes, we use the index
2943 // to uniquely identify which category of opcode we are dealing with.
3044 pub ( crate ) fn to_index ( & self ) -> u8 {
3145 match self {
3246 Opcode :: Arithmetic ( _) => 0 ,
3347 Opcode :: BlackBoxFuncCall ( _) => 1 ,
3448 Opcode :: Directive ( _) => 2 ,
49+ Opcode :: Block ( _, _) => 3 ,
3550 }
3651 }
3752
@@ -53,6 +68,17 @@ impl Opcode {
5368 Opcode :: Arithmetic ( expr) => expr. write ( writer) ,
5469 Opcode :: BlackBoxFuncCall ( func_call) => func_call. write ( writer) ,
5570 Opcode :: Directive ( directive) => directive. write ( writer) ,
71+ Opcode :: Block ( id, trace) => {
72+ write_u32 ( & mut writer, id. 0 ) ?;
73+ write_u32 ( & mut writer, trace. len ( ) as u32 ) ?;
74+
75+ for op in trace {
76+ op. operation . write ( & mut writer) ?;
77+ op. index . write ( & mut writer) ?;
78+ op. value . write ( & mut writer) ?;
79+ }
80+ Ok ( ( ) )
81+ }
5682 }
5783 }
5884 pub fn read < R : Read > ( mut reader : R ) -> std:: io:: Result < Self > {
@@ -74,6 +100,18 @@ impl Opcode {
74100 let directive = Directive :: read ( reader) ?;
75101 Ok ( Opcode :: Directive ( directive) )
76102 }
103+ 3 => {
104+ let id = read_u32 ( & mut reader) ?;
105+ let len = read_u32 ( & mut reader) ?;
106+ let mut trace = Vec :: with_capacity ( len as usize ) ;
107+ for _i in 0 ..len {
108+ let operation = Expression :: read ( & mut reader) ?;
109+ let index = Expression :: read ( & mut reader) ?;
110+ let value = Expression :: read ( & mut reader) ?;
111+ trace. push ( MemOp { operation, index, value } ) ;
112+ }
113+ Ok ( Opcode :: Block ( BlockId ( id) , trace) )
114+ }
77115 _ => Err ( std:: io:: ErrorKind :: InvalidData . into ( ) ) ,
78116 }
79117 }
@@ -175,6 +213,10 @@ impl std::fmt::Display for Opcode {
175213 witnesses. last( ) . unwrap( ) . witness_index( )
176214 ) ,
177215 } ,
216+ Opcode :: Block ( id, trace) => {
217+ write ! ( f, "BLOCK " ) ?;
218+ write ! ( f, "(id: {}, len: {}) " , id. 0 , trace. len( ) )
219+ }
178220 }
179221 }
180222}
0 commit comments