/// <summary> /// Encodes a cash address /// </summary> /// <param name="scriptType">the bitcoin script type in byte format (P2PKH = 0x0, or P2SH = 0x8)</param> /// <param name="hash">byte array representing address</param> /// <param name="header">network - bitcoincash, bchtest, bchreg</param> /// <returns>base32 encoded string with checksum and header</returns> private static string EncodeWithHeaderAndChecksum(string header, byte scriptType, byte[] hash) { // calculate the version byte - in bits, 0 reserved, 1-4 address type, 4-7 size of hash var versionByte = scriptType + GetHashSizeBits(hash); // convert byte array from 8bits to 5, append prefix 0 bit and version byte var base5 = ConvertBits(new[] { (byte)versionByte }.Concat(hash).ToArray(), 8, 5); // generate checksum from base5 array var checksumBytes = CreateChecksum(base5, header); // append the checksum to the base5 array var combined = base5.Concat(checksumBytes).ToArray(); // return address as base32 encoded with header return(header + ":" + Base32Util.Encode(combined)); }
/// <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)); }