neo3/neo_builder/transaction/signers/
account_signer.rs1use std::hash::{Hash, Hasher};
2
3use crate::{
4 builder::{BuilderError, SignerTrait, SignerType, TransactionError, WitnessRule, WitnessScope},
5 codec::{Decoder, Encoder, NeoSerializable, VarSizeTrait},
6 config::NeoConstants,
7 crypto::{PublicKeyExtension, Secp256r1PublicKey},
8 deserialize_script_hash, deserialize_vec_script_hash,
9 neo_protocol::{Account, AccountTrait},
10 neo_types::{deserialize_vec_public_key, serialize_vec_public_key},
11 serialize_script_hash, serialize_vec_script_hash, ScriptHashExtension,
12};
13use getset::{Getters, Setters};
14use primitive_types::H160;
15use serde::{Deserialize, Serialize};
16
17#[derive(Debug, Clone, Serialize, Deserialize, Getters, Setters)]
22pub struct AccountSigner {
23 #[serde(
24 serialize_with = "serialize_script_hash",
25 deserialize_with = "deserialize_script_hash"
26 )]
27 pub(crate) signer_hash: H160,
28 pub(crate) scopes: Vec<WitnessScope>,
29 #[serde(
30 serialize_with = "serialize_vec_script_hash",
31 deserialize_with = "deserialize_vec_script_hash"
32 )]
33 pub(crate) allowed_contracts: Vec<H160>,
34 #[serde(
35 serialize_with = "serialize_vec_public_key",
36 deserialize_with = "deserialize_vec_public_key"
37 )]
38 pub(crate) allowed_groups: Vec<Secp256r1PublicKey>,
39 rules: Vec<WitnessRule>,
40 #[getset(get = "pub")]
41 pub account: Account,
42}
43
44impl AccountSigner {
45 pub fn none(account: &Account) -> Result<Self, TransactionError> {
51 Ok(Self::new(account, WitnessScope::None))
52 }
53
54 pub fn called_by_entry(account: &Account) -> Result<Self, TransactionError> {
60 Ok(Self::new(account, WitnessScope::CalledByEntry))
61 }
62
63 pub fn global(account: &Account) -> Result<Self, TransactionError> {
69 Ok(Self::new(account, WitnessScope::Global))
70 }
71
72 pub fn is_multi_sig(&self) -> bool {
74 matches!(&self.account.verification_script(), Some(script) if script.is_multi_sig())
75 }
76
77 pub fn get_script_hash(&self) -> H160 {
79 self.account.get_script_hash().clone()
80 }
81}
82
83impl NeoSerializable for AccountSigner {
84 type Error = TransactionError;
85
86 fn size(&self) -> usize {
87 let mut size: usize = NeoConstants::HASH160_SIZE as usize + 1;
88 if self.scopes.contains(&WitnessScope::CustomContracts) {
89 size += self.allowed_contracts.var_size();
90 }
91 if self.scopes.contains(&WitnessScope::CustomGroups) {
92 size += self.allowed_groups.var_size();
93 }
94 if self.scopes.contains(&WitnessScope::WitnessRules) {
95 size += self.rules.var_size();
96 }
97 size
98 }
99
100 fn encode(&self, writer: &mut Encoder) {
101 writer.write_serializable_fixed(&self.signer_hash);
102 writer.write_u8(WitnessScope::combine(&self.scopes));
103 if self.scopes.contains(&WitnessScope::CustomContracts) {
104 writer.write_serializable_variable_list(&self.allowed_contracts);
105 }
106 if self.scopes.contains(&WitnessScope::CustomGroups) {
107 writer.write_serializable_variable_list(&self.allowed_groups);
108 }
109 if self.scopes.contains(&WitnessScope::WitnessRules) {
110 writer.write_serializable_variable_list(&self.rules);
111 }
112 }
113
114 fn decode(reader: &mut Decoder) -> Result<Self, Self::Error>
115 where
116 Self: Sized,
117 {
118 let signer_hash = reader.read_serializable::<H160>().unwrap();
119 let scopes = WitnessScope::split(reader.read_u8());
120 let mut allowed_contracts = vec![];
121 let mut allowed_groups = vec![];
122 let mut rules = vec![];
123 if scopes.contains(&WitnessScope::CustomContracts) {
124 allowed_contracts = reader.read_serializable_list::<H160>().unwrap();
125 if allowed_contracts.len() > NeoConstants::MAX_SIGNER_SUBITEMS as usize {
126 return Err(BuilderError::SignerConfiguration(format!(
127 "A signer's scope can only contain {} allowed contracts. The input data contained {} contracts.",
128 NeoConstants::MAX_SIGNER_SUBITEMS,
129 allowed_contracts.len()
130 ))
131 .into());
132 }
133 }
134 if scopes.contains(&WitnessScope::CustomGroups) {
135 allowed_groups = reader.read_serializable_list::<Secp256r1PublicKey>().unwrap();
136 if allowed_groups.len() > NeoConstants::MAX_SIGNER_SUBITEMS as usize {
137 return Err(BuilderError::SignerConfiguration(format!(
138 "A signer's scope can only contain {} allowed contract groups. The input data contained {} groups.",
139 NeoConstants::MAX_SIGNER_SUBITEMS,
140 allowed_groups.len()
141 ))
142 .into());
143 }
144 }
145 if scopes.contains(&WitnessScope::WitnessRules) {
146 rules = reader.read_serializable_list::<WitnessRule>().unwrap();
147 if rules.len() > NeoConstants::MAX_SIGNER_SUBITEMS as usize {
148 return Err(BuilderError::SignerConfiguration(format!(
149 "A signer's scope can only contain {} rules. The input data contained {} rules.",
150 NeoConstants::MAX_SIGNER_SUBITEMS,
151 rules.len()
152 ))
153 .into());
154 }
155 }
156 Ok(Self {
157 signer_hash,
158 scopes,
159 allowed_contracts,
160 allowed_groups,
161 rules,
162 account: Account::from_address(signer_hash.to_address().as_str()).unwrap(),
163 })
164 }
165
166 fn to_array(&self) -> Vec<u8> {
167 let mut writer = Encoder::new();
168 self.encode(&mut writer);
169 writer.to_bytes()
170 }
171}
172
173impl PartialEq for AccountSigner {
174 fn eq(&self, other: &Self) -> bool {
175 self.signer_hash == other.signer_hash
176 && self.scopes == other.scopes
177 && self.allowed_contracts == other.allowed_contracts
178 && self.allowed_groups == other.allowed_groups
179 && self.rules == other.rules
180 }
182}
183
184impl Hash for AccountSigner {
185 fn hash<H: Hasher>(&self, state: &mut H) {
186 self.signer_hash.hash(state);
187 self.scopes.hash(state);
188 self.allowed_contracts.hash(state);
189 for group in self.allowed_groups.iter() {
190 group.to_vec().hash(state);
191 }
192 self.rules.hash(state);
194 }
197}
198
199impl SignerTrait for AccountSigner {
200 fn get_type(&self) -> SignerType {
201 SignerType::AccountSigner
202 }
203
204 fn get_signer_hash(&self) -> &H160 {
205 &self.signer_hash
206 }
207
208 fn set_signer_hash(&mut self, signer_hash: H160) {
209 self.signer_hash = signer_hash;
210 }
211
212 fn get_scopes(&self) -> &Vec<WitnessScope> {
213 &self.scopes
214 }
215
216 fn get_scopes_mut(&mut self) -> &mut Vec<WitnessScope> {
217 &mut self.scopes
218 }
219
220 fn set_scopes(&mut self, scopes: Vec<WitnessScope>) {
221 self.scopes = scopes;
222 }
223
224 fn get_allowed_contracts(&self) -> &Vec<H160> {
225 &self.allowed_contracts
226 }
227
228 fn get_allowed_contracts_mut(&mut self) -> &mut Vec<H160> {
229 &mut self.allowed_contracts
230 }
231
232 fn get_allowed_groups(&self) -> &Vec<Secp256r1PublicKey> {
233 &self.allowed_groups
234 }
235
236 fn get_allowed_groups_mut(&mut self) -> &mut Vec<Secp256r1PublicKey> {
237 &mut self.allowed_groups
238 }
239
240 fn get_rules(&self) -> &Vec<WitnessRule> {
241 &self.rules
242 }
243
244 fn get_rules_mut(&mut self) -> &mut Vec<WitnessRule> {
245 &mut self.rules
246 }
247}
248
249impl AccountSigner {
250 pub fn new(account: &Account, scope: WitnessScope) -> Self {
251 Self {
252 signer_hash: account.get_script_hash().clone(),
253 scopes: vec![scope],
254 allowed_contracts: vec![],
255 allowed_groups: vec![],
256 rules: vec![],
257 account: account.clone(),
258 }
259 }
260
261 pub fn none_hash160(account_hash: H160) -> Result<Self, TransactionError> {
262 let account = Account::from_address(account_hash.to_address().as_str()).unwrap();
263 Ok(Self::new(&account, WitnessScope::None))
264 }
265
266 pub fn called_by_entry_hash160(account_hash: H160) -> Result<Self, TransactionError> {
267 let account = Account::from_address(account_hash.to_address().as_str()).unwrap();
268 Ok(Self::new(&account, WitnessScope::CalledByEntry))
269 }
270
271 pub fn global_hash160(account_hash: H160) -> Result<Self, TransactionError> {
272 let account = Account::from_address(account_hash.to_address().as_str()).unwrap();
273 Ok(Self::new(&account, WitnessScope::Global))
274 }
275}