Skip to main content

avail_rust_core/substrate/
extrinsic.rs

1use crate::{
2	HasHeader,
3	types::{AccountId, ExtrinsicExtra, ExtrinsicSignature, H256, MultiAddress, MultiSignature},
4	utils::decode_already_decoded,
5};
6use codec::{Compact, Decode, Encode};
7use serde::{Deserialize, Serialize};
8use std::borrow::Cow;
9use subxt_core::config::{Hasher, substrate::BlakeTwo256};
10use subxt_signer::sr25519::Keypair;
11
12/// Current version of the [`UncheckedExtrinsic`] encoded format.
13///
14/// This version needs to be bumped if the encoded representation changes.
15/// It ensures that if the representation is changed and the format is not known,
16/// the decoding fails.
17pub const EXTRINSIC_FORMAT_VERSION: u8 = 4;
18
19#[derive(Debug, Clone)]
20pub struct ExtrinsicAdditional {
21	pub spec_version: u32,
22	pub tx_version: u32,
23	pub genesis_hash: H256,
24	pub fork_hash: H256,
25}
26impl Encode for ExtrinsicAdditional {
27	fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
28		self.spec_version.encode_to(dest);
29		self.tx_version.encode_to(dest);
30		self.genesis_hash.encode_to(dest);
31		self.fork_hash.encode_to(dest);
32	}
33}
34impl Decode for ExtrinsicAdditional {
35	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
36		let spec_version = Decode::decode(input)?;
37		let tx_version = Decode::decode(input)?;
38		let genesis_hash = Decode::decode(input)?;
39		let fork_hash = Decode::decode(input)?;
40		Ok(Self { spec_version, tx_version, genesis_hash, fork_hash })
41	}
42}
43
44#[derive(Debug, Clone)]
45pub struct ExtrinsicCall {
46	pub pallet_id: u8,
47	pub variant_id: u8,
48	pub data: Vec<u8>,
49}
50impl ExtrinsicCall {
51	pub fn new(pallet_id: u8, variant_id: u8, data: Vec<u8>) -> Self {
52		Self { pallet_id, variant_id, data }
53	}
54
55	pub fn hash(&self) -> [u8; 32] {
56		let call_vec: Vec<u8> = self.encode();
57		sp_crypto_hashing::blake2_256(&call_vec)
58	}
59}
60impl Encode for ExtrinsicCall {
61	fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
62		self.pallet_id.encode_to(dest);
63		self.variant_id.encode_to(dest);
64		dest.write(&self.data);
65	}
66}
67impl Decode for ExtrinsicCall {
68	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
69		let pallet_id = Decode::decode(input)?;
70		let variant_id = Decode::decode(input)?;
71		let data = decode_already_decoded(input)?;
72		Ok(Self { pallet_id, variant_id, data })
73	}
74}
75
76impl<T: HasHeader + Encode> From<&T> for ExtrinsicCall {
77	fn from(value: &T) -> Self {
78		Self {
79			pallet_id: T::HEADER_INDEX.0,
80			variant_id: T::HEADER_INDEX.1,
81			data: value.encode(),
82		}
83	}
84}
85
86impl TryFrom<String> for ExtrinsicCall {
87	type Error = String;
88
89	fn try_from(value: String) -> Result<Self, Self::Error> {
90		Self::try_from(value.as_str())
91	}
92}
93
94impl TryFrom<&str> for ExtrinsicCall {
95	type Error = String;
96
97	fn try_from(value: &str) -> Result<Self, Self::Error> {
98		let decoded = const_hex::decode(value.trim_start_matches("0x")).map_err(|e| e.to_string())?;
99		Self::try_from(decoded.as_slice())
100	}
101}
102
103impl TryFrom<Vec<u8>> for ExtrinsicCall {
104	type Error = String;
105
106	fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
107		Self::try_from(value.as_slice())
108	}
109}
110
111impl TryFrom<&Vec<u8>> for ExtrinsicCall {
112	type Error = String;
113
114	fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
115		Self::try_from(value.as_slice())
116	}
117}
118
119impl TryFrom<&[u8]> for ExtrinsicCall {
120	type Error = String;
121
122	fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
123		if value.len() < 2 {
124			return Err("Failed to convert array to Extrinsic Call. Not Enough data".into());
125		}
126		if value.len() == 2 {
127			return Ok(ExtrinsicCall::new(value[0], value[1], Vec::new()));
128		}
129
130		Ok(ExtrinsicCall::new(value[0], value[1], value[2..].to_vec()))
131	}
132}
133
134// There is no need for Encode and Decode
135#[derive(Debug, Clone)]
136pub struct ExtrinsicPayload<'a> {
137	pub call: Cow<'a, ExtrinsicCall>,
138	pub extra: ExtrinsicExtra,
139	pub additional: ExtrinsicAdditional,
140}
141
142impl<'a> ExtrinsicPayload<'a> {
143	pub fn new(call: ExtrinsicCall, extra: ExtrinsicExtra, additional: ExtrinsicAdditional) -> Self {
144		Self { call: Cow::Owned(call), extra, additional }
145	}
146
147	pub fn new_borrowed(call: &'a ExtrinsicCall, extra: ExtrinsicExtra, additional: ExtrinsicAdditional) -> Self {
148		Self { call: Cow::Borrowed(call), extra, additional }
149	}
150
151	pub fn sign(&self, signer: &Keypair) -> [u8; 64] {
152		let call = self.call.as_ref();
153		let size_hint = call.size_hint() + self.extra.size_hint() + self.additional.size_hint();
154
155		let mut data: Vec<u8> = Vec::with_capacity(size_hint);
156		self.call.encode_to(&mut data);
157		self.extra.encode_to(&mut data);
158		self.additional.encode_to(&mut data);
159
160		if data.len() > 256 {
161			let hash = BlakeTwo256::hash(&data);
162			signer.sign(hash.as_ref()).0
163		} else {
164			signer.sign(&data).0
165		}
166	}
167}
168
169#[derive(Debug, Clone)]
170pub struct GenericExtrinsic<'a> {
171	pub signature: Option<ExtrinsicSignature>,
172	pub call: Cow<'a, ExtrinsicCall>,
173}
174
175impl<'a> GenericExtrinsic<'a> {
176	pub fn new(account_id: AccountId, signature: [u8; 64], payload: ExtrinsicPayload<'a>) -> Self {
177		let address = MultiAddress::Id(account_id);
178		let signature = MultiSignature::Sr25519(signature);
179		let signature = Some(ExtrinsicSignature { address, signature, extra: payload.extra.clone() });
180
181		Self { signature, call: payload.call }
182	}
183
184	pub fn encode(&self) -> Vec<u8> {
185		let mut encoded_tx_inner = Vec::new();
186		if let Some(signed) = &self.signature {
187			0x84u8.encode_to(&mut encoded_tx_inner);
188			signed.address.encode_to(&mut encoded_tx_inner);
189			signed.signature.encode_to(&mut encoded_tx_inner);
190			signed.extra.encode_to(&mut encoded_tx_inner);
191		} else {
192			0x4u8.encode_to(&mut encoded_tx_inner);
193		}
194
195		let call = self.call.as_ref();
196		call.encode_to(&mut encoded_tx_inner);
197		let mut encoded_tx = Compact(encoded_tx_inner.len() as u32).encode();
198		encoded_tx.append(&mut encoded_tx_inner);
199
200		encoded_tx
201	}
202
203	pub fn hash(&self) -> H256 {
204		let encoded = self.encode();
205		BlakeTwo256::hash(&encoded)
206	}
207}
208
209impl TryFrom<&Vec<u8>> for GenericExtrinsic<'_> {
210	type Error = codec::Error;
211
212	fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
213		Self::try_from(value.as_slice())
214	}
215}
216
217impl TryFrom<&[u8]> for GenericExtrinsic<'_> {
218	type Error = codec::Error;
219
220	fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
221		let mut value = value;
222		Self::decode(&mut value)
223	}
224}
225
226impl Decode for GenericExtrinsic<'_> {
227	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
228		// This is a little more complicated than usual since the binary format must be compatible
229		// with SCALE's generic `Vec<u8>` type. Basically this just means accepting that there
230		// will be a prefix of vector length.
231		let expected_length = Compact::<u32>::decode(input)?;
232		let before_length = input.remaining_len()?;
233
234		let version = input.read_byte()?;
235
236		let is_signed = version & 0b1000_0000 != 0;
237		let version = version & 0b0111_1111;
238		if version != EXTRINSIC_FORMAT_VERSION {
239			return Err("Invalid transaction version".into());
240		}
241
242		let signed = is_signed.then(|| ExtrinsicSignature::decode(input)).transpose()?;
243		let call = ExtrinsicCall::decode(input)?;
244
245		if let Some((before_length, after_length)) = input.remaining_len()?.and_then(|a| before_length.map(|b| (b, a)))
246		{
247			let length = before_length.saturating_sub(after_length);
248
249			if length != expected_length.0 as usize {
250				return Err("Invalid length prefix".into());
251			}
252		}
253
254		Ok(Self { signature: signed, call: Cow::Owned(call) })
255	}
256}
257
258impl Serialize for GenericExtrinsic<'_> {
259	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
260	where
261		S: serde::Serializer,
262	{
263		let bytes = self.encode();
264		impl_serde::serialize::serialize(&bytes, serializer)
265	}
266}
267
268impl<'a> Deserialize<'a> for GenericExtrinsic<'_> {
269	fn deserialize<D>(de: D) -> Result<Self, D::Error>
270	where
271		D: serde::Deserializer<'a>,
272	{
273		let r = impl_serde::serialize::deserialize(de)?;
274		Decode::decode(&mut &r[..]).map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e)))
275	}
276}