Repository: ergoplatform/sigma-rust (language: rust)

Issue:
Replace instances of `Rc<ErgoBox>` with `Box<ErgoBox>`
Allows `Transaction` and other types to be `Send`, so we can pass it between threads.


Discussion / hints:

Fix patch:
diff --git a/ergo-lib/src/wallet/multi_sig.rs b/ergo-lib/src/wallet/multi_sig.rs
index 2e9cacda0..234581233 100644
--- a/ergo-lib/src/wallet/multi_sig.rs
+++ b/ergo-lib/src/wallet/multi_sig.rs
@@ -29,6 +29,7 @@ use ergotree_interpreter::sigma_protocol::verifier::compute_commitments;
 use ergotree_ir::chain::ergo_box::ErgoBox;
 use std::collections::HashMap;
 use std::rc::Rc;
+use std::sync::Arc;
 
 /// TransactionHintsBag
 #[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))]
@@ -293,7 +294,7 @@ pub fn extract_hints(
             .enumerate()
             .map(|(idx, b)| ErgoBox::from_box_candidate(b, tx_ctx.spending_tx.id(), idx as u16))
             .collect::<Result<Vec<ErgoBox>, SigmaSerializationError>>()?;
-        let outputs_ir = outputs.into_iter().map(Rc::new).collect();
+        let outputs_ir = outputs.into_iter().map(Arc::new).collect();
         let data_inputs_ir = if let Some(data_inputs) = tx_ctx.spending_tx.data_inputs.as_ref() {
             Some(data_inputs.clone().enumerated().try_mapped(|(idx, di)| {
                 tx_ctx
@@ -302,7 +303,7 @@ pub fn extract_hints(
                     .ok_or(TxSigningError::DataInputBoxNotFound(idx))?
                     .iter()
                     .find(|b| di.box_id == b.box_id())
-                    .map(|b| Rc::new(b.clone()))
+                    .map(|b| Arc::new(b.clone()))
                     .ok_or(TxSigningError::DataInputBoxNotFound(idx))
             })?)
         } else {
@@ -315,7 +316,7 @@ pub fn extract_hints(
             .try_mapped(|(idx, u)| {
                 tx_ctx
                     .get_input_box(&u)
-                    .map(Rc::new)
+                    .map(Arc::new)
                     .ok_or(TxSigningError::InputBoxNotFound(idx))
             })?;
         let extension = tx_ctx
@@ -332,7 +333,7 @@ pub fn extract_hints(
             .clone();
         let ctx = Rc::new(Context {
             height,
-            self_box: Rc::new(self_box),
+            self_box: Arc::new(self_box),
             outputs: outputs_ir,
             data_inputs: data_inputs_ir,
             inputs: inputs_ir,
diff --git a/ergo-lib/src/wallet/signing.rs b/ergo-lib/src/wallet/signing.rs
index 43308f234..d6d90a983 100644
--- a/ergo-lib/src/wallet/signing.rs
+++ b/ergo-lib/src/wallet/signing.rs
@@ -12,6 +12,7 @@ use ergotree_ir::chain::ergo_box::ErgoBox;
 use ergotree_ir::serialization::SigmaSerializationError;
 use ergotree_ir::sigma_protocol::sigma_boolean::SigmaBoolean;
 use std::rc::Rc;
+use std::sync::Arc;
 
 use crate::ergotree_ir::chain::ergo_box::BoxId;
 use crate::wallet::multi_sig::TransactionHintsBag;
@@ -112,14 +113,14 @@ pub fn make_context(
                 .ok_or(TxSigningError::DataInputBoxNotFound(idx))?
                 .iter()
                 .find(|b| di.box_id == b.box_id())
-                .map(|b| Rc::new(b.clone()))
+                .map(|b| Arc::new(b.clone()))
                 .ok_or(TxSigningError::DataInputBoxNotFound(idx))
         })?)
     } else {
         None
     };
-    let self_box_ir = Rc::new(self_box);
-    let outputs_ir = outputs.into_iter().map(Rc::new).collect();
+    let self_box_ir = Arc::new(self_box);
+    let outputs_ir = outputs.into_iter().map(Arc::new).collect();
     let inputs_ir = tx_ctx
         .spending_tx
         .inputs_ids()
@@ -127,7 +128,7 @@ pub fn make_context(
         .try_mapped(|(idx, u)| {
             tx_ctx
                 .get_input_box(&u)
-                .map(Rc::new)
+                .map(Arc::new)
                 .ok_or(TxSigningError::InputBoxNotFound(idx))
         })?;
     let extension = tx_ctx
@@ -388,8 +389,8 @@ mod tests {
           )
           .unwrap();
 
-          let expected_data_input_boxes = Some(TxIoVec::from_vec(expected_data_input_boxes).unwrap().mapped(Rc::new));
-          let expected_input_boxes = TxIoVec::from_vec(expected_input_boxes).unwrap().mapped(Rc::new);
+          let expected_data_input_boxes = Some(TxIoVec::from_vec(expected_data_input_boxes).unwrap().mapped(Arc::new));
+          let expected_input_boxes = TxIoVec::from_vec(expected_input_boxes).unwrap().mapped(Arc::new);
           for i in 0..num_inputs {
               let context = make_context(&force_any_val::<ErgoStateContext>(), &tx_context, i).unwrap();
               assert_eq!(expected_data_input_boxes, context.data_inputs);
diff --git a/ergo-nipopow/src/autolykos_pow_scheme.rs b/ergo-nipopow/src/autolykos_pow_scheme.rs
index f43c68fd5..bcaeeb0f5 100644
--- a/ergo-nipopow/src/autolykos_pow_scheme.rs
+++ b/ergo-nipopow/src/autolykos_pow_scheme.rs
@@ -179,7 +179,7 @@ fn as_unsigned_byte_array(
         return Ok(bytes);
     }
 
-    let start = if bytes[0] == 0 { 1 } else { 0 };
+    let start = usize::from(bytes[0] == 0);
     let count = bytes.len() - start;
     if count > length {
         return Err(AutolykosPowSchemeError::BigIntToFixedByteArrayError);
diff --git a/ergo-rest/src/api/node.rs b/ergo-rest/src/api/node.rs
index bec5e4006..1eb818bdd 100644
--- a/ergo-rest/src/api/node.rs
+++ b/ergo-rest/src/api/node.rs
@@ -38,10 +38,10 @@ pub async fn get_info(node: NodeConf) -> Result<NodeInfo, NodeError> {
 pub async fn get_header(node: NodeConf, header_id: BlockId) -> Result<Header, NodeError> {
     let header_str = String::from(header_id.0);
     let mut path = "blocks/".to_owned();
-    path.push_str(&*header_str);
+    path.push_str(&header_str);
     path.push_str("/header");
     #[allow(clippy::unwrap_used)]
-    let url = node.addr.as_http_url().join(&*path).unwrap();
+    let url = node.addr.as_http_url().join(&path).unwrap();
     let client = build_client(&node)?;
     let rb = client.get(url);
     Ok(set_req_headers(rb, node)
@@ -129,13 +129,13 @@ pub async fn get_nipopow_proof_by_header_id(
     }
     let header_str = String::from(header_id.0);
     let mut path = "nipopow/proof/".to_owned();
-    path.push_str(&*min_chain_length.to_string());
+    path.push_str(&min_chain_length.to_string());
     path.push('/');
-    path.push_str(&*suffix_len.to_string());
+    path.push_str(&suffix_len.to_string());
     path.push('/');
-    path.push_str(&*header_str);
+    path.push_str(&header_str);
     #[allow(clippy::unwrap_used)]
-    let url = node.addr.as_http_url().join(&*path).unwrap();
+    let url = node.addr.as_http_url().join(&path).unwrap();
     let client = build_client(&node)?;
     let rb = client.get(url);
     Ok(set_req_headers(rb, node)
@@ -154,12 +154,12 @@ pub async fn get_blocks_header_id_proof_for_tx_id(
 ) -> Result<Option<MerkleProof>, NodeError> {
     let header_str = String::from(header_id.0);
     let mut path = "blocks/".to_owned();
-    path.push_str(&*header_str);
+    path.push_str(&header_str);
     path.push_str("/proofFor/");
     let tx_id_str = String::from(tx_id);
-    path.push_str(&*tx_id_str);
+    path.push_str(&tx_id_str);
     #[allow(clippy::unwrap_used)]
-    let url = node.addr.as_http_url().join(&*path).unwrap();
+    let url = node.addr.as_http_url().join(&path).unwrap();
     let client = build_client(&node)?;
     let rb = client.get(url);
     Ok(set_req_headers(rb, node)
diff --git a/ergotree-interpreter/src/eval/coll_by_index.rs b/ergotree-interpreter/src/eval/coll_by_index.rs
index df40bf938..a79683b59 100644
--- a/ergotree-interpreter/src/eval/coll_by_index.rs
+++ b/ergotree-interpreter/src/eval/coll_by_index.rs
@@ -53,6 +53,7 @@ mod tests {
     use crate::eval::tests::eval_out;
     use crate::eval::tests::eval_out_wo_ctx;
     use std::rc::Rc;
+    use std::sync::Arc;
 
     #[test]
     fn eval() {
@@ -61,7 +62,7 @@ mod tests {
             .into();
         let ctx = Rc::new(force_any_val::<Context>());
         assert_eq!(
-            eval_out::<Rc<ErgoBox>>(&expr, ctx.clone()).box_id(),
+            eval_out::<Arc<ErgoBox>>(&expr, ctx.clone()).box_id(),
             ctx.outputs.get(0).unwrap().box_id()
         );
     }
diff --git a/ergotree-interpreter/src/eval/coll_filter.rs b/ergotree-interpreter/src/eval/coll_filter.rs
index fce88488d..28fc94d82 100644
--- a/ergotree-interpreter/src/eval/coll_filter.rs
+++ b/ergotree-interpreter/src/eval/coll_filter.rs
@@ -73,6 +73,7 @@ impl Evaluable for Filter {
 #[cfg(test)]
 mod tests {
     use std::rc::Rc;
+    use std::sync::Arc;
 
     use crate::eval::context::Context;
     use crate::eval::tests::eval_out;
@@ -142,7 +143,7 @@ mod tests {
                          .collect()
                 );
             assert_eq!(
-                eval_out::<Vec<Rc<ErgoBox>>>(&expr, ctx),
+                eval_out::<Vec<Arc<ErgoBox>>>(&expr, ctx),
                 expected,
             );
         }
diff --git a/ergotree-interpreter/src/eval/context.rs b/ergotree-interpreter/src/eval/context.rs
index f4cecccc6..e63d71b6c 100644
--- a/ergotree-interpreter/src/eval/context.rs
+++ b/ergotree-interpreter/src/eval/context.rs
@@ -1,4 +1,4 @@
-use std::rc::Rc;
+use std::sync::Arc;
 
 use crate::sigma_protocol::prover::ContextExtension;
 use bounded_vec::BoundedVec;
@@ -14,13 +14,13 @@ pub struct Context {
     /// Current height
     pub height: u32,
     /// Box that contains the script we're evaluating (from spending transaction inputs)
-    pub self_box: Rc<ErgoBox>,
+    pub self_box: Arc<ErgoBox>,
     /// Spending transaction outputs
-    pub outputs: Vec<Rc<ErgoBox>>,
+    pub outputs: Vec<Arc<ErgoBox>>,
     /// Spending transaction data inputs
-    pub data_inputs: Option<TxIoVec<Rc<ErgoBox>>>,
+    pub data_inputs: Option<TxIoVec<Arc<ErgoBox>>>,
     /// Spending transaction inputs
-    pub inputs: TxIoVec<Rc<ErgoBox>>,
+    pub inputs: TxIoVec<Arc<ErgoBox>>,
     /// Pre header of current block
     pub pre_header: PreHeader,
     /// Fixed number of last block headers in descending order (first header is the newest one)
@@ -73,12 +73,12 @@ mod arbitrary {
                     )| {
                         Self {
                             height,
-                            self_box: Rc::new(self_box),
-                            outputs: outputs.into_iter().map(Rc::new).collect(),
+                            self_box: Arc::new(self_box),
+                            outputs: outputs.into_iter().map(Arc::new).collect(),
                             data_inputs: data_inputs.map(|v| {
-                                TxIoVec::from_vec(v.into_iter().map(Rc::new).collect()).unwrap()
+                                TxIoVec::from_vec(v.into_iter().map(Arc::new).collect()).unwrap()
                             }),
-                            inputs: TxIoVec::from_vec(inputs.into_iter().map(Rc::new).collect())
+                            inputs: TxIoVec::from_vec(inputs.into_iter().map(Arc::new).collect())
                                 .unwrap(),
                             pre_header,
                             extension,
diff --git a/ergotree-interpreter/src/eval/deserialize_register.rs b/ergotree-interpreter/src/eval/deserialize_register.rs
index 6ea2018f5..f85f119a8 100644
--- a/ergotree-interpreter/src/eval/deserialize_register.rs
+++ b/ergotree-interpreter/src/eval/deserialize_register.rs
@@ -62,6 +62,7 @@ impl Evaluable for DeserializeRegister {
 mod tests {
 
     use std::rc::Rc;
+    use std::sync::Arc;
 
     use ergotree_ir::chain::ergo_box::ErgoBox;
     use ergotree_ir::chain::ergo_box::NonMandatoryRegisters;
@@ -83,7 +84,7 @@ mod tests {
         let ctx = force_any_val::<Context>();
         Context {
             height: 0u32,
-            self_box: Rc::new(self_box),
+            self_box: Arc::new(self_box),
             ..ctx
         }
     }
diff --git a/ergotree-interpreter/src/eval/extract_reg_as.rs b/ergotree-interpreter/src/eval/extract_reg_as.rs
index 50a53253d..2bed11268 100644
--- a/ergotree-interpreter/src/eval/extract_reg_as.rs
+++ b/ergotree-interpreter/src/eval/extract_reg_as.rs
@@ -1,5 +1,5 @@
 use std::convert::TryInto;
-use std::rc::Rc;
+use std::sync::Arc;
 
 use ergotree_ir::chain::ergo_box::ErgoBox;
 use ergotree_ir::mir::constant::TryExtractInto;
@@ -16,7 +16,7 @@ impl Evaluable for ExtractRegisterAs {
         let ir_box = self
             .input
             .eval(env, ctx)?
-            .try_extract_into::<Rc<ErgoBox>>()?;
+            .try_extract_into::<Arc<ErgoBox>>()?;
         Ok(Value::Opt(Box::new(
             ir_box
                 .get_register(self.register_id.try_into().map_err(|e| {
diff --git a/ergotree-interpreter/src/eval/global_vars.rs b/ergotree-interpreter/src/eval/global_vars.rs
index d5e6f04bf..9f1371ee6 100644
--- a/ergotree-interpreter/src/eval/global_vars.rs
+++ b/ergotree-interpreter/src/eval/global_vars.rs
@@ -26,6 +26,7 @@ impl Evaluable for GlobalVars {
 #[cfg(test)]
 mod tests {
     use std::rc::Rc;
+    use std::sync::Arc;
 
     use crate::eval::context::Context;
     use crate::eval::tests::eval_out;
@@ -48,7 +49,7 @@ mod tests {
     fn eval_self_box() {
         let ctx = Rc::new(force_any_val::<Context>());
         assert_eq!(
-            eval_out::<Rc<ErgoBox>>(&GlobalVars::SelfBox.into(), ctx.clone()).as_ref(),
+            eval_out::<Arc<ErgoBox>>(&GlobalVars::SelfBox.into(), ctx.clone()).as_ref(),
             ctx.self_box.as_ref()
         );
     }
@@ -57,7 +58,7 @@ mod tests {
     fn eval_outputs() {
         let ctx = Rc::new(force_any_val::<Context>());
         assert_eq!(
-            eval_out::<Vec<Rc<ErgoBox>>>(&GlobalVars::Outputs.into(), ctx.clone()),
+            eval_out::<Vec<Arc<ErgoBox>>>(&GlobalVars::Outputs.into(), ctx.clone()),
             ctx.outputs
         );
     }
@@ -66,7 +67,7 @@ mod tests {
     fn eval_inputs() {
         let ctx = Rc::new(force_any_val::<Context>());
         assert_eq!(
-            eval_out::<Vec<Rc<ErgoBox>>>(&GlobalVars::Inputs.into(), ctx.clone()),
+            eval_out::<Vec<Arc<ErgoBox>>>(&GlobalVars::Inputs.into(), ctx.clone()),
             *ctx.inputs.as_vec()
         );
     }
diff --git a/ergotree-interpreter/src/eval/property_call.rs b/ergotree-interpreter/src/eval/property_call.rs
index d47d0bc51..c36479b25 100644
--- a/ergotree-interpreter/src/eval/property_call.rs
+++ b/ergotree-interpreter/src/eval/property_call.rs
@@ -25,6 +25,7 @@ mod tests {
     use ergotree_ir::types::scontext;
     use sigma_test_util::force_any_val;
     use std::rc::Rc;
+    use std::sync::Arc;
 
     #[test]
     fn eval_context_data_inputs() {
@@ -36,6 +37,6 @@ mod tests {
             .data_inputs
             .clone()
             .map_or(vec![], |d| d.as_vec().clone());
-        assert_eq!(eval_out::<Vec<Rc<ErgoBox>>>(&pc, ctx), expected,);
+        assert_eq!(eval_out::<Vec<Arc<ErgoBox>>>(&pc, ctx), expected,);
     }
 }
diff --git a/ergotree-interpreter/src/eval/sbox.rs b/ergotree-interpreter/src/eval/sbox.rs
index 3fd96f46b..fa19a8907 100644
--- a/ergotree-interpreter/src/eval/sbox.rs
+++ b/ergotree-interpreter/src/eval/sbox.rs
@@ -1,5 +1,5 @@
 use std::convert::TryInto;
-use std::rc::Rc;
+use std::sync::Arc;
 
 use crate::eval::EvalError;
 
@@ -11,13 +11,13 @@ use super::EvalFn;
 
 pub(crate) static VALUE_EVAL_FN: EvalFn = |_env, _ctx, obj, _args| {
     Ok(Value::Long(
-        obj.try_extract_into::<Rc<ErgoBox>>()?.value.as_i64(),
+        obj.try_extract_into::<Arc<ErgoBox>>()?.value.as_i64(),
     ))
 };
 
 pub(crate) static GET_REG_EVAL_FN: EvalFn = |_env, _ctx, obj, args| {
     Ok(Value::Opt(Box::new(
-        obj.try_extract_into::<Rc<ErgoBox>>()?
+        obj.try_extract_into::<Arc<ErgoBox>>()?
             .get_register(
                 args.get(0)
                     .cloned()
@@ -36,7 +36,7 @@ pub(crate) static GET_REG_EVAL_FN: EvalFn = |_env, _ctx, obj, args| {
 };
 
 pub(crate) static TOKENS_EVAL_FN: EvalFn = |_env, _ctx, obj, _args| {
-    let res: Value = obj.try_extract_into::<Rc<ErgoBox>>()?.tokens_raw().into();
+    let res: Value = obj.try_extract_into::<Arc<ErgoBox>>()?.tokens_raw().into();
     Ok(res)
 };
 
diff --git a/ergotree-ir/src/mir/constant.rs b/ergotree-ir/src/mir/constant.rs
index 58e9f21d2..e3ff14b09 100644
--- a/ergotree-ir/src/mir/constant.rs
+++ b/ergotree-ir/src/mir/constant.rs
@@ -26,7 +26,7 @@ use sigma_util::AsVecU8;
 use std::convert::TryFrom;
 use std::convert::TryInto;
 use std::fmt::Formatter;
-use std::rc::Rc;
+use std::sync::Arc;
 
 mod constant_placeholder;
 
@@ -73,7 +73,7 @@ pub enum Literal {
     /// AVL tree
     AvlTree(Box<AvlTreeData>),
     /// Ergo box
-    CBox(Rc<ErgoBox>),
+    CBox(Arc<ErgoBox>),
     /// Collection
     Coll(CollKind<Literal>),
     /// Option type
@@ -166,15 +166,15 @@ impl From<EcPoint> for Literal {
     }
 }
 
-impl From<Rc<ErgoBox>> for Literal {
-    fn from(b: Rc<ErgoBox>) -> Self {
+impl From<Arc<ErgoBox>> for Literal {
+    fn from(b: Arc<ErgoBox>) -> Self {
         Literal::CBox(b)
     }
 }
 
 impl From<ErgoBox> for Literal {
     fn from(b: ErgoBox) -> Self {
-        Literal::CBox(Rc::new(b))
+        Literal::CBox(Arc::new(b))
     }
 }
 
@@ -370,8 +370,8 @@ impl From<EcPoint> for Constant {
     }
 }
 
-impl From<Rc<ErgoBox>> for Constant {
-    fn from(b: Rc<ErgoBox>) -> Self {
+impl From<Arc<ErgoBox>> for Constant {
+    fn from(b: Arc<ErgoBox>) -> Self {
         Constant {
             tpe: SType::SBox,
             v: b.into(),
@@ -629,7 +629,7 @@ impl TryExtractFrom<Literal> for SigmaProp {
     }
 }
 
-impl TryExtractFrom<Literal> for Rc<ErgoBox> {
+impl TryExtractFrom<Literal> for Arc<ErgoBox> {
     fn try_extract_from(c: Literal) -> Result<Self, TryExtractFromError> {
         match c {
             Literal::CBox(b) => Ok(b),
diff --git a/ergotree-ir/src/mir/value.rs b/ergotree-ir/src/mir/value.rs
index d23af558c..45b5416b4 100644
--- a/ergotree-ir/src/mir/value.rs
+++ b/ergotree-ir/src/mir/value.rs
@@ -1,7 +1,7 @@
 //! Ergo data type
 
 use std::convert::TryInto;
-use std::rc::Rc;
+use std::sync::Arc;
 
 use impl_trait_for_tuples::impl_for_tuples;
 use sigma_util::AsVecI8;
@@ -154,7 +154,7 @@ pub enum Value {
     /// Sigma property
     SigmaProp(Box<SigmaProp>),
     /// Ergo box
-    CBox(Rc<ErgoBox>),
+    CBox(Arc<ErgoBox>),
     /// AVL tree
     AvlTree(Box<AvlTreeData>),
     /// Collection of values of the same type
@@ -251,7 +251,7 @@ impl StoreWrapped for i32 {}
 impl StoreWrapped for i64 {}
 impl StoreWrapped for BigInt256 {}
 impl StoreWrapped for Header {}
-impl StoreWrapped for Rc<ErgoBox> {}
+impl StoreWrapped for Arc<ErgoBox> {}
 impl StoreWrapped for EcPoint {}
 impl StoreWrapped for SigmaProp {}
 impl<T: StoreWrapped> StoreWrapped for Option<T> {}
@@ -281,8 +281,8 @@ impl Into<Value> for Tuple {
     }
 }
 
-impl From<Vec<Rc<ErgoBox>>> for Value {
-    fn from(v: Vec<Rc<ErgoBox>>) -> Self {
+impl From<Vec<Arc<ErgoBox>>> for Value {
+    fn from(v: Vec<Arc<ErgoBox>>) -> Self {
         Value::Coll(CollKind::WrappedColl {
             elem_tpe: SType::SBox,
             items: v.into_iter().map(|i| i.into()).collect(),
@@ -362,7 +362,7 @@ impl TryExtractFrom<Value> for SigmaProp {
     }
 }
 
-impl TryExtractFrom<Value> for Rc<ErgoBox> {
+impl TryExtractFrom<Value> for Arc<ErgoBox> {
     fn try_extract_from(c: Value) -> Result<Self, TryExtractFromError> {
         match c {
             Value::CBox(b) => Ok(b),
diff --git a/ergotree-ir/src/serialization/data.rs b/ergotree-ir/src/serialization/data.rs
index 008d3ae32..b977a708a 100644
--- a/ergotree-ir/src/serialization/data.rs
+++ b/ergotree-ir/src/serialization/data.rs
@@ -19,7 +19,7 @@ use ergo_chain_types::EcPoint;
 
 use super::sigma_byte_writer::SigmaByteWrite;
 use std::convert::TryInto;
-use std::rc::Rc;
+use std::sync::Arc;
 
 /// Used to serialize and parse `Literal` and `Value`.
 pub struct DataSerializer {}
@@ -29,7 +29,7 @@ impl DataSerializer {
         // for reference see http://github.com/ScorexFoundation/sigmastate-interpreter/blob/25251c1313b0131835f92099f02cef8a5d932b5e/sigmastate/src/main/scala/sigmastate/serialization/DataSerializer.scala#L26-L26
         Ok(match c {
             Literal::Unit => (),
-            Literal::Boolean(v) => w.put_u8(if *v { 1 } else { 0 })?,
+            Literal::Boolean(v) => w.put_u8(u8::from(*v))?,
             Literal::Byte(v) => w.put_i8(*v)?,
             Literal::Short(v) => w.put_i16(*v)?,
             Literal::Int(v) => w.put_i32(*v)?,
@@ -149,7 +149,7 @@ impl DataSerializer {
                 // is correct
                 Literal::Tup(items.try_into()?)
             }
-            SBox => Literal::CBox(Rc::new(ErgoBox::sigma_parse(r)?)),
+            SBox => Literal::CBox(Arc::new(ErgoBox::sigma_parse(r)?)),
             SAvlTree => Literal::AvlTree(Box::new(AvlTreeData::sigma_parse(r)?)),
             STypeVar(_) => return Err(SigmaParsingError::NotSupported("TypeVar data")),
             SAny => return Err(SigmaParsingError::NotSupported("SAny data")),
diff --git a/ergotree-ir/src/types/stype_companion.rs b/ergotree-ir/src/types/stype_companion.rs
index f07411b0a..1694ae873 100644
--- a/ergotree-ir/src/types/stype_companion.rs
+++ b/ergotree-ir/src/types/stype_companion.rs
@@ -45,15 +45,15 @@ pub enum STypeCompanion {
 impl STypeCompanion {
     fn method_desc<'a>(&'a self) -> &'a Vec<&'static SMethodDesc> {
         match self {
-            STypeCompanion::Context => &*scontext::METHOD_DESC,
-            STypeCompanion::Box => &*sbox::METHOD_DESC,
-            STypeCompanion::Coll => &*scoll::METHOD_DESC,
-            STypeCompanion::GroupElem => &*sgroup_elem::METHOD_DESC,
-            STypeCompanion::Global => &*sglobal::METHOD_DESC,
-            STypeCompanion::Header => &*sheader::METHOD_DESC,
-            STypeCompanion::PreHeader => &*spreheader::METHOD_DESC,
-            STypeCompanion::Option => &*soption::METHOD_DESC,
-            STypeCompanion::AvlTree => &*savltree::METHOD_DESC,
+            STypeCompanion::Context => &scontext::METHOD_DESC,
+            STypeCompanion::Box => &sbox::METHOD_DESC,
+            STypeCompanion::Coll => &scoll::METHOD_DESC,
+            STypeCompanion::GroupElem => &sgroup_elem::METHOD_DESC,
+            STypeCompanion::Global => &sglobal::METHOD_DESC,
+            STypeCompanion::Header => &sheader::METHOD_DESC,
+            STypeCompanion::PreHeader => &spreheader::METHOD_DESC,
+            STypeCompanion::Option => &soption::METHOD_DESC,
+            STypeCompanion::AvlTree => &savltree::METHOD_DESC,
         }
     }
 


Test patch: