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				_ => 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	/// Creates a `Signer` from a byte array.
317	///
318	/// # Arguments
319	///
320	/// * `data` - The byte array containing the serialized signer data.
321	///
322	/// # Returns
323	///
324	/// A `Result` containing the deserialized `Signer` or a `TransactionError`.
325	pub fn from_bytes(data: &[u8]) -> Result<Signer, TransactionError> {
326		let mut reader = Decoder::new(data);
327		Signer::decode(&mut reader)
328	}
329
330	/// Returns the type of the signer.
331	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	/// Returns a reference to the signer's script hash.
339	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	/// Safely converts to AccountSigner
369	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	/// Safely converts to ContractSigner
379	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
412// Keep the existing Into implementations for backward compatibility
413impl 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				// Return a default AccountSigner as fallback
420				AccountSigner::none_hash160(primitive_types::H160::zero()).unwrap_or_else(|_| {
421					// If even the default creation fails, create one with a valid account
422					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::Account(_account_signer) =>
473			// 	panic!("Cannot convert AccountSigner into TransactionSigner"),
474			// Signer::Contract(_contract_signer) =>
475			// 	panic!("Cannot convert ContractSigner into AccountSigner"),
476			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				// Log the error and return a minimal ContractSigner to avoid panic
509				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				// Log the error and return a minimal ContractSigner to avoid panic
522				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			//_ => Ok(Signer::Transaction(TransactionSigner::decode(reader)?)),
570			_ => 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 // Account script hash
959            + 1 // Scope byte
960            + 1 // length byte of allowed contracts list
961            + 20 + 20 // Script hashes of two allowed contracts
962            + 1 // length byte of allowed groups list
963            + 33 + 33 // Public keys of two allowed groups
964            + 1 // length byte of rules list
965            + 1 // byte for WitnessRuleAction Allow
966            + 1 // byte for WitnessCondition type (AndCondition)
967            + 1 // length of AND condition list
968            + 1 // byte for WitnessCondition type (BooleanCondition)
969            + 1 // byte for value of BooleanCondition
970            + 1 // byte for WitnessCondition type (BooleanCondition)
971            + 1 // byte for value of BooleanCondition
972            + 1 // byte for WitnessRuleAction Allow
973            + 1 // byte for WitnessCondition type (AndCondition)
974            + 1 // length of AND condition list
975            + 1 // byte for WitnessCondition type (BooleanCondition)
976            + 1 // byte for value of BooleanCondition
977            + 1 // byte for WitnessCondition type (BooleanCondition)
978            + 1; // byte for value of BooleanCondition
979
980		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}