I post Rust code below which does what you try to do. I am not sure what's wrong with your code, but I hope my code helps.
Please note that the example you use, 1AMGLbW71pvdMuRWkDdmZWibmzRkxa6LVt is not a valid address. With valid checksum it would be 1AMGLbW71pvdMuRWkDdmZWibmzRkyByigA.
In my example I use public key 032d1e1736727f0957a5137ab93bfbbf6e0c293dd0f65a6c8947b563c1f5827376, which produces address bytes 007eefa5452e04cbc2d0f949ce96080aa2afc15c314e858c41 (prefix + pubkey hash + checksum), and address 1CaBE3CYxhqdjcxKCPqwNhsys1weUnZhHJ.
I provide 3 solutions: one with 'manual' steps, one where the bas58 checksum is done by the base58 library, and the shortest where bitcoin crate is used.
use bitcoin::hashes::Hash;
use bitcoin::util::address::Address;
use bitcoin;
fn hex_to_bytes(hex: &str) -> Vec<u8> {
hex::decode(hex).unwrap()
}
fn bytes_to_hex(bytes: &Vec<u8>) -> String {
hex::encode(bytes)
}
fn pubkey_hash(pubkey: &Vec<u8>) -> Vec<u8> {
let sha = bitcoin::hashes::sha256::Hash::hash(pubkey);
bitcoin::hashes::ripemd160::Hash::hash(&sha).to_vec()
}
// All manual steps
fn pubkey_to_addr_detailed(pubkey_hex: &str) -> String {
let pubkey = hex_to_bytes(pubkey_hex);
let mut pubkey_hash = pubkey_hash(&pubkey);
let mut address_bytes = Vec::new();
let prefix: u8 = 0;
address_bytes.push(prefix);
address_bytes.append(&mut pubkey_hash);
let checksum = bitcoin::hashes::sha256d::Hash::hash(&address_bytes).to_vec();
let mut checksum_truncated = checksum[0..4].to_vec();
let mut address_bytes_with_checksum = Vec::new();
address_bytes_with_checksum.append(&mut address_bytes);
address_bytes_with_checksum.append(&mut checksum_truncated);
bitcoin::util::base58::encode_slice(&address_bytes_with_checksum)
}
// Base58 checksum done by base58
fn pubkey_to_addr_base58(pubkey_hex: &str) -> String {
let pubkey = hex_to_bytes(pubkey_hex);
let mut pubkey_hash = pubkey_hash(&pubkey);
let mut address_bytes = Vec::new();
let prefix: u8 = 0;
address_bytes.push(prefix);
address_bytes.append(&mut pubkey_hash);
bitcoin::util::base58::check_encode_slice(&address_bytes)
}
// Using bitcoin::address
fn pubkey_to_addr_bitcoin(pubkey_hex: &str) -> String {
let pubkey_data = hex_to_bytes(pubkey_hex);
let pubkey = bitcoin::PublicKey::from_slice(&pubkey_data).unwrap();
let addr = Address::p2pkh(&pubkey, bitcoin::Network::Bitcoin);
addr.to_string()
}
#[cfg(test)]
mod tests {
use super::*;
const PUBKEY1: &str = "032d1e1736727f0957a5137ab93bfbbf6e0c293dd0f65a6c8947b563c1f5827376";
const ADDRESS: &str = "1CaBE3CYxhqdjcxKCPqwNhsys1weUnZhHJ";
#[test]
fn test_pubkey_to_addr_detailed() {
let addr = pubkey_to_addr_detailed(PUBKEY1);
assert_eq!(addr, ADDRESS);
}
#[test]
fn test_pubkey_to_addr_base58() {
let addr = pubkey_to_addr_base58(PUBKEY1);
assert_eq!(addr, ADDRESS);
}
#[test]
fn test_pubkey_to_addr_bitcoin() {
let addr = pubkey_to_addr_bitcoin(PUBKEY1);
assert_eq!(addr, ADDRESS);
}
#[test]
fn t1() {
let pubkey = hex_to_bytes(PUBKEY1);
let mut pubkey_hash = pubkey_hash(&pubkey);
assert_eq!(bytes_to_hex(&pubkey_hash), "7eefa5452e04cbc2d0f949ce96080aa2afc15c31");
let mut address_bytes = Vec::new();
let prefix: u8 = 0;
address_bytes.push(prefix);
address_bytes.append(&mut pubkey_hash);
assert_eq!(bytes_to_hex(&address_bytes), "007eefa5452e04cbc2d0f949ce96080aa2afc15c31");
let checksum = bitcoin::hashes::sha256d::Hash::hash(&address_bytes).to_vec();
assert_eq!(bytes_to_hex(&checksum), "4e858c4104e953987e6147a2a653a423fa63c4f518c89e9d58c3a3aa40f518e3");
let mut checksum_truncated = checksum[0..4].to_vec();
assert_eq!(bytes_to_hex(&checksum_truncated), "4e858c41");
let mut address_bytes_with_checksum = Vec::new();
address_bytes_with_checksum.append(&mut address_bytes);
address_bytes_with_checksum.append(&mut checksum_truncated);
assert_eq!(bytes_to_hex(&address_bytes_with_checksum), "007eefa5452e04cbc2d0f949ce96080aa2afc15c314e858c41");
let b58 = bitcoin::util::base58::encode_slice(&address_bytes_with_checksum);
assert_eq!(b58, ADDRESS);
}
}