How to resolve the algorithm Bitcoin/address validation step by step in the Rust programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Bitcoin/address validation step by step in the Rust programming language

Table of Contents

Problem Statement

Write a program that takes a bitcoin address as argument, and checks whether or not this address is valid. A bitcoin address uses a base58 encoding, which uses an alphabet of the characters 0 .. 9, A ..Z, a .. z, but without the four characters:

With this encoding, a bitcoin address encodes 25 bytes:

To check the bitcoin address, you must read the first twenty-one bytes, compute the checksum, and check that it corresponds to the last four bytes. The program can either return a boolean value or throw an exception when not valid. You can use a digest library for SHA-256.

It doesn't belong to anyone and is part of the test suite of the bitcoin software.
You can change a few characters in this string and check that it'll fail the test.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Bitcoin/address validation step by step in the Rust programming language

Source code in the rust programming language

extern crate crypto;

use crypto::digest::Digest;
use crypto::sha2::Sha256;

const DIGITS58: [char; 58] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];

fn main() {
    println!("{}", validate_address("1AGNa15ZQXAZUgFiqJ3i7Z2DPU2J6hW62i"));
    println!("{}", validate_address("1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i"));
    println!("{}", validate_address("17NdbrSGoUotzeGCcMMCqnFkEvLymoou9j"));
    println!("{}", validate_address("17NdbrSGoUotzeGCcMMC?nFkEvLymoou9j"));
}

fn validate_address(address: &str) -> bool {
    let decoded = match from_base58(address, 25) {
        Ok(x) => x,
        Err(_) => return false
    };
    if decoded[0] != 0 {
        return false;
    }
    let mut sha = Sha256::new();
    sha.input(&decoded[0..21]);
    let mut first_round = vec![0u8; sha.output_bytes()];
    sha.result(&mut first_round);
    sha.reset();
    
    sha.input(&first_round);
    let mut second_round = vec![0u8; sha.output_bytes()];
    sha.result(&mut second_round);
    if second_round[0..4] != decoded[21..25] {
        return false
    }
    true
}

fn from_base58(encoded: &str, size: usize) -> Result<Vec<u8>, String> {
    let mut res: Vec<u8> = vec![0; size];
    for base58_value in encoded.chars() {
        let mut value: u32 = match DIGITS58
            .iter()
            .position(|x| *x == base58_value){
            Some(x) => x as u32,
            None => return Err(String::from("Invalid character found in encoded string."))
        };
        for result_index in (0..size).rev() {
            value += 58 * res[result_index] as u32;
            res[result_index] = (value % 256) as u8;
            value /= 256;
        }
    }
    Ok(res)
}


  

You may also check:How to resolve the algorithm Averages/Pythagorean means step by step in the M2000 Interpreter programming language
You may also check:How to resolve the algorithm Loops/Nested step by step in the V (Vlang) programming language
You may also check:How to resolve the algorithm Constrained random points on a circle step by step in the Action! programming language
You may also check:How to resolve the algorithm Abbreviations, automatic step by step in the AArch64 Assembly programming language
You may also check:How to resolve the algorithm Nautical bell step by step in the Racket programming language