diem_types/
account_address.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7use crate::transaction::authenticator::AuthenticationKey;
8use diem_crypto::{
9    ed25519::Ed25519PublicKey,
10    hash::{CryptoHasher, HashValue},
11    x25519, ValidCryptoMaterial,
12};
13
14use crate::validator_config::{ConsensusPublicKey, ConsensusVRFPublicKey};
15use cfx_types::H256;
16pub use move_core_types::account_address::AccountAddress;
17use tiny_keccak::{Hasher, Keccak};
18
19pub fn from_public_key(public_key: &Ed25519PublicKey) -> AccountAddress {
20    AuthenticationKey::ed25519(public_key).derived_address()
21}
22
23pub fn from_consensus_public_key(
24    public_key: &ConsensusPublicKey, vrf_public_key: &ConsensusVRFPublicKey,
25) -> AccountAddress {
26    let mut hasher = Keccak::v256();
27    hasher.update(public_key.to_bytes().as_slice());
28    hasher.update(vrf_public_key.to_bytes().as_slice());
29    let mut h = H256::default();
30    hasher.finalize(h.as_bytes_mut());
31    AccountAddress::new(h.0)
32}
33
34// Note: This is inconsistent with current types because AccountAddress is
35// derived from consensus key which is of type Ed25519PublicKey. Since
36// AccountAddress does not mean anything in a setting without remote
37// authentication, we use the network public key to generate a peer_id for the
38// peer. See this issue for potential improvements: https://github.com/diem/diem/issues/3960
39pub fn from_identity_public_key(
40    identity_public_key: x25519::PublicKey,
41) -> AccountAddress {
42    let mut array = [0u8; AccountAddress::LENGTH];
43    let pubkey_slice = identity_public_key.as_slice();
44    // keep only the last 16 bytes
45    array.copy_from_slice(
46        &pubkey_slice[x25519::PUBLIC_KEY_SIZE - AccountAddress::LENGTH..],
47    );
48    AccountAddress::new(array)
49}
50
51// Define the Hasher used for hashing AccountAddress types. In order to properly
52// use the CryptoHasher derive macro we need to have this in its own module so
53// that it doesn't conflict with the imported `AccountAddress` from
54// move-core-types. It needs to have the same name since the hash salt is
55// calculated using the name of the type.
56mod hasher {
57    #[derive(serde::Deserialize, diem_crypto_derive::CryptoHasher)]
58    struct AccountAddress;
59}
60
61pub trait HashAccountAddress {
62    fn hash(&self) -> HashValue;
63}
64
65impl HashAccountAddress for AccountAddress {
66    fn hash(&self) -> HashValue {
67        let mut state = hasher::AccountAddressHasher::default();
68        state.update(self.as_ref());
69        state.finish()
70    }
71}
72
73#[cfg(test)]
74mod test {
75    use super::{AccountAddress, HashAccountAddress};
76    use diem_crypto::hash::HashValue;
77    use hex::FromHex;
78
79    #[test]
80    fn address_hash() {
81        let address: AccountAddress =
82            "ca843279e3427144cead5e4d5999a3d0ca843279e3427144cead5e4d5999a3d0"
83                .parse()
84                .unwrap();
85
86        let hash_vec = &Vec::from_hex(
87            "81fdf1b3fe04abd62ada9adc8852fab3d1b145b875c259f017e697ea2f4da249",
88        )
89        .expect("You must provide a valid Hex format");
90
91        let mut hash = [0u8; 32];
92        let bytes = &hash_vec[..32];
93        hash.copy_from_slice(&bytes);
94
95        assert_eq!(address.hash(), HashValue::new(hash));
96    }
97}