neo3/neo_builder/transaction/signers/
contract_signer.rs

1use crate::{
2	builder::{BuilderError, SignerTrait, SignerType, TransactionError, WitnessRule, WitnessScope},
3	codec::{Decoder, Encoder, NeoSerializable, VarSizeTrait},
4	config::NeoConstants,
5	crypto::Secp256r1PublicKey,
6	deserialize_script_hash, deserialize_vec_script_hash,
7	neo_types::{deserialize_vec_public_key, serialize_vec_public_key},
8	serialize_script_hash, serialize_vec_script_hash, ContractParameter,
9};
10use getset::{Getters, Setters};
11use primitive_types::H160;
12use serde::{Deserialize, Serialize};
13use std::hash::{Hash, Hasher};
14
15/// Represents a contract signer in the NEO blockchain.
16///
17/// This struct contains information about the contract signer, including
18/// the signer hash, scopes, allowed contracts, allowed groups, and witness rules.
19#[derive(Debug, Clone, Serialize, PartialEq, Deserialize, Getters, Setters)]
20pub struct ContractSigner {
21	#[serde(
22		serialize_with = "serialize_script_hash",
23		deserialize_with = "deserialize_script_hash"
24	)]
25	signer_hash: H160,
26	scopes: Vec<WitnessScope>,
27	#[serde(
28		serialize_with = "serialize_vec_script_hash",
29		deserialize_with = "deserialize_vec_script_hash"
30	)]
31	allowed_contracts: Vec<H160>,
32	#[serde(
33		serialize_with = "serialize_vec_public_key",
34		deserialize_with = "deserialize_vec_public_key"
35	)]
36	allowed_groups: Vec<Secp256r1PublicKey>,
37	rules: Vec<WitnessRule>,
38	#[getset(get = "pub")]
39	verify_params: Vec<ContractParameter>,
40	#[serde(
41		serialize_with = "serialize_script_hash",
42		deserialize_with = "deserialize_script_hash"
43	)]
44	#[serde(skip_deserializing)]
45	contract_hash: H160,
46	scope: WitnessScope,
47}
48
49impl Hash for ContractSigner {
50	fn hash<H: Hasher>(&self, state: &mut H) {
51		self.signer_hash.hash(state);
52		self.scopes.hash(state);
53		// self.allowed_contracts.hash(state);
54		// self.allowed_groups.hash(state);
55		self.rules.hash(state);
56		self.verify_params.hash(state);
57		self.contract_hash.hash(state);
58		self.scope.hash(state);
59	}
60}
61
62impl SignerTrait for ContractSigner {
63	fn get_type(&self) -> SignerType {
64		SignerType::ContractSigner
65	}
66
67	fn get_signer_hash(&self) -> &H160 {
68		&self.signer_hash
69	}
70
71	fn set_signer_hash(&mut self, signer_hash: H160) {
72		self.signer_hash = signer_hash;
73	}
74
75	fn get_scopes(&self) -> &Vec<WitnessScope> {
76		&self.scopes
77	}
78
79	fn get_scopes_mut(&mut self) -> &mut Vec<WitnessScope> {
80		&mut self.scopes
81	}
82
83	fn set_scopes(&mut self, scopes: Vec<WitnessScope>) {
84		self.scopes = scopes;
85	}
86
87	fn get_allowed_contracts(&self) -> &Vec<H160> {
88		&self.allowed_contracts
89	}
90
91	fn get_allowed_contracts_mut(&mut self) -> &mut Vec<H160> {
92		&mut self.allowed_contracts
93	}
94
95	fn get_allowed_groups(&self) -> &Vec<Secp256r1PublicKey> {
96		&self.allowed_groups
97	}
98
99	fn get_allowed_groups_mut(&mut self) -> &mut Vec<Secp256r1PublicKey> {
100		&mut self.allowed_groups
101	}
102
103	fn get_rules(&self) -> &Vec<WitnessRule> {
104		&self.rules
105	}
106
107	fn get_rules_mut(&mut self) -> &mut Vec<WitnessRule> {
108		&mut self.rules
109	}
110}
111
112impl ContractSigner {
113	fn new(
114		contract_hash: H160,
115		scope: WitnessScope,
116		verify_params: Vec<ContractParameter>,
117	) -> Self {
118		Self {
119			signer_hash: Default::default(),
120			scopes: vec![],
121			allowed_contracts: vec![],
122			allowed_groups: vec![],
123			rules: vec![],
124			verify_params,
125			contract_hash,
126			scope,
127		}
128	}
129
130	/// Creates a new `ContractSigner` with the "Called By Entry" scope.
131	///
132	/// # Arguments
133	///
134	/// * `contract_hash` - The hash of the contract.
135	/// * `verify_params` - The parameters for contract verification.
136	pub fn called_by_entry(contract_hash: H160, verify_params: &[ContractParameter]) -> Self {
137		Self::new(contract_hash, WitnessScope::CalledByEntry, verify_params.to_vec())
138	}
139
140	/// Creates a new `ContractSigner` with the "Global" scope.
141	///
142	/// # Arguments
143	///
144	/// * `contract_hash` - The hash of the contract.
145	/// * `verify_params` - The parameters for contract verification.
146	pub fn global(contract_hash: H160, verify_params: &[ContractParameter]) -> Self {
147		Self::new(contract_hash, WitnessScope::Global, verify_params.to_vec())
148	}
149}
150
151impl NeoSerializable for ContractSigner {
152	type Error = TransactionError;
153
154	fn size(&self) -> usize {
155		let mut size: usize = NeoConstants::HASH160_SIZE as usize;
156		if self.scopes.contains(&WitnessScope::CustomContracts) {
157			size += self.allowed_contracts.var_size();
158		}
159		if self.scopes.contains(&WitnessScope::CustomGroups) {
160			size += self.allowed_groups.var_size();
161		}
162		if self.scopes.contains(&WitnessScope::WitnessRules) {
163			size += self.rules.var_size();
164		}
165		size
166	}
167
168	fn encode(&self, writer: &mut Encoder) {
169		writer.write_serializable_fixed(&self.signer_hash);
170		writer.write_u8(WitnessScope::combine(&self.scopes));
171		if self.scopes.contains(&WitnessScope::CustomContracts) {
172			writer.write_serializable_variable_list(&self.allowed_contracts);
173		}
174		if self.scopes.contains(&WitnessScope::CustomGroups) {
175			writer.write_serializable_variable_list(&self.allowed_groups);
176		}
177		if self.scopes.contains(&WitnessScope::WitnessRules) {
178			writer.write_serializable_variable_list(&self.rules);
179		}
180	}
181
182	fn decode(reader: &mut Decoder) -> Result<Self, Self::Error>
183	where
184		Self: Sized,
185	{
186		let signer_hash = reader.read_serializable::<H160>().unwrap();
187		let scopes = WitnessScope::split(reader.read_u8());
188		let mut allowed_contracts = vec![];
189		let mut allowed_groups = vec![];
190		let mut rules = vec![];
191		if scopes.contains(&WitnessScope::CustomContracts) {
192			allowed_contracts = reader.read_serializable_list::<H160>().unwrap();
193			if allowed_contracts.len() > NeoConstants::MAX_SIGNER_SUBITEMS as usize {
194				return Err(BuilderError::SignerConfiguration(format!(
195                    "A signer's scope can only contain {} allowed contracts. The input data contained {} contracts.",
196                    NeoConstants::MAX_SIGNER_SUBITEMS,
197                    allowed_contracts.len()
198                ))
199                    .into());
200			}
201		}
202		if scopes.contains(&WitnessScope::CustomGroups) {
203			allowed_groups = reader.read_serializable_list::<Secp256r1PublicKey>().unwrap();
204			if allowed_groups.len() > NeoConstants::MAX_SIGNER_SUBITEMS as usize {
205				return Err(BuilderError::SignerConfiguration(format!(
206                    "A signer's scope can only contain {} allowed contract groups. The input data contained {} groups.",
207                    NeoConstants::MAX_SIGNER_SUBITEMS,
208                    allowed_groups.len()
209                ))
210                    .into());
211			}
212		}
213		if scopes.contains(&WitnessScope::WitnessRules) {
214			rules = reader.read_serializable_list::<WitnessRule>().unwrap();
215			if rules.len() > NeoConstants::MAX_SIGNER_SUBITEMS as usize {
216				return Err(BuilderError::SignerConfiguration(format!(
217                    "A signer's scope can only contain {} rules. The input data contained {} rules.",
218                    NeoConstants::MAX_SIGNER_SUBITEMS,
219                    rules.len()
220                ))
221                    .into());
222			}
223		}
224		Ok(Self {
225			signer_hash,
226			scopes,
227			allowed_contracts,
228			allowed_groups,
229			rules,
230			verify_params: vec![],
231			contract_hash: Default::default(),
232			scope: WitnessScope::None,
233		})
234	}
235
236	fn to_array(&self) -> Vec<u8> {
237		let mut writer = Encoder::new();
238		self.encode(&mut writer);
239		writer.to_bytes()
240	}
241}