Skip to content

Commit

Permalink
add extra prefixed field
Browse files Browse the repository at this point in the history
  • Loading branch information
tadeohepperle committed Jul 10, 2023
1 parent ad4d228 commit d39a45c
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 15 deletions.
20 changes: 9 additions & 11 deletions subxt/src/blocks/extrinsic_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ where
// Attempt to dynamically decode a single extrinsic from the given input.
pub(crate) fn decode_from(
index: u32,
encoded_extrinsic_bytes: Arc<[u8]>,
prefixed_extrinsic_bytes: Arc<[u8]>,
client: C,
block_hash: T::Hash,
cached_events: CachedEvents<T>,
Expand All @@ -215,13 +215,13 @@ where

let metadata = client.metadata();

let decoded_extrinsic_bytes: Vec<u8> = Decode::decode(&mut &encoded_extrinsic_bytes[..])?;
let extrinsic_bytes: Vec<u8> = Decode::decode(&mut &prefixed_extrinsic_bytes[..])?;

// Extrinsic are encoded in memory in the following way:
// - first byte: abbbbbbb (a = 0 for unsigned, 1 for signed, b = version)
// - signature: [unknown TBD with metadata].
// - extrinsic data
let first_byte: u8 = Decode::decode(&mut &decoded_extrinsic_bytes[..])?;
let first_byte: u8 = Decode::decode(&mut &extrinsic_bytes[..])?;

let version = first_byte & VERSION_MASK;
if version != LATEST_EXTRINSIC_VERSION {
Expand All @@ -231,13 +231,13 @@ where
let is_signed = first_byte & SIGNATURE_MASK != 0;

// Skip over the first byte which denotes the version and signing.
let cursor = &mut &decoded_extrinsic_bytes[1..];
let cursor = &mut &extrinsic_bytes[1..];

let mut address_start_idx = 0;
let mut address_end_idx = 0;

if is_signed {
address_start_idx = decoded_extrinsic_bytes.len() - cursor.len();
address_start_idx = extrinsic_bytes.len() - cursor.len();

// Skip over the address, signature and extra fields.
scale_decode::visitor::decode_with_visitor(
Expand All @@ -247,7 +247,7 @@ where
scale_decode::visitor::IgnoreVisitor,
)
.map_err(scale_decode::Error::from)?;
address_end_idx = decoded_extrinsic_bytes.len() - cursor.len();
address_end_idx = extrinsic_bytes.len() - cursor.len();

scale_decode::visitor::decode_with_visitor(
cursor,
Expand All @@ -266,19 +266,17 @@ where
.map_err(scale_decode::Error::from)?;
}

let call_start_idx = decoded_extrinsic_bytes.len() - cursor.len();
let call_start_idx = extrinsic_bytes.len() - cursor.len();

// Decode the pallet index, then the call variant.
let cursor = &mut &decoded_extrinsic_bytes[call_start_idx..];
let cursor = &mut &extrinsic_bytes[call_start_idx..];

let pallet_index: u8 = Decode::decode(cursor)?;
let variant_index: u8 = Decode::decode(cursor)?;

let decoded_extrinsic_bytes: Arc<[u8]> =
Arc::from(decoded_extrinsic_bytes.into_boxed_slice());
Ok(ExtrinsicDetails {
index,
bytes: decoded_extrinsic_bytes,
bytes: extrinsic_bytes.into(),
is_signed,
address_start_idx,
address_end_idx,
Expand Down
12 changes: 8 additions & 4 deletions subxt/src/tx/tx_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,10 @@ where
/// This represents an extrinsic that has been signed and is ready to submit.
pub struct SubmittableExtrinsic<T, C> {
client: C,
/// scale encoded bytes of the extrinsic
encoded: Encoded,
/// scale encoded bytes as a Vec<u8> that is prefixed by the compact-encoded length
encoded_prefixed: Vec<u8>,
marker: std::marker::PhantomData<T>,
}

Expand All @@ -417,12 +420,13 @@ where
pub fn from_bytes(client: C, tx_bytes: Vec<u8>) -> Self {
Self {
client,
encoded_prefixed: tx_bytes.encode(),
encoded: Encoded(tx_bytes),
marker: std::marker::PhantomData,
}
}

/// Returns the SCALE encoded extrinsic bytes.
/// Returns the SCALE encoded extrinsic bytes
pub fn encoded(&self) -> &[u8] {
&self.encoded.0
}
Expand All @@ -445,11 +449,11 @@ where
/// and obtain details about it, once it has made it into a block.
pub async fn submit_and_watch(&self) -> Result<TxProgress<T, C>, Error> {
// Get a hash of the extrinsic (we'll need this later)
// The `.encode()` is necessary to produce the same hash as in the raw extrinsic bytes returned from the RPC call).
let ext_hash = T::Hasher::hash_of(&self.encoded.encode());
// We use the `encoded_prefixed` to calculate the hash, because it has the same hash
// as the extrinsic bytes returned from the RPC call, that are also prefixed .
let ext_hash = T::Hasher::hash_of(&self.encoded_prefixed);
// Submit and watch for transaction progress.
let sub = self.client.rpc().watch_extrinsic(&self.encoded).await?;

Ok(TxProgress::new(sub, self.client.clone(), ext_hash))
}

Expand Down

0 comments on commit d39a45c

Please sign in to comment.