/// <summary> /// Constructor that takes a single Escrow Invitation Code and produces a Payment Invitation Code. /// </summary> public EscrowCodeSet(string escrowInvitationCode, bool doCompressed=false, byte networkByte = 0) { byte[] pubpart, privpart; int identifier30; string failreason = parseEscrowCode(escrowInvitationCode, out pubpart, out privpart, out identifier30); if (failreason != null) throw new ArgumentException(failreason); // produce a new factor byte[] z = new byte[32]; SecureRandom sr = new SecureRandom(); sr.NextBytes(z); // calculate Gxy then Gxyz PublicKey pk = new PublicKey(pubpart); ECPoint Gxyz = pk.GetECPoint().Multiply(new BigInteger(1, privpart)).Multiply(new BigInteger(1, z)); // Uncompress it Gxyz = PublicKey.GetUncompressed(Gxyz); // We can get the Bitcoin address now, so do so PublicKey pkxyz = new PublicKey(Gxyz); byte[] hash160 = pkxyz.Hash160; BitcoinAddress = new AddressBase(hash160, networkByte).AddressBase58; // make the payment invitation record byte[] invp = new byte[74]; long headP = headbaseP + (long)identifier30; for (int i = 7; i >= 0; i--) { invp[i] = (byte)(headP & 0xff); headP >>= 8; } invp[8] = networkByte; Array.Copy(z, 0, invp, 8 + 1 + 1, 32); // set flag to indicate if einvb was used to generate this, and make it available in the object if (escrowInvitationCode.StartsWith("einvb")) { invp[8 + 1 + 1 + 32 + 20] = 0x2; } // copy hash160 Array.Copy(hash160, 0, invp, 8 + 1 + 1 + 32, 20); PaymentInvitationCode = Bitcoin.ByteArrayToBase58Check(invp); setAddressConfirmationCode(identifier30, networkByte, invp[8 + 1 + 1 + 32 + 20], z, hash160); }
/// <summary> /// Allows calculation of address with a different AddressType /// </summary> public AddressBase(AddressBase otheraddress, byte addressType) { // Hash160 setter validates length and throws exception if needed Hash160 = otheraddress.Hash160; this.AddressType = addressType; }
/// <summary> /// Constructor that calculates the address given one escrow invitation code and one matching payment invitation code. /// They can be provided in any order. /// </summary> public EscrowCodeSet(string code1, string code2) { if (code1 == null || code2 == null || code1 == "" || code2 == "") { throw new ArgumentException("Two codes are required to use this function."); } string escrowInvitationCode=null, paymentInvitationCode=null; if (code1.StartsWith("einva") || code1.StartsWith("einvb")) escrowInvitationCode = code1; if (code2.StartsWith("einva") || code2.StartsWith("einvb")) escrowInvitationCode = code2; if (code1.StartsWith("einvp")) paymentInvitationCode = code1; if (code2.StartsWith("einvp")) paymentInvitationCode = code2; if (escrowInvitationCode == null || paymentInvitationCode == null) { throw new ArgumentException("In order to use this function, one code MUST be an Escrow Invitation (starting " + "with \"einva\" or \"einvb\") and the other code MUST be a Payment Invitation (starting with \"einvp\")."); } byte[] pubpart, privpart; int identifier30; string failreason = parseEscrowCode(escrowInvitationCode, out pubpart, out privpart, out identifier30); if (failreason != null) throw new ArgumentException(failreason); string notvalid = "Not a valid Payment Invitation Code"; string notvalid2 = "Code is not a valid Payment Invitation Code or may have a typo or other error."; string notvalid3 = "The Payment Invitation does not belong to the provided Escrow Invitation."; long head; byte[] invbytes; string failReason = parseEitherCode(paymentInvitationCode, notvalid, notvalid2, out invbytes, out head); if (head < headbaseP) throw new ArgumentException(notvalid); long identifier30L = head - headbaseP; if (identifier30L < 0 || identifier30L > 0x3FFFFFFFL) throw new ArgumentException(notvalid); if ((long)identifier30 != identifier30L) { throw new ArgumentException(notvalid3); } byte[] privpartz = new byte[32]; Array.Copy(invbytes, 8 + 1 + 1, privpartz, 0, 32); byte networkByte = invbytes[8]; bool compressedFlag = (invbytes[8+1+1+32+20] & 0x1) == 1; // get bitcoin address PublicKey pk = new PublicKey(pubpart); ECPoint Gxyz = pk.GetECPoint().Multiply(new BigInteger(1, privpart)).Multiply(new BigInteger(1, privpartz)); // uncompress if compress is not indicated if (compressedFlag == false) Gxyz = PublicKey.GetUncompressed(Gxyz); // We can get the Bitcoin address now, so do so PublicKey pkxyz = new PublicKey(Gxyz); byte[] addrhash160 = pkxyz.Hash160; BitcoinAddress = new AddressBase(addrhash160, networkByte).AddressBase58; // Does the hash160 match? for (int i = 0; i < 20; i++) { if (addrhash160[i] != invbytes[8+1+1+32+i]) { throw new ArgumentException(notvalid3); } } this.PaymentInvitationCode = paymentInvitationCode; byte expectedabflag = (byte)(escrowInvitationCode.StartsWith("einva") ? 2 : 0); if ((invbytes[8+1+1+32+20] & 0x1) != expectedabflag) { SamePartyWarningApplies = true; } }
public KeyCollectionItem(AddressBase address) { this.Address = address; }