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);
        }
Example #2
0
        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);
        }
Example #4
0
        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)));
        }
Example #5
0
        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));
            }
        }
Example #6
0
		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;
			}
		}
Example #7
0
        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);
            }
        }
Example #8
0
        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);
            }
        }
Example #9
0
        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);
            }
        }