Skip to content

Commit

Permalink
feat: ed25519 and secp256k1 signing scheme for anychain-polkadot
Browse files Browse the repository at this point in the history
  • Loading branch information
aya015757881 committed Jan 2, 2024
1 parent 7a00c5f commit fbfc6af
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 88 deletions.
3 changes: 2 additions & 1 deletion anychain-polkadot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ 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 }
serde_json = { workspace = true }
rand.workspace = true
38 changes: 29 additions & 9 deletions anychain-polkadot/src/address.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::{fmt::Display, marker::PhantomData, str::FromStr};

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

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

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct PolkadotAddress<N: PolkadotNetwork> {
Expand Down Expand Up @@ -90,16 +90,21 @@ impl<N: PolkadotNetwork> Display for PolkadotAddress<N> {

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

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

#[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,
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);

Expand All @@ -111,8 +116,23 @@ mod tests {

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

#[test]
fn test_address_3() {
let addr = "5DoW9HHuqSfpf55Ux5pLdJbHFWvbngeg8Ynhub9DrdtxmZeV";
let addr = PolkadotAddress::<Substrate>::from_str(addr).unwrap();
let payload = addr.to_payload().unwrap();
let payload = hex::encode(payload);
println!("{}", payload);
}

#[test]
fn f() {
let s = "012eaaeadc3e26dcb6ce0479ff94b009fdb8f81d9c6cf43ba2a4595496564b7d10c8498f90139462d5ce300599a85335515ef970bf3645f7ced5e22181231d638c";
println!("len = {}", s.len());
}
}
10 changes: 8 additions & 2 deletions anychain-polkadot/src/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,18 @@ impl<N: PolkadotNetwork> PublicKey for PolkadotPublicKey<N> {
Self::SecretKey::Secp256k1(sk) => {
let pk = libsecp256k1::PublicKey::from_secret_key(sk);
let pk = PublicKeyContent::Secp256k1(pk);
Self { key: pk, _network: PhantomData }
Self {
key: pk,
_network: PhantomData,
}
}
Self::SecretKey::Ed25519(sk) => {
let pk = ed25519_dalek_fiat::PublicKey::from(sk);
let pk = PublicKeyContent::Ed25519(pk);
Self { key: pk, _network: PhantomData }
Self {
key: pk,
_network: PhantomData,
}
}
}
}
Expand Down
144 changes: 68 additions & 76 deletions anychain-polkadot/src/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
use crate::{PolkadotAddress, PolkadotFormat, PolkadotNetwork, PolkadotPublicKey};
use anychain_core::{
crypto::{blake2b_256, keccak256, sha256, sha512},
hex, Transaction, TransactionError, TransactionId,
};
use anychain_core::{crypto::blake2b_256, hex, Transaction, TransactionError, TransactionId};
use parity_scale_codec::{Decode, Encode, HasCompact};
use std::fmt::Display;

#[derive(Clone)]
pub struct PolkadotTransactionParameters<N: PolkadotNetwork> {
pub module_method: String,
pub version: String,
pub from: PolkadotAddress<N>,
pub to: PolkadotAddress<N>,
pub amount: u64,
pub nonce: u64,
pub tip: u64,
pub block_height: u64,
pub block_hash: String,
pub genesis_hash: String,
pub spec_version: u32,
pub tx_version: u32,
pub era_height: u64,
}

