• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ergoplatform / sigma-rust / 12515632034

27 Dec 2024 11:41AM UTC coverage: 78.537% (+0.09%) from 78.445%
12515632034

Pull #797

github

web-flow
Merge 64e1cbcd6 into 1d4ef472c
Pull Request #797: Global.serialize, tree-based versioning for methods

107 of 118 new or added lines in 19 files covered. (90.68%)

6 existing lines in 1 file now uncovered.

11047 of 14066 relevant lines covered (78.54%)

3.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.0
/ergotree-interpreter/src/eval/sglobal.rs
1
use alloc::{string::ToString, sync::Arc};
2

3
use crate::eval::EvalError;
4

5
use ergotree_ir::{
6
    mir::{
7
        constant::Constant,
8
        value::{CollKind, NativeColl, Value},
9
    },
10
    serialization::{data::DataSerializer, sigma_byte_writer::SigmaByteWriter},
11
};
12

13
use ergo_chain_types::ec_point::generator;
14

15
use super::EvalFn;
16

17
fn helper_xor(x: &[i8], y: &[i8]) -> Arc<[i8]> {
1✔
18
    x.iter().zip(y.iter()).map(|(x1, x2)| *x1 ^ *x2).collect()
3✔
19
}
20

21
pub(crate) static GROUP_GENERATOR_EVAL_FN: EvalFn = |_mc, _env, _ctx, obj, _args| {
1✔
22
    if obj != Value::Global {
2✔
23
        return Err(EvalError::UnexpectedValue(format!(
×
24
            "sglobal.groupGenerator expected obj to be Value::Global, got {:?}",
25
            obj
26
        )));
27
    }
28
    Ok(Value::from(generator()))
2✔
29
};
30

31
pub(crate) static XOR_EVAL_FN: EvalFn = |_mc, _env, _ctx, obj, args| {
1✔
32
    if obj != Value::Global {
2✔
33
        return Err(EvalError::UnexpectedValue(format!(
×
34
            "sglobal.xor expected obj to be Value::Global, got {:?}",
35
            obj
36
        )));
37
    }
38
    let right_v = args
2✔
39
        .first()
40
        .cloned()
41
        .ok_or_else(|| EvalError::NotFound("xor: missing right arg".to_string()))?;
×
42
    let left_v = args
2✔
43
        .get(1)
44
        .cloned()
45
        .ok_or_else(|| EvalError::NotFound("xor: missing left arg".to_string()))?;
×
46

47
    match (left_v.clone(), right_v.clone()) {
3✔
48
        (
49
            Value::Coll(CollKind::NativeColl(NativeColl::CollByte(l_byte))),
1✔
50
            Value::Coll(CollKind::NativeColl(NativeColl::CollByte(r_byte))),
1✔
51
        ) => {
52
            let xor = helper_xor(&l_byte, &r_byte);
2✔
53
            Ok(CollKind::NativeColl(NativeColl::CollByte(xor)).into())
1✔
54
        }
55
        _ => Err(EvalError::UnexpectedValue(format!(
×
56
            "expected Xor input to be byte array, got: {0:?}",
57
            (left_v, right_v)
×
58
        ))),
59
    }
60
};
61

62
pub(crate) static SERIALIZE_EVAL_FN: EvalFn = |_mc, _env, _ctx, obj, args| {
1✔
63
    if obj != Value::Global {
2✔
NEW
64
        return Err(EvalError::UnexpectedValue(format!(
×
65
            "sglobal.groupGenerator expected obj to be Value::Global, got {:?}",
66
            obj
67
        )));
68
    }
69
    let arg: Constant = args
3✔
70
        .first()
NEW
71
        .ok_or_else(|| EvalError::NotFound("serialize: missing first arg".into()))?
×
72
        .to_static()
73
        .try_into()
NEW
74
        .map_err(EvalError::UnexpectedValue)?;
×
75

76
    let mut buf = vec![];
1✔
77
    let mut writer = SigmaByteWriter::new(&mut buf, None);
1✔
78
    DataSerializer::sigma_serialize(&arg.v, &mut writer)?;
3✔
79
    Ok(Value::from(buf))
2✔
80
};
81

