diem_types/
account_address.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3use crate::transaction::authenticator::AuthenticationKey;
4use diem_crypto::{
5    ed25519::Ed25519PublicKey,
6    hash::{CryptoHasher, HashValue},
7    x25519,
8};
9
10pub use move_core_types::account_address::AccountAddress;
11
12pub fn from_public_key(public_key: &Ed25519PublicKey) -> AccountAddress {
13    AuthenticationKey::ed25519(public_key).derived_address()
14}
15
16// Note: This is inconsistent with current types because AccountAddress is derived
17// from consensus key which is of type Ed25519PublicKey. Since AccountAddress does
18// not mean anything in a setting without remote authentication, we use the network
19// public key to generate a peer_id for the peer.
20// See this issue for potential improvements: https://github.com/diem/diem/issues/3960
21pub fn from_identity_public_key(identity_public_key: x25519::PublicKey) -> AccountAddress {
22    let mut array = [0u8; AccountAddress::LENGTH];
23    let pubkey_slice = identity_public_key.as_slice();
24    // keep only the last 16 bytes
25    array.copy_from_slice(&pubkey_slice[x25519::PUBLIC_KEY_SIZE - AccountAddress::LENGTH..]);
26    AccountAddress::new(array)
27}
28
29// Define the Hasher used for hashing AccountAddress types. In order to properly use the
30// CryptoHasher derive macro we need to have this in its own module so that it doesn't conflict
31// with the imported `AccountAddress` from move-core-types. It needs to have the same name since
32// the hash salt is calculated using the name of the type.
33mod hasher {
34    #[derive(serde::Deserialize, diem_crypto_derive::CryptoHasher)]
35    struct AccountAddress;
36}
37
38pub trait HashAccountAddress {
39    fn hash(&self) -> HashValue;
40}
41
42impl HashAccountAddress for AccountAddress {
43    fn hash(&self) -> HashValue {
44        let mut state = hasher::AccountAddressHasher::default();
45        state.update(self.as_ref());
46        state.finish()
47    }
48}
49
50#[cfg(test)]
51mod test {
52    use super::{AccountAddress, HashAccountAddress};
53    use diem_crypto::hash::HashValue;
54    use hex::FromHex;
55
56    #[test]
57    fn address_hash() {
58        let address: AccountAddress = "ca843279e3427144cead5e4d5999a3d0".parse().unwrap();
59
60        let hash_vec =
61            &Vec::from_hex("6403c4906e79cf4536edada922040805c6a8d0e735fa4516a9cc40038bd125c8")
62                .expect("You must provide a valid Hex format");
63
64        let mut hash = [0u8; 32];
65        let bytes = &hash_vec[..32];
66        hash.copy_from_slice(bytes);
67
68        assert_eq!(address.hash(), HashValue::new(hash));
69    }
70}