Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: display jdenticon for root #1998

Merged
merged 19 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions .spellcheck/signer.dic
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ grayscale
html
iOS
identicon/S
jdenticon/S
init
invariants
io
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.parity.signer.components.networkicon.blockies.BlockiesIcon
import io.parity.signer.components.networkicon.dot.DotIcon
import io.parity.signer.components.networkicon.jdenticon.Jdenticon
import io.parity.signer.ui.helpers.PreviewData
import io.parity.signer.ui.theme.SignerNewTheme
import io.parity.signer.uniffi.Identicon
Expand All @@ -33,28 +34,15 @@ fun IdentIconImage(
}

is Identicon.Dots -> {
DotIcon(seed = identIcon.identity,
DotIcon(
seed = identIcon.identity,
size = size,
modifier = modifier,
)
)
}
is Identicon.Jdenticon -> {
Jdenticon(seed = identIcon.identity, size = size, modifier = modifier)
}
// is ImageContent.Svg -> {//will be used for another type of icons
// val context = LocalContext.current
// val painter = rememberAsyncImagePainter(
// model = ImageRequest.Builder(context)
// .decoderFactory(SvgDecoder.Factory())
// .data(identIcon.toByteArray())
// .size(Size.ORIGINAL) // Set the target size to load the image at.
// .build(),
// )
// Image(
// painter = painter,
// contentDescription = stringResource(R.string.description_identicon),
// modifier = modifier
// .size(size)
// .clip(CircleShape)
// )
// }
}
}

