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

Issue:
Box.R0-R3 access



Discussion / hints:

Fix patch:
diff --git a/ergo-lib/CHANGELOG.md b/ergo-lib/CHANGELOG.md
index d5135ba95..fd106d6ec 100644
--- a/ergo-lib/CHANGELOG.md
+++ b/ergo-lib/CHANGELOG.md
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ### Added 
 - `proveDlog`, `box.creationInfo`, `Box.id`, `Coll.exists`, `SigmaProp.propBytes`, `Option.isDefined`, `Option.getOrElse` IR nodes (evaluation, serialization) [#209](https://github.com/ergoplatform/sigma-rust/pull/209);
+- `Box.R0..R3` register access [#213](https://github.com/ergoplatform/sigma-rust/pull/213);
 
 ## [0.7.0] - 2021-03-03
 
diff --git a/ergo-lib/src/chain/ergo_box.rs b/ergo-lib/src/chain/ergo_box.rs
index b9ec772cb..2e03dd0f8 100644
--- a/ergo-lib/src/chain/ergo_box.rs
+++ b/ergo-lib/src/chain/ergo_box.rs
@@ -8,18 +8,20 @@ mod register;
 pub use box_id::*;
 pub use box_value::*;
 use ergotree_ir::ergo_tree::ErgoTree;
+use ergotree_ir::ir_ergo_box::IrBoxId;
 use ergotree_ir::ir_ergo_box::IrErgoBox;
 use ergotree_ir::mir::constant::Constant;
 use ergotree_ir::serialization::sigma_byte_reader::SigmaByteRead;
 use ergotree_ir::serialization::sigma_byte_writer::SigmaByteWrite;
 use ergotree_ir::serialization::SerializationError;
 use ergotree_ir::serialization::SigmaSerializable;
+use ergotree_ir::util::AsVecI8;
 pub use register::*;
-use sigma_util::DIGEST32_SIZE;
 
 #[cfg(feature = "json")]
 use super::json;
 use super::token::TokenAmount;
+use super::Digest32;
 use super::{
     digest32::blake2b256_hash,
     token::{Token, TokenId},
@@ -155,7 +157,9 @@ impl ErgoBox {
         match id {
             RegisterId::MandatoryRegisterId(id) => match id {
                 MandatoryRegisterId::R0 => Some(self.value.clone().into()),
-                _ => todo!(),
+                MandatoryRegisterId::R1 => Some(self.script_bytes().into()),
+                MandatoryRegisterId::R2 => Some(self.tokens_raw().into()),
+                MandatoryRegisterId::R3 => Some(self.creation_info().into()),
             },
             RegisterId::NonMandatoryRegisterId(id) => self.additional_registers.get(id).cloned(),
         }
@@ -163,15 +167,15 @@ impl ErgoBox {
 }
 
 impl IrErgoBox for ErgoBox {
-    fn id(&self) -> &[u8; DIGEST32_SIZE] {
-        &self.box_id.0 .0
+    fn id(&self) -> IrBoxId {
+        self.box_id.clone().into()
     }
 
     fn value(&self) -> i64 {
         self.value.as_i64()
     }
 
-    fn tokens(&self) -> Vec<(Vec<i8>, i64)> {
+    fn tokens_raw(&self) -> Vec<(Vec<i8>, i64)> {
         self.tokens
             .clone()
             .into_iter()
@@ -193,8 +197,17 @@ impl IrErgoBox for ErgoBox {
         self.creation_height as i32
     }
 
-    fn script_bytes(&self) -> Vec<u8> {
-        self.sigma_serialize_bytes()
+    fn script_bytes(&self) -> Vec<i8> {
+        self.sigma_serialize_bytes().as_vec_i8()
+    }
+
+    /// Tuple of height when block got included into the blockchain and transaction identifier with
+    /// box index in the transaction outputs serialized to the byte array.
+    fn creation_info(&self) -> (i32, Vec<i8>) {
+        let mut bytes = Vec::with_capacity(Digest32::SIZE + 2);
+        bytes.extend_from_slice(self.transaction_id.0 .0.as_ref());
+        bytes.extend_from_slice(&self.index.to_be_bytes());
+        (self.creation_height as i32, bytes.as_vec_i8())
     }
 }
 
@@ -520,7 +533,6 @@ mod tests {
 
     use super::box_value::tests::ArbBoxValueRange;
     use super::*;
-    use ergotree_ir::mir::constant::TryExtractInto;
     use ergotree_ir::serialization::sigma_serialize_roundtrip;
     use proptest::{arbitrary::Arbitrary, collection::vec, prelude::*};
     use sigma_test_util::force_any_val;
@@ -599,15 +611,31 @@ mod tests {
     #[test]
     fn get_register_mandatory() {
         let b = force_any_val::<ErgoBox>();
+        assert_eq!(b.get_register(RegisterId::R0).unwrap(), b.value.into());
+        assert_eq!(
+            b.get_register(RegisterId::R1).unwrap(),
+            b.script_bytes().into()
+        );
+        assert_eq!(
+            b.get_register(RegisterId::R2).unwrap(),
+            b.tokens_raw().into()
+        );
         assert_eq!(
-            b.value.as_i64(),
-            b.get_register(RegisterId::R0)
-                .unwrap()
-                .try_extract_into::<i64>()
-                .unwrap()
+            b.get_register(RegisterId::R3).unwrap(),
+            b.creation_info().into()
         );
     }
 
+    #[test]
+    fn creation_info() {
+        let b = force_any_val::<ErgoBox>();
+        assert_eq!(b.creation_info().0, b.creation_height as i32);
+        let mut expected_bytes = Vec::new();
+        expected_bytes.extend_from_slice(b.transaction_id.0 .0.as_ref());
+        expected_bytes.extend_from_slice(&b.index.to_be_bytes());
+        assert_eq!(b.creation_info().1, expected_bytes.to_vec().as_vec_i8());
+    }
+
     proptest! {
 
         #[test]
diff --git a/ergo-lib/src/chain/ergo_box/box_id.rs b/ergo-lib/src/chain/ergo_box/box_id.rs
index 458361da4..6d66849f0 100644
--- a/ergo-lib/src/chain/ergo_box/box_id.rs
+++ b/ergo-lib/src/chain/ergo_box/box_id.rs
@@ -1,7 +1,9 @@
 //! Box id type
+use std::convert::TryInto;
 use std::io;
 
 use ergotree_ir::ir_ergo_box::IrBoxId;
+
 #[cfg(feature = "json")]
 use serde::{Deserialize, Serialize};
 
@@ -44,7 +46,16 @@ impl Into<String> for BoxId {
 
 impl From<&IrBoxId> for BoxId {
     fn from(irb: &IrBoxId) -> Self {
-        BoxId(irb.0.into())
+        let u8bytes: Vec<u8> = irb.0.iter().map(|b| *b as u8).collect();
+        let arr: [u8; Digest32::SIZE] = u8bytes.as_slice().try_into().unwrap();
+        BoxId(arr.into())
+    }
+}
+
+impl From<BoxId> for IrBoxId {
+    fn from(id: BoxId) -> Self {
+        let i8bytes: Vec<i8> = id.0 .0.iter().map(|b| *b as i8).collect();
+        IrBoxId::new(i8bytes.try_into().unwrap())
     }
 }
 
diff --git a/ergo-lib/src/chain/ergo_box/register.rs b/ergo-lib/src/chain/ergo_box/register.rs
index 9041a59ac..79be12768 100644
--- a/ergo-lib/src/chain/ergo_box/register.rs
+++ b/ergo-lib/src/chain/ergo_box/register.rs
@@ -23,6 +23,12 @@ pub enum RegisterId {
 impl RegisterId {
     /// R0 register id (box.value)
     pub const R0: RegisterId = RegisterId::MandatoryRegisterId(MandatoryRegisterId::R0);
+    /// R1 register id (serialized ErgoTree)
+    pub const R1: RegisterId = RegisterId::MandatoryRegisterId(MandatoryRegisterId::R1);
+    /// R2 register id (tokens)
+    pub const R2: RegisterId = RegisterId::MandatoryRegisterId(MandatoryRegisterId::R2);
+    /// R2 register id (creationInfo)
+    pub const R3: RegisterId = RegisterId::MandatoryRegisterId(MandatoryRegisterId::R3);
 }
 
 /// Register id out of bounds error (not in 0-9 range)
diff --git a/ergo-lib/src/wallet/signing.rs b/ergo-lib/src/wallet/signing.rs
index 0317e3d61..1b153bd9e 100644
--- a/ergo-lib/src/wallet/signing.rs
+++ b/ergo-lib/src/wallet/signing.rs
@@ -75,12 +75,6 @@ impl IrErgoBoxArena for ErgoBoxArena {
     }
 }
 
-impl From<BoxId> for IrBoxId {
-    fn from(id: BoxId) -> Self {
-        IrBoxId::new(*id.0 .0)
-    }
-}
-
 /// `self_index` - index of the SELF box in the tx_ctx.boxes_to_spend
 pub fn make_context(
     state_ctx: &ErgoStateContext,
diff --git a/ergotree-interpreter/src/eval/context.rs b/ergotree-interpreter/src/eval/context.rs
index 9ed490ce9..baf7578a4 100644
--- a/ergotree-interpreter/src/eval/context.rs
+++ b/ergotree-interpreter/src/eval/context.rs
@@ -26,6 +26,7 @@ mod arbitrary {
 
     use super::ir_ergo_box_dummy::*;
     use super::*;
+    use ergotree_ir::ir_ergo_box::IrErgoBox;
     use proptest::collection::vec;
     use proptest::prelude::*;
 
@@ -40,16 +41,16 @@ mod arbitrary {
                 vec(any::<IrErgoBoxDummy>(), 0..3),
             )
                 .prop_map(|(height, self_box, outputs, data_inputs)| {
-                    let self_box_id = self_box.id.clone();
-                    let outputs_ids = outputs.iter().map(|b| b.id.clone()).collect();
-                    let data_inputs_ids = data_inputs.iter().map(|b| b.id.clone()).collect();
+                    let self_box_id = self_box.id();
+                    let outputs_ids = outputs.iter().map(|b| b.id()).collect();
+                    let data_inputs_ids = data_inputs.iter().map(|b| b.id()).collect();
                     let mut m = HashMap::new();
                     m.insert(self_box_id.clone(), self_box);
                     outputs.into_iter().for_each(|b| {
-                        m.insert(b.id.clone(), b);
+                        m.insert(b.id(), b);
                     });
                     data_inputs.into_iter().for_each(|b| {
-                        m.insert(b.id.clone(), b);
+                        m.insert(b.id(), b);
                     });
                     let box_arena = IrErgoBoxDummyArena(m);
                     Self {
diff --git a/ergotree-interpreter/src/eval/context/ir_ergo_box_dummy.rs b/ergotree-interpreter/src/eval/context/ir_ergo_box_dummy.rs
index d672e2576..a909903b7 100644
--- a/ergotree-interpreter/src/eval/context/ir_ergo_box_dummy.rs
+++ b/ergotree-interpreter/src/eval/context/ir_ergo_box_dummy.rs
@@ -6,7 +6,6 @@ use ergotree_ir::ir_ergo_box::IrErgoBox;
 use ergotree_ir::ir_ergo_box::IrErgoBoxArena;
 use ergotree_ir::ir_ergo_box::IrErgoBoxArenaError;
 use ergotree_ir::mir::constant::Constant;
-use sigma_util::DIGEST32_SIZE;
 
 #[derive(PartialEq, Eq, Debug, Clone)]
 pub(crate) struct IrErgoBoxDummyArena(pub HashMap<IrBoxId, IrErgoBoxDummy>);
@@ -23,25 +22,25 @@ impl IrErgoBoxArena for IrErgoBoxDummyArena {
 
 #[derive(PartialEq, Eq, Debug, Clone)]
 pub(crate) struct IrErgoBoxDummy {
-    pub(crate) id: IrBoxId,
-    pub(crate) value: i64,
-    pub(crate) tokens: Vec<(Vec<i8>, i64)>,
-    pub(crate) additional_registers: Vec<Constant>,
-    pub(crate) creation_height: i32,
-    pub(crate) script_bytes: Vec<u8>,
-    pub(crate) creation_info: (i32, Vec<u8>),
+    id: IrBoxId,
+    value: i64,
+    tokens: Vec<(Vec<i8>, i64)>,
+    additional_registers: Vec<Constant>,
+    creation_height: i32,
+    script_bytes: Vec<i8>,
+    creation_info: (i32, Vec<i8>),
 }
 
 impl IrErgoBox for IrErgoBoxDummy {
-    fn id(&self) -> &[u8; DIGEST32_SIZE] {
-        &self.id.0
+    fn id(&self) -> IrBoxId {
+        self.id.clone()
     }
 
     fn value(&self) -> i64 {
         self.value
     }
 
-    fn tokens(&self) -> Vec<(Vec<i8>, i64)> {
+    fn tokens_raw(&self) -> Vec<(Vec<i8>, i64)> {
         self.tokens.clone()
     }
 
@@ -52,6 +51,8 @@ impl IrErgoBox for IrErgoBoxDummy {
     fn get_register(&self, id: i8) -> Option<Constant> {
         match id {
             0 => Some(self.value.into()),
+            1 => Some(self.script_bytes.clone().into()),
+            2 => Some(self.tokens.clone().into()),
             3 => Some(self.creation_info.clone().into()),
             _ => self.additional_registers.get(id as usize).cloned(),
         }
@@ -61,17 +62,21 @@ impl IrErgoBox for IrErgoBoxDummy {
         self.creation_height
     }
 
-    fn script_bytes(&self) -> Vec<u8> {
+    fn script_bytes(&self) -> Vec<i8> {
         self.script_bytes.clone()
     }
+
+    fn creation_info(&self) -> (i32, Vec<i8>) {
+        self.creation_info.clone()
+    }
 }
 
 #[cfg(feature = "arbitrary")]
 /// Arbitrary impl
 pub(crate) mod arbitrary {
+    use sigma_util::DIGEST32_SIZE;
 
     use super::*;
-    use ergotree_ir::util::AsVecI8;
     use proptest::collection::vec;
     use proptest::prelude::*;
 
@@ -82,13 +87,13 @@ pub(crate) mod arbitrary {
 
         fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
             (
-                any::<[u8; DIGEST32_SIZE]>(),
+                any::<[i8; DIGEST32_SIZE]>(),
                 100000i64..999999999,
-                vec(any::<([u8; DIGEST32_SIZE], u64)>(), 0..3),
+                vec(any::<([i8; DIGEST32_SIZE], u64)>(), 0..3),
                 1i32..1000,
                 vec(any::<Constant>(), 0..5),
-                vec(any::<u8>(), 100..1000),
-                vec(any::<u8>(), DIGEST32_SIZE + 2..=DIGEST32_SIZE + 2),
+                vec(any::<i8>(), 100..1000),
+                vec(any::<i8>(), DIGEST32_SIZE + 2..=DIGEST32_SIZE + 2),
             )
                 .prop_map(
                     |(
@@ -105,7 +110,7 @@ pub(crate) mod arbitrary {
                             value,
                             tokens: tokens
                                 .into_iter()
-                                .map(|(id, amount)| (id.to_vec().as_vec_i8(), abs(amount as i64)))
+                                .map(|(id, amount)| (id.to_vec(), abs(amount as i64)))
                                 .collect(),
                             additional_registers,
                             creation_height,
@@ -119,3 +124,19 @@ pub(crate) mod arbitrary {
         type Strategy = BoxedStrategy<Self>;
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use sigma_test_util::force_any_val;
+
+    use super::*;
+
+    #[test]
+    fn get_register() {
+        let b = force_any_val::<IrErgoBoxDummy>();
+        assert_eq!(b.get_register(0).unwrap(), b.value().into());
+        assert_eq!(b.get_register(1).unwrap(), b.script_bytes().into());
+        assert_eq!(b.get_register(2).unwrap(), b.tokens_raw().into());
+        assert_eq!(b.get_register(3).unwrap(), b.creation_info().into());
+    }
+}
diff --git a/ergotree-interpreter/src/eval/extract_creation_info.rs b/ergotree-interpreter/src/eval/extract_creation_info.rs
index 1618308cf..4dca2cb0e 100644
--- a/ergotree-interpreter/src/eval/extract_creation_info.rs
+++ b/ergotree-interpreter/src/eval/extract_creation_info.rs
@@ -10,13 +10,7 @@ impl Evaluable for ExtractCreationInfo {
     fn eval(&self, env: &Env, ctx: &mut EvalContext) -> Result<Value, EvalError> {
         let input_v = self.input.eval(env, ctx)?;
         match input_v {
-            Value::CBox(b) => Ok(ctx
-                .ctx
-                .box_arena
-                .get(&b)?
-                .get_register(3)
-                .map(|c| c.v)
-                .unwrap()), // unwrap() is safe because R3 is a mandatory register and cannot be empty
+            Value::CBox(b) => Ok(ctx.ctx.box_arena.get(&b)?.creation_info().into()),
             _ => Err(EvalError::UnexpectedValue(format!(
                 "Expected ExtractCreationInfo input to be Value::CBox, got {0:?}",
                 input_v
@@ -31,7 +25,6 @@ mod tests {
     use crate::eval::Context;
     use std::rc::Rc;
 
-    use ergotree_ir::mir::constant::TryExtractInto;
     use ergotree_ir::mir::expr::Expr;
     use ergotree_ir::mir::global_vars::GlobalVars;
     use sigma_test_util::force_any_val;
@@ -44,17 +37,13 @@ mod tests {
             .unwrap()
             .into();
         let ctx = Rc::new(force_any_val::<Context>());
-        let v = eval_out::<(i32, Vec<u8>)>(&expr, ctx.clone());
+        let v = eval_out::<(i32, Vec<i8>)>(&expr, ctx.clone());
         assert_eq!(
             v,
             ctx.self_box
                 .get_box(&ctx.box_arena)
                 .unwrap()
-                .get_register(3)
-                .unwrap()
-                .v
-                .try_extract_into::<(i32, Vec<u8>)>()
-                .unwrap()
+                .creation_info()
         );
     }
 }
diff --git a/ergotree-interpreter/src/eval/extract_id.rs b/ergotree-interpreter/src/eval/extract_id.rs
index f6de7be58..cf7e4ba69 100644
--- a/ergotree-interpreter/src/eval/extract_id.rs
+++ b/ergotree-interpreter/src/eval/extract_id.rs
@@ -10,7 +10,7 @@ impl Evaluable for ExtractId {
     fn eval(&self, env: &Env, ctx: &mut EvalContext) -> Result<Value, EvalError> {
         let input_v = self.input.eval(env, ctx)?;
         match input_v {
-            Value::CBox(b) => Ok((ctx.ctx.box_arena.get(&b)?.id()).to_vec().into()),
+            Value::CBox(b) => Ok(ctx.ctx.box_arena.get(&b)?.id().to_bytes().into()),
             _ => Err(EvalError::UnexpectedValue(format!(
                 "Expected ExtractId input to be Value::CBox, got {0:?}",
                 input_v
@@ -37,8 +37,12 @@ mod tests {
         .into();
         let ctx = Rc::new(force_any_val::<Context>());
         assert_eq!(
-            eval_out::<Vec<u8>>(&e, ctx.clone()),
-            ctx.self_box.get_box(&ctx.box_arena).unwrap().id().to_vec()
+            eval_out::<Vec<i8>>(&e, ctx.clone()),
+            ctx.self_box
+                .get_box(&ctx.box_arena)
+                .unwrap()
+                .id()
+                .to_bytes()
         );
     }
 }
diff --git a/ergotree-interpreter/src/eval/extract_reg_as.rs b/ergotree-interpreter/src/eval/extract_reg_as.rs
index aed33bf01..a291a9af7 100644
--- a/ergotree-interpreter/src/eval/extract_reg_as.rs
+++ b/ergotree-interpreter/src/eval/extract_reg_as.rs
@@ -34,7 +34,7 @@ mod tests {
     use std::rc::Rc;
 
     #[test]
-    fn eval_box_get_reg() {
+    fn eval_box_get_reg_r0() {
         let get_reg_expr: Expr = ExtractRegisterAs::new(
             GlobalVars::SelfBox.into(),
             0,
diff --git a/ergotree-interpreter/src/eval/extract_script_bytes.rs b/ergotree-interpreter/src/eval/extract_script_bytes.rs
index df1c142c6..84a8400da 100644
--- a/ergotree-interpreter/src/eval/extract_script_bytes.rs
+++ b/ergotree-interpreter/src/eval/extract_script_bytes.rs
@@ -37,7 +37,7 @@ mod tests {
         .into();
         let ctx = Rc::new(force_any_val::<Context>());
         assert_eq!(
-            eval_out::<Vec<u8>>(&e, ctx.clone()),
+            eval_out::<Vec<i8>>(&e, ctx.clone()),
             ctx.self_box.get_box(&ctx.box_arena).unwrap().script_bytes()
         );
     }
diff --git a/ergotree-interpreter/src/eval/sbox.rs b/ergotree-interpreter/src/eval/sbox.rs
index bfa72fcd8..fd7dcb3e0 100644
--- a/ergotree-interpreter/src/eval/sbox.rs
+++ b/ergotree-interpreter/src/eval/sbox.rs
@@ -32,7 +32,7 @@ pub static TOKENS_EVAL_FN: EvalFn = |ctx, obj, _args| {
     let res: Value = obj
         .try_extract_into::<IrBoxId>()?
         .get_box(&ctx.box_arena)?
-        .tokens()
+        .tokens_raw()
         .into();
     Ok(res)
 };
@@ -74,7 +74,7 @@ mod tests {
         let ctx = Rc::new(force_any_val::<Context>());
         assert_eq!(
             eval_out::<Vec<(Vec<i8>, i64)>>(&expr, ctx.clone()),
-            ctx.self_box.get_box(&ctx.box_arena).unwrap().tokens()
+            ctx.self_box.get_box(&ctx.box_arena).unwrap().tokens_raw()
         );
     }
 }
diff --git a/ergotree-ir/src/ir_ergo_box.rs b/ergotree-ir/src/ir_ergo_box.rs
index 3ac4857db..2bc986b1d 100644
--- a/ergotree-ir/src/ir_ergo_box.rs
+++ b/ergotree-ir/src/ir_ergo_box.rs
@@ -7,11 +7,11 @@ use thiserror::Error;
 
 /// Ergo box id
 #[derive(PartialEq, Eq, Debug, Clone, Hash)]
-pub struct IrBoxId(pub [u8; DIGEST32_SIZE]);
+pub struct IrBoxId(pub [i8; DIGEST32_SIZE]);
 
 impl IrBoxId {
     /// Make new box id
-    pub fn new(id: [u8; DIGEST32_SIZE]) -> Self {
+    pub fn new(id: [i8; DIGEST32_SIZE]) -> Self {
         IrBoxId(id)
     }
 
@@ -22,6 +22,11 @@ impl IrBoxId {
     ) -> Result<Rc<dyn IrErgoBox>, IrErgoBoxArenaError> {
         arena.get(self)
     }
+
+    /// Returns id as byte array
+    pub fn to_bytes(&self) -> Vec<i8> {
+        self.0.to_vec()
+    }
 }
 
 /// Arena (store) for boxes
@@ -38,11 +43,11 @@ pub struct IrErgoBoxArenaError(pub String);
 /// Ergo box properties
 pub trait IrErgoBox: Debug {
     /// Box id
-    fn id(&self) -> &[u8; DIGEST32_SIZE];
+    fn id(&self) -> IrBoxId;
     /// Box value
     fn value(&self) -> i64;
     /// Box tokens
-    fn tokens(&self) -> Vec<(Vec<i8>, i64)>;
+    fn tokens_raw(&self) -> Vec<(Vec<i8>, i64)>;
     /// R4-R9 optional registers, where element with index 0 is R4, etc.
     fn additional_registers(&self) -> &[Constant];
     /// Returns a register value for the given register index (0 is R0, 9 is R9)
@@ -50,5 +55,8 @@ pub trait IrErgoBox: Debug {
     /// Box creation height
     fn creation_height(&self) -> i32;
     /// Box guarding script serialized
-    fn script_bytes(&self) -> Vec<u8>;
+    fn script_bytes(&self) -> Vec<i8>;
+    /// Tuple of height when block got included into the blockchain and transaction identifier with
+    /// box index in the transaction outputs serialized to the byte array.
+    fn creation_info(&self) -> (i32, Vec<i8>);
 }
diff --git a/ergotree-ir/src/mir/extract_reg_as.rs b/ergotree-ir/src/mir/extract_reg_as.rs
index 18a24ddd8..5b9b4f156 100644
--- a/ergotree-ir/src/mir/extract_reg_as.rs
+++ b/ergotree-ir/src/mir/extract_reg_as.rs
@@ -8,12 +8,12 @@ use crate::types::stype::SType;
 use super::expr::Expr;
 use super::expr::InvalidArgumentError;
 
-/// Get box register value (Box.R1 - R9)
+/// Get box register value (Box.R0 - R9)
 #[derive(PartialEq, Eq, Debug, Clone)]
 pub struct ExtractRegisterAs {
     /// Box
     pub input: Box<Expr>,
-    /// Register id to extract value from
+    /// Register id to extract value from (0 is R0 .. 9 for R9)
     pub register_id: i8,
     /// Result type, to be wrapped in SOption
     pub elem_tpe: SType,
diff --git a/ergotree-ir/src/mir/value.rs b/ergotree-ir/src/mir/value.rs
index 90b61ae61..943395baa 100644
--- a/ergotree-ir/src/mir/value.rs
+++ b/ergotree-ir/src/mir/value.rs
@@ -145,12 +145,6 @@ impl Into<Value> for EcPoint {
     }
 }
 
-// impl From<Box<dyn IrErgoBox>> for Value {
-//     fn from(b: dyn IrErgoBox) -> Self {
-//         Value::CBox(Box::new(b))
-//     }
-// }
-
 impl From<Vec<i8>> for Value {
     fn from(v: Vec<i8>) -> Self {
         Value::Coll(CollKind::NativeColl(NativeColl::CollByte(v)))


Test patch: