neo3/neo_builder/transaction/signers/
transaction_signer.rs

1use std::hash::{Hash, Hasher};
2
3use crate::{
4	builder::{SignerTrait, SignerType, TransactionError, WitnessRule, WitnessScope},
5	codec::{Decoder, Encoder, NeoSerializable, VarSizeTrait},
6	config::NeoConstants,
7	crypto::Secp256r1PublicKey,
8	deserialize_scopes, deserialize_script_hash, deserialize_vec_script_hash_option,
9	neo_types::{deserialize_vec_public_key_option, serialize_vec_public_key_option},
10	serialize_scopes, serialize_script_hash, serialize_vec_script_hash_option,
11};
12use lazy_static::lazy_static;
13use primitive_types::H160;
14use serde::{Deserialize, Serialize};
15
16lazy_static! {
17	static ref EMPTY_CONTRACTS: Vec<H160> = Vec::new();
18	static ref EMPTY_GROUPS: Vec<Secp256r1PublicKey> = Vec::new();
19	static ref EMPTY_RULES: Vec<WitnessRule> = Vec::new();
20}
21
22/// Represents a transaction signer in the NEO blockchain.
23///
24/// This struct contains information about the signer, including the account,
25/// scopes, allowed contracts, allowed groups, and witness rules.
26#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq)]
27pub struct TransactionSigner {
28	#[serde(rename = "account")]
29	#[serde(serialize_with = "serialize_script_hash")]
30	#[serde(deserialize_with = "deserialize_script_hash")]
31	pub account: H160,
32
33	#[serde(rename = "scopes")]
34	#[serde(serialize_with = "serialize_scopes")]
35	#[serde(deserialize_with = "deserialize_scopes")]
36	pub scopes: Vec<WitnessScope>,
37
38	#[serde(rename = "allowedcontracts")]
39	#[serde(serialize_with = "serialize_vec_script_hash_option")]
40	#[serde(deserialize_with = "deserialize_vec_script_hash_option")]
41	#[serde(skip_serializing_if = "Option::is_none")]
42	#[serde(default)]
43	pub allowed_contracts: Option<Vec<H160>>,
44
45	#[serde(rename = "allowedgroups")]
46	#[serde(serialize_with = "serialize_vec_public_key_option")]
47	#[serde(deserialize_with = "deserialize_vec_public_key_option")]
48	#[serde(skip_serializing_if = "Option::is_none")]
49	#[serde(default)]
50	pub allowed_groups: Option<Vec<Secp256r1PublicKey>>,
51
52	#[serde(rename = "rules")]
53	#[serde(default)]
54	pub rules: Option<Vec<WitnessRule>>,
55}
56
57impl Hash for TransactionSigner {
58	fn hash<H: Hasher>(&self, state: &mut H) {
59		self.account.hash(state);
60		self.scopes.hash(state);
61		self.allowed_contracts.hash(state);
62		self.allowed_groups.hash(state);
63		self.rules.hash(state);
64	}
65}
66
67impl TransactionSigner {
68	/// Creates a new `TransactionSigner` with basic information.
69	///
70	/// # Arguments
71	///
72	/// * `account` - The account hash of the signer.
73	/// * `scopes` - The witness scopes for this signer.
74	pub fn new(account: H160, scopes: Vec<WitnessScope>) -> Self {
75		Self { account, scopes, allowed_contracts: None, allowed_groups: None, rules: None }
76	}
77
78	/// Creates a new `TransactionSigner` with full information.
79	///
80	/// # Arguments
81	///
82	/// * `account` - The account hash of the signer.
83	/// * `scopes` - The witness scopes for this signer.
84	/// * `allowed_contracts` - The list of allowed contract script hashes.
85	/// * `allowed_groups` - The list of allowed group public keys.
86	/// * `rules` - The list of witness rules.
87	pub fn new_full(
88		account: H160,
89		scopes: Vec<WitnessScope>,
90		allowed_contracts: Vec<H160>,
91		allowed_groups: Vec<Secp256r1PublicKey>,
92		rules: Vec<WitnessRule>,
93	) -> Self {
94		Self {
95			account,
96			scopes,
97			allowed_contracts: Some(allowed_contracts),
98			allowed_groups: Some(allowed_groups),
99			rules: Some(rules),
100		}
101	}
102}
103
104impl SignerTrait for TransactionSigner {
105	fn get_type(&self) -> SignerType {
106		SignerType::TransactionSigner
107	}
108
109	fn get_signer_hash(&self) -> &H160 {
110		&self.account
111	}
112
113	fn set_signer_hash(&mut self, signer_hash: H160) {
114		self.account = signer_hash;
115	}
116
117	fn get_scopes(&self) -> &Vec<WitnessScope> {
118		&self.scopes
119	}
120
121	fn get_scopes_mut(&mut self) -> &mut Vec<WitnessScope> {
122		&mut self.scopes
123	}
124
125	fn set_scopes(&mut self, scopes: Vec<WitnessScope>) {
126		self.scopes = scopes;
127	}
128
129	fn get_allowed_contracts(&self) -> &Vec<H160> {
130		self.allowed_contracts.as_ref().unwrap_or(&EMPTY_CONTRACTS)
131	}
132
133	fn get_allowed_contracts_mut(&mut self) -> &mut Vec<H160> {
134		self.allowed_contracts.get_or_insert_with(Vec::new)
135	}
136
137	fn get_allowed_groups(&self) -> &Vec<Secp256r1PublicKey> {
138		self.allowed_groups.as_ref().unwrap_or(&EMPTY_GROUPS)
139	}
140
141	fn get_allowed_groups_mut(&mut self) -> &mut Vec<Secp256r1PublicKey> {
142		self.allowed_groups.get_or_insert_with(Vec::new)
143	}
144
145	fn get_rules(&self) -> &Vec<WitnessRule> {
146		self.rules.as_ref().unwrap_or(&EMPTY_RULES)
147	}
148
149	fn get_rules_mut(&mut self) -> &mut Vec<WitnessRule> {
150		self.rules.get_or_insert_with(Vec::new)
151	}
152}
153
154impl NeoSerializable for TransactionSigner {
155	type Error = TransactionError;
156
157	/// Calculates the size of the serialized `TransactionSigner`.
158	fn size(&self) -> usize {
159		let mut size = (NeoConstants::HASH160_SIZE + 1) as usize;
160		if self.scopes.contains(&WitnessScope::CustomContracts) {
161			size += &self.allowed_contracts.clone().unwrap().var_size();
162		}
163		if self.scopes.contains(&WitnessScope::CustomGroups) {
164			size += &self.allowed_groups.clone().unwrap().var_size();
165		}
166
167		if self.scopes.contains(&WitnessScope::WitnessRules) {
168			size += &self.rules.clone().unwrap().var_size();
169		}
170
171		size
172	}
173
174	/// Encodes the `TransactionSigner` into bytes.
175	fn encode(&self, writer: &mut Encoder) {
176		writer.write_serializable_fixed(self.get_signer_hash());
177		writer.write_u8(WitnessScope::combine(self.scopes.as_slice()));
178		if self.scopes.contains(&WitnessScope::CustomContracts) {
179			writer.write_serializable_variable_list(self.allowed_contracts.as_ref().unwrap());
180		}
181		if self.scopes.contains(&WitnessScope::CustomGroups) {
182			writer.write_serializable_variable_list(self.allowed_groups.as_ref().unwrap());
183		}
184		if self.scopes.contains(&WitnessScope::WitnessRules) {
185			writer.write_serializable_variable_list(self.rules.as_ref().unwrap());
186		}
187	}
188
189	/// Decodes a `TransactionSigner` from bytes.
190	fn decode(reader: &mut Decoder) -> Result<Self, Self::Error>
191	where
192		Self: Sized,
193	{
194		let mut signer = TransactionSigner::default();
195		signer.set_signer_hash(reader.read_serializable().unwrap());
196		let scopes = WitnessScope::split(reader.read_u8());
197		signer.set_scopes(scopes);
198		if signer.get_scopes().contains(&WitnessScope::CustomContracts) {
199			signer.allowed_contracts = Some(reader.read_serializable_list().unwrap());
200		}
201		if signer.get_scopes().contains(&WitnessScope::CustomGroups) {
202			signer.allowed_groups = Some(reader.read_serializable_list().unwrap());
203		}
204		if signer.get_scopes().contains(&WitnessScope::WitnessRules) {
205			signer.rules = Some(reader.read_serializable_list().unwrap());
206		}
207		Ok(signer)
208	}
209
210	/// Converts the `TransactionSigner` into a byte array.
211	fn to_array(&self) -> Vec<u8> {
212		let writer = &mut Encoder::new();
213		self.encode(writer);
214		writer.to_bytes()
215	}
216}