Exemplo n.º 1
0
 public ExtKey(Key key, byte[] chainCode, byte depth, byte[] fingerprint, uint child)
 {
     if (key == null)
     {
         throw new ArgumentNullException(nameof(key));
     }
     if (chainCode == null)
     {
         throw new ArgumentNullException(nameof(chainCode));
     }
     if (fingerprint == null)
     {
         throw new ArgumentNullException(nameof(fingerprint));
     }
     if (fingerprint.Length != 4)
     {
         throw new ArgumentException(string.Format("The fingerprint must be {0} bytes.", 4), "fingerprint");
     }
     if (chainCode.Length != ChainCodeLength)
     {
         throw new ArgumentException(string.Format("The chain code must be {0} bytes.", ChainCodeLength), "chainCode");
     }
     this.key          = key;
     this.nDepth       = depth;
     this.nChild       = child;
     parentFingerprint = new HDFingerprint(fingerprint);
     Buffer.BlockCopy(chainCode, 0, vchChainCode, 0, ChainCodeLength);
 }
        /// <summary>
        /// Add keypath information to this PSBT
        /// </summary>
        /// <param name="fingerprint">The fingerprint of the master's key</param>
        /// <param name="pubkey">A public key to add</param>
        /// <param name="path">The key path</param>
        /// <param name="scriptPubKey">A specific scriptPubKey this pubkey is involved with</param>
        /// <returns>This PSBT</returns>
        public PSBT AddKeyPath(HDFingerprint fingerprint, PubKey pubkey, KeyPath path, Script scriptPubKey)
        {
            if (pubkey == null)
            {
                throw new ArgumentNullException(nameof(pubkey));
            }
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            var txBuilder = CreateTransactionBuilder();

            foreach (var o in this.Inputs.OfType <PSBTCoin>().Concat(this.Outputs))
            {
                var coin = o.GetCoin();
                if (coin == null)
                {
                    continue;
                }
                if ((scriptPubKey != null && coin.ScriptPubKey == scriptPubKey) ||
                    ((o.GetSignableCoin() ?? coin.TryToScriptCoin(pubkey)) is Coin c && txBuilder.IsCompatibleKeyFromScriptCode(pubkey, c.GetScriptCode())) ||
                    txBuilder.IsCompatibleKeyFromScriptCode(pubkey, coin.ScriptPubKey))
                {
                    o.AddKeyPath(fingerprint, pubkey, path);
                }
            }
            return(this);
        }
Exemplo n.º 3
0
        public ExtPubKey(byte[] bytes, int offset, int length)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException(nameof(bytes));
            }
            if (bytes.Length - offset != Length)
            {
                throw new FormatException($"An extpubkey should be {Length} bytes");
            }
            int i = offset;

            nDepth = bytes[i];
            i++;
            parentFingerprint = new HDFingerprint(bytes, i);
            i           += 4;
            nChild       = Utils.ToUInt32(bytes, i, false);
            i           += 4;
            vchChainCode = new byte[32];
            Array.Copy(bytes, i, vchChainCode, 0, 32);
            i += 32;
            var pk = new byte[33];

            Array.Copy(bytes, i, pk, 0, 33);
            pubkey = new PubKey(pk);
        }
Exemplo n.º 4
0
        public ExtPubKey(ReadOnlySpan <byte> bytes)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException(nameof(bytes));
            }
            if (bytes.Length != Length)
            {
                throw new FormatException($"An extpubkey should be {Length} bytes");
            }
            int i = 0;

            nDepth = bytes[i];
            i++;
            parentFingerprint = new HDFingerprint(bytes.Slice(i, 4));
            i           += 4;
            nChild       = Utils.ToUInt32(bytes.Slice(i, 4), false);
            i           += 4;
            vchChainCode = new byte[32];
            bytes.Slice(i, 32).CopyTo(vchChainCode);
            i += 32;
            Span <byte> pk = stackalloc byte[33];

            bytes.Slice(i, 33).CopyTo(pk);
            pubkey = new PubKey(pk);
        }
Exemplo n.º 5
0
 public void AddKeyPath(HDFingerprint fingerprint, PubKey key, KeyPath path)
 {
     if (path == null)
     {
         throw new ArgumentNullException(nameof(path));
     }
 }
