Skip to content

Commit

Permalink
Merge pull request #168 from 0xcregis/15-feat-anychain-polkadot
Browse files Browse the repository at this point in the history
feat: anychain polkadot
  • Loading branch information
shuimuliang authored Jan 3, 2024
2 parents c965b6d + c946d46 commit 41f5d88
Show file tree
Hide file tree
Showing 11 changed files with 799 additions and 0 deletions.
6 changes: 6 additions & 0 deletions anychain-polkadot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ edition = "2021"

[dependencies]
anychain-core = { path = "../anychain-core", version = "0.1.1" }
sp-core = "24.0.0"
base58 = { workspace = true }
parity-scale-codec = { version = "3.6.5" }
ed25519-dalek-fiat = "0.1.0"
serde_json = { workspace = true }
rand.workspace = true
132 changes: 132 additions & 0 deletions anychain-polkadot/src/address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use std::{fmt::Display, marker::PhantomData, str::FromStr};

use anychain_core::{hex, Address, AddressError, PublicKey, TransactionError};

use crate::{PolkadotFormat, PolkadotNetwork, PolkadotPublicKey, PolkadotSecretKey};
use base58::{FromBase58, ToBase58};
use sp_core::hashing::blake2_512;

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct PolkadotAddress<N: PolkadotNetwork> {
addr: String,
_network: PhantomData<N>,
}

impl<N: PolkadotNetwork> Address for PolkadotAddress<N> {
type SecretKey = PolkadotSecretKey;
type PublicKey = PolkadotPublicKey<N>;
type Format = PolkadotFormat;

fn from_secret_key(
secret_key: &Self::SecretKey,
format: &Self::Format,
) -> Result<Self, anychain_core::AddressError> {
Self::PublicKey::from_secret_key(secret_key).to_address(format)
}

fn from_public_key(
public_key: &Self::PublicKey,
_format: &Self::Format,
) -> Result<Self, anychain_core::AddressError> {
Self::from_payload(&hex::encode(public_key.address_payload()))
}
}

impl<N: PolkadotNetwork> PolkadotAddress<N> {
pub fn from_payload(payload: &str) -> Result<Self, AddressError> {
let payload = hex::decode(payload).unwrap();
let payload = [vec![N::VERSION], payload].concat();

let ss_prefix = vec![0x53u8, 0x53, 0x35, 0x38, 0x50, 0x52, 0x45];

let checksum = blake2_512(&[ss_prefix, payload.clone()].concat()).to_vec();
let addr = [payload, checksum[..2].to_vec()].concat().to_base58();

Ok(PolkadotAddress {
addr,
_network: PhantomData::<N>,
})
}

pub fn to_payload(&self) -> Result<Vec<u8>, AddressError> {
let bin = self.addr.as_str().from_base58()?;
Ok(bin[1..33].to_vec())
}
}

impl<N: PolkadotNetwork> FromStr for PolkadotAddress<N> {
type Err = TransactionError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let bytes = s.from_base58()?;
if N::VERSION != bytes[0] {
return Err(TransactionError::Message(format!(
"Invalid version byte {} for polkadot network {}",
bytes[0],
N::NAME,
)));
}
let checksum_provided = bytes[33..].to_vec();
let ss_prefix = vec![0x53u8, 0x53, 0x35, 0x38, 0x50, 0x52, 0x45];
let checksum_expected =
blake2_512(&[ss_prefix, bytes[..33].to_vec()].concat())[..2].to_vec();
if checksum_expected != checksum_provided {
return Err(TransactionError::Message(format!(
"Invalid {} address",
N::NAME
)));
}
Ok(PolkadotAddress {
addr: s.to_string(),
_network: PhantomData,
})
}
}

impl<N: PolkadotNetwork> Display for PolkadotAddress<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.addr)
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;

use crate::{PolkadotAddress, PolkadotFormat, PolkadotSecretKey, Westend};
use anychain_core::{hex, Address};
use ed25519_dalek_fiat::SecretKey;

#[test]
fn test_address() {
let sk = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32,
];
let h = hex::encode(sk);
println!("{}", h);

let sk = SecretKey::from_bytes(&sk).unwrap();
let sk = PolkadotSecretKey::Ed25519(sk);

let address =
PolkadotAddress::<Westend>::from_secret_key(&sk, &PolkadotFormat::Standard).unwrap();

println!("address = {}", address);
}

#[test]
fn test_address_2() {
let hash = "8ee504148e75c34e8f051899b3c6e4241ff18dc1c9211260b6a6a434bedb485f";
let address = PolkadotAddress::<Westend>::from_payload(hash).unwrap();
println!("address = {}", address);
}

