private TaprootFullPubKey(ECXOnlyPubKey outputKey, bool outputParity, TaprootInternalPubKey internalKey, uint256?merkleRoot) : base(outputKey) { OutputKey = new TaprootPubKey(outputKey); OutputKeyParity = outputParity; InternalKey = internalKey; MerkleRoot = merkleRoot; }
public static bool TryCreate(ReadOnlySpan <byte> pubkey, [MaybeNullWhen(false)] out TaprootInternalPubKey result) { if (ECXOnlyPubKey.TryCreate(pubkey, out var k)) { result = new TaprootInternalPubKey(k); return(true); } result = null; return(false); }
public bool CheckTapTweak(TaprootInternalPubKey internalPubKey, uint256?merkleRoot, bool parity) { if (internalPubKey is null) { throw new ArgumentNullException(nameof(internalPubKey)); } Span <byte> tweak32 = stackalloc byte[32]; TaprootFullPubKey.ComputeTapTweak(internalPubKey, merkleRoot, tweak32); return(this.pubkey.CheckIsTweakedWith(internalPubKey.pubkey, tweak32, parity)); }
internal static void ComputeTapTweak(TaprootInternalPubKey internalKey, uint256?merkleRoot, Span <byte> tweak32) { using Secp256k1.SHA256 sha = new Secp256k1.SHA256(); sha.InitializeTagged("TapTweak"); internalKey.pubkey.WriteToSpan(tweak32); sha.Write(tweak32); if (merkleRoot is uint256) { merkleRoot.ToBytes(tweak32); sha.Write(tweak32); } sha.GetHash(tweak32); }
public static TaprootFullPubKey Create(TaprootInternalPubKey internalKey, uint256?merkleRoot) { if (internalKey is null) { throw new ArgumentNullException(nameof(internalKey)); } Span <byte> tweak32 = stackalloc byte[32]; ComputeTapTweak(internalKey, merkleRoot, tweak32); var outputKey = internalKey.pubkey.AddTweak(tweak32).ToXOnlyPubKey(out var parity); return(new TaprootFullPubKey(outputKey, parity, internalKey, merkleRoot)); }
public static bool TryCreate(byte[] pubkey, [MaybeNullWhen(false)] out TaprootInternalPubKey result) { #if HAS_SPAN return(TryCreate(pubkey.AsSpan(), out result)); #else if (pubkey.Length != 32) { result = null; return(false); } result = new TaprootInternalPubKey(pubkey); return(true); #endif }
public int CompareTo(TaprootInternalPubKey other) { return(BytesComparer.Instance.Compare(this.pubkey, other.pubkey)); }
public int CompareTo(TaprootInternalPubKey other) { return(this.pubkey.CompareTo(other.pubkey)); }
public bool CheckTapTweak(TaprootInternalPubKey internalPubKey) { return(this.CheckTapTweak(internalPubKey, MerkleRoot, OutputKeyParity)); }
internal PSBTOutput(BitcoinStream stream, PSBT parent, uint index, TxOut txOut) : base(parent) { if (txOut == null) { throw new ArgumentNullException(nameof(txOut)); } if (parent == null) { throw new ArgumentNullException(nameof(parent)); } TxOut = txOut; Index = index; byte[] k = new byte[0]; byte[] v = new byte[0]; try { stream.ReadWriteAsVarString(ref k); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTOutput. Could not read key", e); } while (k.Length != 0) { try { stream.ReadWriteAsVarString(ref v); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTOutput. Could not read value", e); } switch (k.First()) { case PSBTConstants.PSBT_OUT_REDEEMSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTOutput. Contains illegal value in key for redeem script"); } if (redeem_script != null) { throw new FormatException("Invalid PSBTOutput, duplicate key for redeem_script"); } redeem_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_OUT_WITNESSSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTOutput. Unexpected key length for PSBT_OUT_BIP32_DERIVATION"); } if (witness_script != null) { throw new FormatException("Invalid PSBTOutput, duplicate key for redeem_script"); } witness_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_OUT_BIP32_DERIVATION: var pubkey2 = new PubKey(k.Skip(1).ToArray()); if (hd_keypaths.ContainsKey(pubkey2)) { throw new FormatException("Invalid PSBTOutput, duplicate key for hd_keypaths"); } KeyPath path = KeyPath.FromBytes(v.Skip(4).ToArray()); hd_keypaths.Add(pubkey2, new RootedKeyPath(new HDFingerprint(v.Take(4).ToArray()), path)); break; case PSBTConstants.PSBT_OUT_TAP_BIP32_DERIVATION: var pubkey3 = new TaprootPubKey(k.Skip(1).ToArray()); if (hd_taprootkeypaths.ContainsKey(pubkey3)) { throw new FormatException("Invalid PSBTOutput, duplicate key for hd_taproot_keypaths"); } var bs = new BitcoinStream(v); List <uint256> hashes = null !; bs.ReadWrite(ref hashes); var pos = (int)bs.Inner.Position; KeyPath path2 = KeyPath.FromBytes(v.Skip(pos + 4).ToArray()); hd_taprootkeypaths.Add(pubkey3, new TaprootKeyPath( new RootedKeyPath(new HDFingerprint(v.Skip(pos).Take(4).ToArray()), path2), hashes.ToArray())); break; case PSBTConstants.PSBT_OUT_TAP_INTERNAL_KEY: if (k.Length != 1) { throw new FormatException("Invalid PSBTOutput. Contains illegal value in key for internal taproot pubkey"); } if (!TaprootInternalPubKey.TryCreate(v, out var tpk)) { throw new FormatException("Invalid PSBTOutput. Contains invalid internal taproot pubkey"); } TaprootInternalKey = tpk; break; default: if (unknown.ContainsKey(k)) { throw new FormatException("Invalid PSBTInput, duplicate key for unknown value"); } unknown.Add(k, v); break; } stream.ReadWriteAsVarString(ref k); } }