/// <summary> /// Compute group ID for a group of unsigned transactions /// </summary> /// <param name="txns">array of transactions</param> /// <returns>Digest</returns> public static Digest ComputeGroupID(params Transaction[] txns) { if (txns != null && txns.Length > 0) { if (txns.Length > MAX_TX_GROUP_SIZE) { throw new ArgumentException("max group size is " + MAX_TX_GROUP_SIZE); } Digest[] txIDs = new Digest[txns.Length]; for (int i = 0; i < txns.Length; ++i) { txIDs[i] = txns[i].RawTxID(); } TxGroup txgroup = new TxGroup(txIDs); try { byte[] gid = Digester.Digest(txgroup.BytesToSign()); return(new Digest(gid)); } catch (Exception e) { throw new ArgumentException("tx computation failed", e); } } else { throw new ArgumentException("empty transaction list"); } }
/// <summary> /// check if the address is valid /// </summary> /// <param name="encodedAddress">Address</param> /// <returns>valid or not</returns> public static bool IsValid(string encodedAddress) { // interpret as base32 var checksumAddr = Base32.DecodeFromString(encodedAddress).ToList(); if (checksumAddr.Count != LEN_BYTES + CHECKSUM_LEN_BYTES) { return(false); } // split into checksum byte[] checksum = checksumAddr.GetRange(LEN_BYTES, checksumAddr.Count - LEN_BYTES).ToArray(); byte[] addr = checksumAddr.GetRange(0, LEN_BYTES).ToArray(); // compute expected checksum var hashedAddr = Digester.Digest(addr).ToList(); byte[] expectedChecksum = hashedAddr.GetRange(LEN_BYTES - CHECKSUM_LEN_BYTES, hashedAddr.Count - LEN_BYTES + CHECKSUM_LEN_BYTES).ToArray(); // compare if (Enumerable.SequenceEqual(checksum, expectedChecksum)) { return(true); } else { return(false); } }
// returns a word corresponding to the 11 bit checksum of the data internal static string Checksum(byte[] data) { //CryptoProvider.setupIfNeeded(); //MessageDigest digest = MessageDigest.getInstance(CHECKSUM_ALG); //digest.update(Arrays.copyOf(data, data.length)); //byte[] d = digest.digest(); byte[] d = Digester.Digest(data); // optimize for CHECKSUM_LEN_WORDS = 1 //d = Arrays.copyOfRange(d, 0, 2); return(ApplyWord(ToUintNArray(new byte[] { d[0], d[1] })[0])); }
/// <summary> /// building an address object helps us generate string representations /// </summary> /// <returns>the address</returns> public Address ToAddress() { List <byte> hashable = new List <byte>(PREFIX) { Convert.ToByte(this.version), Convert.ToByte(this.threshold) }; foreach (var key in publicKeys) { hashable.AddRange(key.GetEncoded()); } return(new Address(Digester.Digest(hashable.ToArray()))); }
/// <summary> /// EncodeAsString converts the address to a human-readable representation, with /// a 4-byte checksum appended at the end, using SHA256. Note that string representations /// of addresses generated by different SDKs may not be compatible. /// </summary> /// <returns>the encoded address string</returns> public string EncodeAsString() { // compute sha512/256 checksum, and take the last 4 bytes as the checksum var checksum = Digester.Digest(Bytes).ToList().GetRange(LEN_BYTES - CHECKSUM_LEN_BYTES, CHECKSUM_LEN_BYTES); // concat the hashed address and the bytes var checksumAddress = Enumerable.Concat(Bytes, checksum); string res = Base32.EncodeToString(checksumAddress.ToArray(), false); if (res.Length != EXPECTED_STR_ENCODED_LEN) { throw new ArgumentException("unexpected address length " + res.Length); } return(res); }