Пример #1
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);
            }
        }
Пример #2
0
        public void Serialize(BitcoinStream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            // Write the utxo
            // If there is a non-witness utxo, then don't serialize the witness one.
            if (witness_utxo != null)
            {
                // key
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_WITNESS_UTXO;
                stream.ReadWrite(ref key);

                // value
                var data = witness_utxo.ToBytes();
                stream.ReadWriteAsVarString(ref data);
            }

            if (non_witness_utxo != null)
            {
                // key
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_NON_WITNESS_UTXO;
                stream.ReadWrite(ref key);
                // value
                byte[] data = non_witness_utxo.ToBytes();
                stream.ReadWriteAsVarString(ref data);
            }

            // Write the sighash type
            if (sighash_type > 0)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_SIGHASH;
                stream.ReadWrite(ref key);
                var tmp = Utils.ToBytes((uint)sighash_type, true);
                stream.ReadWriteAsVarString(ref tmp);
            }

            // Write the redeem script
            if (redeem_script != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_REDEEMSCRIPT;
                stream.ReadWrite(ref key);
                var value = redeem_script.ToBytes();
                stream.ReadWriteAsVarString(ref value);
            }

            // Write the witness script
            if (witness_script != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_WITNESSSCRIPT;
                stream.ReadWrite(ref key);
                var value = witness_script.ToBytes();
                stream.ReadWriteAsVarString(ref value);
            }

            // Write any partial signatures
            foreach (var sig_pair in partial_sigs)
            {
                var key = new byte[] { PSBTConstants.PSBT_IN_PARTIAL_SIG }.Concat(sig_pair.Key.ToBytes());
                stream.ReadWriteAsVarString(ref key);
                var sig = sig_pair.Value.ToBytes();
                stream.ReadWriteAsVarString(ref sig);
            }

            // Write any hd keypaths
            foreach (var pathPair in hd_keypaths)
            {
                var key = new byte[] { PSBTConstants.PSBT_IN_BIP32_DERIVATION }.Concat(pathPair.Key.ToBytes());
                stream.ReadWriteAsVarString(ref key);
                var masterFingerPrint = pathPair.Value.MasterFingerprint;
                var path              = pathPair.Value.KeyPath.ToBytes();
                var pathInfo          = masterFingerPrint.ToBytes().Concat(path);
                stream.ReadWriteAsVarString(ref pathInfo);
            }

            // Write script sig
            if (final_script_sig != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_SCRIPTSIG;
                stream.ReadWrite(ref key);
                byte[] value = final_script_sig.ToBytes();
                stream.ReadWriteAsVarString(ref value);
            }

            // write script witness
            if (final_script_witness != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_SCRIPTWITNESS;
                stream.ReadWrite(ref key);
                var stack = final_script_witness.ToBytes();
                stream.ReadWriteAsVarString(ref stack);
            }

            // Write unknown things
            foreach (var entry in unknown)
            {
                var k = entry.Key;
                var v = entry.Value;
                stream.ReadWriteAsVarString(ref k);
                stream.ReadWriteAsVarString(ref v);
            }

            var sep = PSBTConstants.PSBT_SEPARATOR;

            stream.ReadWrite(ref sep);
        }
Пример #3
0
        internal PSBTOutput(BitcoinStream stream, PSBT parent, uint index, TxOut txOut)
        {
            if (txOut == null)
            {
                throw new ArgumentNullException(nameof(txOut));
            }
            if (parent == null)
            {
                throw new ArgumentNullException(nameof(parent));
            }
            hd_keypaths = new HDKeyPathKVMap(new PubKeyComparer());
            unknown     = new UnKnownKVMap(BytesComparer.Instance);
            Parent      = 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);
            }
        }
