protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps) { var ops = scriptSigOps; if (ops.Length == 0) { return(false); } if (!scriptSig.IsPushOnly) { return(false); } if (scriptPubKey != null) { var expectedHash = ExtractScriptPubKeyParameters(scriptPubKey); if (expectedHash == null) { return(false); } if (expectedHash != Script.FromBytesUnsafe(ops[ops.Length - 1].PushData).Hash) { return(false); } } var redeemBytes = ops[ops.Length - 1].PushData; if (redeemBytes.Length > 520) { return(false); } return(Script.FromBytesUnsafe(ops[ops.Length - 1].PushData).IsValid); }
public PayToScriptHashSigParameters?ExtractScriptSigParameters(Script scriptSig, Script?scriptPubKey) { var ops = scriptSig.ToOps().ToArray(); var ops2 = scriptPubKey == null ? null : scriptPubKey.ToOps().ToArray(); if (!CheckScriptSigCore(scriptSig, ops, scriptPubKey, ops2)) { return(null); } return(new PayToScriptHashSigParameters(Script.FromBytesUnsafe(ops[ops.Length - 1].PushData), ops.Take(ops.Length - 1).Select(o => o.PushData).ToArray())); }
public PayToScriptHashSigParameters ExtractScriptSigParameters(Network network, Script scriptSig, Script scriptPubKey) { Op[] ops = scriptSig.ToOps().ToArray(); Op[] ops2 = scriptPubKey == null ? null : scriptPubKey.ToOps().ToArray(); if (!CheckScriptSigCore(network, scriptSig, ops, scriptPubKey, ops2)) { return(null); } var result = new PayToScriptHashSigParameters(); result.RedeemScript = Script.FromBytesUnsafe(ops[ops.Length - 1].PushData); result.Pushes = ops.Take(ops.Length - 1).Select(o => o.PushData).ToArray(); return(result); }
public Script ReadWrite(Script data) { if (this.Serializing) { var bytes = data == null?Script.Empty.ToBytes(true) : data.ToBytes(true); ReadWriteAsVarString(ref bytes); return(data); } var varString = new VarString(); varString.ReadWrite(this); return(Script.FromBytesUnsafe(varString.GetString(true))); }
public Script ReadWrite(Script data) { if (Serializing) { var bytes = data == null?Script.Empty.ToBytes(true) : data.ToBytes(true); ReadWriteAsVarString(ref bytes); return(data); } else { byte[] bytes = null; VarString.StaticRead(this, ref bytes); return(Script.FromBytesUnsafe(bytes)); } }
public PayToScriptHashSigParameters ExtractScriptSigParameters(Script scriptSig, Script scriptPubKey) { var ops = scriptSig.ToOps().ToArray(); var ops2 = scriptPubKey == null ? null : scriptPubKey.ToOps().ToArray(); if(!CheckScriptSigCore(scriptSig, ops, scriptPubKey, ops2)) return null; try { var multiSig = ops.Length > 0 && ops[0].Code == OpcodeType.OP_0; PayToScriptHashSigParameters result = new PayToScriptHashSigParameters(); result.Signatures = ops .Skip(multiSig ? 1 : 0) .Take(ops.Length - 1 - (multiSig ? 1 : 0)) .Select(o => o.Code == OpcodeType.OP_0 ? null : new TransactionSignature(o.PushData)) .ToArray(); result.RedeemScript = Script.FromBytesUnsafe(ops[ops.Length - 1].PushData); return result; } catch(Exception) { return null; } }
internal PSBTInput(BitcoinStream stream, PSBT parent, uint index, TxIn input) : base(parent) { TxIn = input; Index = index; originalScriptSig = TxIn.ScriptSig ?? Script.Empty; originalWitScript = TxIn.WitScript ?? WitScript.Empty; byte[] k = new byte[0]; byte[] v = new byte[0]; try { stream.ReadWriteAsVarString(ref k); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTInput. Failed to Parse key.", e); } while (k.Length != 0) { try { stream.ReadWriteAsVarString(ref v); } catch (EndOfStreamException e) { throw new FormatException("Invalid PSBTInput. Failed to parse key.", e); } switch (k.First()) { case PSBTConstants.PSBT_IN_NON_WITNESS_UTXO: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for NonWitnessUTXO"); } if (non_witness_utxo != null) { throw new FormatException("Invalid PSBTInput. Duplicate non_witness_utxo"); } non_witness_utxo = this.GetConsensusFactory().CreateTransaction(); non_witness_utxo.FromBytes(v); break; case PSBTConstants.PSBT_IN_WITNESS_UTXO: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for WitnessUTXO"); } if (witness_utxo != null) { throw new FormatException("Invalid PSBTInput. Duplicate witness_utxo"); } if (this.GetConsensusFactory().TryCreateNew <TxOut>(out var txout)) { witness_utxo = txout; } else { witness_utxo = new TxOut(); } witness_utxo.FromBytes(v); break; case PSBTConstants.PSBT_IN_PARTIAL_SIG: var pubkey = new PubKey(k.Skip(1).ToArray()); if (partial_sigs.ContainsKey(pubkey)) { throw new FormatException("Invalid PSBTInput. Duplicate key for partial_sigs"); } partial_sigs.Add(pubkey, new TransactionSignature(v)); break; case PSBTConstants.PSBT_IN_SIGHASH: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for SigHash type"); } if (!(sighash_type is null)) { throw new FormatException("Invalid PSBTInput. Duplicate key for sighash_type"); } if (v.Length != 4) { throw new FormatException("Invalid PSBTInput. SigHash Type is not 4 byte"); } var value = Utils.ToUInt32(v, 0, true); if (!Enum.IsDefined(typeof(SigHash), value)) { throw new FormatException($"Invalid PSBTInput Unknown SigHash Type {value}"); } sighash_type = (SigHash)value; break; case PSBTConstants.PSBT_IN_REDEEMSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for redeem script"); } if (redeem_script != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for redeem_script"); } redeem_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_IN_WITNESSSCRIPT: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for witness script"); } if (witness_script != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for redeem_script"); } witness_script = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_IN_BIP32_DERIVATION: var pubkey2 = new PubKey(k.Skip(1).ToArray()); if (hd_keypaths.ContainsKey(pubkey2)) { throw new FormatException("Invalid PSBTInput. Duplicate key for hd_keypaths"); } var masterFingerPrint = new HDFingerprint(v.Take(4).ToArray()); KeyPath path = KeyPath.FromBytes(v.Skip(4).ToArray()); hd_keypaths.Add(pubkey2, new RootedKeyPath(masterFingerPrint, path)); break; case PSBTConstants.PSBT_IN_SCRIPTSIG: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for final scriptsig"); } if (final_script_sig != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for final_script_sig"); } final_script_sig = Script.FromBytesUnsafe(v); break; case PSBTConstants.PSBT_IN_SCRIPTWITNESS: if (k.Length != 1) { throw new FormatException("Invalid PSBTInput. Contains illegal value in key for final script witness"); } if (final_script_witness != null) { throw new FormatException("Invalid PSBTInput. Duplicate key for final_script_witness"); } final_script_witness = new WitScript(v); 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); } }
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. Contains illegal value in key for witness script"); } 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, Tuple.Create(new HDFingerprint(v.Take(4).ToArray()), path)); 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); } }
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); } }