cairo_vm/hint_processor/builtin_hint_processor/
signature.rs

1use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*};
2
3use crate::{
4    hint_processor::{
5        builtin_hint_processor::hint_utils::{get_integer_from_var_name, get_ptr_from_var_name},
6        hint_processor_definition::HintReference,
7    },
8    serde::deserialize_program::ApTracking,
9    types::instance_definitions::ecdsa_instance_def::CELLS_PER_SIGNATURE,
10    vm::{
11        errors::{hint_errors::HintError, vm_errors::VirtualMachineError},
12        vm_core::VirtualMachine,
13    },
14};
15
16pub fn verify_ecdsa_signature(
17    vm: &mut VirtualMachine,
18    ids_data: &HashMap<String, HintReference>,
19    ap_tracking: &ApTracking,
20) -> Result<(), HintError> {
21    let signature_r = get_integer_from_var_name("signature_r", vm, ids_data, ap_tracking)?;
22    let signature_s = get_integer_from_var_name("signature_s", vm, ids_data, ap_tracking)?;
23    let ecdsa_ptr = get_ptr_from_var_name("ecdsa_ptr", vm, ids_data, ap_tracking)?;
24    let ecdsa_builtin = &mut vm.get_signature_builtin()?;
25    if ecdsa_ptr.segment_index != ecdsa_builtin.base() as isize {
26        return Err(HintError::AddSignatureWrongEcdsaPtr(Box::new(ecdsa_ptr)));
27    }
28    if !num_integer::Integer::is_multiple_of(&ecdsa_ptr.offset, &(CELLS_PER_SIGNATURE as usize)) {
29        return Err(HintError::AddSignatureNotAPublicKey(Box::new(ecdsa_ptr)));
30    }
31    ecdsa_builtin
32        .add_signature(ecdsa_ptr, &(signature_r, signature_s))
33        .map_err(VirtualMachineError::Memory)?;
34    Ok(())
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    use crate::{
42        any_box,
43        hint_processor::{
44            builtin_hint_processor::{
45                builtin_hint_processor_definition::{BuiltinHintProcessor, HintProcessorData},
46                hint_code::VERIFY_ECDSA_SIGNATURE,
47            },
48            hint_processor_definition::HintProcessorLogic,
49        },
50        utils::test_utils::*,
51        vm::runners::builtin_runner::SignatureBuiltinRunner,
52    };
53    use assert_matches::assert_matches;
54
55    #[cfg(target_arch = "wasm32")]
56    use wasm_bindgen_test::*;
57
58    #[test]
59    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
60    fn verify_ecdsa_signature_valid() {
61        let mut vm = vm!();
62        vm.builtin_runners = vec![SignatureBuiltinRunner::new(Some(512), true).into()];
63        vm.segments = segments![
64            ((1, 0), (0, 0)),
65            (
66                (1, 1),
67                (
68                    "3086480810278599376317923499561306189851900463386393948998357832163236918254",
69                    10
70                )
71            ),
72            (
73                (1, 2),
74                (
75                    "598673427589502599949712887611119751108407514580626464031881322743364689811",
76                    10
77                )
78            )
79        ];
80        vm.run_context.fp = 3;
81        let ids_data = ids_data!["ecdsa_ptr", "signature_r", "signature_s"];
82        assert_matches!(run_hint!(vm, ids_data, VERIFY_ECDSA_SIGNATURE), Ok(()));
83    }
84
85    #[test]
86    fn verify_ecdsa_signature_invalid_ecdsa_ptr() {
87        let mut vm = vm!();
88        vm.builtin_runners = vec![SignatureBuiltinRunner::new(Some(512), true).into()];
89        vm.segments = segments![
90            ((1, 0), (3, 0)),
91            (
92                (1, 1),
93                (
94                    "3086480810278599376317923499561306189851900463386393948998357832163236918254",
95                    10
96                )
97            ),
98            (
99                (1, 2),
100                (
101                    "598673427589502599949712887611119751108407514580626464031881322743364689811",
102                    10
103                )
104            )
105        ];
106        vm.run_context.fp = 3;
107        let ids_data = ids_data!["ecdsa_ptr", "signature_r", "signature_s"];
108        assert_matches!(run_hint!(vm, ids_data, VERIFY_ECDSA_SIGNATURE), Err(HintError::AddSignatureWrongEcdsaPtr(bx)) if *bx == (3,0).into());
109    }
110
111    #[test]
112    fn verify_ecdsa_signature_invalid_input_cell() {
113        let mut vm = vm!();
114        vm.builtin_runners = vec![SignatureBuiltinRunner::new(Some(512), true).into()];
115        vm.segments = segments![
116            ((1, 0), (0, 3)),
117            (
118                (1, 1),
119                (
120                    "3086480810278599376317923499561306189851900463386393948998357832163236918254",
121                    10
122                )
123            ),
124            (
125                (1, 2),
126                (
127                    "598673427589502599949712887611119751108407514580626464031881322743364689811",
128                    10
129                )
130            )
131        ];
132        vm.run_context.fp = 3;
133        let ids_data = ids_data!["ecdsa_ptr", "signature_r", "signature_s"];
134        assert_matches!(run_hint!(vm, ids_data, VERIFY_ECDSA_SIGNATURE), Err(HintError::AddSignatureNotAPublicKey(bx)) if *bx == (0,3).into());
135    }
136}