예제 #1
0
        internal TxOut orphanTxOut           = null; // When this input is not segwit, but we don't have the previous tx

        internal PSBTInput(PSBT parent, uint index, TxIn input) : base(parent)
        {
            TxIn              = input;
            Index             = index;
            originalScriptSig = TxIn.ScriptSig ?? Script.Empty;
            originalWitScript = TxIn.WitScript ?? WitScript.Empty;
        }
예제 #2
0
        /// <summary>
        /// Adds a witness stack to the list of elements that will be used for building the filter.
        /// </summary>
        /// <param name="witScript">The witScript.</param>
        /// <returns>The updated filter builder instance.</returns>
        public void AddWitness(WitScript witScript)
        {
            if (witScript == null)
            {
                throw new ArgumentNullException(nameof(witScript));
            }

            AddEntries(witScript.Pushes);
        }
예제 #3
0
        public override bool Equals(object obj)
        {
            WitScript item = obj as WitScript;

            if (item == null)
            {
                return(false);
            }
            return(EqualsCore(item));
        }
예제 #4
0
 public PayToWitPubkeyHashScriptSigParameters?ExtractWitScriptParameters(WitScript witScript)
 {
     if (!CheckWitScriptCore(witScript))
     {
         return(null);
     }
     if (PubKey.TryCreatePubKey(witScript[1], out var pk))
     {
         return(new PayToWitPubkeyHashScriptSigParameters((witScript[0].Length == 0) ? null : new TransactionSignature(witScript[0]), pk));
     }
     return(null);
 }
예제 #5
0
 private bool EqualsCore(WitScript item)
 {
     if (_Pushes.Length != item._Pushes.Length)
     {
         return(false);
     }
     for (int i = 0; i < _Pushes.Length; i++)
     {
         if (!Utils.ArrayEqual(_Pushes[i], item._Pushes[i]))
         {
             return(false);
         }
     }
     return(true);
 }
예제 #6
0
        /// <summary>
        /// Extract witness redeem from WitScript
        /// </summary>
        /// <param name="witScript">Witscript to extract information from</param>
        /// <param name="expectedScriptId">Expected redeem hash</param>
        /// <returns>The witness redeem</returns>
        public Script ExtractWitScriptParameters(WitScript witScript, WitScriptId expectedScriptId)
        {
            if (witScript.PushCount == 0)
            {
                return(null);
            }
            var    last   = witScript.GetUnsafePush(witScript.PushCount - 1);
            Script redeem = new Script(last);

            if (expectedScriptId != null)
            {
                if (expectedScriptId != redeem.WitHash)
                {
                    return(null);
                }
            }
            return(redeem);
        }
예제 #7
0
 public PayToWitPubkeyHashScriptSigParameters ExtractWitScriptParameters(WitScript witScript)
 {
     if (!CheckWitScriptCore(witScript))
     {
         return(null);
     }
     try
     {
         return(new PayToWitPubkeyHashScriptSigParameters()
         {
             TransactionSignature = (witScript[0].Length == 1 && witScript[0][0] == 0) ? null : new TransactionSignature(witScript[0]),
             PublicKey = new PubKey(witScript[1], true),
         });
     }
     catch (FormatException)
     {
         return(null);
     }
 }
예제 #8
0
        internal void Combine(PSBTInput other)
        {
            if (this.IsFinalized())
            {
                return;
            }

            foreach (var uk in other.unknown)
            {
                unknown.TryAdd(uk.Key, uk.Value);
            }


            if (other.final_script_sig != null)
            {
                final_script_sig = other.final_script_sig;
            }

            if (other.final_script_witness != null)
            {
                final_script_witness = other.final_script_witness;
            }
            if (IsFinalized())
            {
                ClearForFinalize();
                return;
            }

            if (non_witness_utxo == null && other.non_witness_utxo != null)
            {
                non_witness_utxo = other.non_witness_utxo;
            }

            if (witness_utxo == null && other.witness_utxo != null)
            {
                non_witness_utxo = other.non_witness_utxo;
            }

            if (sighash_type == 0 && other.sighash_type > 0)
            {
                sighash_type = other.sighash_type;
            }

            if (redeem_script == null && other.redeem_script != null)
            {
                redeem_script = other.redeem_script;
            }

            if (witness_script == null && other.witness_script != null)
            {
                witness_script = other.witness_script;
            }

            foreach (var sig in other.partial_sigs)
            {
                partial_sigs.TryAdd(sig.Key, sig.Value);
            }

            foreach (var keyPath in other.hd_keypaths)
            {
                hd_keypaths.TryAdd(keyPath.Key, keyPath.Value);
            }
        }
예제 #9
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);
            }
        }
예제 #10
0
 private bool CheckWitScriptCore(WitScript witScript)
 {
     return(witScript.PushCount == 2 &&
            ((witScript[0].Length == 1 && witScript[0][0] == 0) || (TransactionSignature.IsValid(witScript[0], ScriptVerify.None))) &&
            PubKey.Check(witScript[1], false));
 }
예제 #11
0
        /// <summary>
        /// Import informations contained by <paramref name="other"/> into this instance.
        /// </summary>
        /// <param name="other"></param>
        public void UpdateFrom(PSBTInput other)
        {
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }

            foreach (var uk in other.unknown)
            {
                unknown.TryAdd(uk.Key, uk.Value);
            }


            if (other.final_script_sig != null)
            {
                final_script_sig = other.final_script_sig;
            }

            if (other.final_script_witness != null)
            {
                final_script_witness = other.final_script_witness;
            }

            if (non_witness_utxo == null && other.non_witness_utxo != null)
            {
                non_witness_utxo = other.non_witness_utxo;
            }

            if (witness_utxo == null && other.witness_utxo != null)
            {
                witness_utxo = other.witness_utxo;
            }

            if (sighash_type == 0 && other.sighash_type > 0)
            {
                sighash_type = other.sighash_type;
            }

            if (redeem_script == null && other.redeem_script != null)
            {
                redeem_script = other.redeem_script;
            }

            if (witness_script == null && other.witness_script != null)
            {
                witness_script = other.witness_script;
            }

            foreach (var sig in other.partial_sigs)
            {
                partial_sigs.TryAdd(sig.Key, sig.Value);
            }

            foreach (var keyPath in other.hd_keypaths)
            {
                hd_keypaths.TryAdd(keyPath.Key, keyPath.Value);
            }

            if (IsFinalized())
            {
                ClearForFinalize();
            }
        }