/// <summary> /// Checks is a given cash address has correct checksum /// </summary> /// <param name="address">cash address to validate</param> /// <param name="decoded">decoded address matching the cashAddress</param> /// <returns>true if checksum is valid, false otherwise</returns> public static bool ValidateChecksum(string address, DecodedBitcoinAddress decoded) { // split at the separator colon; format address in lower case var pieces = address.ToLower().Split(':'); // trim the prefix (should be "bitcoincash", "bchtest", or "bchreg") - the first chunk separated by colon var prefix = pieces[0]; // base32 decode the payload (second chunk) var payload = Base32Util.Decode(pieces[1]); // get start value for polymod var startValue = GetPolyModStartValue(prefix); // polymod on payload including checksum should be 0 return(PolyMod(payload, startValue) == 0); }
/// <summary> /// Decodes a CashAddress into prefix, type, and hash160 /// </summary> /// <param name="address">Cash Address formatted address</param> /// <returns>prefix, type, hash160 bytes</returns> private static DecodedBitcoinAddress Decode(string address) { // split at the separator colon; format address in lower case var pieces = address.ToLower().Split(':'); // trim the prefix (should be "bitcoincash" or "bchtest") - the first chunk separated by colon var prefix = pieces[0]; // base32 decode the payload (second chunk) var payload = Base32Util.Decode(pieces[1]); // trim the checksum var data = payload.Take(payload.Length - 8).ToArray(); // convert byte data from 5bit to 8bit var payloadData = ConvertBits(data, 5, 8, true); // version byte (and type) is determined by the first byte in the result var versionByte = payloadData[0]; var type = GetType(versionByte); // hash is the rest of the data after the version byte var hash = payloadData.Skip(1).ToArray(); return(new DecodedBitcoinAddress(prefix, type, hash)); }