1use std::{
2 collections::HashMap,
3 fmt::{Debug, Formatter},
4 str::FromStr,
5};
6
7use getset::{Getters, Setters};
8use primitive_types::H160;
9use serde::{Deserialize, Serialize};
10
11use crate::{
12 crypto::Secp256r1PublicKey,
13 neo_crypto::utils::{FromHexString, ToHexString},
14 neo_types::{
15 script_hash::ScriptHashExtension, Address, OpCode, ScriptHash, StackItem, TypeError,
16 },
17 prelude::Bytes,
18};
19
20use crate::{
21 builder::{BuilderError, InteropService, ScriptBuilder},
22 codec::{Decoder, Encoder, NeoSerializable},
23 config::NeoConstants,
24 crypto::{HashableForVec, Secp256r1Signature},
25 var_size,
26};
27use hex;
28use num_bigint::BigInt;
29use num_traits::{ToPrimitive, Zero};
30use p256::pkcs8::der::Encode;
31
32#[derive(Debug, Clone, PartialEq, Eq, Hash, Getters, Setters, Serialize, Deserialize)]
33pub struct VerificationScript {
34 #[getset(get = "pub", set = "pub")]
35 script: Bytes,
36}
37
38impl VerificationScript {
39 pub fn new() -> Self {
40 Self { script: Bytes::new() }
41 }
42
43 pub fn from(script: Bytes) -> Self {
44 Self { script: script.to_vec() }
45 }
46
47 pub fn from_public_key(public_key: &Secp256r1PublicKey) -> Self {
48 let mut builder = ScriptBuilder::new();
49 builder
50 .push_data(public_key.get_encoded(true))
51 .sys_call(InteropService::SystemCryptoCheckSig);
52 Self::from(builder.to_bytes())
53 }
54
55 pub fn from_multi_sig(public_keys: &mut [Secp256r1PublicKey], threshold: u8) -> Self {
56 let mut builder = ScriptBuilder::new();
58 builder.push_integer(BigInt::from(threshold));
59 public_keys.sort();
60 for key in public_keys.iter() {
61 builder.push_data(key.get_encoded(true));
62 }
63 builder
64 .push_integer(BigInt::from(public_keys.len()))
65 .sys_call(InteropService::SystemCryptoCheckMultiSig);
66 Self::from(builder.to_bytes())
67 }
68
69 pub fn is_single_sig(&self) -> bool {
73 if self.script.len() != 40 {
74 return false;
75 }
76
77 let interop_service = &self.script[self.script.len() - 4..]; let interop_service_hex = interop_service.to_hex_string();
79
80 self.script[0] == OpCode::PushData1.opcode()
81 && self.script[1] == 33
82 && self.script[35] == OpCode::Syscall.opcode()
83 && interop_service_hex == InteropService::SystemCryptoCheckSig.hash() }
85
86 #[doc(hidden)]
91 pub fn is_multi_sig(&self) -> bool {
92 if self.script.len() < 42 {
93 return false;
94 }
95
96 let mut reader = Decoder::new(&self.script);
97
98 let threshold = match reader.by_ref().read_push_int() {
99 Ok(n) => n,
100 Err(_) => return false,
101 };
102 if !(1..=NeoConstants::MAX_PUBLIC_KEYS_PER_MULTI_SIG)
103 .contains(&(threshold.to_u32().unwrap()))
104 {
105 return false;
106 }
107
108 let mut m: BigInt = BigInt::zero();
109 while reader.by_ref().read_u8() == OpCode::PushData1.opcode() {
110 let len = reader.by_ref().read_u8();
111 if len != 33 {
112 return false;
113 }
114 reader.by_ref().read_encoded_ec_point();
115 m += 1;
116 reader.mark();
117 }
118
119 if !(m >= threshold && m <= BigInt::from(NeoConstants::MAX_PUBLIC_KEYS_PER_MULTI_SIG)) {
120 return false;
121 }
122
123 reader.reset();
124
125 if BigInt::from(reader.read_push_int().unwrap()) != m
126 || reader.read_u8() != OpCode::Syscall.opcode()
127 {
128 return false;
129 }
130
131 let service_bytes = &reader.read_bytes(4).unwrap().to_hex_string();
132 let hash = &InteropService::SystemCryptoCheckMultiSig.hash(); if service_bytes != hash {
135 return false;
136 }
137
138 true
151 }
152
153 pub fn hash(&self) -> H160 {
155 let mut script_hash = self.script.sha256_ripemd160();
156 script_hash.reverse();
157 H160::from_slice(&script_hash)
158 }
159
160 pub fn get_signatures(&self) -> Vec<Secp256r1Signature> {
161 let mut reader = Decoder::new(&self.script);
162 let mut signatures = vec![];
163
164 while reader.by_ref().read_u8() == OpCode::PushData1 as u8 {
165 let len = reader.by_ref().read_u8();
166 let sig =
167 Secp256r1Signature::from_bytes(&reader.by_ref().read_bytes(len as usize).unwrap())
168 .unwrap();
169 signatures.push(sig);
170 }
171
172 signatures
173 }
174
175 pub fn get_public_keys(&self) -> Result<Vec<Secp256r1PublicKey>, BuilderError> {
176 if self.is_single_sig() {
177 let mut reader = Decoder::new(&self.script);
178 reader.by_ref().read_u8(); reader.by_ref().read_u8(); let mut point = [0; 33];
182 point.copy_from_slice(&reader.by_ref().read_bytes(33).unwrap());
183
184 let key = Secp256r1PublicKey::from_bytes(&point).unwrap();
185 return Ok(vec![key]);
186 }
187
188 if self.is_multi_sig() {
189 let mut reader = Decoder::new(&self.script);
190 reader.by_ref().read_var_int().unwrap(); let mut keys = vec![];
193 while reader.by_ref().read_u8() == OpCode::PushData1 as u8 {
194 reader.by_ref().read_u8(); let mut point = [0; 33];
196 point.copy_from_slice(&reader.by_ref().read_bytes(33).unwrap());
197 keys.push(Secp256r1PublicKey::from_bytes(&point).unwrap());
198 }
199
200 return Ok(keys);
201 }
202
203 Err(BuilderError::InvalidScript("Invalid verification script".to_string()))
204 }
205
206 pub fn get_signing_threshold(&self) -> Result<usize, BuilderError> {
207 if self.is_single_sig() {
208 Ok(1)
209 } else if self.is_multi_sig() {
210 let reader = &mut Decoder::new(&self.script);
211 Ok(reader.by_ref().read_push_int()?.to_usize().unwrap())
212 } else {
214 Err(BuilderError::InvalidScript("Invalid verification script".to_string()))
215 }
216 }
217
218 pub fn get_nr_of_accounts(&self) -> Result<usize, BuilderError> {
219 match self.get_public_keys() {
220 Ok(keys) => Ok(keys.len()),
221 Err(e) => Err(e),
222 }
223 }
224}
225
226impl NeoSerializable for VerificationScript {
227 type Error = BuilderError;
228
229 fn size(&self) -> usize {
230 var_size(self.script.len()) + self.script.len()
231 }
232
233 fn encode(&self, writer: &mut Encoder) {
234 writer.write_var_bytes(&self.script);
235 }
236
237 fn decode(reader: &mut Decoder) -> Result<Self, Self::Error> {
238 let script = reader.read_var_bytes()?;
239 Ok(Self { script })
240 }
241 fn to_array(&self) -> Vec<u8> {
242 let mut writer = Encoder::new();
243 self.encode(&mut writer);
244 writer.to_bytes()
245 }
246}
247
248#[cfg(test)]
249mod tests {
250 use hex_literal::hex;
251
252 use super::*;
253
254 #[test]
255 fn test_from_public_key() {
256 let key = "035fdb1d1f06759547020891ae97c729327853aeb1256b6fe0473bc2e9fa42ff50";
257 let pubkey = Secp256r1PublicKey::from_encoded(key.clone()).unwrap();
258 let script = VerificationScript::from_public_key(&pubkey);
259 let expected = format!(
260 "{}21{}{}{}",
261 OpCode::PushData1.to_hex_string(),
262 key,
263 OpCode::Syscall.to_hex_string(),
264 InteropService::SystemCryptoCheckSig.hash()
265 )
266 .from_hex_string()
267 .unwrap();
268
269 assert_eq!(script.script(), &expected);
270 }
271
272 #[test]
273 fn test_from_public_keys() {
274 let key1 =
275 hex!("035fdb1d1f06759547020891ae97c729327853aeb1256b6fe0473bc2e9fa42ff50").to_vec();
276 let key2 =
277 hex!("03eda286d19f7ee0b472afd1163d803d620a961e1581a8f2704b52c0285f6e022d").to_vec();
278 let key3 =
279 hex!("03ac81ec17f2f15fd6d193182f927c5971559c2a32b9408a06fec9e711fb7ca02e").to_vec();
280
281 let mut pubkeys = vec![
282 Secp256r1PublicKey::from(key1.clone()),
283 Secp256r1PublicKey::from(key2.clone()),
284 Secp256r1PublicKey::from(key3.clone()),
285 ];
286
287 let script = VerificationScript::from_multi_sig(&mut pubkeys, 2);
288
289 let expected = format!(
290 "{}{}21{}{}21{}{}21{}{}{}{}",
291 OpCode::Push2.to_hex_string(),
292 OpCode::PushData1.to_hex_string(),
293 key1.to_hex_string(),
294 OpCode::PushData1.to_hex_string(),
295 key3.to_hex_string(),
296 OpCode::PushData1.to_hex_string(),
297 key2.to_hex_string(),
298 OpCode::Push3.to_hex_string(),
299 OpCode::Syscall.to_hex_string(),
300 InteropService::SystemCryptoCheckMultiSig.hash()
301 )
302 .from_hex_string()
303 .unwrap();
304
305 assert_eq!(script.script(), &expected);
306 }
307
308 #[test]
309 fn test_serialize_deserialize() {
310 let key = "035fdb1d1f06759547020891ae97c729327853aeb1256b6fe0473bc2e9fa42ff50";
311 let pubkey = Secp256r1PublicKey::from_encoded(key.clone()).unwrap();
312
313 let script = VerificationScript::from_public_key(&pubkey);
314
315 let expected = format!(
316 "{}21{}{}{}",
317 OpCode::PushData1.to_hex_string(),
318 key,
319 OpCode::Syscall.to_hex_string(),
320 InteropService::SystemCryptoCheckSig.hash()
321 );
322
323 let serialized = script.to_array();
324
325 let deserialized = VerificationScript::from(serialized[1..].to_vec());
327
328 assert_eq!(deserialized.script(), &expected.from_hex_string().unwrap());
330 }
331
332 #[test]
333 fn test_get_signing_threshold() {
334 }
342
343 #[test]
344 fn test_invalid_script() {
345 let script = VerificationScript::from(hex!("0123456789abcdef").to_vec());
346
347 assert!(script.get_signing_threshold().is_err());
348 assert!(script.get_public_keys().is_err());
349 assert!(script.get_nr_of_accounts().is_err());
350 }
351
352 #[test]
353 fn test_is_single_sig_script() -> Result<(), BuilderError> {
354 let script = format!(
355 "{}2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef{}{}",
356 OpCode::PushData1.to_hex_string(),
357 OpCode::Syscall.to_hex_string(),
358 InteropService::SystemCryptoCheckSig.hash()
359 );
360
361 let verification =
362 VerificationScript::from(hex::decode(&script).map_err(|e| {
363 BuilderError::InvalidScript(format!("Failed to decode hex: {}", e))
364 })?);
365 assert!(verification.is_single_sig());
366
367 Ok(())
368 }
369
370 #[test]
371 fn test_is_multi_sig() -> Result<(), BuilderError> {
372 let script = format!(
373 "{}{}{}{}{}{}{}{}{}{}",
374 OpCode::Push2.to_hex_string(),
375 OpCode::PushData1.to_hex_string(),
376 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
377 OpCode::PushData1.to_hex_string(),
378 "21031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
379 OpCode::PushData1.to_hex_string(),
380 "2103f0f9b358dfed564e74ffe242713f8bc866414226649f59859b140a130818898b",
381 OpCode::Push3.to_hex_string(),
382 OpCode::Syscall.to_hex_string(),
383 InteropService::SystemCryptoCheckMultiSig.hash()
384 );
385
386 let verification =
387 VerificationScript::from(hex::decode(&script).map_err(|e| {
388 BuilderError::InvalidScript(format!("Failed to decode hex: {}", e))
389 })?);
390 assert!(verification.is_multi_sig());
391
392 Ok(())
393 }
394
395 #[test]
396 fn test_fail_is_multi_sig_too_short() -> Result<(), BuilderError> {
397 let script = hex::decode("a89429c3be9f")
398 .map_err(|e| BuilderError::InvalidScript(format!("Failed to decode hex: {}", e)))?;
399 let verification = VerificationScript::from(script);
400 assert!(!verification.is_multi_sig());
401
402 Ok(())
403 }
404
405 #[test]
406 fn test_fail_is_multi_sig_n_less_than_one() -> Result<(), BuilderError> {
407 let script = format!(
408 "{}{}{}{}{}{}3073b3bb",
409 OpCode::Push0.to_hex_string(),
410 OpCode::PushData1.to_hex_string(),
411 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
412 OpCode::Push1.to_hex_string(),
413 OpCode::PushNull.to_hex_string(),
414 OpCode::Syscall.to_hex_string(),
415 );
416
417 let verification =
418 VerificationScript::from(hex::decode(&script).map_err(|e| {
419 BuilderError::InvalidScript(format!("Failed to decode hex: {}", e))
420 })?);
421 assert!(!verification.is_multi_sig());
422
423 Ok(())
424 }
425
426 #[test]
427 fn test_fail_is_multi_sig_abrupt_end() -> Result<(), BuilderError> {
428 let script = hex::decode(&format!(
429 "{}{}2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
430 OpCode::Push2.to_hex_string(),
431 OpCode::PushData1.to_hex_string(),
432 ))
433 .map_err(|e| BuilderError::InvalidScript(format!("Failed to decode hex: {}", e)))?;
434
435 let verification = VerificationScript::from(script);
436 assert!(!verification.is_multi_sig());
437
438 Ok(())
439 }
440
441 #[test]
442 fn test_fail_is_multi_sig_wrong_push_data() -> Result<(), BuilderError> {
443 let script = hex::decode(&format!(
444 "{}{}{}{}{}{}{}{}3073b3bb",
445 OpCode::Push2.to_hex_string(),
446 OpCode::PushData1.to_hex_string(),
447 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
448 OpCode::PushData1.to_hex_string(),
449 "43031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
450 OpCode::Push2.to_hex_string(),
451 OpCode::PushNull.to_hex_string(),
452 OpCode::Syscall.to_hex_string(),
453 ))
454 .map_err(|e| BuilderError::InvalidScript(format!("Failed to decode hex: {}", e)))?;
455
456 let verification = VerificationScript::from(script);
457 assert!(!verification.is_multi_sig());
458
459 Ok(())
460 }
461
462 #[test]
463 fn test_fail_is_multi_sig_n_greater_than_m() -> Result<(), BuilderError> {
464 let script = hex::decode(&format!(
465 "{}{}{}{}{}{}{}{}3073b3bb",
466 OpCode::Push3.to_hex_string(),
467 OpCode::PushData1.to_hex_string(),
468 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
469 OpCode::PushData1.to_hex_string(),
470 "21031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
471 OpCode::Push2.to_hex_string(),
472 OpCode::PushNull.to_hex_string(),
473 OpCode::Syscall.to_hex_string()
474 ))
475 .map_err(|e| BuilderError::InvalidScript(format!("Failed to decode hex: {}", e)))?;
476
477 let verification = VerificationScript::from(script);
478 assert!(!verification.is_multi_sig());
479
480 Ok(())
481 }
482
483 #[test]
484 fn test_fail_is_multi_sig_m_incorrect() -> Result<(), BuilderError> {
485 let script = hex::decode(&format!(
486 "{}{}{}{}{}{}{}{}3073b3bb",
487 OpCode::Push2.to_hex_string(),
488 OpCode::PushData1.to_hex_string(),
489 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
490 OpCode::PushData1.to_hex_string(),
491 "21031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
492 OpCode::Push3.to_hex_string(),
493 OpCode::PushNull.to_hex_string(),
494 OpCode::Syscall.to_hex_string()
495 ))
496 .map_err(|e| BuilderError::InvalidScript(format!("Failed to decode hex: {}", e)))?;
497
498 let verification = VerificationScript::from(script);
499 assert!(!verification.is_multi_sig());
500
501 Ok(())
502 }
503
504 #[test]
505 fn test_fail_is_multi_sig_missing_push_null() -> Result<(), BuilderError> {
506 let script = hex::decode(&format!(
507 "{}{}{}{}{}{}{}3073b3bb",
508 OpCode::Push2.to_hex_string(),
509 OpCode::PushData1.to_hex_string(),
510 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
511 OpCode::PushData1.to_hex_string(),
512 "21031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
513 OpCode::Push2.to_hex_string(),
514 OpCode::Syscall.to_hex_string()
515 ))
516 .map_err(|e| BuilderError::InvalidScript(format!("Failed to decode hex: {}", e)))?;
517
518 let verification = VerificationScript::from(script);
519 assert!(!verification.is_multi_sig());
520
521 Ok(())
522 }
523
524 #[test]
525 fn test_fail_is_multi_sig_missing_syscall() -> Result<(), BuilderError> {
526 let script = hex::decode(&format!(
527 "{}{}{}{}{}{}{}3073b3bb",
528 OpCode::Push2.to_hex_string(),
529 OpCode::PushData1.to_hex_string(),
530 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
531 OpCode::PushData1.to_hex_string(),
532 "21031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
533 OpCode::Push2.to_hex_string(),
534 OpCode::PushNull.to_hex_string()
535 ))
536 .map_err(|e| BuilderError::InvalidScript(format!("Failed to decode hex: {}", e)))?;
537
538 let verification = VerificationScript::from(script);
539 assert!(!verification.is_multi_sig());
540
541 Ok(())
542 }
543
544 #[test]
545 fn test_fail_is_multi_sig_wrong_interop_service() -> Result<(), BuilderError> {
546 let script = hex::decode(&format!(
547 "{}{}{}{}{}{}{}{}103ab300",
548 OpCode::Push2.to_hex_string(),
549 OpCode::PushData1.to_hex_string(),
550 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
551 OpCode::PushData1.to_hex_string(),
552 "21031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
553 OpCode::Push3.to_hex_string(),
554 OpCode::PushNull.to_hex_string(),
555 OpCode::Syscall.to_hex_string()
556 ))
557 .map_err(|e| BuilderError::InvalidScript(format!("Failed to decode hex: {}", e)))?;
558
559 let verification = VerificationScript::from(script);
560 assert!(!verification.is_multi_sig());
561
562 Ok(())
563 }
564
565 #[test]
566 fn test_public_keys_from_single_sig() -> Result<(), BuilderError> {
567 let script = format!(
568 "{}{}{}{}",
569 OpCode::PushData1.to_hex_string(),
570 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
571 OpCode::Syscall.to_hex_string(),
572 InteropService::SystemCryptoCheckSig.hash()
573 );
574
575 let verification =
576 VerificationScript::from(hex::decode(&script).map_err(|e| {
577 BuilderError::InvalidScript(format!("Failed to decode hex: {}", e))
578 })?);
579
580 let keys = verification.get_public_keys().unwrap();
581
582 assert_eq!(keys.len(), 1);
583
584 let encoded = keys[0].get_encoded(true);
585
586 assert_eq!(
587 hex::encode(&encoded),
588 "02028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef"
589 );
590
591 Ok(())
592 }
593
594 #[test]
595 fn test_public_keys_from_multi_sig() -> Result<(), BuilderError> {
596 let script = format!(
597 "{}{}{}{}{}{}{}{}{}{}",
598 OpCode::Push2.to_hex_string(),
599 OpCode::PushData1.to_hex_string(),
600 "2102028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
601 OpCode::PushData1.to_hex_string(),
602 "21031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
603 OpCode::PushData1.to_hex_string(),
604 "2103f0f9b358dfed564e74ffe242713f8bc866414226649f59859b140a130818898b",
605 OpCode::Push3.to_hex_string(),
606 OpCode::Syscall.to_hex_string(),
607 InteropService::SystemCryptoCheckMultiSig.hash()
608 );
609
610 let verification =
611 VerificationScript::from(hex::decode(&script).map_err(|e| {
612 BuilderError::InvalidScript(format!("Failed to decode hex: {}", e))
613 })?);
614
615 let keys = verification.get_public_keys()?;
616
617 assert_eq!(keys.len(), 3);
618
619 let key1 = keys[0].get_encoded(true);
620 let key2 = keys[1].get_encoded(true);
621 let key3 = keys[2].get_encoded(true);
622
623 assert_eq!(
624 hex::encode(&key1),
625 "02028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef"
626 );
627 assert_eq!(
628 hex::encode(&key2),
629 "031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9"
630 );
631 assert_eq!(
632 hex::encode(&key3),
633 "03f0f9b358dfed564e74ffe242713f8bc866414226649f59859b140a130818898b"
634 );
635
636 Ok(())
637 }
638}