Skip to content

Commit

Permalink
feat(aptos_rust): Continue address implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Milerius committed Oct 23, 2023
1 parent d58f7d7 commit 5174968
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 6 deletions.
5 changes: 2 additions & 3 deletions rust/tw_any_coin/tests/tw_any_address_ffi_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn test_any_address_derive() {

// TODO match `CoinType` when it's generated.
let expected_address = match coin.blockchain {
BlockchainType::Aptos => "",
BlockchainType::Aptos => "0x9006fa46f038224e8004bdda97f2e7a60c2c3d135bce7cb15541e5c0aae907a4",
// By default, Bitcoin will return a P2PKH address.
BlockchainType::Bitcoin => "19cAJn4Ms8jodBBGtroBNNpCZiHAWGAq7X",
BlockchainType::Ethereum => "0xAc1ec44E4f0ca7D172B7803f6836De87Fb72b309",
Expand Down Expand Up @@ -111,9 +111,8 @@ fn test_any_address_is_valid_coin() {
"0xeeff357ea5c1a4e7bc11b2b17ff2dc2dcca69750bfef1e1ebcaccf8c8018175b",
"eeff357ea5c1a4e7bc11b2b17ff2dc2dcca69750bfef1e1ebcaccf8c8018175b",
"19aadeca9388e009d136245b9a67423f3eee242b03142849eb4f81a4a409e59c",
"777821c78442e17d82c3d7a371f42de7189e4248e529fe6eee6bca40ddbb",
"0x777821c78442e17d82c3d7a371f42de7189e4248e529fe6eee6bca40ddbb",
"eeff357ea5c1a4e7bc11b2b17ff2dc2dcca69750bfef1e1ebcaccf8c8018175" // Too short automatically padded
"0xeeff357ea5c1a4e7bc11b2b17ff2dc2dcca69750bfef1e1ebcaccf8c8018175"
],
BlockchainType::Bitcoin => vec![
"1MrZNGN7mfWZiZNQttrzHjfw72jnJC2JNx",
Expand Down
67 changes: 66 additions & 1 deletion rust/tw_aptos/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,33 @@ use std::str::FromStr;
use move_core_types::account_address::{AccountAddress, AccountAddressParseError};
use tw_coin_entry::coin_entry::CoinAddress;
use tw_coin_entry::error::AddressError;
use tw_keypair::ed25519;
use tw_memory::Data;
use tw_hash::sha3::sha3_256;


#[derive(Debug)]
#[repr(u8)]
pub enum Scheme {
Ed25519 = 0,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Address {
addr: AccountAddress,
}

impl Address {
/// Initializes an address with a `ed25519` public key.
pub fn with_ed25519_pubkey(pubkey: &ed25519::sha512::PublicKey) -> Result<Address, AddressError> {
let mut to_hash = pubkey.as_slice().to_vec();
to_hash.push(Scheme::Ed25519 as u8);
let hashed = sha3_256(to_hash.as_slice());
let addr = AccountAddress::from_bytes(hashed).map_err(from_account_error)?;
Ok(Address{addr})
}
}

impl Display for Address {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.addr.to_hex_literal())
Expand All @@ -38,7 +58,52 @@ impl FromStr for Address {
type Err = AddressError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let addr = AccountAddress::from_str(s).map_err(from_account_error)?;
const NUM_CHARS: usize = AccountAddress::LENGTH * 2;
let mut has_0x = false;
let mut working = s.trim();

// Checks if it has a 0x at the beginning, which is okay
if working.starts_with("0x") {
has_0x = true;
working = &working[2..];
}

if working.len() > NUM_CHARS {
return Err(AddressError::InvalidInput)
} else if !has_0x && working.len() < NUM_CHARS {
return Err(AddressError::InvalidInput)
}

if !working.chars().all(|c| char::is_ascii_hexdigit(&c)) {
return Err(AddressError::InvalidInput)
}

let addr = if has_0x {
AccountAddress::from_hex_literal(s.trim())
} else {
AccountAddress::from_str(s.trim())
}.map_err(from_account_error)?;

Ok(Address{addr})
}
}

#[cfg(test)]
mod tests {
use super::*;
use tw_keypair::ed25519::sha512::PrivateKey;

#[test]
fn test_from_public_key() {
let private = PrivateKey::try_from(
"afeefca74d9a325cf1d6b6911d61a65c32afa8e02bd5e78e2e4ac2910bab45f5",
)
.unwrap();
let public = private.public();
let addr = Address::with_ed25519_pubkey(&public);
assert_eq!(
addr.unwrap().to_string(),
"0x9006fa46f038224e8004bdda97f2e7a60c2c3d135bce7cb15541e5c0aae907a4"
);
}
}
7 changes: 5 additions & 2 deletions rust/tw_aptos/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::str::FromStr;
use tw_coin_entry::coin_context::CoinContext;
use tw_coin_entry::coin_entry::{CoinEntry, PublicKeyBytes, SignatureBytes};
use tw_coin_entry::derivation::Derivation;
use tw_coin_entry::error::{AddressResult};
use tw_coin_entry::error::{AddressError, AddressResult};
use tw_coin_entry::modules::json_signer::NoJsonSigner;
use tw_coin_entry::modules::message_signer::NoMessageSigner;
use tw_coin_entry::modules::plan_builder::NoPlanBuilder;
Expand Down Expand Up @@ -51,7 +51,10 @@ impl CoinEntry for AptosEntry {
_derivation: Derivation,
_prefix: Option<Self::AddressPrefix>,
) -> AddressResult<Self::Address> {
todo!()
let public_key = public_key
.to_ed25519()
.ok_or(AddressError::PublicKeyTypeMismatch)?;
Address::with_ed25519_pubkey(public_key)
}

#[inline]
Expand Down
9 changes: 9 additions & 0 deletions rust/tw_keypair/src/tw/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,13 @@ impl PublicKey {
_ => None,
}
}

pub fn to_ed25519(&self) -> Option<&ed25519::sha512::PublicKey> {
match self {
PublicKey::Ed25519(ed25519) => {
Some(ed25519)
},
_ => None,
}
}
}

0 comments on commit 5174968

Please sign in to comment.