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

ergoplatform / sigma-rust / 8953175335

04 May 2024 08:51PM UTC coverage: 80.473% (+0.1%) from 80.331%
8953175335

Pull #736

github

web-flow
Merge 0fdf2d258 into 57a105462
Pull Request #736: Transaction Validation

165 of 228 new or added lines in 15 files covered. (72.37%)

8 existing lines in 2 files now uncovered.

10723 of 13325 relevant lines covered (80.47%)

3.29 hits per line

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

81.08
/ergotree-interpreter/src/eval/scontext.rs
1
use ergotree_ir::mir::avl_tree_data::AvlTreeData;
2
use ergotree_ir::mir::avl_tree_data::AvlTreeFlags;
3
use ergotree_ir::mir::value::CollKind;
4
use ergotree_ir::mir::value::Value;
5
use ergotree_ir::serialization::SigmaSerializable;
6
use ergotree_ir::types::stype::SType;
7

8
use super::EvalError;
9
use super::EvalFn;
10

11
pub(crate) static DATA_INPUTS_EVAL_FN: EvalFn = |_env, ctx, obj, _args| {
1✔
12
    if obj != Value::Context {
2✔
13
        return Err(EvalError::UnexpectedValue(format!(
×
14
            "Context.dataInputs: expected object of Value::Context, got {:?}",
15
            obj
16
        )));
17
    }
18
    Ok(Value::Coll(CollKind::WrappedColl {
1✔
19
        items: ctx
3✔
20
            .ctx
21
            .data_inputs
22
            .clone()
1✔
23
            .map_or(vec![], |d| d.mapped(Value::CBox).as_vec().clone()),
4✔
24
        elem_tpe: SType::SBox,
1✔
25
    }))
26
};
27

28
pub(crate) static SELF_BOX_INDEX_EVAL_FN: EvalFn = |_env, ctx, obj, _args| {
1✔
29
    if obj != Value::Context {
2✔
30
        return Err(EvalError::UnexpectedValue(format!(
×
31
            "Context.selfBoxIndex: expected object of Value::Context, got {:?}",
32
            obj
33
        )));
34
    }
35
    let box_index = ctx
4✔
36
        .ctx
37
        .inputs
38
        .clone()
39
        .iter()
40
        .position(|it| it == &ctx.ctx.self_box)
4✔
41
        .ok_or_else(|| EvalError::NotFound("Context.selfBoxIndex: box not found".to_string()))?;
1✔
42
    Ok(Value::Int(box_index as i32))
1✔
43
};
44

45
pub(crate) static HEADERS_EVAL_FN: EvalFn = |_env, ctx, obj, _args| {
1✔
46
    if obj != Value::Context {
2✔
47
        return Err(EvalError::UnexpectedValue(format!(
×
48
            "Context.headers: expected object of Value::Context, got {:?}",
49
            obj
50
        )));
51
    }
52
    Ok(Value::Coll(CollKind::WrappedColl {
1✔
53
        items: ctx
2✔
54
            .ctx
55
            .headers
56
            .clone()
57
            .map(Box::new)
58
            .map(Value::Header)
59
            .to_vec(),
60
        elem_tpe: SType::SHeader,
1✔
61
    }))
62
};
63

64
pub(crate) static PRE_HEADER_EVAL_FN: EvalFn = |_env, ctx, obj, _args| {
1✔
65
    if obj != Value::Context {
2✔
66
        return Err(EvalError::UnexpectedValue(format!(
×
67
            "Context.preHeader: expected object of Value::Context, got {:?}",
68
            obj
69
        )));
70
    }
71
    Ok(Box::from(ctx.ctx.pre_header.clone()).into())
2✔
72
};
73

74
pub(crate) static LAST_BLOCK_UTXO_ROOT_HASH_EVAL_FN: EvalFn = |_env, ctx, obj, _args| {
1✔
75
    if obj != Value::Context {
2✔
76
        return Err(EvalError::UnexpectedValue(format!(
×
77
            "Context.LastBlockUtxoRootHash: expected object of Value::Context, got {:?}",
78
            obj
79
        )));
80
    }
81
    let digest = ctx.ctx.headers[0].state_root;
2✔
82
    let tree_flags = AvlTreeFlags::new(true, true, true);
1✔
83
    Ok(Value::AvlTree(Box::from(AvlTreeData {
1✔
84
        digest,
85
        tree_flags,
86
        key_length: 32,
87
        value_length_opt: None,
1✔
88
    })))
89
};
90