Пример #4
0
 public void ReadWrite(BitcoinStream stream)
 {
     stream.ReadWriteAsVarString(ref _Data);
 }
        internal PSBT(BitcoinStream stream)
        {
            Inputs  = new PSBTInputList();
            Outputs = new PSBTOutputList();
            var magicBytes = stream.Inner.ReadBytes(PSBT_MAGIC_BYTES.Length);

            if (!magicBytes.SequenceEqual(PSBT_MAGIC_BYTES))
            {
                throw new FormatException("Invalid PSBT magic bytes");
            }

            // It will be reassigned in `ReadWriteAsVarString` so no worry to assign 0 length array here.
            byte[] k       = new byte[0];
            byte[] v       = new byte[0];
            var    txFound = false;

            stream.ReadWriteAsVarString(ref k);
            while (k.Length != 0)
            {
                switch (k.First())
                {
                case PSBTConstants.PSBT_GLOBAL_UNSIGNED_TX:
                    if (k.Length != 1)
                    {
                        throw new FormatException("Invalid PSBT. Contains illegal value in key global tx");
                    }
                    if (tx != null)
                    {
                        throw new FormatException("Duplicate Key, unsigned tx already provided");
                    }
                    tx = stream.ConsensusFactory.CreateTransaction();
                    uint size = 0;
                    stream.ReadWriteAsVarInt(ref size);
                    var pos = stream.Counter.ReadenBytes;
                    tx.ReadWrite(stream);
                    if (stream.Counter.ReadenBytes - pos != size)
                    {
                        throw new FormatException("Malformed global tx. Unexpected size.");
                    }
                    if (tx.Inputs.Any(txin => txin.ScriptSig != Script.Empty || txin.WitScript != WitScript.Empty))
                    {
                        throw new FormatException("Malformed global tx. It should not contain any scriptsig or witness by itself");
                    }
                    txFound = true;
                    break;

                default:
                    if (unknown.ContainsKey(k))
                    {
                        throw new FormatException("Invalid PSBTInput, duplicate key for unknown value");
                    }
                    stream.ReadWriteAsVarString(ref v);
                    unknown.Add(k, v);
                    break;
                }
                stream.ReadWriteAsVarString(ref k);
            }
            if (!txFound)
            {
                throw new FormatException("Invalid PSBT. No global TX");
            }

            int i = 0;

            while (stream.Inner.CanRead && i < tx.Inputs.Count)
            {
                var psbtin = new PSBTInput(stream, this, (uint)i, tx.Inputs[i]);
                Inputs.Add(psbtin);
                i++;
            }
            if (i != tx.Inputs.Count)
            {
                throw new FormatException("Invalid PSBT. Number of input does not match to the global tx");
            }

            i = 0;
            while (stream.Inner.CanRead && i < tx.Outputs.Count)
            {
                var psbtout = new PSBTOutput(stream, this, (uint)i, tx.Outputs[i]);
                Outputs.Add(psbtout);
                i++;
            }
            if (i != tx.Outputs.Count)
            {
                throw new FormatException("Invalid PSBT. Number of outputs does not match to the global tx");
            }
        }
Пример #6
0
        internal PSBT(BitcoinStream stream, Network network)
        {
            if (network == null)
            {
                throw new ArgumentNullException(nameof(network));
            }
            Network = network;
            Inputs  = new PSBTInputList();
            Outputs = new PSBTOutputList();
            var magicBytes = stream.Inner.ReadBytes(PSBT_MAGIC_BYTES.Length);

            if (!magicBytes.SequenceEqual(PSBT_MAGIC_BYTES))
            {
                throw new FormatException("Invalid PSBT magic bytes");
            }

            // It will be reassigned in `ReadWriteAsVarString` so no worry to assign 0 length array here.
            byte[] k       = new byte[0];
            byte[] v       = new byte[0];
            var    txFound = false;

            stream.ReadWriteAsVarString(ref k);
            while (k.Length != 0)
            {
                switch (k[0])
                {
                case PSBTConstants.PSBT_GLOBAL_UNSIGNED_TX:
                    if (k.Length != 1)
                    {
                        throw new FormatException("Invalid PSBT. Contains illegal value in key global tx");
                    }
                    if (tx != null)
                    {
                        throw new FormatException("Duplicate Key, unsigned tx already provided");
                    }
                    tx = stream.ConsensusFactory.CreateTransaction();
                    uint size = 0;
                    stream.ReadWriteAsVarInt(ref size);
                    var pos = stream.Counter.ReadenBytes;
                    tx.ReadWrite(stream);
                    if (stream.Counter.ReadenBytes - pos != size)
                    {
                        throw new FormatException("Malformed global tx. Unexpected size.");
                    }
                    if (tx.Inputs.Any(txin => txin.ScriptSig != Script.Empty || txin.WitScript != WitScript.Empty))
                    {
                        throw new FormatException("Malformed global tx. It should not contain any scriptsig or witness by itself");
                    }
                    txFound = true;
                    break;

                case PSBTConstants.PSBT_GLOBAL_XPUB when XPubVersionBytes != null:
                    if (k.Length != 1 + XPubVersionBytes.Length + 74)
                    {
                        throw new FormatException("Malformed global xpub.");
                    }
                    for (int ii = 0; ii < XPubVersionBytes.Length; ii++)
                    {
                        if (k[1 + ii] != XPubVersionBytes[ii])
                        {
                            throw new FormatException("Malformed global xpub.");
                        }
                    }
                    stream.ReadWriteAsVarString(ref v);
                    KeyPath path          = KeyPath.FromBytes(v.Skip(4).ToArray());
                    var     rootedKeyPath = new RootedKeyPath(new HDFingerprint(v.Take(4).ToArray()), path);
                    GlobalXPubs.Add(new ExtPubKey(k, 1 + XPubVersionBytes.Length, 74).GetWif(Network), rootedKeyPath);
                    break;

                default:
                    if (unknown.ContainsKey(k))
                    {
                        throw new FormatException("Invalid PSBTInput, duplicate key for unknown value");
                    }
                    stream.ReadWriteAsVarString(ref v);
                    unknown.Add(k, v);
                    break;
                }
                stream.ReadWriteAsVarString(ref k);
            }
            if (!txFound)
            {
                throw new FormatException("Invalid PSBT. No global TX");
            }

            int i = 0;

            while (stream.Inner.CanRead && i < tx.Inputs.Count)
            {
                var psbtin = new PSBTInput(stream, this, (uint)i, tx.Inputs[i]);
                Inputs.Add(psbtin);
                i++;
            }
            if (i != tx.Inputs.Count)
            {
                throw new FormatException("Invalid PSBT. Number of input does not match to the global tx");
            }

            i = 0;
            while (stream.Inner.CanRead && i < tx.Outputs.Count)
            {
                var psbtout = new PSBTOutput(stream, this, (uint)i, tx.Outputs[i]);
                Outputs.Add(psbtout);
                i++;
            }
            if (i != tx.Outputs.Count)
            {
                throw new FormatException("Invalid PSBT. Number of outputs does not match to the global tx");
            }
        }
