Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 0 additions & 75 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,3 @@ scale-value = { version = "0.16.2", default-features = false }
pythonize = "0.23.0"
log = { version = "0.4.25", default-features = false }
pyo3-log = { version = "0.12.1", default-features = false }
blake2 = "0.10"
base58 = "0.2"
6 changes: 1 addition & 5 deletions bt_decode.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -346,18 +346,14 @@ class PortableRegistry:
pass

def decode(
type_string: str,
portable_registry: PortableRegistry,
encoded: bytes,
legacy_account_id: bool = True,
type_string: str, portable_registry: PortableRegistry, encoded: bytes
) -> Any:
pass

def decode_list(
list_type_strings: list[str],
portable_registry: PortableRegistry,
list_encoded: list[bytes],
legacy_account_id: bool = True,
) -> list[Any]:
"""
Decode a list of SCALE-encoded types using a list of their type-strings.
Expand Down
114 changes: 21 additions & 93 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ mod dyndecoder;
mod bt_decode {
use std::collections::HashMap;

use base58::ToBase58;
use blake2::{Blake2b512, Digest};
use dyndecoder::{fill_memo_using_well_known_types, get_type_id_from_type_string};
use frame_metadata::v15::RuntimeMetadataV15;
use pyo3::types::{PyDict, PyInt, PyList, PyTuple};
Expand All @@ -46,25 +44,6 @@ mod bt_decode {

use super::*;

fn account_id_to_ss58(account_id: [u8; 32], ss58_prefix: u16) -> String {
let mut data = Vec::with_capacity(35);
match ss58_prefix {
0..=63 => data.push(ss58_prefix as u8),
64..=16383 => {
data.push(((ss58_prefix & 0b0011_1111) | 0b0100_0000) as u8);
data.push((ss58_prefix >> 6) as u8);
}
_ => panic!("Invalid SS58 prefix"),
}
data.extend(account_id);
let checksum = Blake2b512::new()
.chain_update(b"SS58PRE")
.chain_update(&data)
.finalize();
data.extend_from_slice(&checksum[..2]);
data.to_base58()
}

#[pyclass(name = "AxonInfo", get_all)]
#[derive(Clone, Encode, Decode)]
struct AxonInfo {
Expand Down Expand Up @@ -390,40 +369,32 @@ mod bt_decode {
}
}

fn composite_to_py_object(
py: Python,
value: Composite<u32>,
legacy_account_id: bool,
) -> PyResult<Py<PyAny>> {
fn composite_to_py_object(py: Python, value: Composite<u32>) -> PyResult<Py<PyAny>> {
match value {
Composite::Named(inner_) => {
let dict = PyDict::new_bound(py);
for (key, val) in inner_.iter() {
let val_py = value_to_pyobject(py, val.clone(), legacy_account_id)?;
let val_py = value_to_pyobject(py, val.clone())?;
dict.set_item(key, val_py)?;
}

Ok(dict.to_object(py))
}
Composite::Unnamed(inner_) => {
let items: Vec<Py<PyAny>> = inner_
.iter()
.map(|val| value_to_pyobject(py, val.clone(), legacy_account_id))
.collect::<PyResult<Vec<Py<PyAny>>>>()?;
if !legacy_account_id && inner_.len() == 1 && inner_[0].context == 1 {
// AccountIds are the only ones with context of 1, this will cause them to not be placed in a tuple
return Ok(items[0].clone_ref(py));
}
let tuple = PyTuple::new_bound(py, items);
let tuple = PyTuple::new_bound(
py,
inner_
.iter()
.map(|val| value_to_pyobject(py, val.clone()))
.collect::<PyResult<Vec<Py<PyAny>>>>()?,
);

Ok(tuple.to_object(py))
}
}
}

fn value_to_pyobject(
py: Python,
value: Value<u32>,
legacy_account_id: bool,
) -> PyResult<Py<PyAny>> {
fn value_to_pyobject(py: Python, value: Value<u32>) -> PyResult<Py<PyAny>> {
match value.value {
ValueDef::<u32>::Primitive(inner) => {
let value = match inner {
Expand All @@ -443,58 +414,17 @@ mod bt_decode {

Ok(value)
}
ValueDef::<u32>::Composite(composite) => {
if legacy_account_id {
let value = composite_to_py_object(py, composite, legacy_account_id)?;
return Ok(value);
} else {
match &composite {
Composite::Unnamed(ref inner) if inner.len() == 32 => {
let mut account_id_bytes: Vec<u8> = Vec::with_capacity(32);

for val in inner.iter() {
match val.value {
ValueDef::<u32>::Primitive(Primitive::U128(byte)) => {
account_id_bytes.push(byte as u8);
}
_ => {
let value = composite_to_py_object(
py,
composite,
legacy_account_id,
)?;
return Ok(value);
}
}
}

let account_id_array: [u8; 32] =
account_id_bytes.try_into().map_err(|_| {
PyErr::new::<pyo3::exceptions::PyValueError, _>(
"Invalid AccountId length",
)
})?;
ValueDef::<u32>::Composite(inner) => {
let value = composite_to_py_object(py, inner)?;

let ss58_address = account_id_to_ss58(account_id_array, 42);
Ok(ss58_address.as_str().to_object(py))
}
_ => {
let value = composite_to_py_object(py, composite, legacy_account_id)?;
Ok(value)
}
}
}
Ok(value)
}
ValueDef::<u32>::Variant(inner) => {
if inner.name == "None" || inner.name == "Some" {
match inner.name.as_str() {
"None" => Ok(py.None()),
"Some" => {
let some = composite_to_py_object(
py,
inner.values.clone(),
legacy_account_id,
)?;
let some = composite_to_py_object(py, inner.values.clone())?;
if inner.values.len() == 1 {
let tuple = some
.downcast_bound::<PyTuple>(py)
Expand All @@ -516,7 +446,7 @@ mod bt_decode {
let value = PyDict::new_bound(py);
value.set_item(
inner.name.clone(),
composite_to_py_object(py, inner.values, legacy_account_id)?,
composite_to_py_object(py, inner.values)?,
)?;

Ok(value.to_object(py))
Expand Down Expand Up @@ -1100,13 +1030,12 @@ mod bt_decode {
pyobject_to_value_no_option_check(py, to_encode, ty, type_id, portable_registry)
}

#[pyfunction(name = "decode", signature = (type_string, portable_registry, encoded, legacy_account_id=true))]
#[pyfunction(name = "decode")]
fn py_decode(
py: Python,
type_string: &str,
portable_registry: &PyPortableRegistry,
encoded: &[u8],
legacy_account_id: bool,
) -> PyResult<Py<PyAny>> {
// Create a memoization table for the type string to type id conversion
let mut memo = HashMap::<String, u32>::new();
Expand All @@ -1128,16 +1057,15 @@ mod bt_decode {
))
})?;

value_to_pyobject(py, decoded, legacy_account_id)
value_to_pyobject(py, decoded)
}

#[pyfunction(name = "decode_list", signature = (list_type_strings, portable_registry, list_encoded, legacy_account_id=true))]
#[pyfunction(name = "decode_list")]
fn py_decode_list(
py: Python,
list_type_strings: Vec<String>,
portable_registry: &PyPortableRegistry,
list_encoded: Vec<Vec<u8>>,
legacy_account_id: bool,
) -> PyResult<Vec<Py<PyAny>>> {
// Create a memoization table for the type string to type id conversion
let mut memo = HashMap::<String, u32>::new();
Expand Down Expand Up @@ -1165,7 +1093,7 @@ mod bt_decode {
))
})?;

decoded_list.push(value_to_pyobject(py, decoded, legacy_account_id)?);
decoded_list.push(value_to_pyobject(py, decoded)?);
}

Ok(decoded_list)
Expand Down
Loading