cairo_vm/hint_processor/builtin_hint_processor/
signature.rs

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