I have not been able to find a technical explanation of how to validate that a given string is a valid Cardano address via its checksum. The closest that I could find in the documentation is here. However, none of the values in the example are ADA addresses. Given an address such as DdzFFzCqrhsgwQmeWNBTsG8VjYunBLK9GNR93GSLTGj1FeMm8kFoby2cTHxEHBEraHQXmgTtFGz7fThjDRNNvwzcaw6fQdkYySBneRas
, how do I get it into the format where it can be validated via CRC32? I assume I decode it from base58, but then what?
You could back into it, check how the API is returning interesting information about an address.
Just a heads up: Cardano (currently) has 2 different addressing schemes.
Yep, Yoroi and Daedalus wallets use different key schemes.
If you are using Rust check out the cardano_address_is_valid() function - an example I just did, calling Rust from C, your address is the first one.
smith$ cat check_address.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "../cardano.h"
int main(int argc, char* argv[]) {
char *a="DdzFFzCqrhsgwQmeWNBTsG8VjYunBLK9GNR93GSLTGj1FeMm8kFoby2cTHxEHBEraHQXmgTtFGz7fThjDRNNvwzcaw6fQdkYySBneRas";
printf("address:\n%s\n? is valid: %s\n",a, cardano_address_is_valid(a) ? "NO" : "YES");
char *b="DdzFFzCqrhsgwQmeWNBTsG8VjYunBLK9GNR93GSLTGj1FeMm8kFoby2cTHxEHBEraHQXmgTtFGz7fThjDRNNvwzcaw6fQdkYySBneRaX";
printf("address:\n%s\n? is valid: %s\n",b, cardano_address_is_valid(b) ? "NO" : "YES");
return 0;
}
smith$ ./a.out
address:
DdzFFzCqrhsgwQmeWNBTsG8VjYunBLK9GNR93GSLTGj1FeMm8kFoby2cTHxEHBEraHQXmgTtFGz7fThjDRNNvwzcaw6fQdkYySBneRas
? is valid: YES
address:
DdzFFzCqrhsgwQmeWNBTsG8VjYunBLK9GNR93GSLTGj1FeMm8kFoby2cTHxEHBEraHQXmgTtFGz7fThjDRNNvwzcaw6fQdkYySBneRaX
? is valid: NO
Hijack threads much?
Iām also really interested in creating a Cardano address validator. Would prefer a javascript solution though.
I made an address checker in python:
import base58
import cbor
import binascii
import sys
addr = sys.argv[1]
decodedAddr = base58.b58decode(addr)
decodedAddr = cbor.loads(decodedAddr)
taggedAddr = decodedAddr[0]
addrChecksum = decodedAddr[1]
Checksum = binascii.crc32(taggedAddr.value)
print("Address data: ", taggedAddr.value.hex())
print("Provided Checksum:", addrChecksum)
print("Computed Checksum:", Checksum)
print("Match: ", addrChecksum == Checksum)
Edit: I put it on github
I am getting this error when I run the script:
addr = sys.argv[1]
IndexError: list index out of range
You need to specify the address to check in the command line, like so:
python addrCheck.py DdzFFzCqrhsgwQmeWNBTsG8VjYunBLK9GNR93GSLTGj1FeMm8kFoby2cTHxEHBEraHQXmgTtFGz7fThjDRNNvwzcaw6fQdkYySBneRas
Very good.
Did you provide an argument, like this:
$: python ./b58.py DdzFFzCqrhszg6GVew17iad3FDTTpAKo91pwhj7Nc64v1myy3NwGoPZ4YmTbqyuxQQMDPAA9FSbYniWHWS24jK6bvKb7YkbgRbjhZ3Qb
('Address data: ', '83581c9fb50d50654faedb0ee769fe184cffb4d206f4e966c0b2d95604828ca101581e581c50ec25b2d5c9eb7eb30c93bfafe85343c5b4158e1304d9db81fd38c800')
('Provided Checksum:', 443419360L)
('Computed Checksum:', 443419360)
('Match: ', True)
Thanks. In hindsight that was not a very smart question.
Lol all good
I made a new version on github that will catch that error.
JS Implementation of @Steve python validator
const base58 = require('./crypto/base58')
const cbor = require('cbor')
const crc32 = require('crc-32')
function isValidAdaAddress (address, currency, networkType) {
var decodedAddr = base58.decode(address)
decodedAddr = cbor.decode(Buffer.from(decodedAddr))
var taggedAddr = decodedAddr[0]
if (taggedAddr === undefined) {
return false
}
var addrChecksum = decodedAddr[1]
var calculatedChecksum = crc32.buf(taggedAddr.value)
console.log('DECODED ADDRESS', taggedAddr.value.toString('hex'))
console.log('CALCULATED CHECKSUM', calculatedChecksum)
console.log('CHECKSUM:', addrChecksum)
return calculatedChecksum === addrChecksum
}
module.exports = {
isValidAddress: function (address, currency, networkType) {
return isValidAdaAddress(address, currency, networkType)
}
}
Base58 Implemented Locally
var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
var ALPHABET_MAP = {}
for (var i = 0; i < ALPHABET.length; ++i) {
ALPHABET_MAP[ALPHABET.charAt(i)] = i
}
var BASE = ALPHABET.length
module.exports = {
decode: function (string) {
if (string.length === 0) return []
var i; var j; var bytes = [0]
for (i = 0; i < string.length; ++i) {
var c = string[i]
if (!(c in ALPHABET_MAP)) throw new Error('Non-base58 character')
for (j = 0; j < bytes.length; ++j) bytes[j] *= BASE
bytes[0] += ALPHABET_MAP[c]
var carry = 0
for (j = 0; j < bytes.length; ++j) {
bytes[j] += carry
carry = bytes[j] >> 8
bytes[j] &= 0xff
}
while (carry) {
bytes.push(carry & 0xff)
carry >>= 8
}
}
// deal with leading zeros
for (i = 0; string[i] === '1' && i < string.length - 1; ++i) {
bytes.push(0)
}
return bytes.reverse()
}
}
Thanks looks good.
Very similar to:
Thank you guys for this implementation:
just a quick question that might be stupid
does this code include the addresses such as DdzFFzCqrhsvVTfF9rnf.....7dJATZiWAKFGfB
?