Exemplo n.º 6
0
 private ExtKey(ReadOnlySpan <byte> bytes, bool isSeed)
 {
     if (isSeed)
     {
         key = CalculateKey(bytes, out var cc);
         this.vchChainCode = cc;
     }
     else
     {
         if (bytes.Length != Length)
         {
             throw new FormatException($"An extpubkey should be {Length} bytes");
         }
         int i = 0;
         nDepth = bytes[i];
         i++;
         parentFingerprint = new HDFingerprint(bytes.Slice(1, 4));
         i           += 4;
         nChild       = Utils.ToUInt32(bytes.Slice(i, 4), false);
         i           += 4;
         vchChainCode = new byte[32];
         bytes.Slice(i, 32).CopyTo(vchChainCode);
         i += 32;
         if (bytes[i++] != 0)
         {
             throw new FormatException($"Invalid ExtKey");
         }
         Span <byte> pk = stackalloc byte[32];
         bytes.Slice(i, 32).CopyTo(pk);
         key = new Key(pk);
     }
 }
Exemplo n.º 7
0
        public static bool TryParse(string str, out RootedKeyPath result)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }
            result = null;
            var separator = str.IndexOf('/');

            if (separator == -1)
            {
                if (!HDFingerprint.TryParse(str, out var fp))
                {
                    return(false);
                }
                result = new RootedKeyPath(fp, KeyPath.Empty);
            }
            else
            {
                if (!HDFingerprint.TryParse(str.Substring(0, separator), out var fp))
                {
                    return(false);
                }
                if (!NBitcoin.KeyPath.TryParse(str.Substring(separator + 1), out var keyPath))
                {
                    return(false);
                }
                result = new RootedKeyPath(fp, keyPath);
            }
            return(true);
        }
Exemplo n.º 8
0
 public RootedKeyPath(HDFingerprint masterFingerprint, KeyPath keyPath)
 {
     if (keyPath == null)
     {
         throw new ArgumentNullException(nameof(keyPath));
     }
     _KeyPath           = keyPath;
     _MasterFingerprint = masterFingerprint;
 }
Exemplo n.º 9
0
        public void ReadWrite(ref HDFingerprint fingerPrint)
        {
            var v = fingerPrint.ToUInt32();

            ReadWrite(ref v);
            if (!this.Serializing)
            {
                fingerPrint = new HDFingerprint(v);
            }
        }
Exemplo n.º 10
0
 public HDFingerprint GetHDFingerPrint()
 {
     if (fp is HDFingerprint f)
     {
         return(f);
     }
     f  = new HDFingerprint(this.Hash.ToBytes(), 0);
     fp = f;
     return(f);
 }
Exemplo n.º 11
0
 public void AddKeyPath(HDFingerprint fingerprint, PubKey key, KeyPath keyPath)
 {
     if (keyPath == null)
     {
         throw new ArgumentNullException(nameof(keyPath));
     }
     if (key == null)
     {
         throw new ArgumentNullException(nameof(key));
     }
     hd_keypaths.Add(key, new Tuple <HDFingerprint, KeyPath>(fingerprint, keyPath));
 }
Exemplo n.º 12
0
 public static bool TryParse(string str, out HDFingerprint result)
 {
     if (str == null)
     {
         throw new ArgumentNullException(nameof(str));
     }
     result = default;
     if (!HexEncoder.IsWellFormed(str) || str.Length != 4 * 2)
     {
         return(false);
     }
     result = new HDFingerprint(Encoders.Hex.DecodeData(str));
     return(true);
 }
Exemplo n.º 13
0
        public void ReadWrite(ref HDFingerprint fingerPrint)
        {
#if HAS_SPAN
            Span <byte> bytes = stackalloc byte[4];
            fingerPrint.ToBytes(bytes);
#else
            var bytes = fingerPrint.ToBytes();
#endif
            ReadWrite(ref bytes);
            if (!this.Serializing)
            {
                fingerPrint = new HDFingerprint(bytes);
            }
        }