Пример #7
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);
            }
        }
Пример #8
0
        public void Serialize(BitcoinStream stream)
        {
            if (redeem_script != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                stream.ReadWrite(PSBTConstants.PSBT_OUT_REDEEMSCRIPT);
                var value = redeem_script.ToBytes();
                stream.ReadWriteAsVarString(ref value);
            }

            if (witness_script != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                stream.ReadWrite(PSBTConstants.PSBT_OUT_WITNESSSCRIPT);
                var value = witness_script.ToBytes();
                stream.ReadWriteAsVarString(ref value);
            }

            if (this.TaprootInternalKey is TaprootInternalPubKey tp)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_OUT_TAP_INTERNAL_KEY;
                stream.ReadWrite(ref key);
                var b = tp.ToBytes();
                stream.ReadWriteAsVarString(ref b);
            }

            foreach (var pathPair in hd_keypaths)
            {
                var key = new byte[] { PSBTConstants.PSBT_OUT_BIP32_DERIVATION }.Concat(pathPair.Key.ToBytes());
                stream.ReadWriteAsVarString(ref key);
                var path     = pathPair.Value.KeyPath.ToBytes();
                var pathInfo = pathPair.Value.MasterFingerprint.ToBytes().Concat(path);
                stream.ReadWriteAsVarString(ref pathInfo);
            }
            foreach (var pathPair in hd_taprootkeypaths)
            {
                var key = new byte[] { PSBTConstants.PSBT_OUT_TAP_BIP32_DERIVATION }.Concat(pathPair.Key.ToBytes());
                stream.ReadWriteAsVarString(ref key);
                uint          leafCount = (uint)pathPair.Value.LeafHashes.Length;
                BitcoinStream bs        = new BitcoinStream(new MemoryStream(), true);
                bs.ReadWriteAsVarInt(ref leafCount);
                foreach (var hash in pathPair.Value.LeafHashes)
                {
                    bs.ReadWrite(hash);
                }
                var b = pathPair.Value.RootedKeyPath.MasterFingerprint.ToBytes();
                bs.ReadWrite(ref b);
                b = pathPair.Value.RootedKeyPath.KeyPath.ToBytes();
                bs.ReadWrite(ref b);
                b = ((MemoryStream)bs.Inner).ToArrayEfficient();
                stream.ReadWriteAsVarString(ref b);
            }

            foreach (var entry in unknown)
            {
                var k = entry.Key;
                var v = entry.Value;
                stream.ReadWriteAsVarString(ref k);
                stream.ReadWriteAsVarString(ref v);
            }

            var sep = PSBTConstants.PSBT_SEPARATOR;

            stream.ReadWrite(ref sep);
        }
Пример #9
0
 private static byte[] ReadPush(BitcoinStream stream)
 {
     byte[] push = null;
     stream.ReadWriteAsVarString(ref push);
     return(push);
 }