Expand All @@ -76,16 +64,21 @@ private fun PreviewIdentIcon() {
SignerNewTheme {
val iconDot = PreviewData.Identicon.dotIcon
val iconBlockies = PreviewData.Identicon.blockiesIcon
val iconJdenticon = PreviewData.Identicon.jdenticonIcon

Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
IdentIconImage(iconDot)
IdentIconImage(iconBlockies)
//jdenticon preview works if you run it, not in default preview and svg showing async
IdentIconImage(iconJdenticon)
IdentIconImage(iconDot, size = 18.dp)
IdentIconImage(iconBlockies, size = 18.dp)
IdentIconImage(iconJdenticon, size = 18.dp)
IdentIconImage(iconDot, size = 56.dp)
IdentIconImage(iconBlockies, size = 56.dp)
IdentIconImage(iconJdenticon, size = 56.dp)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ object PreviewData {
object Identicon {
val dotIcon = io.parity.signer.uniffi.Identicon.Dots(identity = DotIconConstants.previewAliceSeed)
val blockiesIcon = io.parity.signer.uniffi.Identicon.Blockies(identity = "0x7204ddf9dc5f672b64ca6692da7b8f13b4d408e7")
val jdenticonIcon = io.parity.signer.uniffi.Identicon.Jdenticon(identity = "8PegJD6VsjWwinrP6AfgNqejWYdJ8KqF4xutpyq7AdFJ3W5")
}

///Bytes to be encoded to qr code to show it
Expand Down
3 changes: 3 additions & 0 deletions ios/PolkadotVault/Components/Image/Identicon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ struct IdenticonView: View {
)
.frame(width: rowHeight, height: rowHeight)
.clipShape(Circle())
case let .jdenticon(identity):
Spacer()
.frame(width: rowHeight, height: rowHeight)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion rust/db_handling/src/identities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1708,7 +1708,7 @@ pub fn export_secret_key(
}
let public_key = multisigner_to_public(multisigner);

let style = address_details.encryption.identicon_style();
let style = address_details.identicon_style();
let address = Address {
path: address_details.path.to_string(),
has_pwd: address_details.has_pwd,
Expand Down
77 changes: 14 additions & 63 deletions rust/db_handling/src/interface_signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,24 +57,16 @@ pub fn get_all_seed_names_with_identicons(
database: &sled::Db,
names_phone_knows: &[String],
) -> Result<Vec<SeedNameCard>> {
let mut data_set: HashMap<String, Vec<MultiSigner>> = HashMap::new();
let mut data_set: HashMap<String, Identicon> = HashMap::new();
let mut derivation_count: HashMap<String, u32> = HashMap::new();
let mut used_in_networks: HashMap<String, HashSet<String>> = HashMap::new();
let mut network_names_cache: HashMap<NetworkSpecsKey, String> = HashMap::new();

for (multisigner, address_details) in get_all_addresses(database)?.into_iter() {
if address_details.is_root() {
// found a seed key; could be any of the supported encryptions;
match data_set.get(&address_details.seed_name) {
Some(root_set) => {
let mut new_root_set = root_set.to_vec();
new_root_set.push(multisigner);
data_set.insert(address_details.seed_name.to_string(), new_root_set);
}
None => {
data_set.insert(address_details.seed_name.to_string(), vec![multisigner]);
}
}
let identicon =
make_identicon_from_multisigner(&multisigner, address_details.identicon_style());
data_set.insert(address_details.seed_name.to_string(), identicon);
} else {
if let Some(network) = address_details.network_id {
if !network_names_cache.contains_key(&network) {
Expand All @@ -94,18 +86,18 @@ pub fn get_all_seed_names_with_identicons(
.and_modify(|e| *e += 1)
.or_insert(1);
if data_set.get(&address_details.seed_name).is_none() {
data_set.insert(address_details.seed_name.to_string(), Vec::new());
data_set.insert(address_details.seed_name.to_string(), Identicon::default());
}
}
}
for x in names_phone_knows.iter() {
if data_set.get(x).is_none() {
data_set.insert(x.to_string(), Vec::new());
data_set.insert(x.to_string(), Identicon::default());
}
}
let mut res: Vec<_> = data_set
.into_iter()
.map(|(seed_name, multisigner_set)| {
.map(|(seed_name, identicon)| {
let mut used_in_networks = used_in_networks
.get(&seed_name)
.cloned()
Expand All @@ -114,7 +106,7 @@ pub fn get_all_seed_names_with_identicons(
used_in_networks.sort();
SeedNameCard {
seed_name: seed_name.clone(),
identicon: preferred_multisigner_identicon(&multisigner_set),
identicon,
derived_keys_count: *derivation_count.get(&seed_name).unwrap_or(&0),
used_in_networks,
}
Expand All @@ -124,41 +116,6 @@ pub fn get_all_seed_names_with_identicons(
Ok(res)
}

/// Create a `PNG` identicon data, for preferred encryption if
/// multiple encryption algorithms are supported.
///
/// Output is:
///
/// - empty `PNG` if no seed key is available
/// - the available seed key if there is only one
/// - preferred seed key, if there are more than one; order of preference:
/// `Sr25519`, `Ed25519`, `Ecdsa`
fn preferred_multisigner_identicon(multisigner_set: &[MultiSigner]) -> Identicon {
if multisigner_set.is_empty() {
Identicon::default()
} else {
let mut got_sr25519 = None;
let mut got_ed25519 = None;
let mut got_ecdsa = None;
for x in multisigner_set.iter() {
match x {
MultiSigner::Ed25519(_) => got_ed25519 = Some(x.to_owned()),
MultiSigner::Sr25519(_) => got_sr25519 = Some(x.to_owned()),
MultiSigner::Ecdsa(_) => got_ecdsa = Some(x.to_owned()),
}
}
if let Some(a) = got_sr25519 {
make_identicon_from_multisigner(&a, IdenticonStyle::Dots)
} else if let Some(a) = got_ed25519 {
make_identicon_from_multisigner(&a, IdenticonStyle::Dots)
} else if let Some(a) = got_ecdsa {
make_identicon_from_multisigner(&a, IdenticonStyle::Dots)
} else {
Identicon::default()
}
}
}

/// Return a `Vec` with address-associated public data for all addresses from the
/// Vault database.
///
Expand All @@ -179,7 +136,7 @@ pub fn print_all_identities(database: &sled::Db) -> Result<Vec<MRawKey>> {
Some(network_specs.specs.genesis_hash),
); // to click
let public_key = multisigner_to_public(&multisigner); // to display
let style = address_details.encryption.identicon_style();
let style = address_details.identicon_style();
let identicon = make_identicon_from_multisigner(&multisigner, style);
Some(MRawKey {
address: Address {
Expand Down Expand Up @@ -210,10 +167,7 @@ pub fn keys_by_seed_name(database: &sled::Db, seed_name: &str) -> Result<MKeysNe
has_pwd: false,
path: String::new(),
seed_name: seed_name.to_string(),
identicon: make_identicon_from_multisigner(
&root.0,
root.1.encryption.identicon_style(),
),
identicon: make_identicon_from_multisigner(&root.0, root.1.identicon_style()),
secret_exposed: root.1.secret_exposed,
};
// TODO: root always prefix 42 for substrate.
Expand All @@ -230,10 +184,8 @@ pub fn keys_by_seed_name(database: &sled::Db, seed_name: &str) -> Result<MKeysNe
if let Some(id) = &address_details.network_id {
let network_specs = get_network_specs(database, id)?;

let identicon = make_identicon_from_multisigner(
&multisigner,
network_specs.specs.encryption.identicon_style(),
);
let identicon =
make_identicon_from_multisigner(&multisigner, address_details.identicon_style());
let base58 = print_multisigner_as_base58_or_eth(
&multisigner,
Some(network_specs.specs.base58prefix),
Expand Down Expand Up @@ -386,8 +338,7 @@ pub fn export_key(
);

let public_key = multisigner_to_public(multisigner);
let identicon =
make_identicon_from_multisigner(multisigner, network_specs.encryption.identicon_style());
let identicon = make_identicon_from_multisigner(multisigner, address_details.identicon_style());
let qr = {
if address_details.network_id.as_ref() == Some(network_specs_key) {
let prefix = if network_specs.encryption == Encryption::Ethereum {
Expand Down Expand Up @@ -559,7 +510,7 @@ fn dynamic_path_check_unhexed(
);
let identicon = make_identicon_from_multisigner(
&multisigner,
address_details.encryption.identicon_style(),
address_details.identicon_style(),
);
let address_key = hex::encode(
AddressKey::new(
Expand Down
12 changes: 5 additions & 7 deletions rust/db_handling/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use std::collections::HashMap;
use std::{convert::TryInto, str::FromStr};

use constants::{
test_values::{
alice_sr_alice, alice_sr_root, empty_png, types_known, westend_9000, westend_9010,
},
test_values::{alice_sr_alice, empty_png, types_known, westend_9000, westend_9010},
ADDRTREE, ALICE_SEED_PHRASE, METATREE, SPECSTREE,
};
use db_handling::Error;
Expand Down Expand Up @@ -88,8 +86,8 @@ fn print_seed_names() {
let cards = get_all_seed_names_with_identicons(&db, &[String::from("Alice")]).unwrap();
let expected_cards = vec![SeedNameCard {
seed_name: "Alice".to_string(),
identicon: Identicon::Dots {
identity: alice_sr_root(),
identicon: Identicon::Jdenticon {
identity: "8PegJD6VsjWwinrP6AfgNqejWYdJ8KqF4xutpyq7AdFJ3W5".to_string(),
},
used_in_networks: vec!["westend".to_string()],
derived_keys_count: 1, // "//Alice"
Expand All @@ -110,8 +108,8 @@ fn print_seed_names_with_orphan() {
let expected_cards = vec![
SeedNameCard {
seed_name: "Alice".to_string(),
identicon: Identicon::Dots {
identity: alice_sr_root(),
identicon: Identicon::Jdenticon {
identity: "8PegJD6VsjWwinrP6AfgNqejWYdJ8KqF4xutpyq7AdFJ3W5".to_string(),
},
used_in_networks: vec!["westend".to_string()],
derived_keys_count: 1,
Expand Down
10 changes: 10 additions & 0 deletions rust/definitions/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ pub enum IdenticonStyle {

/// Blockies style used in Ethereum networks.
Blockies,

/// Jdenticon style used to identify key sets.
Jdenticon,
}

use crate::navigation::Identicon;
Expand All @@ -83,6 +86,13 @@ pub fn make_identicon_from_multisigner(
}
}
}
IdenticonStyle::Jdenticon => Identicon::Jdenticon {
identity: print_multisigner_as_base58_or_eth(
multisigner,
None,
multisigner_to_encryption(multisigner),
),
},
}
}

Expand Down
6 changes: 5 additions & 1 deletion rust/definitions/src/navigation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -648,14 +648,18 @@ pub struct MSCFieldNumber {
pub enum Identicon {
Dots { identity: Vec<u8> },
Blockies { identity: String },
Jdenticon { identity: String },
}

impl std::fmt::Debug for Identicon {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Identicon::Dots { identity } => write!(f, "Dots {}", hex::encode(&identity[..32])),
Identicon::Blockies { identity } => {
write!(f, "Blockies {}", hex::encode(&identity[..32]))
write!(f, "Blockies {identity}")
}
Identicon::Jdenticon { identity } => {
write!(f, "Jdenticon {identity}")
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions rust/definitions/src/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use parity_scale_codec::{Decode, Encode};
use sled::IVec;
use sp_runtime::MultiSigner;

use crate::helpers::IdenticonStyle;
use crate::{
crypto::Encryption,
error::{Error, Result},
Expand Down Expand Up @@ -113,4 +114,15 @@ impl AddressDetails {
pub fn is_root(&self) -> bool {
self.path.is_empty() && !self.has_pwd && self.network_id.is_none()
}

/// The style to use for identicons.
///
/// Jdenticon for root key.
/// Otherwise, the style is taken from the encryption algorithm.
pub fn identicon_style(&self) -> IdenticonStyle {
if self.is_root() {
return IdenticonStyle::Jdenticon;
}
self.encryption.identicon_style()
}
}
1 change: 1 addition & 0 deletions rust/signer/src/signer.udl
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,7 @@ dictionary MSCFieldNumber {
interface Identicon {
Dots(sequence<u8> identity);
Blockies(string identity);
Jdenticon(string identity);
};

dictionary MSCId {
Expand Down
5 changes: 1 addition & 4 deletions rust/transaction_parsing/src/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,7 @@ pub(crate) fn make_author_info(
base58,
address_key,
address: Address {
identicon: make_identicon_from_multisigner(
author,
address_details.encryption.identicon_style(),
),
identicon: make_identicon_from_multisigner(author, address_details.identicon_style()),
seed_name: address_details.seed_name.clone(),
path: address_details.path.clone(),
has_pwd: address_details.has_pwd,
Expand Down
Loading