#[test]
fn test_address_3() {
let addr = "5DoW9HHuqSfpf55Ux5pLdJbHFWvbngeg8Ynhub9DrdtxmZeV";
let addr = PolkadotAddress::<Westend>::from_str(addr).unwrap();
let payload = addr.to_payload().unwrap();
let payload = hex::encode(payload);
println!("{}", payload);
}
}
15 changes: 15 additions & 0 deletions anychain-polkadot/src/format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use anychain_core::Format;
use std::fmt::Display;

#[derive(Hash, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub enum PolkadotFormat {
Standard,
}

impl Format for PolkadotFormat {}

impl Display for PolkadotFormat {
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!()
}
}
13 changes: 13 additions & 0 deletions anychain-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
mod public_key;
pub use public_key::*;

mod address;
pub use address::*;

mod format;
pub use format::*;

mod transaction;
pub use transaction::*;

mod network;
pub use network::*;
31 changes: 31 additions & 0 deletions anychain-polkadot/src/network/kusama.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::{fmt::Display, str::FromStr};

use crate::PolkadotNetwork;
use anychain_core::{Network, NetworkError};

#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct Kusama;

impl Network for Kusama {
const NAME: &'static str = "kusama";
}

impl PolkadotNetwork for Kusama {
const VERSION: u8 = 0x02;
const PALLET_ASSET: u8 = 4;
const TRANSFER_ALLOW_DEATH: u8 = 0;
const TRANSFER_KEEP_ALIVE: u8 = 3;
}

impl FromStr for Kusama {
type Err = NetworkError;
fn from_str(_s: &str) -> Result<Self, Self::Err> {
todo!()
}
}

impl Display for Kusama {
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!()
}
}
20 changes: 20 additions & 0 deletions anychain-polkadot/src/network/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
mod polkadot;
pub use polkadot::*;

mod kusama;
pub use kusama::*;

mod westend;
pub use westend::*;

mod rococo;
pub use rococo::*;

use anychain_core::Network;

pub trait PolkadotNetwork: Network {
const VERSION: u8;
const PALLET_ASSET: u8;
const TRANSFER_ALLOW_DEATH: u8;
const TRANSFER_KEEP_ALIVE: u8;
}
31 changes: 31 additions & 0 deletions anychain-polkadot/src/network/polkadot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::{fmt::Display, str::FromStr};

use crate::PolkadotNetwork;
use anychain_core::{Network, NetworkError};

#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct Polkadot;

impl Network for Polkadot {
const NAME: &'static str = "polkadot";
}

impl PolkadotNetwork for Polkadot {
const VERSION: u8 = 0x00;
const PALLET_ASSET: u8 = 5;
const TRANSFER_ALLOW_DEATH: u8 = 0;
const TRANSFER_KEEP_ALIVE: u8 = 3;
}

impl FromStr for Polkadot {
type Err = NetworkError;
fn from_str(_s: &str) -> Result<Self, Self::Err> {
todo!()
}
}

impl Display for Polkadot {
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!()
}
}
31 changes: 31 additions & 0 deletions anychain-polkadot/src/network/rococo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::{fmt::Display, str::FromStr};

use crate::PolkadotNetwork;
use anychain_core::{Network, NetworkError};

#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct Rococo;

impl Network for Rococo {
const NAME: &'static str = "rococo";
}

impl PolkadotNetwork for Rococo {
const VERSION: u8 = 0x2a;
const PALLET_ASSET: u8 = 4;
const TRANSFER_ALLOW_DEATH: u8 = 0;
const TRANSFER_KEEP_ALIVE: u8 = 3;
}

impl FromStr for Rococo {
type Err = NetworkError;
fn from_str(_s: &str) -> Result<Self, Self::Err> {
todo!()
}
}

impl Display for Rococo {
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!()
}
}
31 changes: 31 additions & 0 deletions anychain-polkadot/src/network/westend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::{fmt::Display, str::FromStr};

use crate::PolkadotNetwork;
use anychain_core::{Network, NetworkError};

#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct Westend;

impl Network for Westend {
const NAME: &'static str = "westend";
}

impl PolkadotNetwork for Westend {
const VERSION: u8 = 0x2a;
const PALLET_ASSET: u8 = 4;
const TRANSFER_ALLOW_DEATH: u8 = 0;
const TRANSFER_KEEP_ALIVE: u8 = 3;
}

impl FromStr for Westend {
type Err = NetworkError;
fn from_str(_s: &str) -> Result<Self, Self::Err> {
todo!()
}
}

impl Display for Westend {
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!()
}
}
Loading

0 comments on commit 41f5d88

Please sign in to comment.