91
pub(crate) static MINER_PUBKEY_EVAL_FN: EvalFn = |_env, ctx, obj, _args| {
1✔
92
    if obj != Value::Context {
2✔
NEW
93
        return Err(EvalError::UnexpectedValue(format!(
×
94
            "Context.preHeader: expected object of Value::Context, got {:?}",
95
            obj
96
        )));
97
    }
98
    Ok(ctx
3✔
99
        .ctx
100
        .pre_header
101
        .miner_pk
102
        .clone()
NEW
103
        .sigma_serialize_bytes()?
×
104
        .into())
105
};
106

107
#[cfg(test)]
108
#[cfg(feature = "arbitrary")]
109
#[allow(clippy::unwrap_used, clippy::expect_used)]
110
mod tests {
111
    use crate::eval::context::{Context, TxIoVec};
112
    use crate::eval::tests::eval_out;
113
    use ergo_chain_types::{Header, PreHeader};
114
    use ergotree_ir::chain::ergo_box::ErgoBox;
115
    use ergotree_ir::mir::avl_tree_data::{AvlTreeData, AvlTreeFlags};
116
    use ergotree_ir::mir::expr::Expr;
117
    use ergotree_ir::mir::property_call::PropertyCall;
118
    use ergotree_ir::serialization::SigmaSerializable;
119
    use ergotree_ir::types::scontext;
120
    use sigma_test_util::force_any_val;
121
    use std::rc::Rc;
122

123
    fn make_ctx_inputs_includes_self_box() -> Context {
124
        let ctx = force_any_val::<Context>();
125
        let self_box = force_any_val::<ErgoBox>();
126
        let inputs = TxIoVec::from_vec(vec![
127
            force_any_val::<ErgoBox>().into(),
128
            self_box.clone().into(),
129
        ])
130
        .unwrap();
131
        Context {
132
            height: 0u32,
133
            self_box: self_box.into(),
134
            inputs,
135
            ..ctx
136
        }
137
    }
138

139
    #[test]
140
    fn eval_self_box_index() {
141
        let expr: Expr =
142
            PropertyCall::new(Expr::Context, scontext::SELF_BOX_INDEX_PROPERTY.clone())
143
                .unwrap()
144
                .into();
145
        let rc = Rc::new(make_ctx_inputs_includes_self_box());
146
        assert_eq!(eval_out::<i32>(&expr, rc), 1);
147
    }
148

149
    #[test]
150
    fn eval_headers() {
151
        let expr: Expr = PropertyCall::new(Expr::Context, scontext::HEADERS_PROPERTY.clone())
152
            .expect("internal error: `headers` method has parameters length != 1")
153
            .into();
154
        let ctx = Rc::new(force_any_val::<Context>());
155
        assert_eq!(eval_out::<[Header; 10]>(&expr, ctx.clone()), ctx.headers);
156
    }
157

158
    #[test]
159
    fn eval_preheader() {
160
        let expr: Expr = PropertyCall::new(Expr::Context, scontext::PRE_HEADER_PROPERTY.clone())
161
            .unwrap()
162
            .into();
163
        let ctx = Rc::new(force_any_val::<Context>());
164
        assert_eq!(eval_out::<PreHeader>(&expr, ctx.clone()), ctx.pre_header);
165
    }
166

167
    #[test]
168
    fn eval_miner_pubkey() {
169
        let expr: Expr = PropertyCall::new(Expr::Context, scontext::MINER_PUBKEY_PROPERTY.clone())
170
            .unwrap()
171
            .into();
172
        let ctx = Rc::new(force_any_val::<Context>());
173
        assert_eq!(
174
            eval_out::<Vec<u8>>(&expr, ctx.clone()),
175
            ctx.pre_header.miner_pk.sigma_serialize_bytes().unwrap()
176
        );
177
    }
178

179
    #[test]
180
    fn eval_last_block_utxo_root_hash() {
181
        let expr: Expr = PropertyCall::new(
182
            Expr::Context,
183
            scontext::LAST_BLOCK_UTXO_ROOT_HASH_PROPERTY.clone(),
184
        )
185
        .unwrap()
186
        .into();
187
        let ctx = Rc::new(force_any_val::<Context>());
188
        let digest = ctx.headers[0].state_root;
189
        let tree_flags = AvlTreeFlags::new(true, true, true);
190
        let avl_tree_data = AvlTreeData {
191
            digest,
192
            tree_flags,
193
            key_length: 32,
194
            value_length_opt: None,
195
        };
196
        assert_eq!(eval_out::<AvlTreeData>(&expr, ctx), avl_tree_data);
197
    }
198
}
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