Exemplo n.º 14
0
 /// <summary>
 /// Constructor. Creates an extended key from the public key and corresponding private key.
 /// </summary>
 /// <remarks>
 /// <para>
 /// The ExtPubKey has the relevant values for child number, depth, chain code, and fingerprint.
 /// </para>
 /// </remarks>
 public ExtKey(ExtPubKey extPubKey, Key privateKey)
 {
     if (extPubKey == null)
     {
         throw new ArgumentNullException(nameof(extPubKey));
     }
     if (privateKey == null)
     {
         throw new ArgumentNullException(nameof(privateKey));
     }
     this.nChild            = extPubKey.nChild;
     this.nDepth            = extPubKey.nDepth;
     this.vchChainCode      = extPubKey.vchChainCode;
     this.parentFingerprint = extPubKey.parentFingerprint;
     this.key = privateKey;
 }
Exemplo n.º 15
0
 public ExtPubKey(PubKey pubkey, byte[] chainCode, byte depth, HDFingerprint fingerprint, uint child)
 {
     if (pubkey == null)
     {
         throw new ArgumentNullException(nameof(pubkey));
     }
     if (chainCode == null)
     {
         throw new ArgumentNullException(nameof(chainCode));
     }
     if (chainCode.Length != ChainCodeLength)
     {
         throw new ArgumentException(string.Format("The chain code must be {0} bytes.", ChainCodeLength), "chainCode");
     }
     this.pubkey       = pubkey;
     this.nDepth       = depth;
     this.nChild       = child;
     parentFingerprint = fingerprint;
     Buffer.BlockCopy(chainCode, 0, vchChainCode, 0, ChainCodeLength);
 }
 /// <summary>
 /// Rebase the keypaths.
 /// If a PSBT updater only know the child HD public key but not the root one, another updater knowing the parent master key it is based on
 /// can rebase the paths.
 /// </summary>
 /// <param name="oldFingerprint">The old fingerprint</param>
 /// <param name="newFingerprint">The new fingerprint of the master key</param>
 /// <param name="newRoot">The root of the KeyPath who had the old fingerprint</param>
 /// <returns></returns>
 public PSBT RebaseKeyPaths(HDFingerprint oldFingerprint, HDFingerprint newFingerprint, KeyPath newRoot)
 {
     if (newRoot == null)
     {
         throw new ArgumentNullException(nameof(newRoot));
     }
     foreach (var o in Inputs.OfType <PSBTCoin>().Concat(Outputs))
     {
         foreach (var keypath in o.HDKeyPaths.ToList())
         {
             if (keypath.Value.Item1 == oldFingerprint)
             {
                 var newKeyPath = newRoot.Derive(keypath.Value.Item2);
                 o.HDKeyPaths.Remove(keypath.Key);
                 o.HDKeyPaths.Add(keypath.Key, Tuple.Create(newFingerprint, newKeyPath));
             }
         }
     }
     return(this);
 }
        /// <summary>
        /// Add keypath information to this PSBT
        /// </summary>
        /// <param name="fingerprint">The fingerprint of the master's key</param>
        /// <param name="pubkey">A public key to add</param>
        /// <param name="path">The key path</param>
        /// <param name="scriptPubKey">A specific scriptPubKey this pubkey is involved with</param>
        /// <returns>This PSBT</returns>
        public PSBT AddKeyPath(HDFingerprint fingerprint, PubKey pubkey, KeyPath path, Script scriptPubKey)
        {
            if (pubkey == null)
            {
                throw new ArgumentNullException(nameof(pubkey));
            }
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            foreach (var input in this.Inputs)
            {
                if (scriptPubKey != null)
                {
                    if (scriptPubKey == input.GetProbableScriptPubKey())
                    {
                        input.AddKeyPath(fingerprint, pubkey, path);
                    }
                }
                else if (input.IsRelatedKey(pubkey))
                {
                    input.AddKeyPath(fingerprint, pubkey, path);
                }
            }
            foreach (var ouptut in this.Outputs)
            {
                if (scriptPubKey != null)
                {
                    if (scriptPubKey == ouptut.ScriptPubKey)
                    {
                        ouptut.AddKeyPath(fingerprint, pubkey, path);
                    }
                }
                else if (ouptut.IsRelatedKey(pubkey))
                {
                    ouptut.AddKeyPath(fingerprint, pubkey, path);
                }
            }
            return(this);
        }
Exemplo n.º 18
0
        public virtual void AddKeyPath(HDFingerprint fingerprint, PubKey key, KeyPath path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            hd_keypaths.AddOrReplace(key, new Tuple <HDFingerprint, KeyPath>(fingerprint, path));

            // Let's try to be smart, if the added key match the scriptPubKey then we are in p2psh p2wpkh
            if (Parent.Settings.IsSmart && redeem_script == null)
            {
                var output = GetCoin();
                if (output != null)
                {
                    if (key.WitHash.ScriptPubKey.Hash.ScriptPubKey == output.ScriptPubKey)
                    {
                        redeem_script = key.WitHash.ScriptPubKey;
                    }
                }
            }
        }
        /// <summary>
        /// Rebase the keypaths.
        /// If a PSBT updater only know the child HD public key but not the root one, another updater knowing the parent master key it is based on
        /// can rebase the paths.
        /// </summary>
        /// <param name="accountKey">The current account key</param>
        /// <param name="accountKeyPath">The path from the master key to the accountKey</param>
        /// <param name="masterFingerprint">The master key fingerprint</param>
        /// <returns></returns>
        public PSBT RebaseKeyPaths(IHDKey accountKey, KeyPath accountKeyPath, HDFingerprint masterFingerprint)
        {
            if (accountKey == null)
            {
                throw new ArgumentNullException(nameof(accountKey));
            }
            if (accountKeyPath == null)
            {
                throw new ArgumentNullException(nameof(accountKeyPath));
            }
            accountKey = accountKey.AsHDKeyCache();
            var accountKeyFP = accountKey.GetPublicKey().GetHDFingerPrint();

            foreach (var o in HDKeysFor(null, accountKey).GroupBy(c => c.Coin))
            {
                foreach (var keyPath in o)
                {
                    o.Key.HDKeyPaths.Remove(keyPath.PubKey);
                    o.Key.HDKeyPaths.Add(keyPath.PubKey, Tuple.Create(masterFingerprint, accountKeyPath.Derive(keyPath.KeyPath)));
                }
            }
            return(this);
        }
Exemplo n.º 20
0
 private ExtKey(byte[] bytes, bool isSeed)
 {
     if (isSeed)
     {
         key = CalculateKey(bytes, out var cc);
         this.vchChainCode = cc;
     }
     else
     {
         if (bytes == null)
         {
             throw new ArgumentNullException(nameof(bytes));
         }
         if (bytes.Length != Length)
         {
             throw new FormatException($"An extpubkey should be {Length} bytes");
         }
         int i = 0;
         nDepth = bytes[i];
         i++;
         parentFingerprint = new HDFingerprint(bytes, i);
         i           += 4;
         nChild       = Utils.ToUInt32(bytes, i, false);
         i           += 4;
         vchChainCode = new byte[32];
         Array.Copy(bytes, i, vchChainCode, 0, 32);
         i += 32;
         if (bytes[i++] != 0)
         {
             throw new FormatException($"Invalid ExtKey");
         }
         var pk = new byte[32];
         Array.Copy(bytes, i, pk, 0, 32);
         key = new Key(pk);
     }
 }
Exemplo n.º 21
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);
            }
        }
Exemplo n.º 22
0
 public override void AddKeyPath(HDFingerprint fingerprint, PubKey key, KeyPath path)
 {
     base.AddKeyPath(fingerprint, key, path);
     TrySlimOutput();
 }
Exemplo n.º 23
0
 public RootedKeyPath ToRootedKeyPath(HDFingerprint masterFingerprint)
 {
     return(new RootedKeyPath(masterFingerprint, this));
 }
 /// <summary>
 /// Add keypath information to this PSBT for each input or output involving it
 /// </summary>
 /// <param name="fingerprint">The fingerprint of the master's key</param>
 /// <param name="pubkey">A public key to add</param>
 /// <param name="path">The key path</param>
 /// <returns>This PSBT</returns>
 public PSBT AddKeyPath(HDFingerprint fingerprint, PubKey pubkey, KeyPath path)
 {
     return(AddKeyPath(fingerprint, pubkey, path, null));
 }