82
#[allow(clippy::unwrap_used)]
83
#[cfg(test)]
84
#[cfg(feature = "arbitrary")]
85
mod tests {
86
    use ergo_chain_types::EcPoint;
87
    use ergotree_ir::ergo_tree::ErgoTreeVersion;
88
    use ergotree_ir::mir::constant::Constant;
89
    use ergotree_ir::mir::expr::Expr;
90
    use ergotree_ir::mir::long_to_byte_array::LongToByteArray;
91
    use ergotree_ir::mir::method_call::MethodCall;
92
    use ergotree_ir::mir::property_call::PropertyCall;
93
    use ergotree_ir::mir::sigma_prop_bytes::SigmaPropBytes;
94
    use ergotree_ir::mir::unary_op::OneArgOpTryBuild;
95
    use ergotree_ir::sigma_protocol::sigma_boolean::SigmaProp;
96
    use ergotree_ir::types::sgroup_elem::GET_ENCODED_METHOD;
97
    use ergotree_ir::types::stype_param::STypeVar;
98
    use proptest::proptest;
99

100
    use crate::eval::tests::{eval_out, eval_out_wo_ctx, try_eval_out_with_version};
101
    use ergotree_ir::chain::context::Context;
102
    use ergotree_ir::types::sglobal::{self, SERIALIZE_METHOD};
103
    use sigma_test_util::force_any_val;
104

105
    fn serialize(val: impl Into<Constant>) -> Vec<u8> {
106
        let constant = val.into();
107
        let serialize_node = MethodCall::new(
108
            Expr::Global,
109
            SERIALIZE_METHOD.clone().with_concrete_types(
110
                &[(STypeVar::t(), constant.tpe.clone())]
111
                    .iter()
112
                    .cloned()
113
                    .collect(),
114
            ),
115
            vec![constant.into()],
116
        )
117
        .unwrap();
118
        let ctx = force_any_val::<Context>();
119
        assert!((0u8..ErgoTreeVersion::V3.into()).all(|version| {
120
            try_eval_out_with_version::<Vec<u8>>(&serialize_node.clone().into(), &ctx, version, 3)
121
                .is_err()
122
        }));
123
        try_eval_out_with_version(&serialize_node.into(), &ctx, ErgoTreeVersion::V3.into(), 3)
124
            .unwrap()
125
    }
126

127
    #[test]
128
    fn eval_group_generator() {
129
        let expr: Expr = PropertyCall::new(Expr::Global, sglobal::GROUP_GENERATOR_METHOD.clone())
130
            .unwrap()
131
            .into();
132
        let ctx = force_any_val::<Context>();
133
        assert_eq!(
134
            eval_out::<EcPoint>(&expr, &ctx),
135
            ergo_chain_types::ec_point::generator()
136
        );
137
    }
138

139
    #[test]
140
    fn eval_xor() {
141
        let left = vec![1_i8, 1, 0, 0];
142
        let right = vec![0_i8, 1, 0, 1];
143
        let expected_xor = vec![1_i8, 0, 0, 1];
144

145
        let expr: Expr = MethodCall::new(
146
            Expr::Global,
147
            sglobal::XOR_METHOD.clone(),
148
            vec![right.into(), left.into()],
149
        )
150
        .unwrap()
151
        .into();
152
        let ctx = force_any_val::<Context>();
153
        assert_eq!(
154
            eval_out::<Vec<i8>>(&expr, &ctx).as_slice(),
155
            expected_xor.as_slice()
156
        );
157
    }
158

159
    #[test]
160
    fn serialize_byte() {
161
        assert_eq!(serialize(-128i8), vec![-128i8 as u8]);
162
        assert_eq!(serialize(-1i8), vec![-1i8 as u8]);
163
        assert_eq!(serialize(0i8), vec![0u8]);
164
        assert_eq!(serialize(1i8), vec![1]);
165
        assert_eq!(serialize(127i8), vec![127u8]);
166
    }
167

168
    #[test]
169
    fn serialize_short() {
170
        assert_eq!(serialize(i16::MIN), vec![0xff, 0xff, 0x03]);
171
        assert_eq!(serialize(-1i16), vec![0x01]);
172
        assert_eq!(serialize(0i16), vec![0x00]);
173
        assert_eq!(serialize(1i16), vec![0x02]);
174
        assert_eq!(serialize(i16::MAX), vec![0xfe, 0xff, 0x03]);
175
    }
176

177
    #[test]
178
    fn serialize_byte_array() {
179
        let arr = vec![0xc0, 0xff, 0xee];
180
        let serialized = serialize(arr.clone());
181

182
        assert_eq!(serialized[0], arr.len() as u8);
183
        assert_eq!(&serialized[1..], &arr)
184
    }
185

186
    // test that serialize(long) != longToByteArray()
187
    #[test]
188
    fn serialize_long_ne_tobytearray() {
189
        let num = -1000i64;
190
        let long_to_byte_array = LongToByteArray::try_build(Constant::from(num).into()).unwrap();
191
        let serialized = serialize(num);
192
        assert!(serialized != eval_out_wo_ctx::<Vec<u8>>(&long_to_byte_array.into()))
193
    }
194

195
    // test equivalence between Global.serialize and ge.getEncoded
196
    #[test]
197
    fn serialize_group_element() {
198
        let ec_point = EcPoint::from_base16_str(String::from(
199
            "026930cb9972e01534918a6f6d6b8e35bc398f57140d13eb3623ea31fbd069939b",
200
        ))
201
        .unwrap();
202
        let get_encoded = MethodCall::new(
203
            Constant::from(ec_point.clone()).into(),
204
            GET_ENCODED_METHOD.clone(),
205
            vec![],
206
        )
207
        .unwrap();
208
        assert_eq!(
209
            eval_out_wo_ctx::<Vec<u8>>(&get_encoded.into()),
210
            serialize(ec_point)
211
        );
212
    }
213

214
    proptest! {
215
        #[test]
216
        fn serialize_sigmaprop_eq_prop_bytes(sigma_prop: SigmaProp) {
217
            let prop_bytes = SigmaPropBytes::try_build(Constant::from(sigma_prop.clone()).into()).unwrap();
218
            assert_eq!(serialize(sigma_prop), &eval_out_wo_ctx::<Vec<u8>>(&prop_bytes.into())[2..])
219
        }
220
    }
221
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc