cairo_vm/hint_processor/builtin_hint_processor/
signature.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*};

use num_integer::Integer;

use crate::{
    hint_processor::{
        builtin_hint_processor::hint_utils::{get_integer_from_var_name, get_ptr_from_var_name},
        hint_processor_definition::HintReference,
    },
    serde::deserialize_program::ApTracking,
    types::instance_definitions::ecdsa_instance_def::CELLS_PER_SIGNATURE,
    vm::{
        errors::{hint_errors::HintError, vm_errors::VirtualMachineError},
        vm_core::VirtualMachine,
    },
};

pub fn verify_ecdsa_signature(
    vm: &mut VirtualMachine,
    ids_data: &HashMap<String, HintReference>,
    ap_tracking: &ApTracking,
) -> Result<(), HintError> {
    let signature_r = get_integer_from_var_name("signature_r", vm, ids_data, ap_tracking)?;
    let signature_s = get_integer_from_var_name("signature_s", vm, ids_data, ap_tracking)?;
    let ecdsa_ptr = get_ptr_from_var_name("ecdsa_ptr", vm, ids_data, ap_tracking)?;
    let ecdsa_builtin = &mut vm.get_signature_builtin()?;
    if ecdsa_ptr.segment_index != ecdsa_builtin.base() as isize {
        return Err(HintError::AddSignatureWrongEcdsaPtr(Box::new(ecdsa_ptr)));
    }
    if !ecdsa_ptr
        .offset
        .is_multiple_of(&(CELLS_PER_SIGNATURE as usize))
    {
        return Err(HintError::AddSignatureNotAPublicKey(Box::new(ecdsa_ptr)));
    }
    ecdsa_builtin
        .add_signature(ecdsa_ptr, &(signature_r, signature_s))
        .map_err(VirtualMachineError::Memory)?;
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    use crate::{
        any_box,
        hint_processor::{
            builtin_hint_processor::{
                builtin_hint_processor_definition::{BuiltinHintProcessor, HintProcessorData},
                hint_code::VERIFY_ECDSA_SIGNATURE,
            },
            hint_processor_definition::HintProcessorLogic,
        },
        utils::test_utils::*,
        vm::runners::builtin_runner::SignatureBuiltinRunner,
    };
    use assert_matches::assert_matches;

    #[cfg(target_arch = "wasm32")]
    use wasm_bindgen_test::*;

    #[test]
    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
    fn verify_ecdsa_signature_valid() {
        let mut vm = vm!();
        vm.builtin_runners = vec![SignatureBuiltinRunner::new(Some(512), true).into()];
        vm.segments = segments![
            ((1, 0), (0, 0)),
            (
                (1, 1),
                (
                    "3086480810278599376317923499561306189851900463386393948998357832163236918254",
                    10
                )
            ),
            (
                (1, 2),
                (
                    "598673427589502599949712887611119751108407514580626464031881322743364689811",
                    10
                )
            )
        ];
        vm.run_context.fp = 3;
        let ids_data = ids_data!["ecdsa_ptr", "signature_r", "signature_s"];
        assert_matches!(run_hint!(vm, ids_data, VERIFY_ECDSA_SIGNATURE), Ok(()));
    }

    #[test]
    fn verify_ecdsa_signature_invalid_ecdsa_ptr() {
        let mut vm = vm!();
        vm.builtin_runners = vec![SignatureBuiltinRunner::new(Some(512), true).into()];
        vm.segments = segments![
            ((1, 0), (3, 0)),
            (
                (1, 1),
                (
                    "3086480810278599376317923499561306189851900463386393948998357832163236918254",
                    10
                )
            ),
            (
                (1, 2),
                (
                    "598673427589502599949712887611119751108407514580626464031881322743364689811",
                    10
                )
            )
        ];
        vm.run_context.fp = 3;
        let ids_data = ids_data!["ecdsa_ptr", "signature_r", "signature_s"];
        assert_matches!(run_hint!(vm, ids_data, VERIFY_ECDSA_SIGNATURE), Err(HintError::AddSignatureWrongEcdsaPtr(bx)) if *bx == (3,0).into());
    }

    #[test]
    fn verify_ecdsa_signature_invalid_input_cell() {
        let mut vm = vm!();
        vm.builtin_runners = vec![SignatureBuiltinRunner::new(Some(512), true).into()];
        vm.segments = segments![
            ((1, 0), (0, 3)),
            (
                (1, 1),
                (
                    "3086480810278599376317923499561306189851900463386393948998357832163236918254",
                    10
                )
            ),
            (
                (1, 2),
                (
                    "598673427589502599949712887611119751108407514580626464031881322743364689811",
                    10
                )
            )
        ];
        vm.run_context.fp = 3;
        let ids_data = ids_data!["ecdsa_ptr", "signature_r", "signature_s"];
        assert_matches!(run_hint!(vm, ids_data, VERIFY_ECDSA_SIGNATURE), Err(HintError::AddSignatureNotAPublicKey(bx)) if *bx == (0,3).into());
    }
}