neo3/neo_builder/transaction/signers/
signer.rs

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/// Represents the type of signer in the NEO blockchain.
23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub enum SignerType {
25	AccountSigner,
26	ContractSigner,
27	TransactionSigner,
28}
29
30/// A trait for common signer operations in the NEO blockchain.
31pub 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 set_allowed_contracts(&mut self, allowed_contracts: Vec<H160>);
48
49	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	// Set allowed contracts
56	fn set_allowed_contracts(&mut self, contracts: Vec<H160>) -> Result<(), BuilderError> {
57		// Validate
58		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		// Update state
74		// if !self.get_scopes().contains(&WitnessScope::CustomContracts) {
75		// 	if self.get_scopes().contains(&WitnessScope::None) {
76		// 		self.set_scopes(vec![WitnessScope::CustomContracts]);
77		// 	} else {
78		// 		self.get_scopes_mut().push(WitnessScope::CustomContracts);
79		// 	}
80		// }
81		// Remove WitnessScope::None if it is present
82		self.get_scopes_mut().retain(|scope| *scope != WitnessScope::None);
83
84		// Add WitnessScope::CustomContracts if it is not already present
85		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	// Set allowed groups
95	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			))); // ::)
157		}
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/// Represents a signer in the NEO blockchain.
180///
181/// This enum can be either an `AccountSigner`, `ContractSigner`, or `TransactionSigner`.
182#[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				},
196				_ => false,
197			},
198			Signer::ContractSigner(contract_signer) => match other {
199				Signer::ContractSigner(other_contract_signer) => {
200					contract_signer.get_signer_hash() == other_contract_signer.get_signer_hash()
201				},
202				_ => false,
203			},
204			Signer::TransactionSigner(transaction_signer) => match other {
205				Signer::TransactionSigner(other_transaction_signer) => {
206					transaction_signer.get_signer_hash()
207						== other_transaction_signer.get_signer_hash()
208				},
209				_ => false,
210			},
211		}
212	}
213}
214
215impl SignerTrait for Signer {
216	fn get_type(&self) -> SignerType {
217		match self {
218			Signer::AccountSigner(account_signer) => account_signer.get_type(),
219			Signer::ContractSigner(contract_signer) => contract_signer.get_type(),
220			Signer::TransactionSigner(transaction_signer) => transaction_signer.get_type(),
221		}
222	}
223
224	fn get_signer_hash(&self) -> &H160 {
225		match self {
226			Signer::AccountSigner(account_signer) => account_signer.get_signer_hash(),
227			Signer::ContractSigner(contract_signer) => contract_signer.get_signer_hash(),
228			Signer::TransactionSigner(transaction_signer) => transaction_signer.get_signer_hash(),
229		}
230	}
231
232	fn set_signer_hash(&mut self, signer_hash: H160) {
233		match self {
234			Signer::AccountSigner(account_signer) => account_signer.set_signer_hash(signer_hash),
235			Signer::ContractSigner(contract_signer) => contract_signer.set_signer_hash(signer_hash),
236			Signer::TransactionSigner(transaction_signer) => {
237				transaction_signer.set_signer_hash(signer_hash)
238			},
239		}
240	}
241
242	fn get_scopes(&self) -> &Vec<WitnessScope> {
243		match self {
244			Signer::AccountSigner(account_signer) => account_signer.get_scopes(),
245			Signer::ContractSigner(contract_signer) => contract_signer.get_scopes(),
246			Signer::TransactionSigner(transaction_signer) => transaction_signer.get_scopes(),
247		}
248	}
249
250	fn get_scopes_mut(&mut self) -> &mut Vec<WitnessScope> {
251		match self {
252			Signer::AccountSigner(account_signer) => account_signer.get_scopes_mut(),
253			Signer::ContractSigner(contract_signer) => contract_signer.get_scopes_mut(),
254			Signer::TransactionSigner(transaction_signer) => transaction_signer.get_scopes_mut(),
255		}
256	}
257
258	fn set_scopes(&mut self, scopes: Vec<WitnessScope>) {
259		match self {
260			Signer::AccountSigner(account_signer) => account_signer.set_scopes(scopes),
261			Signer::ContractSigner(contract_signer) => contract_signer.set_scopes(scopes),
262			Signer::TransactionSigner(transaction_signer) => transaction_signer.set_scopes(scopes),
263		}
264	}
265
266	fn get_allowed_contracts(&self) -> &Vec<H160> {
267		match self {
268			Signer::AccountSigner(account_signer) => account_signer.get_allowed_contracts(),
269			Signer::ContractSigner(contract_signer) => contract_signer.get_allowed_contracts(),
270			Signer::TransactionSigner(transaction_signer) => {
271				transaction_signer.get_allowed_contracts()
272			},
273		}
274	}
275
276	fn get_allowed_contracts_mut(&mut self) -> &mut Vec<H160> {
277		match self {
278			Signer::AccountSigner(account_signer) => account_signer.get_allowed_contracts_mut(),
279			Signer::ContractSigner(contract_signer) => contract_signer.get_allowed_contracts_mut(),
280			Signer::TransactionSigner(transaction_signer) => {
281				transaction_signer.get_allowed_contracts_mut()
282			},
283		}
284	}
285
286	fn get_allowed_groups(&self) -> &Vec<Secp256r1PublicKey> {
287		match self {
288			Signer::AccountSigner(account_signer) => account_signer.get_allowed_groups(),
289			Signer::ContractSigner(contract_signer) => contract_signer.get_allowed_groups(),
290			Signer::TransactionSigner(transaction_signer) => {
291				transaction_signer.get_allowed_groups()
292			},
293		}
294	}
295
296	fn get_allowed_groups_mut(&mut self) -> &mut Vec<Secp256r1PublicKey> {
297		match self {
298			Signer::AccountSigner(account_signer) => account_signer.get_allowed_groups_mut(),
299			Signer::ContractSigner(contract_signer) => contract_signer.get_allowed_groups_mut(),
300			Signer::TransactionSigner(transaction_signer) => {
301				transaction_signer.get_allowed_groups_mut()
302			},
303		}
304	}
305
306	fn get_rules(&self) -> &Vec<WitnessRule> {
307		match self {
308			Signer::AccountSigner(account_signer) => account_signer.get_rules(),
309			Signer::ContractSigner(contract_signer) => contract_signer.get_rules(),
310			Signer::TransactionSigner(transaction_signer) => transaction_signer.get_rules(),
311		}
312	}
313
314	fn get_rules_mut(&mut self) -> &mut Vec<WitnessRule> {
315		match self {
316			Signer::AccountSigner(account_signer) => account_signer.get_rules_mut(),
317			Signer::ContractSigner(contract_signer) => contract_signer.get_rules_mut(),
318			Signer::TransactionSigner(transaction_signer) => transaction_signer.get_rules_mut(),
319		}
320	}
321}
322
323impl Signer {
324	/// Creates a `Signer` from a byte array.
325	///
326	/// # Arguments
327	///
328	/// * `data` - The byte array containing the serialized signer data.
329	///
330	/// # Returns
331	///
332	/// A `Result` containing the deserialized `Signer` or a `TransactionError`.
333	pub fn from_bytes(data: &[u8]) -> Result<Signer, TransactionError> {
334		let mut reader = Decoder::new(data);
335		Signer::decode(&mut reader)
336	}
337
338	/// Returns the type of the signer.
339	pub fn get_type(&self) -> SignerType {
340		match self {
341			Signer::AccountSigner(account_signer) => account_signer.get_type(),
342			Signer::ContractSigner(contract_signer) => contract_signer.get_type(),
343			Signer::TransactionSigner(transaction_signer) => transaction_signer.get_type(),
344		}
345	}
346	/// Returns a reference to the signer's script hash.
347	pub fn get_signer_hash(&self) -> &H160 {
348		match self {
349			Signer::AccountSigner(account_signer) => account_signer.get_signer_hash(),
350			Signer::ContractSigner(contract_signer) => contract_signer.get_signer_hash(),
351			Signer::TransactionSigner(transaction_signer) => transaction_signer.get_signer_hash(),
352		}
353	}
354
355	pub fn as_account_signer(&self) -> Option<&AccountSigner> {
356		match self {
357			Signer::AccountSigner(account_signer) => Some(account_signer),
358			_ => None,
359		}
360	}
361
362	pub fn as_contract_signer(&self) -> Option<&ContractSigner> {
363		match self {
364			Signer::ContractSigner(contract_signer) => Some(contract_signer),
365			_ => None,
366		}
367	}
368
369	pub fn as_transaction_signer(&self) -> Option<&TransactionSigner> {
370		match self {
371			Signer::TransactionSigner(transaction_signer) => Some(transaction_signer),
372			_ => None,
373		}
374	}
375
376	/// Safely converts to AccountSigner
377	pub fn to_account_signer(self) -> Result<AccountSigner, String> {
378		match self {
379			Signer::AccountSigner(account_signer) => Ok(account_signer),
380			_ => {
381				Err("Cannot convert ContractSigner or TransactionSigner into AccountSigner"
382					.to_string())
383			},
384		}
385	}
386
387	/// Safely converts to ContractSigner
388	pub fn to_contract_signer(self) -> Result<ContractSigner, String> {
389		match self {
390			Signer::AccountSigner(_) => {
391				Err("Cannot convert AccountSigner into ContractSigner".to_string())
392			},
393			Signer::ContractSigner(contract_signer) => Ok(contract_signer),
394			Signer::TransactionSigner(_) => {
395				Err("Cannot convert TransactionSigner into ContractSigner".to_string())
396			},
397		}
398	}
399}
400
401impl Hash for Signer {
402	fn hash<H: Hasher>(&self, state: &mut H) {
403		match self {
404			Signer::AccountSigner(account_signer) => account_signer.hash(state),
405			Signer::ContractSigner(contract_signer) => contract_signer.hash(state),
406			Signer::TransactionSigner(transaction_signer) => transaction_signer.hash(state),
407		}
408	}
409}
410
411impl From<AccountSigner> for Signer {
412	fn from(account_signer: AccountSigner) -> Self {
413		Signer::AccountSigner(account_signer)
414	}
415}
416
417impl From<ContractSigner> for Signer {
418	fn from(contract_signer: ContractSigner) -> Self {
419		Signer::ContractSigner(contract_signer)
420	}
421}
422
423// Keep the existing Into implementations for backward compatibility
424impl Into<AccountSigner> for Signer {
425	fn into(self) -> AccountSigner {
426		match self {
427			Signer::AccountSigner(account_signer) => account_signer,
428			_ => {
429				eprintln!("Warning: Cannot convert ContractSigner or TransactionSigner into AccountSigner, returning default");
430				// Return a default AccountSigner as fallback
431				AccountSigner::none_hash160(primitive_types::H160::zero()).unwrap_or_else(|_| {
432					// If even the default creation fails, create one with a valid account
433					let account = crate::neo_protocol::Account::from_wif(
434						"L1WMhxazScMhUrdv34JqQb1HFSQmWeN2Kpc1R9JGKwL7CDNP21uR",
435					)
436					.unwrap();
437					AccountSigner::new(&account, crate::builder::WitnessScope::None)
438				})
439			},
440		}
441	}
442}
443
444impl Into<TransactionSigner> for Signer {
445	fn into(self) -> TransactionSigner {
446		match self {
447			Signer::AccountSigner(account_signer) => TransactionSigner::new_full(
448				account_signer.account.get_script_hash(),
449				account_signer.get_scopes().to_vec(),
450				account_signer.get_allowed_contracts().to_vec(),
451				account_signer.get_allowed_groups().to_vec(),
452				account_signer.get_rules().to_vec(),
453			),
454			Signer::ContractSigner(contract_signer) => TransactionSigner::new_full(
455				*contract_signer.get_signer_hash(),
456				contract_signer.get_scopes().to_vec(),
457				contract_signer.get_allowed_contracts().to_vec(),
458				contract_signer.get_allowed_groups().to_vec(),
459				contract_signer.get_rules().to_vec(),
460			),
461			Signer::TransactionSigner(transaction_signer) => transaction_signer,
462		}
463	}
464}
465
466impl Into<TransactionSigner> for &Signer {
467	fn into(self) -> TransactionSigner {
468		match self {
469			Signer::AccountSigner(account_signer) => TransactionSigner::new_full(
470				account_signer.account.get_script_hash(),
471				account_signer.get_scopes().to_vec(),
472				account_signer.get_allowed_contracts().to_vec(),
473				account_signer.get_allowed_groups().to_vec(),
474				account_signer.get_rules().to_vec(),
475			),
476			Signer::ContractSigner(contract_signer) => TransactionSigner::new_full(
477				*contract_signer.get_signer_hash(),
478				contract_signer.get_scopes().to_vec(),
479				contract_signer.get_allowed_contracts().to_vec(),
480				contract_signer.get_allowed_groups().to_vec(),
481				contract_signer.get_rules().to_vec(),
482			),
483			// Signer::Account(_account_signer) =>
484			// 	panic!("Cannot convert AccountSigner into TransactionSigner"),
485			// Signer::Contract(_contract_signer) =>
486			// 	panic!("Cannot convert ContractSigner into AccountSigner"),
487			Signer::TransactionSigner(transaction_signer) => transaction_signer.clone(),
488		}
489	}
490}
491
492impl Into<TransactionSigner> for &mut Signer {
493	fn into(self) -> TransactionSigner {
494		match self {
495			Signer::AccountSigner(account_signer) => TransactionSigner::new_full(
496				account_signer.account.get_script_hash(),
497				account_signer.get_scopes().to_vec(),
498				account_signer.get_allowed_contracts().to_vec(),
499				account_signer.get_allowed_groups().to_vec(),
500				account_signer.get_rules().to_vec(),
501			),
502			Signer::ContractSigner(contract_signer) => TransactionSigner::new_full(
503				*contract_signer.get_signer_hash(),
504				contract_signer.get_scopes().to_vec(),
505				contract_signer.get_allowed_contracts().to_vec(),
506				contract_signer.get_allowed_groups().to_vec(),
507				contract_signer.get_rules().to_vec(),
508			),
509			Signer::TransactionSigner(transaction_signer) => transaction_signer.clone(),
510		}
511	}
512}
513
514impl Into<ContractSigner> for &mut Signer {
515	fn into(self) -> ContractSigner {
516		match self {
517			Signer::ContractSigner(contract_signer) => contract_signer.clone(),
518			_ => {
519				// Log the error and return a minimal ContractSigner to avoid panic
520				eprintln!("Warning: Cannot convert signer type to ContractSigner, returning minimal fallback");
521				ContractSigner::called_by_entry(H160::zero(), &[])
522			},
523		}
524	}
525}
526
527impl Into<ContractSigner> for Signer {
528	fn into(self) -> ContractSigner {
529		match self {
530			Signer::ContractSigner(contract_signer) => contract_signer,
531			_ => {
532				// Log the error and return a minimal ContractSigner to avoid panic
533				eprintln!("Warning: Cannot convert signer type to ContractSigner, returning minimal fallback");
534				ContractSigner::called_by_entry(H160::zero(), &[])
535			},
536		}
537	}
538}
539
540impl Serialize for Signer {
541	fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
542	where
543		S: Serializer,
544	{
545		match self {
546			Signer::AccountSigner(account_signer) => account_signer.serialize(serializer),
547			Signer::ContractSigner(contract_signer) => contract_signer.serialize(serializer),
548			Signer::TransactionSigner(transaction_signer) => {
549				transaction_signer.serialize(serializer)
550			},
551		}
552	}
553}
554
555impl NeoSerializable for Signer {
556	type Error = TransactionError;
557
558	fn size(&self) -> usize {
559		match self {
560			Signer::AccountSigner(account_signer) => account_signer.size(),
561			Signer::ContractSigner(contract_signer) => contract_signer.size(),
562			Signer::TransactionSigner(transaction_signer) => transaction_signer.size(),
563		}
564	}
565
566	fn encode(&self, writer: &mut Encoder) {
567		match self {
568			Signer::AccountSigner(account_signer) => account_signer.encode(writer),
569			Signer::ContractSigner(contract_signer) => contract_signer.encode(writer),
570			Signer::TransactionSigner(transaction_signer) => transaction_signer.encode(writer),
571		}
572	}
573
574	fn decode(reader: &mut Decoder) -> Result<Self, Self::Error>
575	where
576		Self: Sized,
577	{
578		match reader.read_u8() {
579			0 => Ok(Signer::AccountSigner(AccountSigner::decode(reader)?)),
580			1 => Ok(Signer::ContractSigner(ContractSigner::decode(reader)?)),
581			//_ => Ok(Signer::Transaction(TransactionSigner::decode(reader)?)),
582			_ => Err(TransactionError::InvalidTransaction),
583		}
584	}
585
586	fn to_array(&self) -> Vec<u8> {
587		match self {
588			Signer::AccountSigner(account_signer) => account_signer.to_array(),
589			Signer::ContractSigner(contract_signer) => contract_signer.to_array(),
590			Signer::TransactionSigner(transaction_signer) => transaction_signer.to_array(),
591		}
592	}
593}
594
595#[cfg(test)]
596mod tests {
597	use std::{collections::HashSet, ops::Deref};
598
599	use lazy_static::lazy_static;
600	use primitive_types::H160;
601
602	use crate::{
603		builder::{
604			AccountSigner, BuilderError, ContractSigner, SignerTrait, WitnessAction,
605			WitnessCondition, WitnessRule, WitnessScope,
606		},
607		codec::{Encoder, NeoSerializable},
608		config::NeoConstants,
609		crypto::Secp256r1PublicKey,
610		neo_protocol::{Account, AccountTrait},
611		ScriptHash, ScriptHashExtension,
612	};
613	use neo3::builder::Signer;
614
615	lazy_static! {
616		pub static ref SCRIPT_HASH: ScriptHash = {
617			Account::from_wif("Kzt94tAAiZSgH7Yt4i25DW6jJFprZFPSqTgLr5dWmWgKDKCjXMfZ")
618				.unwrap()
619				.get_script_hash()
620		};
621		pub static ref SCRIPT_HASH1: H160 = H160::from_script(&hex::decode("d802a401").unwrap());
622		pub static ref SCRIPT_HASH2: H160 = H160::from_script(&hex::decode("c503b112").unwrap());
623		pub static ref GROUP_PUB_KEY1: Secp256r1PublicKey = Secp256r1PublicKey::from_encoded(
624			"0306d3e7f18e6dd477d34ce3cfeca172a877f3c907cc6c2b66c295d1fcc76ff8f7",
625		)
626		.unwrap();
627		pub static ref GROUP_PUB_KEY2: Secp256r1PublicKey = Secp256r1PublicKey::from_encoded(
628			"02958ab88e4cea7ae1848047daeb8883daf5fdf5c1301dbbfe973f0a29fe75de60",
629		)
630		.unwrap();
631	}
632
633	#[test]
634	fn test_create_signer_with_call_by_entry_scope() {
635		let signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
636
637		assert_eq!(signer.signer_hash, *SCRIPT_HASH);
638		assert_eq!(signer.scopes, vec![WitnessScope::CalledByEntry]);
639		assert!(signer.get_allowed_contracts().is_empty());
640		assert!(signer.get_allowed_groups().is_empty());
641	}
642
643	#[test]
644	fn test_create_signer_with_global_scope() {
645		let signer = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
646
647		assert_eq!(signer.signer_hash, *SCRIPT_HASH);
648		assert_eq!(signer.scopes, vec![WitnessScope::Global]);
649		assert!(signer.get_allowed_contracts().is_empty());
650		assert!(signer.get_allowed_groups().is_empty());
651	}
652
653	#[test]
654	fn test_build_valid_signer1() {
655		let mut signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into())
656			.expect("Should be able to create AccountSigner with called_by_entry scope in test");
657		signer
658			.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2])
659			.expect("Should be able to set allowed contracts in test");
660
661		assert_eq!(signer.signer_hash, *SCRIPT_HASH);
662		assert_eq!(
663			signer.get_scopes().iter().cloned().collect::<HashSet<_>>(),
664			vec![WitnessScope::CalledByEntry, WitnessScope::CustomContracts]
665				.into_iter()
666				.collect()
667		);
668		assert_eq!(
669			signer.get_allowed_contracts().iter().cloned().collect::<HashSet<_>>(),
670			vec![*SCRIPT_HASH1, *SCRIPT_HASH2].into_iter().collect()
671		);
672		assert!(signer.get_allowed_groups().is_empty());
673	}
674
675	#[test]
676	fn test_build_valid_signer2() {
677		let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into())
678			.expect("Should be able to create AccountSigner with none scope in test");
679		signer
680			.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2])
681			.expect("Should be able to set allowed contracts in test");
682
683		assert_eq!(signer.signer_hash, *SCRIPT_HASH);
684		assert_eq!(signer.get_scopes(), &vec![WitnessScope::CustomContracts]);
685		assert_eq!(
686			signer.get_allowed_contracts().iter().cloned().collect::<HashSet<_>>(),
687			vec![*SCRIPT_HASH1, *SCRIPT_HASH2].into_iter().collect()
688		);
689		assert!(signer.get_allowed_groups().is_empty());
690	}
691
692	#[test]
693	fn test_build_valid_signer3() {
694		let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into())
695			.expect("Should be able to create AccountSigner with none scope in test");
696		signer
697			.set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
698			.expect("Should be able to set allowed groups in test");
699
700		assert_eq!(signer.signer_hash, *SCRIPT_HASH);
701		assert_eq!(signer.get_scopes(), &vec![WitnessScope::CustomGroups]);
702		assert_eq!(
703			signer.get_allowed_groups().iter().cloned().collect::<HashSet<_>>(),
704			vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()].into_iter().collect()
705		);
706		assert!(signer.get_allowed_contracts().is_empty());
707	}
708
709	#[test]
710	fn test_fail_building_signer_with_global_scope_and_custom_contracts() {
711		let mut signer = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
712		let err = signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).unwrap_err();
713
714		assert_eq!(
715			err,
716			BuilderError::SignerConfiguration(
717				"Trying to set allowed contracts on a Signer with global scope.".to_string()
718			)
719		);
720	}
721
722	#[test]
723	fn test_fail_building_signer_with_global_scope_and_custom_groups() {
724		let mut signer = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
725		let err = signer
726			.set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
727			.unwrap_err();
728
729		assert_eq!(
730			err,
731			BuilderError::SignerConfiguration(
732				"Trying to set allowed contract groups on a Signer with global scope.".to_string()
733			)
734		);
735	}
736
737	#[test]
738	fn test_fail_building_signer_too_many_contracts() {
739		let script = H160::from_hex("3ab0be8672e25cf475219d018ded961ec684ca88").unwrap();
740		let contracts = (0..=16).map(|_| script.clone()).collect::<Vec<_>>();
741
742		let err = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into())
743			.unwrap()
744			.set_allowed_contracts(contracts)
745			.unwrap_err();
746
747		assert_eq!(
748			err,
749			BuilderError::SignerConfiguration(format!(
750				"Trying to set more than {} allowed contracts on a signer.",
751				NeoConstants::MAX_SIGNER_SUBITEMS
752			))
753		);
754	}
755
756	#[test]
757	fn test_fail_building_signer_too_many_contracts_added_separately() {
758		let script = H160::from_hex("3ab0be8672e25cf475219d018ded961ec684ca88").unwrap();
759		let contracts = (0..=15).map(|_| script.clone()).collect::<Vec<_>>();
760
761		let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
762		signer.set_allowed_contracts(vec![script]).expect("");
763
764		let err = signer.set_allowed_contracts(contracts).unwrap_err();
765
766		assert_eq!(
767			err,
768			BuilderError::SignerConfiguration(format!(
769				"Trying to set more than {} allowed contracts on a signer.",
770				NeoConstants::MAX_SIGNER_SUBITEMS
771			))
772		);
773	}
774
775	#[test]
776	fn test_fail_building_signer_too_many_groups() {
777		let public_key = Secp256r1PublicKey::from_encoded(
778			"0306d3e7f18e6dd477d34ce3cfeca172a877f3c907cc6c2b66c295d1fcc76ff8f7",
779		)
780		.unwrap();
781		let groups = (0..=16).map(|_| public_key.clone()).collect::<Vec<_>>();
782
783		let err = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into())
784			.unwrap()
785			.set_allowed_groups(groups)
786			.unwrap_err();
787
788		assert_eq!(
789			err,
790			BuilderError::SignerConfiguration(format!(
791				"Trying to set more than {} allowed contract groups on a signer.",
792				NeoConstants::MAX_SIGNER_SUBITEMS
793			))
794		);
795	}
796
797	#[test]
798	fn test_fail_building_signer_too_many_groups_added_separately() {
799		let public_key = Secp256r1PublicKey::from_encoded(
800			"0306d3e7f18e6dd477d34ce3cfeca172a877f3c907cc6c2b66c295d1fcc76ff8f7",
801		)
802		.unwrap();
803		let groups = (0..=15).map(|_| public_key.clone()).collect::<Vec<_>>();
804
805		let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
806		signer.set_allowed_groups(vec![public_key]).expect("");
807
808		let err = signer.set_allowed_groups(groups).unwrap_err();
809
810		assert_eq!(
811			err,
812			BuilderError::SignerConfiguration(format!(
813				"Trying to set more than {} allowed contract groups on a signer.",
814				NeoConstants::MAX_SIGNER_SUBITEMS
815			))
816		);
817	}
818
819	#[test]
820	fn test_serialize_global_scope() {
821		let mut buffer = Encoder::new();
822
823		AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap().encode(&mut buffer);
824
825		let expected = format!(
826			"{}{:02x}",
827			hex::encode(SCRIPT_HASH.as_bytes()),
828			WitnessScope::Global.byte_repr()
829		);
830		assert_eq!(hex::encode(buffer.to_bytes()), expected);
831	}
832
833	#[test]
834	fn test_serialize_custom_contracts_scope_produces_correct_byte_array() {
835		let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
836		signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).unwrap();
837
838		let expected = format!(
839			"{}{:02x}02{}{}",
840			hex::encode(SCRIPT_HASH.as_bytes()),
841			WitnessScope::CustomContracts.byte_repr(),
842			hex::encode(SCRIPT_HASH1.as_bytes()),
843			hex::encode(SCRIPT_HASH2.as_bytes())
844		);
845
846		assert_eq!(signer.to_array(), hex::decode(&expected).unwrap());
847	}
848
849	#[test]
850	fn test_serialize_custom_group_scope() {
851		let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
852		signer
853			.set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
854			.expect("");
855
856		let expected = format!(
857			"{}{:02x}02{}{}",
858			hex::encode(SCRIPT_HASH.as_bytes()),
859			WitnessScope::CustomGroups.byte_repr(),
860			GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
861			GROUP_PUB_KEY2.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
862		);
863
864		assert_eq!(signer.to_array(), hex::decode(&expected).unwrap());
865	}
866
867	#[test]
868	fn test_serialize_multiple_scopes_contracts_groups_and_rules() {
869		let rule = WitnessRule::new(
870			WitnessAction::Allow,
871			WitnessCondition::CalledByContract(*SCRIPT_HASH1),
872		);
873		let mut signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
874		signer
875			.set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
876			.expect("");
877		signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
878		signer.set_rules(vec![rule]).expect("");
879
880		let expected = format!(
881			"{}{}{}{}{}{}{}{}{}{}{}{}",
882			hex::encode(SCRIPT_HASH.as_bytes()),
883			"71",
884			"02",
885			hex::encode(SCRIPT_HASH1.as_bytes()),
886			hex::encode(SCRIPT_HASH2.as_bytes()),
887			"02",
888			GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
889			GROUP_PUB_KEY2.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
890			"01",
891			"01",
892			"28",
893			hex::encode(SCRIPT_HASH1.as_bytes())
894		);
895
896		assert_eq!(signer.to_array(), hex::decode(&expected).unwrap());
897	}
898
899	#[test]
900	fn test_fail_deserialize_too_many_contracts() {
901		let mut serialized = format!("{}1111", hex::encode(SCRIPT_HASH.as_bytes()));
902		for _ in 0..=17 {
903			serialized.push_str(&hex::encode(SCRIPT_HASH1.as_bytes()));
904		}
905		let mut data = hex::decode(&serialized).unwrap();
906		data.insert(0, 1);
907
908		let err = Signer::from_bytes(&data).unwrap_err();
909
910		assert!(err.to_string().contains(&format!(
911			"A signer's scope can only contain {} allowed contracts.",
912			NeoConstants::MAX_SIGNER_SUBITEMS
913		)));
914	}
915
916	#[test]
917	fn test_fail_deserialize_too_many_contract_groups() {
918		let mut serialized = format!("{}2111", hex::encode(SCRIPT_HASH.as_bytes()));
919		for _ in 0..=17 {
920			serialized.push_str(
921				&GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
922			);
923		}
924		let mut data = hex::decode(&serialized).unwrap();
925		data.insert(0, 1);
926
927		let err = Signer::from_bytes(&data).unwrap_err();
928
929		assert!(err.to_string().contains(&format!(
930			"A signer's scope can only contain {} allowed contract groups.",
931			NeoConstants::MAX_SIGNER_SUBITEMS
932		)));
933	}
934
935	#[test]
936	fn test_fail_deserialize_too_many_rules() {
937		let mut serialized = format!("{}4111", hex::encode(SCRIPT_HASH.as_bytes()));
938		for _ in 0..=17 {
939			serialized.push_str("01");
940			serialized.push_str("28");
941			serialized.push_str(&hex::encode(SCRIPT_HASH1.as_bytes()));
942		}
943		let mut data = hex::decode(&serialized).unwrap();
944		data.insert(0, 1);
945
946		let err = Signer::from_bytes(&data).unwrap_err();
947
948		assert!(err.to_string().contains(&format!(
949			"A signer's scope can only contain {} rules.",
950			NeoConstants::MAX_SIGNER_SUBITEMS
951		)));
952	}
953
954	#[test]
955	fn test_get_size() {
956		let rule = WitnessRule::new(
957			WitnessAction::Allow,
958			WitnessCondition::And(vec![
959				WitnessCondition::Boolean(true),
960				WitnessCondition::Boolean(false),
961			]),
962		);
963		let mut signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
964		signer
965			.set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
966			.expect("");
967		signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
968		signer.set_rules(vec![rule.clone(), rule]).expect("");
969
970		let expected_size = 20 // Account script hash
971            + 1 // Scope byte
972            + 1 // length byte of allowed contracts list
973            + 20 + 20 // Script hashes of two allowed contracts
974            + 1 // length byte of allowed groups list
975            + 33 + 33 // Public keys of two allowed groups
976            + 1 // length byte of rules list
977            + 1 // byte for WitnessRuleAction Allow
978            + 1 // byte for WitnessCondition type (AndCondition)
979            + 1 // length of AND condition list
980            + 1 // byte for WitnessCondition type (BooleanCondition)
981            + 1 // byte for value of BooleanCondition
982            + 1 // byte for WitnessCondition type (BooleanCondition)
983            + 1 // byte for value of BooleanCondition
984            + 1 // byte for WitnessRuleAction Allow
985            + 1 // byte for WitnessCondition type (AndCondition)
986            + 1 // length of AND condition list
987            + 1 // byte for WitnessCondition type (BooleanCondition)
988            + 1 // byte for value of BooleanCondition
989            + 1 // byte for WitnessCondition type (BooleanCondition)
990            + 1; // byte for value of BooleanCondition
991
992		assert_eq!(signer.size(), expected_size);
993	}
994
995	#[test]
996	fn test_serialize_deserialize_max_nested_rules() {
997		let rule = WitnessRule::new(
998			WitnessAction::Allow,
999			WitnessCondition::And(vec![WitnessCondition::And(vec![WitnessCondition::Boolean(
1000				true,
1001			)])]),
1002		);
1003
1004		let mut buffer = Encoder::new();
1005		let mut account_signer = AccountSigner::none(&ScriptHash::zero().into()).unwrap();
1006
1007		account_signer.set_rules(vec![rule]).unwrap();
1008		account_signer.encode(&mut buffer);
1009
1010		let expected =
1011			hex::decode("0000000000000000000000000000000000000000400101020102010001").unwrap();
1012		assert_eq!(buffer.to_bytes(), expected);
1013	}
1014
1015	#[test]
1016	fn test_fail_adding_rules_to_global_signer() {
1017		let rule =
1018			WitnessRule::new(WitnessAction::Allow, WitnessCondition::ScriptHash(*SCRIPT_HASH));
1019
1020		let mut signer = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
1021
1022		let err = signer.set_rules(vec![rule]).unwrap_err();
1023
1024		assert_eq!(
1025			err,
1026			BuilderError::SignerConfiguration(
1027				"Trying to set witness rules on a Signer with global scope.".to_string()
1028			)
1029		);
1030	}
1031
1032	#[test]
1033	fn test_fail_adding_too_many_rules() {
1034		let rule =
1035			WitnessRule::new(WitnessAction::Allow, WitnessCondition::ScriptHash(*SCRIPT_HASH));
1036
1037		let mut signer = AccountSigner::none(&SCRIPT_HASH.deref().into()).unwrap();
1038
1039		for _ in 0..NeoConstants::MAX_SIGNER_SUBITEMS {
1040			signer.set_rules(vec![rule.clone()]).unwrap();
1041		}
1042
1043		let err = signer.set_rules(vec![rule]).unwrap_err();
1044
1045		assert_eq!(
1046			err,
1047			BuilderError::SignerConfiguration(format!(
1048				"Trying to set more than {} allowed witness rules on a signer.",
1049				NeoConstants::MAX_SIGNER_SUBITEMS
1050			))
1051		);
1052	}
1053
1054	#[test]
1055	fn test_signer_equals() {
1056		let signer1 = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
1057		let signer2 = AccountSigner::global(&SCRIPT_HASH.deref().into()).unwrap();
1058
1059		assert_eq!(signer1, signer2);
1060
1061		let signer3 = ContractSigner::called_by_entry(*SCRIPT_HASH, &[]);
1062		let signer4 = ContractSigner::called_by_entry(*SCRIPT_HASH, &[]);
1063
1064		assert_eq!(signer3, signer4);
1065
1066		let mut signer5 = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
1067		signer5
1068			.set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
1069			.expect("");
1070		signer5.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
1071
1072		let mut signer6 = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
1073		signer6
1074			.set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
1075			.expect("");
1076		signer6.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
1077
1078		assert_eq!(signer5, signer6);
1079	}
1080
1081	#[test]
1082	fn test_serialize_with_multiple_scopes_contracts_groups_and_rules() {
1083		let rule = WitnessRule::new(
1084			WitnessAction::Allow,
1085			WitnessCondition::CalledByContract(*SCRIPT_HASH1),
1086		);
1087		let mut signer = AccountSigner::called_by_entry(&SCRIPT_HASH.deref().into()).unwrap();
1088		signer
1089			.set_allowed_groups(vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()])
1090			.expect("");
1091		signer.set_allowed_contracts(vec![*SCRIPT_HASH1, *SCRIPT_HASH2]).expect("");
1092		signer.set_rules(vec![rule]).expect("");
1093
1094		let expected = format!(
1095			"{}{}{}{}{}{}{}{}{}{}{}{}",
1096			hex::encode(SCRIPT_HASH.as_bytes()),
1097			"71",
1098			"02",
1099			hex::encode(SCRIPT_HASH1.as_bytes()),
1100			hex::encode(SCRIPT_HASH2.as_bytes()),
1101			"02",
1102			GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
1103			GROUP_PUB_KEY2.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
1104			"01",
1105			"01",
1106			"28",
1107			hex::encode(SCRIPT_HASH1.as_bytes())
1108		);
1109
1110		assert_eq!(signer.to_array(), hex::decode(&expected).unwrap());
1111	}
1112
1113	#[test]
1114	fn test_deserialize() {
1115		let data_str = format!(
1116			"{}{}{}{}{}{}{}{}{}{}{}{}",
1117			hex::encode(SCRIPT_HASH.as_bytes()),
1118			"71",
1119			"02",
1120			hex::encode(SCRIPT_HASH1.as_bytes()),
1121			hex::encode(SCRIPT_HASH2.as_bytes()),
1122			"02",
1123			GROUP_PUB_KEY1.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
1124			GROUP_PUB_KEY2.get_encoded_compressed_hex().trim_start_matches("0x").to_string(),
1125			"01",
1126			"01",
1127			"28",
1128			hex::encode(SCRIPT_HASH1.as_bytes())
1129		);
1130		let mut serialized = hex::decode(&data_str).unwrap();
1131		serialized.insert(0, 1);
1132
1133		let signer = Signer::from_bytes(&serialized).unwrap();
1134
1135		assert_eq!(signer.get_signer_hash(), SCRIPT_HASH.deref());
1136
1137		let expected_scopes: HashSet<WitnessScope> = vec![
1138			WitnessScope::CalledByEntry,
1139			WitnessScope::CustomContracts,
1140			WitnessScope::CustomGroups,
1141			WitnessScope::WitnessRules,
1142		]
1143		.into_iter()
1144		.collect();
1145		assert_eq!(signer.get_scopes().iter().cloned().collect::<HashSet<_>>(), expected_scopes);
1146
1147		assert_eq!(
1148			signer.get_allowed_contracts().iter().cloned().collect::<HashSet<_>>(),
1149			vec![*SCRIPT_HASH1, *SCRIPT_HASH2].into_iter().collect()
1150		);
1151
1152		assert_eq!(
1153			signer.get_allowed_groups().iter().cloned().collect::<HashSet<_>>(),
1154			vec![GROUP_PUB_KEY1.clone(), GROUP_PUB_KEY2.clone()].into_iter().collect()
1155		);
1156
1157		let rule = &signer.get_rules()[0];
1158		assert_eq!(rule.action, WitnessAction::Allow);
1159		assert_eq!(rule.condition, WitnessCondition::CalledByContract(*SCRIPT_HASH1));
1160	}
1161}