struct TxInterim {
Expand Down Expand Up @@ -59,29 +52,6 @@ struct CompactWrapper<T: HasCompact> {
val: T,
}

fn get_era(block_height: u64, mut era_height: u64) -> Vec<u8> {
if era_height == 0 {
era_height = 64
}
let phase = block_height % era_height;
let index = 6u64;
let trailing_zero = index - 1;

let mut encoded = if trailing_zero > 15 {
15
} else if trailing_zero < 1 {
1
} else {
trailing_zero
};

encoded += phase / 1 << 4;
let first = (encoded >> 8) as u8;
let second = (encoded & 0xff) as u8;

vec![second, first]
}

fn encode(val: u64) -> Vec<u8> {
if val == 0 {
vec![0]
Expand All @@ -104,14 +74,15 @@ impl<N: PolkadotNetwork> Transaction for PolkadotTransaction<N> {
})
}

fn sign(&mut self, rs: Vec<u8>, _recid: u8) -> Result<Vec<u8>, TransactionError> {
fn sign(&mut self, rs: Vec<u8>, recid: u8) -> Result<Vec<u8>, TransactionError> {
if rs.len() != 64 {
return Err(TransactionError::Message(format!(
"Invalid signature length {}",
rs.len(),
)));
}
self.signature = Some(rs);
// self.signature = Some([vec![recid], rs].concat());
self.signature = Some([rs, vec![recid]].concat());
self.to_bytes()
}

Expand All @@ -123,14 +94,13 @@ impl<N: PolkadotNetwork> Transaction for PolkadotTransaction<N> {
match &self.signature {
Some(sig) => {
let interim = self.to_interim()?;
let version = hex::decode(&self.params.version)?;
let from = self.params.from.to_payload()?;

let stream = [
version,
vec![0x84], // version = 0x84
vec![0],
from,
vec![2], // secp256k1 signature scheme = 2
vec![2], // ed25519 = 0, sr25519 = 1, secp256k1 = 2
sig.clone(),
interim.era,
interim.nonce,
Expand Down Expand Up @@ -163,7 +133,7 @@ impl<N: PolkadotNetwork> Transaction for PolkadotTransaction<N> {

fn to_transaction_id(&self) -> Result<Self::TransactionId, TransactionError> {
Ok(PolkadotTransactionId {
txid: self.digest(1)?,
txid: self.digest()?,
})
}
}
Expand All @@ -172,10 +142,9 @@ impl<N: PolkadotNetwork> PolkadotTransaction<N> {
fn to_interim(&self) -> Result<TxInterim, TransactionError> {
let params = &self.params;

let method = hex::decode(&params.module_method)?;
let to = params.to.to_payload()?;
let amount = encode(params.amount);
let era = get_era(params.block_height, params.era_height);
let era = vec![0];

let nonce = encode(params.nonce);
let tip = encode(params.tip);
Expand All @@ -186,8 +155,11 @@ impl<N: PolkadotNetwork> PolkadotTransaction<N> {
let genesis_hash = hex::decode(&params.genesis_hash)?;
let block_hash = hex::decode(&params.block_hash)?;

let pallet_index = 4;
let function_index = 3;

let interim = TxInterim {
method: [method, vec![0], to, amount].concat(),
method: [vec![pallet_index, function_index], vec![0], to, amount].concat(),
era,
nonce,
tip,
Expand All @@ -200,14 +172,8 @@ impl<N: PolkadotNetwork> PolkadotTransaction<N> {
Ok(interim)
}

pub fn digest(&self, index: u8) -> Result<Vec<u8>, TransactionError> {
match index {
0 => Ok(blake2b_256(&self.to_bytes()?).to_vec()),
1 => Ok(sha256(&self.to_bytes()?).to_vec()),
2 => Ok(keccak256(&self.to_bytes()?).to_vec()),
3 => Ok(sha512(&self.to_bytes()?)[..32].to_vec()),
_ => Err(TransactionError::Message("invalid digest code".to_string())),
}
pub fn digest(&self) -> Result<Vec<u8>, TransactionError> {
Ok(blake2b_256(&self.to_bytes()?).to_vec())
}
}

Expand All @@ -220,8 +186,8 @@ impl<N: PolkadotNetwork> Display for PolkadotTransaction<N> {
#[cfg(test)]
mod tests {
use crate::{
PolkadotAddress, PolkadotFormat, PolkadotNetwork, PolkadotTransaction,
PolkadotTransactionParameters, Substrate, PolkadotSecretKey,
PolkadotAddress, PolkadotFormat, PolkadotNetwork, PolkadotSecretKey, PolkadotTransaction,
PolkadotTransactionParameters, Substrate,
};
use anychain_core::Address;
use anychain_core::{hex, libsecp256k1, Transaction};
Expand All @@ -231,38 +197,28 @@ mod tests {
fn tx_from_str<N: PolkadotNetwork>(json: &str) -> PolkadotTransaction<N> {
let json = serde_json::from_str::<Value>(json).unwrap();

let module_method = json["module_method"].as_str().unwrap().to_string();

let version = json["version"].as_str().unwrap().to_string();

let from = PolkadotAddress::<N>::from_str(json["from"].as_str().unwrap()).unwrap();

let to = PolkadotAddress::<N>::from_str(json["to"].as_str().unwrap()).unwrap();

let amount = json["amount"].as_u64().unwrap();
let nonce = json["nonce"].as_u64().unwrap();
let tip = json["tip"].as_u64().unwrap();
let block_height = json["block_height"].as_u64().unwrap();
let block_hash = json["block_hash"].as_str().unwrap().to_string();
let genesis_hash = json["genesis_hash"].as_str().unwrap().to_string();
let spec_version = json["spec_version"].as_u64().unwrap() as u32;
let tx_version = json["tx_version"].as_u64().unwrap() as u32;
let era_height = json["era_height"].as_u64().unwrap();

let params = PolkadotTransactionParameters::<N> {
module_method,
version,
from,
to,
amount,
nonce,
tip,
block_height,
block_hash,
genesis_hash,
spec_version,
tx_version,
era_height,
};

PolkadotTransaction::<N>::new(&params).unwrap()
Expand All @@ -273,8 +229,8 @@ mod tests {
let format = &PolkadotFormat::Standard;

let sk_from = [
1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1u8,
228u8, 121, 108, 167, 244, 6, 57, 61, 104, 68, 229, 88, 23, 16, 212, 157, 110, 171, 36,
26, 232, 171, 144, 41, 109, 182, 148, 243, 20, 23, 29, 61,
];

let sk_to = [
Expand All @@ -297,33 +253,69 @@ mod tests {
#[test]
fn test_tx_gen() {
let tx = r#"{
"module_method": "",
"version": "84",
"from": "5GgTpADDzFUTBtjY6KcHHJ1mwVsFQbE38WWjc5TmaYY5b7zF",
"from": "5FnS6tYbCTAtK3QCfNnddwVR61ypLLM7APRrs98paFs7yMSY",
"to": "5DoW9HHuqSfpf55Ux5pLdJbHFWvbngeg8Ynhub9DrdtxmZeV",
"amount": 50000000000000,
"amount": 1000000000000,
"nonce": 0,
"tip": 1000000000000,
"block_height": 8117556,
"block_hash": "d268b9ef1c92dbaf68bd850ef65b3ea2764b9dabc41980c56d440848288f536c",
"genesis_hash": "e3777fa922cafbff200cadeaea1a76bd7898ad5b89f7848999058b50e715f636",
"spec_version": 104000,
"tx_version": 3,
"era_height": 88888
"tip": 0,
"block_hash": "e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e",
"genesis_hash": "e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e",
"spec_version": 1005000,
"tx_version": 24
}"#;

let mut tx = tx_from_str::<Substrate>(tx);
let hash = tx.to_transaction_id().unwrap().txid;
let msg = libsecp256k1::Message::parse_slice(&hash).unwrap();

let sk = [
1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1u8,
228u8, 121, 108, 167, 244, 6, 57, 61, 104, 68, 229, 88, 23, 16, 212, 157, 110, 171, 36,
26, 232, 171, 144, 41, 109, 182, 148, 243, 20, 23, 29, 61,
];

let sk = libsecp256k1::SecretKey::parse_slice(&sk).unwrap();
let sig = libsecp256k1::sign(&msg, &sk).0;
let (sig, rec) = libsecp256k1::sign(&msg, &sk);
let sig = sig.serialize().to_vec();
let rec = rec.serialize();

let signed_tx = tx.sign(sig, rec).unwrap();
let signed_tx = hex::encode(&signed_tx);

println!("signed tx = {}", signed_tx);
}

#[test]
fn test_tx_gen_2() {
use ed25519_dalek_fiat::Signer;

let tx = r#"{
"from": "5DPaKszR7KpCbvNNtGCGTfrGdeDTUNRt1UdxwXp9G6iWvdk7",
"to": "5D1NKGqfc2Q8hw53icrX74YQryjb3MMySWwFBhM71afKbdad",
"amount": 1000000000000,
"nonce": 2,
"tip": 0,
"block_hash": "e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e",
"genesis_hash": "e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e",
"spec_version": 1005000,
"tx_version": 24
}"#;

let mut tx = tx_from_str::<Substrate>(tx);
let msg = tx.to_bytes().unwrap();

let sk = [
228u8, 121, 108, 167, 244, 6, 57, 61, 104, 68, 229, 88, 23, 16, 212, 157, 110, 171, 36,
26, 232, 171, 144, 41, 109, 182, 148, 243, 20, 23, 29, 61,
];

let sk = ed25519_dalek_fiat::SecretKey::from_bytes(&sk).unwrap();
let pk = ed25519_dalek_fiat::PublicKey::from(&sk);

let kp = ed25519_dalek_fiat::Keypair {
secret: sk,
public: pk,
};
let sig = kp.sign(&msg).to_bytes().to_vec();

let signed_tx = tx.sign(sig, 0).unwrap();
let signed_tx = hex::encode(&signed_tx);
Expand Down

0 comments on commit fbfc6af

Please sign in to comment.