1use crate::{
2 builder::{
3 AccountSigner, BuilderError, ContractSigner, TransactionError, TransactionSigner,
4 WitnessCondition, WitnessRule, WitnessScope,
5 },
6 codec::{Decoder, Encoder, NeoSerializable},
7 config::NeoConstants,
8 crypto::Secp256r1PublicKey,
9 neo_protocol::AccountTrait,
10};
11use elliptic_curve::pkcs8::der::Encode;
12use primitive_types::H160;
13use serde::{Deserialize, Serialize, Serializer};
14use std::{
15 collections::HashSet,
16 hash::{Hash, Hasher},
17 ops::Deref,
18};
19
20use lazy_static::lazy_static;
21
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub enum SignerType {
25 AccountSigner,
26 ContractSigner,
27 TransactionSigner,
28}
29
30pub trait SignerTrait {
32 fn get_type(&self) -> SignerType;
33
34 fn get_signer_hash(&self) -> &H160;
35
36 fn set_signer_hash(&mut self, signer_hash: H160);
37
38 fn get_scopes(&self) -> &Vec<WitnessScope>;
39 fn get_scopes_mut(&mut self) -> &mut Vec<WitnessScope>;
40
41 fn set_scopes(&mut self, scopes: Vec<WitnessScope>);
42
43 fn get_allowed_contracts(&self) -> &Vec<H160>;
44
45 fn get_allowed_contracts_mut(&mut self) -> &mut Vec<H160>;
46
47 fn get_allowed_groups(&self) -> &Vec<Secp256r1PublicKey>;
50 fn get_allowed_groups_mut(&mut self) -> &mut Vec<Secp256r1PublicKey>;
51
52 fn get_rules(&self) -> &Vec<WitnessRule>;
53 fn get_rules_mut(&mut self) -> &mut Vec<WitnessRule>;
54
55 fn set_allowed_contracts(&mut self, contracts: Vec<H160>) -> Result<(), BuilderError> {
57 if self.get_scopes().contains(&WitnessScope::Global) {
59 return Err(BuilderError::SignerConfiguration(
60 "Trying to set allowed contracts on a Signer with global scope.".to_string(),
61 ));
62 }
63
64 if self.get_allowed_contracts().len() + contracts.len()
65 > NeoConstants::MAX_SIGNER_SUBITEMS as usize
66 {
67 return Err(BuilderError::SignerConfiguration(format!(
68 "Trying to set more than {} allowed contracts on a signer.",
69 NeoConstants::MAX_SIGNER_SUBITEMS
70 )));
71 }
72
73 self.get_scopes_mut().retain(|scope| *scope != WitnessScope::None);
83
84 if !self.get_scopes().contains(&WitnessScope::CustomContracts) {
86 self.get_scopes_mut().push(WitnessScope::CustomContracts);
87 }
88
89 self.get_allowed_contracts_mut().extend(contracts);
90
91 Ok(())
92 }
93
94 fn set_allowed_groups(&mut self, groups: Vec<Secp256r1PublicKey>) -> Result<(), BuilderError> {
96 if self.get_scopes().contains(&WitnessScope::Global) {
97 return Err(BuilderError::SignerConfiguration(
98 "Trying to set allowed contract groups on a Signer with global scope.".to_string(),
99 ));
100 }
101
102 if self.get_allowed_groups().len() + groups.len()
103 > NeoConstants::MAX_SIGNER_SUBITEMS as usize
104 {
105 return Err(BuilderError::SignerConfiguration(format!(
106 "Trying to set more than {} allowed contract groups on a signer.",
107 NeoConstants::MAX_SIGNER_SUBITEMS
108 )));
109 }
110
111 self.get_scopes_mut().retain(|scope| *scope != WitnessScope::None);
112
113 if !self.get_scopes().contains(&WitnessScope::CustomGroups) {
114 self.get_scopes_mut().push(WitnessScope::CustomGroups);
115 }
116
117 self.get_allowed_groups_mut().extend(groups);
118
119 Ok(())
120 }
121
122 fn set_rules(&mut self, mut rules: Vec<WitnessRule>) -> Result<&mut Self, BuilderError> {
123 if !rules.is_empty() {
124 if self.get_scopes().contains(&WitnessScope::Global) {
125 return Err(BuilderError::SignerConfiguration(
126 "Trying to set witness rules on a Signer with global scope.".to_string(),
127 ));
128 }
129
130 if self.get_rules().len() + rules.len() > NeoConstants::MAX_SIGNER_SUBITEMS as usize {
131 return Err(BuilderError::SignerConfiguration(format!(
132 "Trying to set more than {} allowed witness rules on a signer.",
133 NeoConstants::MAX_SIGNER_SUBITEMS
134 )));
135 }
136
137 for rule in &rules {
138 self.check_depth(&rule.condition, WitnessCondition::MAX_NESTING_DEPTH as i8)?;
139 }
140
141 if !self.get_scopes().contains(&WitnessScope::WitnessRules) {
142 self.get_scopes_mut().push(WitnessScope::WitnessRules);
143 }
144
145 self.get_rules_mut().append(&mut rules);
146 }
147
148 Ok(self)
149 }
150
151 fn check_depth(&self, condition: &WitnessCondition, depth: i8) -> Result<(), BuilderError> {
152 if depth < 0 {
153 return Err(BuilderError::IllegalState(format!(
154 "A maximum nesting depth of {} is allowed for witness conditions",
155 WitnessCondition::MAX_NESTING_DEPTH
156 ))); }
158
159 match condition {
160 WitnessCondition::And(conditions) | WitnessCondition::Or(conditions) => {
161 for c in conditions {
162 self.check_depth(c, depth - 1)?
163 }
164 },
165 _ => (),
166 };
167
168 Ok(())
169 }
170
171 fn validate_subitems(&self, count: usize, _name: &str) -> Result<(), BuilderError> {
172 if count > NeoConstants::MAX_SIGNER_SUBITEMS as usize {
173 return Err(BuilderError::TooManySigners("".to_string()));
174 }
175 Ok(())
176 }
177}
178
179#[derive(Debug, Clone, Deserialize)]
183pub enum Signer {
184 AccountSigner(AccountSigner),
185 ContractSigner(ContractSigner),
186 TransactionSigner(TransactionSigner),
187}
188
189impl PartialEq for Signer {
190 fn eq(&self, other: &Self) -> bool {
191 match self {
192 Signer::AccountSigner(account_signer) => match other {
193 Signer::AccountSigner(other_account_signer) =>
194 account_signer.get_signer_hash() == other_account_signer.get_signer_hash(),
195 _ => false,
196 },
197 Signer::ContractSigner(contract_signer) => match other {
198 Signer::ContractSigner(other_contract_signer) =>
199 contract_signer.get_signer_hash() == other_contract_signer.get_signer_hash(),
200 _ => false,
201 },
202 Signer::TransactionSigner(transaction_signer) => match other {
203 Signer::TransactionSigner(other_transaction_signer) =>
204 transaction_signer.get_signer_hash()
205 == other_transaction_signer.get_signer_hash(),
206 _ => false,
207 },
208 }
209 }
210}
211
212impl SignerTrait for Signer {
213 fn get_type(&self) -> SignerType {
214 match self {
215 Signer::AccountSigner(account_signer) => account_signer.get_type(),
216 Signer::ContractSigner(contract_signer) => contract_signer.get_type(),
217 Signer::TransactionSigner(transaction_signer) => transaction_signer.get_type(),
218 }
219 }
220
221 fn get_signer_hash(&self) -> &H160 {
222 match self {
223 Signer::AccountSigner(account_signer) => account_signer.get_signer_hash(),
224 Signer::ContractSigner(contract_signer) => contract_signer.get_signer_hash(),
225 Signer::TransactionSigner(transaction_signer) => transaction_signer.get_signer_hash(),
226 }
227 }
228
229 fn set_signer_hash(&mut self, signer_hash: H160) {
230 match self {
231 Signer::AccountSigner(account_signer) => account_signer.set_signer_hash(signer_hash),
232 Signer::ContractSigner(contract_signer) => contract_signer.set_signer_hash(signer_hash),
233 Signer::TransactionSigner(transaction_signer) =>
234 transaction_signer.set_signer_hash(signer_hash),
235 }
236 }
237
238 fn get_scopes(&self) -> &Vec<WitnessScope> {
239 match self {
240 Signer::AccountSigner(account_signer) => account_signer.get_scopes(),
241 Signer::ContractSigner(contract_signer) => contract_signer.get_scopes(),
242 Signer::TransactionSigner(transaction_signer) => transaction_signer.get_scopes(),
243 }
244 }
245
246 fn get_scopes_mut(&mut self) -> &mut Vec<WitnessScope> {
247 match self {
248 Signer::AccountSigner(account_signer) => account_signer.get_scopes_mut(),
249 Signer::ContractSigner(contract_signer) => contract_signer.get_scopes_mut(),
250 Signer::TransactionSigner(transaction_signer) => transaction_signer.get_scopes_mut(),
251 }
252 }
253
254 fn set_scopes(&mut self, scopes: Vec<WitnessScope>) {
255 match self {
256 Signer::AccountSigner(account_signer) => account_signer.set_scopes(scopes),
257 Signer::ContractSigner(contract_signer) => contract_signer.set_scopes(scopes),
258 Signer::TransactionSigner(transaction_signer) => transaction_signer.set_scopes(scopes),
259 }
260 }
261
262 fn get_allowed_contracts(&self) -> &Vec<H160> {
263 match self {
264 Signer::AccountSigner(account_signer) => account_signer.get_allowed_contracts(),
265 Signer::ContractSigner(contract_signer) => contract_signer.get_allowed_contracts(),
266 Signer::TransactionSigner(transaction_signer) =>
267 transaction_signer.get_allowed_contracts(),
268 }
269 }
270
271 fn get_allowed_contracts_mut(&mut self) -> &mut Vec<H160> {
272 match self {
273 Signer::AccountSigner(account_signer) => account_signer.get_allowed_contracts_mut(),
274 Signer::ContractSigner(contract_signer) => contract_signer.get_allowed_contracts_mut(),
275 Signer::TransactionSigner(transaction_signer) =>
276 transaction_signer.get_allowed_contracts_mut(),
277 }
278 }
279
280 fn get_allowed_groups(&self) -> &Vec<Secp256r1PublicKey> {
281 match self {
282 Signer::AccountSigner(account_signer) => account_signer.get_allowed_groups(),
283 Signer::ContractSigner(contract_signer) => contract_signer.get_allowed_groups(),
284 Signer::TransactionSigner(transaction_signer) =>
285 transaction_signer.get_allowed_groups(),
286 }
287 }
288
289 fn get_allowed_groups_mut(&mut self) -> &mut Vec<Secp256r1PublicKey> {
290 match self {
291 Signer::AccountSigner(account_signer) => account_signer.get_allowed_groups_mut(),
292 Signer::ContractSigner(contract_signer) => contract_signer.get_allowed_groups_mut(),
293 Signer::TransactionSigner(transaction_signer) =>
294 transaction_signer.get_allowed_groups_mut(),
295 }
296 }
297
298 fn get_rules(&self) -> &Vec<WitnessRule> {
299 match self {
300 Signer::AccountSigner(account_signer) => account_signer.get_rules(),
301 Signer::ContractSigner(contract_signer) => contract_signer.get_rules(),
302 Signer::TransactionSigner(transaction_signer) => transaction_signer.get_rules(),
303 }
304 }
305
306 fn get_rules_mut(&mut self) -> &mut Vec<WitnessRule> {
307 match self {
308 Signer::AccountSigner(account_signer) => account_signer.get_rules_mut(),
309 Signer::ContractSigner(contract_signer) => contract_signer.get_rules_mut(),
310 Signer::TransactionSigner(transaction_signer) => transaction_signer.get_rules_mut(),
311 }
312 }
313}
314
315impl Signer {
316 pub fn from_bytes(data: &[u8]) -> Result<Signer, TransactionError> {
326 let mut reader = Decoder::new(data);
327 Signer::decode(&mut reader)
328 }
329
330 pub fn get_type(&self) -> SignerType {
332 match self {
333 Signer::AccountSigner(account_signer) => account_signer.get_type(),
334 Signer::ContractSigner(contract_signer) => contract_signer.get_type(),
335 Signer::TransactionSigner(transaction_signer) => transaction_signer.get_type(),
336 }
337 }
338 pub fn get_signer_hash(&self) -> &H160 {
340 match self {
341 Signer::AccountSigner(account_signer) => account_signer.get_signer_hash(),
342 Signer::ContractSigner(contract_signer) => contract_signer.get_signer_hash(),
343 Signer::TransactionSigner(transaction_signer) => transaction_signer.get_signer_hash(),
344 }
345 }
346
347 pub fn as_account_signer(&self) -> Option<&AccountSigner> {
348 match self {
349 Signer::AccountSigner(account_signer) => Some(account_signer),
350 _ => None,
351 }
352 }
353
354 pub fn as_contract_signer(&self) -> Option<&ContractSigner> {
355 match self {
356 Signer::ContractSigner(contract_signer) => Some(contract_signer),
357 _ => None,
358 }
359 }
360
361 pub fn as_transaction_signer(&self) -> Option<&TransactionSigner> {
362 match self {
363 Signer::TransactionSigner(transaction_signer) => Some(transaction_signer),
364 _ => None,
365 }
366 }
367
368 pub fn to_account_signer(self) -> Result<AccountSigner, String> {
370 match self {
371 Signer::AccountSigner(account_signer) => Ok(account_signer),
372 _ =>
373 Err("Cannot convert ContractSigner or TransactionSigner into AccountSigner"
374 .to_string()),
375 }
376 }
377
378 pub fn to_contract_signer(self) -> Result<ContractSigner, String> {
380 match self {
381 Signer::AccountSigner(_) =>
382 Err("Cannot convert AccountSigner into ContractSigner".to_string()),
383 Signer::ContractSigner(contract_signer) => Ok(contract_signer),
384 Signer::TransactionSigner(_) =>
385 Err("Cannot convert TransactionSigner into ContractSigner".to_string()),
386 }
387 }
388}
389
390impl Hash for Signer {
391 fn hash<H: Hasher>(&self, state: &mut H) {
392 match self {
393 Signer::AccountSigner(account_signer) => account_signer.hash(state),
394 Signer::ContractSigner(contract_signer) => contract_signer.hash(state),
395 Signer::TransactionSigner(transaction_signer) => transaction_signer.hash(state),
396 }
397 }
398}
399
400impl From<AccountSigner> for Signer {
401 fn from(account_signer: AccountSigner) -> Self {
402 Signer::AccountSigner(account_signer)
403 }
404}
405
406impl From<ContractSigner> for Signer {
407 fn from(contract_signer: ContractSigner) -> Self {
408 Signer::ContractSigner(contract_signer)
409 }
410}
411
412impl Into<AccountSigner> for Signer {
414 fn into(self) -> AccountSigner {
415 match self {
416 Signer::AccountSigner(account_signer) => account_signer,
417 _ => {
418 eprintln!("Warning: Cannot convert ContractSigner or TransactionSigner into AccountSigner, returning default");
419 AccountSigner::none_hash160(primitive_types::H160::zero()).unwrap_or_else(|_| {
421 let account = crate::neo_protocol::Account::from_wif(
423 "L1WMhxazScMhUrdv34JqQb1HFSQmWeN2Kpc1R9JGKwL7CDNP21uR",
424 )
425 .unwrap();
426 AccountSigner::new(&account, crate::builder::WitnessScope::None)
427 })
428 },
429 }
430 }
431}
432
433impl Into<TransactionSigner> for Signer {
434 fn into(self) -> TransactionSigner {
435 match self {
436 Signer::AccountSigner(account_signer) => TransactionSigner::new_full(
437 account_signer.account.get_script_hash(),
438 account_signer.get_scopes().to_vec(),
439 account_signer.get_allowed_contracts().to_vec(),
440 account_signer.get_allowed_groups().to_vec(),
441 account_signer.get_rules().to_vec(),
442 ),
443 Signer::ContractSigner(contract_signer) => TransactionSigner::new_full(
444 *contract_signer.get_signer_hash(),
445 contract_signer.get_scopes().to_vec(),
446 contract_signer.get_allowed_contracts().to_vec(),
447 contract_signer.get_allowed_groups().to_vec(),
448 contract_signer.get_rules().to_vec(),
449 ),
450 Signer::TransactionSigner(transaction_signer) => transaction_signer,
451 }
452 }
453}
454
455impl Into<TransactionSigner> for &Signer {
456 fn into(self) -> TransactionSigner {
457 match self {
458 Signer::AccountSigner(account_signer) => TransactionSigner::new_full(
459 account_signer.account.get_script_hash(),
460 account_signer.get_scopes().to_vec(),
461 account_signer.get_allowed_contracts().to_vec(),
462 account_signer.get_allowed_groups().to_vec(),
463 account_signer.get_rules().to_vec(),
464 ),
465 Signer::ContractSigner(contract_signer) => TransactionSigner::new_full(
466 *contract_signer.get_signer_hash(),
467 contract_signer.get_scopes().to_vec(),
468 contract_signer.get_allowed_contracts().to_vec(),
469 contract_signer.get_allowed_groups().to_vec(),
470 contract_signer.get_rules().to_vec(),
471 ),
472 Signer::TransactionSigner(transaction_signer) => transaction_signer.clone(),
477 }
478 }
479}
480
481impl Into<TransactionSigner> for &mut Signer {
482 fn into(self) -> TransactionSigner {
483 match self {
484 Signer::AccountSigner(account_signer) => TransactionSigner::new_full(
485 account_signer.account.get_script_hash(),
486 account_signer.get_scopes().to_vec(),
487 account_signer.get_allowed_contracts().to_vec(),
488 account_signer.get_allowed_groups().to_vec(),
489 account_signer.get_rules().to_vec(),
490 ),
491 Signer::ContractSigner(contract_signer) => TransactionSigner::new_full(
492 *contract_signer.get_signer_hash(),
493 contract_signer.get_scopes().to_vec(),
494 contract_signer.get_allowed_contracts().to_vec(),
495 contract_signer.get_allowed_groups().to_vec(),
496 contract_signer.get_rules().to_vec(),
497 ),
498 Signer::TransactionSigner(transaction_signer) => transaction_signer.clone(),
499 }
500 }
501}
502
503impl Into<ContractSigner> for &mut Signer {
504 fn into(self) -> ContractSigner {
505 match self {
506 Signer::ContractSigner(contract_signer) => contract_signer.clone(),
507 _ => {
508 eprintln!("Warning: Cannot convert signer type to ContractSigner, returning minimal fallback");
510 ContractSigner::called_by_entry(H160::zero(), &[])
511 },
512 }
513 }
514}
515
516impl Into<ContractSigner> for Signer {
517 fn into(self) -> ContractSigner {
518 match self {
519 Signer::ContractSigner(contract_signer) => contract_signer,
520 _ => {
521 eprintln!("Warning: Cannot convert signer type to ContractSigner, returning minimal fallback");
523 ContractSigner::called_by_entry(H160::zero(), &[])
524 },
525 }
526 }
527}
528
529impl Serialize for Signer {
530 fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
531 where
532 S: Serializer,
533 {
534 match self {
535 Signer::AccountSigner(account_signer) => account_signer.serialize(serializer),
536 Signer::ContractSigner(contract_signer) => contract_signer.serialize(serializer),
537 Signer::TransactionSigner(transaction_signer) =>
538 transaction_signer.serialize(serializer),
539 }
540 }
541}
542
543impl NeoSerializable for Signer {
544 type Error = TransactionError;
545
546 fn size(&self) -> usize {
547 match self {
548 Signer::AccountSigner(account_signer) => account_signer.size(),
549 Signer::ContractSigner(contract_signer) => contract_signer.size(),
550 Signer::TransactionSigner(transaction_signer) => transaction_signer.size(),
551 }
552 }
553
554 fn encode(&self, writer: &mut Encoder) {
555 match self {
556 Signer::AccountSigner(account_signer) => account_signer.encode(writer),
557 Signer::ContractSigner(contract_signer) => contract_signer.encode(writer),
558 Signer::TransactionSigner(transaction_signer) => transaction_signer.encode(writer),
559 }
560 }
561
562 fn decode(reader: &mut Decoder) -> Result<Self, Self::Error>
563 where
564 Self: Sized,
565 {
566 match reader.read_u8() {
567 0 => Ok(Signer::AccountSigner(AccountSigner::decode(reader)?)),
568 1 => Ok(Signer::ContractSigner(ContractSigner::decode(reader)?)),
569 _ => Err(TransactionError::InvalidTransaction),
571 }
572 }
573
574 fn to_array(&self) -> Vec<u8> {
575 match self {
576 Signer::AccountSigner(account_signer) => account_signer.to_array(),
577 Signer::ContractSigner(contract_signer) => contract_signer.to_array(),
578 Signer::TransactionSigner(transaction_signer) => transaction_signer.to_array(),
579 }
580 }
581}
582
583#[cfg(test)]
584mod tests {
585 use std::{collections::HashSet, ops::Deref};
586
587 use lazy_static::lazy_static;
588 use primitive_types::H160;
589
590 use crate::{
591 builder::{
592 AccountSigner, BuilderError, ContractSigner, SignerTrait, WitnessAction,
593 WitnessCondition, WitnessRule, WitnessScope,
594 },
595 codec::{Encoder, NeoSerializable},
596 config::NeoConstants,
597 crypto::Secp256r1PublicKey,
598 neo_protocol::{Account, AccountTrait},
599 ScriptHash, ScriptHashExtension,
600 };
601 use neo3::builder::Signer;
602
603 lazy_static! {
604 pub static ref SCRIPT_HASH: ScriptHash = {
605 Account::from_wif("Kzt94tAAiZSgH7Yt4i25DW6jJFprZFPSqTgLr5dWmWgKDKCjXMfZ")
606 .unwrap()
607 .get_script_hash()
608 };
609 pub static ref SCRIPT_HASH1: H160 = H160::from_script(&hex::decode("d802a401").unwrap());
610 pub static ref SCRIPT_HASH2: H160 = H160::from_script(&hex::decode("c503b112").unwrap());
611 pub static ref GROUP_PUB_KEY1: Secp256r1PublicKey = Secp256r1PublicKey::from_encoded(
612 "0306d3e7f18e6dd477d34ce3cfeca172a877f3c907cc6c2b66c295d1fcc76ff8f7",
613 )
614 .unwrap();
615 pub static ref GROUP_PUB_KEY2: Secp256r1PublicKey = Secp256r1PublicKey::from_encoded(
616 "02958ab88e4cea7ae1848047daeb8883daf5fdf5c1301dbbfe973f0a29fe75de60",
617 )
618 .unwrap();
619 }
620
621 #[test]
622 fn test_create_signer_with_call_by_entry_scope() {
623 let signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
624
625 assert_eq!(signer.signer_hash, *SCRIPT_HASH);
626 assert_eq!(signer.scopes, vec![WitnessScope::CalledByEntry]);
627 assert!(signer.get_allowed_contracts().is_empty());
628 assert!(signer.get_allowed_groups().is_empty());
629 }
630
631 #[test]
632 fn test_create_signer_with_global_scope() {
633 let signer = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
634
635 assert_eq!(signer.signer_hash, *SCRIPT_HASH);
636 assert_eq!(signer.scopes, vec![WitnessScope::Global]);
637 assert!(signer.get_allowed_contracts().is_empty());
638 assert!(signer.get_allowed_groups().is_empty());
639 }
640
641 #[test]
642 fn test_build_valid_signer1() {
643 let mut signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into())
644 .expect("Should be able to create AccountSigner with called_by_entry scope in test");
645 signer
646 .set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2])
647 .expect("Should be able to set allowed contracts in test");
648
649 assert_eq!(signer.signer_hash, *SCRIPT_HASH);
650 assert_eq!(
651 signer.get_scopes().iter().cloned().collect::<HashSet<_>>(),
652 vec![WitnessScope::CalledByEntry, WitnessScope::CustomContracts]
653 .into_iter()
654 .collect()
655 );
656 assert_eq!(
657 signer.get_allowed_contracts().iter().cloned().collect::<HashSet<_>>(),
658 vec![*SCRIPT_HASH1, *SCRIPT_HASH2].into_iter().collect()
659 );
660 assert!(signer.get_allowed_groups().is_empty());
661 }
662
663 #[test]
664 fn test_build_valid_signer2() {
665 let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into())
666 .expect("Should be able to create AccountSigner with none scope in test");
667 signer
668 .set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2])
669 .expect("Should be able to set allowed contracts in test");
670
671 assert_eq!(signer.signer_hash, *SCRIPT_HASH);
672 assert_eq!(signer.get_scopes(), &vec![WitnessScope::CustomContracts]);
673 assert_eq!(
674 signer.get_allowed_contracts().iter().cloned().collect::<HashSet<_>>(),
675 vec![*SCRIPT_HASH1, *SCRIPT_HASH2].into_iter().collect()
676 );
677 assert!(signer.get_allowed_groups().is_empty());
678 }
679
680 #[test]
681 fn test_build_valid_signer3() {
682 let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into())
683 .expect("Should be able to create AccountSigner with none scope in test");
684 signer
685 .set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
686 .expect("Should be able to set allowed groups in test");
687
688 assert_eq!(signer.signer_hash, *SCRIPT_HASH);
689 assert_eq!(signer.get_scopes(), &vec![WitnessScope::CustomGroups]);
690 assert_eq!(
691 signer.get_allowed_groups().iter().cloned().collect::<HashSet<_>>(),
692 vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()].into_iter().collect()
693 );
694 assert!(signer.get_allowed_contracts().is_empty());
695 }
696
697 #[test]
698 fn test_fail_building_signer_with_global_scope_and_custom_contracts() {
699 let mut signer = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
700 let err = signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).unwrap_err();
701
702 assert_eq!(
703 err,
704 BuilderError::SignerConfiguration(
705 "Trying to set allowed contracts on a Signer with global scope.".to_string()
706 )
707 );
708 }
709
710 #[test]
711 fn test_fail_building_signer_with_global_scope_and_custom_groups() {
712 let mut signer = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
713 let err = signer
714 .set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
715 .unwrap_err();
716
717 assert_eq!(
718 err,
719 BuilderError::SignerConfiguration(
720 "Trying to set allowed contract groups on a Signer with global scope.".to_string()
721 )
722 );
723 }
724
725 #[test]
726 fn test_fail_building_signer_too_many_contracts() {
727 let script = H160::from_hex("3ab0be8672e25cf475219d018ded961ec684ca88").unwrap();
728 let contracts = (0..=16).map(|_| script.clone()).collect::<Vec<_>>();
729
730 let err = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into())
731 .unwrap()
732 .set_allowed_contracts(contracts)
733 .unwrap_err();
734
735 assert_eq!(
736 err,
737 BuilderError::SignerConfiguration(format!(
738 "Trying to set more than {} allowed contracts on a signer.",
739 NeoConstants::MAX_SIGNER_SUBITEMS
740 ))
741 );
742 }
743
744 #[test]
745 fn test_fail_building_signer_too_many_contracts_added_separately() {
746 let script = H160::from_hex("3ab0be8672e25cf475219d018ded961ec684ca88").unwrap();
747 let contracts = (0..=15).map(|_| script.clone()).collect::<Vec<_>>();
748
749 let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
750 signer.set_allowed_contracts(vec![script]).expect("");
751
752 let err = signer.set_allowed_contracts(contracts).unwrap_err();
753
754 assert_eq!(
755 err,
756 BuilderError::SignerConfiguration(format!(
757 "Trying to set more than {} allowed contracts on a signer.",
758 NeoConstants::MAX_SIGNER_SUBITEMS
759 ))
760 );
761 }
762
763 #[test]
764 fn test_fail_building_signer_too_many_groups() {
765 let public_key = Secp256r1PublicKey::from_encoded(
766 "0306d3e7f18e6dd477d34ce3cfeca172a877f3c907cc6c2b66c295d1fcc76ff8f7",
767 )
768 .unwrap();
769 let groups = (0..=16).map(|_| public_key.clone()).collect::<Vec<_>>();
770
771 let err = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into())
772 .unwrap()
773 .set_allowed_groups(groups)
774 .unwrap_err();
775
776 assert_eq!(
777 err,
778 BuilderError::SignerConfiguration(format!(
779 "Trying to set more than {} allowed contract groups on a signer.",
780 NeoConstants::MAX_SIGNER_SUBITEMS
781 ))
782 );
783 }
784
785 #[test]
786 fn test_fail_building_signer_too_many_groups_added_separately() {
787 let public_key = Secp256r1PublicKey::from_encoded(
788 "0306d3e7f18e6dd477d34ce3cfeca172a877f3c907cc6c2b66c295d1fcc76ff8f7",
789 )
790 .unwrap();
791 let groups = (0..=15).map(|_| public_key.clone()).collect::<Vec<_>>();
792
793 let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
794 signer.set_allowed_groups(vec![public_key]).expect("");
795
796 let err = signer.set_allowed_groups(groups).unwrap_err();
797
798 assert_eq!(
799 err,
800 BuilderError::SignerConfiguration(format!(
801 "Trying to set more than {} allowed contract groups on a signer.",
802 NeoConstants::MAX_SIGNER_SUBITEMS
803 ))
804 );
805 }
806
807 #[test]
808 fn test_serialize_global_scope() {
809 let mut buffer = Encoder::new();
810
811 AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap().encode(&mut buffer);
812
813 let expected = format!(
814 "{}{:02x}",
815 hex::encode(SCRIPT_HASH.as_bytes()),
816 WitnessScope::Global.byte_repr()
817 );
818 assert_eq!(hex::encode(buffer.to_bytes()), expected);
819 }
820
821 #[test]
822 fn test_serialize_custom_contracts_scope_produces_correct_byte_array() {
823 let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
824 signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).unwrap();
825
826 let expected = format!(
827 "{}{:02x}02{}{}",
828 hex::encode(SCRIPT_HASH.as_bytes()),
829 WitnessScope::CustomContracts.byte_repr(),
830 hex::encode(SCRIPT_HASH1.as_bytes()),
831 hex::encode(SCRIPT_HASH2.as_bytes())
832 );
833
834 assert_eq!(signer.to_array(), hex::decode(&expected).unwrap());
835 }
836
837 #[test]
838 fn test_serialize_custom_group_scope() {
839 let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
840 signer
841 .set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
842 .expect("");
843
844 let expected = format!(
845 "{}{:02x}02{}{}",
846 hex::encode(SCRIPT_HASH.as_bytes()),
847 WitnessScope::CustomGroups.byte_repr(),
848 GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
849 GROUP_PUB_KEY2.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
850 );
851
852 assert_eq!(signer.to_array(), hex::decode(&expected).unwrap());
853 }
854
855 #[test]
856 fn test_serialize_multiple_scopes_contracts_groups_and_rules() {
857 let rule = WitnessRule::new(
858 WitnessAction::Allow,
859 WitnessCondition::CalledByContract(*SCRIPT_HASH1),
860 );
861 let mut signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
862 signer
863 .set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
864 .expect("");
865 signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
866 signer.set_rules(vec![rule]).expect("");
867
868 let expected = format!(
869 "{}{}{}{}{}{}{}{}{}{}{}{}",
870 hex::encode(SCRIPT_HASH.as_bytes()),
871 "71",
872 "02",
873 hex::encode(SCRIPT_HASH1.as_bytes()),
874 hex::encode(SCRIPT_HASH2.as_bytes()),
875 "02",
876 GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
877 GROUP_PUB_KEY2.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
878 "01",
879 "01",
880 "28",
881 hex::encode(SCRIPT_HASH1.as_bytes())
882 );
883
884 assert_eq!(signer.to_array(), hex::decode(&expected).unwrap());
885 }
886
887 #[test]
888 fn test_fail_deserialize_too_many_contracts() {
889 let mut serialized = format!("{}1111", hex::encode(SCRIPT_HASH.as_bytes()));
890 for _ in 0..=17 {
891 serialized.push_str(&hex::encode(SCRIPT_HASH1.as_bytes()));
892 }
893 let mut data = hex::decode(&serialized).unwrap();
894 data.insert(0, 1);
895
896 let err = Signer::from_bytes(&data).unwrap_err();
897
898 assert!(err.to_string().contains(&format!(
899 "A signer's scope can only contain {} allowed contracts.",
900 NeoConstants::MAX_SIGNER_SUBITEMS
901 )));
902 }
903
904 #[test]
905 fn test_fail_deserialize_too_many_contract_groups() {
906 let mut serialized = format!("{}2111", hex::encode(SCRIPT_HASH.as_bytes()));
907 for _ in 0..=17 {
908 serialized.push_str(
909 &GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
910 );
911 }
912 let mut data = hex::decode(&serialized).unwrap();
913 data.insert(0, 1);
914
915 let err = Signer::from_bytes(&data).unwrap_err();
916
917 assert!(err.to_string().contains(&format!(
918 "A signer's scope can only contain {} allowed contract groups.",
919 NeoConstants::MAX_SIGNER_SUBITEMS
920 )));
921 }
922
923 #[test]
924 fn test_fail_deserialize_too_many_rules() {
925 let mut serialized = format!("{}4111", hex::encode(SCRIPT_HASH.as_bytes()));
926 for _ in 0..=17 {
927 serialized.push_str("01");
928 serialized.push_str("28");
929 serialized.push_str(&hex::encode(SCRIPT_HASH1.as_bytes()));
930 }
931 let mut data = hex::decode(&serialized).unwrap();
932 data.insert(0, 1);
933
934 let err = Signer::from_bytes(&data).unwrap_err();
935
936 assert!(err.to_string().contains(&format!(
937 "A signer's scope can only contain {} rules.",
938 NeoConstants::MAX_SIGNER_SUBITEMS
939 )));
940 }
941
942 #[test]
943 fn test_get_size() {
944 let rule = WitnessRule::new(
945 WitnessAction::Allow,
946 WitnessCondition::And(vec![
947 WitnessCondition::Boolean(true),
948 WitnessCondition::Boolean(false),
949 ]),
950 );
951 let mut signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
952 signer
953 .set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
954 .expect("");
955 signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
956 signer.set_rules(vec![rule.clone(), rule]).expect("");
957
958 let expected_size = 20 + 1 + 1 + 20 + 20 + 1 + 33 + 33 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1; assert_eq!(signer.size(), expected_size);
981 }
982
983 #[test]
984 fn test_serialize_deserialize_max_nested_rules() {
985 let rule = WitnessRule::new(
986 WitnessAction::Allow,
987 WitnessCondition::And(vec![WitnessCondition::And(vec![WitnessCondition::Boolean(
988 true,
989 )])]),
990 );
991
992 let mut buffer = Encoder::new();
993 let mut account_signer = AccountSigner::none(&ScriptHash::zero().into()).unwrap();
994
995 account_signer.set_rules(vec![rule]).unwrap();
996 account_signer.encode(&mut buffer);
997
998 let expected =
999 hex::decode("0000000000000000000000000000000000000000400101020102010001").unwrap();
1000 assert_eq!(buffer.to_bytes(), expected);
1001 }
1002
1003 #[test]
1004 fn test_fail_adding_rules_to_global_signer() {
1005 let rule =
1006 WitnessRule::new(WitnessAction::Allow, WitnessCondition::ScriptHash(*SCRIPT_HASH));
1007
1008 let mut signer = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
1009
1010 let err = signer.set_rules(vec![rule]).unwrap_err();
1011
1012 assert_eq!(
1013 err,
1014 BuilderError::SignerConfiguration(
1015 "Trying to set witness rules on a Signer with global scope.".to_string()
1016 )
1017 );
1018 }
1019
1020 #[test]
1021 fn test_fail_adding_too_many_rules() {
1022 let rule =
1023 WitnessRule::new(WitnessAction::Allow, WitnessCondition::ScriptHash(*SCRIPT_HASH));
1024
1025 let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
1026
1027 for _ in 0..NeoConstants::MAX_SIGNER_SUBITEMS {
1028 signer.set_rules(vec![rule.clone()]).unwrap();
1029 }
1030
1031 let err = signer.set_rules(vec![rule]).unwrap_err();
1032
1033 assert_eq!(
1034 err,
1035 BuilderError::SignerConfiguration(format!(
1036 "Trying to set more than {} allowed witness rules on a signer.",
1037 NeoConstants::MAX_SIGNER_SUBITEMS
1038 ))
1039 );
1040 }
1041
1042 #[test]
1043 fn test_signer_equals() {
1044 let signer1 = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
1045 let signer2 = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
1046
1047 assert_eq!(signer1, signer2);
1048
1049 let signer3 = ContractSigner::called_by_entry(*SCRIPT_HASH, &[]);
1050 let signer4 = ContractSigner::called_by_entry(*SCRIPT_HASH, &[]);
1051
1052 assert_eq!(signer3, signer4);
1053
1054 let mut signer5 = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
1055 signer5
1056 .set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
1057 .expect("");
1058 signer5.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
1059
1060 let mut signer6 = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
1061 signer6
1062 .set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
1063 .expect("");
1064 signer6.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
1065
1066 assert_eq!(signer5, signer6);
1067 }
1068
1069 #[test]
1070 fn test_serialize_with_multiple_scopes_contracts_groups_and_rules() {
1071 let rule = WitnessRule::new(
1072 WitnessAction::Allow,
1073 WitnessCondition::CalledByContract(*SCRIPT_HASH1),
1074 );
1075 let mut signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
1076 signer
1077 .set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
1078 .expect("");
1079 signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
1080 signer.set_rules(vec![rule]).expect("");
1081
1082 let expected = format!(
1083 "{}{}{}{}{}{}{}{}{}{}{}{}",
1084 hex::encode(SCRIPT_HASH.as_bytes()),
1085 "71",
1086 "02",
1087 hex::encode(SCRIPT_HASH1.as_bytes()),
1088 hex::encode(SCRIPT_HASH2.as_bytes()),
1089 "02",
1090 GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
1091 GROUP_PUB_KEY2.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
1092 "01",
1093 "01",
1094 "28",
1095 hex::encode(SCRIPT_HASH1.as_bytes())
1096 );
1097
1098 assert_eq!(signer.to_array(), hex::decode(&expected).unwrap());
1099 }
1100
1101 #[test]
1102 fn test_deserialize() {
1103 let data_str = format!(
1104 "{}{}{}{}{}{}{}{}{}{}{}{}",
1105 hex::encode(SCRIPT_HASH.as_bytes()),
1106 "71",
1107 "02",
1108 hex::encode(SCRIPT_HASH1.as_bytes()),
1109 hex::encode(SCRIPT_HASH2.as_bytes()),
1110 "02",
1111 GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
1112 GROUP_PUB_KEY2.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
1113 "01",
1114 "01",
1115 "28",
1116 hex::encode(SCRIPT_HASH1.as_bytes())
1117 );
1118 let mut serialized = hex::decode(&data_str).unwrap();
1119 serialized.insert(0, 1);
1120
1121 let signer = Signer::from_bytes(&serialized).unwrap();
1122
1123 assert_eq!(signer.get_signer_hash(), SCRIPT_HASH.deref());
1124
1125 let expected_scopes: HashSet<WitnessScope> = vec![
1126 WitnessScope::CalledByEntry,
1127 WitnessScope::CustomContracts,
1128 WitnessScope::CustomGroups,
1129 WitnessScope::WitnessRules,
1130 ]
1131 .into_iter()
1132 .collect();
1133 assert_eq!(signer.get_scopes().iter().cloned().collect::<HashSet<_>>(), expected_scopes);
1134
1135 assert_eq!(
1136 signer.get_allowed_contracts().iter().cloned().collect::<HashSet<_>>(),
1137 vec![*SCRIPT_HASH1, *SCRIPT_HASH2].into_iter().collect()
1138 );
1139
1140 assert_eq!(
1141 signer.get_allowed_groups().iter().cloned().collect::<HashSet<_>>(),
1142 vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()].into_iter().collect()
1143 );
1144
1145 let rule = &signer.get_rules()[0];
1146 assert_eq!(rule.action, WitnessAction::Allow);
1147 assert_eq!(rule.condition, WitnessCondition::CalledByContract(*SCRIPT_HASH1));
1148 }
1149}