/// <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. If the PSBT is all finalized this operation is a no-op
        /// </summary>
        /// <param name="accountKey">The current account key</param>
        /// <param name="newRoot">The KeyPath with the fingerprint of the new root key</param>
        /// <returns>This PSBT</returns>
        public PSBT RebaseKeyPaths(IHDKey accountKey, RootedKeyPath newRoot)
        {
            if (accountKey == null)
            {
                throw new ArgumentNullException(nameof(accountKey));
            }
            if (newRoot == null)
            {
                throw new ArgumentNullException(nameof(newRoot));
            }
            if (IsAllFinalized())
            {
                return(this);
            }
            accountKey = accountKey.AsHDKeyCache();
            var accountKeyFP = accountKey.GetPublicKey().GetHDFingerPrint();

            foreach (var o in HDKeysFor(accountKey).GroupBy(c => c.Coin))
            {
                if (o.Key is PSBTInput i && i.IsFinalized())
                {
                    continue;
                }
                foreach (var keyPath in o)
                {
                    o.Key.HDKeyPaths.Remove(keyPath.PubKey);
                    o.Key.HDKeyPaths.Add(keyPath.PubKey, newRoot.Derive(keyPath.RootedKeyPath.KeyPath));
                }
            }
            foreach (var xpub in GlobalXPubs.ToList())
            {
                if (xpub.Key.ExtPubKey.PubKey == accountKey.GetPublicKey())
                {
                    GlobalXPubs.Remove(xpub.Key);
                    GlobalXPubs.Add(xpub.Key, newRoot.Derive(xpub.Value.KeyPath));
                }
            }
            return(this);
        }
Ejemplo n.º 2
0
 public RootedKeyPath(IHDKey masterKey, KeyPath keyPath)
 {
     if (masterKey == null)
     {
         throw new ArgumentNullException(nameof(masterKey));
     }
     if (keyPath == null)
     {
         throw new ArgumentNullException(nameof(keyPath));
     }
     _KeyPath           = keyPath;
     _MasterFingerprint = masterKey.GetPublicKey().GetHDFingerPrint();
 }
        /// <summary>
        /// Get the balance change if you were signing this transaction.
        /// </summary>
        /// <returns>The balance change</returns>
        public Money GetBalance(IHDKey masterKey)
        {
            if (masterKey == null)
            {
                throw new ArgumentNullException(nameof(masterKey));
            }
            var             masterFP        = masterKey.GetPublicKey().GetHDFingerPrint();
            Money           total           = Money.Zero;
            DerivationCache derivationCache = new DerivationCache(masterKey);

            foreach (var o in Inputs.OfType <PSBTCoin>().Concat(Outputs))
            {
                var amount = o.GetCoin()?.Amount;
                if (amount == null)
                {
                    continue;
                }
                if (o is PSBTInput)
                {
                    amount = -amount;
                }
                foreach (var hdk in o.HDKeyPaths)
                {
                    var pubkey  = hdk.Key;
                    var keyPath = hdk.Value.Item2;
                    var fp      = hdk.Value.Item1;

                    if ((fp == masterKey.GetPublicKey().GetHDFingerPrint() || fp == default) &&
                        (derivationCache.Derive(keyPath).GetPublicKey() == pubkey))
                    {
                        total += amount;
                    }
                }
            }
            return(total);
        }
Ejemplo n.º 4
0
        internal IEnumerable <PSBTHDKeyMatch <T> > GetHDKeys(HDFingerprint?masterFingerprint, IHDKey accountKey)
        {
            if (accountKey == null)
            {
                throw new ArgumentNullException(nameof(accountKey));
            }
            accountKey = accountKey.AsHDKeyCache();
            var accountFingerprint = accountKey.GetPublicKey().GetHDFingerPrint();

            foreach (var c in this)
            {
                foreach (var match in c.HDKeysFor(masterFingerprint, accountKey, accountFingerprint))
                {
                    yield return((PSBTHDKeyMatch <T>)match);
                }
            }
        }
Ejemplo n.º 5
0
        internal IEnumerable <PSBTHDKeyMatch <T> > GetHDKeys(IHDScriptPubKey hdScriptPubKey, IHDKey accountKey, RootedKeyPath accountKeyPath = null)
        {
            if (accountKey == null)
            {
                throw new ArgumentNullException(nameof(accountKey));
            }
            accountKey     = accountKey.AsHDKeyCache();
            hdScriptPubKey = hdScriptPubKey?.AsHDKeyCache();
            var accountFingerprint = accountKey.GetPublicKey().GetHDFingerPrint();

            foreach (var c in this)
            {
                foreach (var match in c.HDKeysFor(hdScriptPubKey, accountKey, accountKeyPath, accountFingerprint))
                {
                    yield return((PSBTHDKeyMatch <T>)match);
                }
            }
        }
        /// <summary>
        /// Add keypath information to this PSBT for each input or output involving it
        /// </summary>
        /// <param name="masterKey">The master key of the keypaths</param>
        /// <param name="paths">The path of the public keys with their expected scriptPubKey</param>
        /// <returns>This PSBT</returns>
        public PSBT AddKeyPath(IHDKey masterKey, params Tuple <KeyPath, Script>[] paths)
        {
            if (masterKey == null)
            {
                throw new ArgumentNullException(nameof(masterKey));
            }
            if (paths == null)
            {
                throw new ArgumentNullException(nameof(paths));
            }

            masterKey = masterKey.AsHDKeyCache();
            foreach (var path in paths)
            {
                var key = masterKey.Derive(path.Item1);
                AddKeyPath(masterKey.GetPublicKey().GetHDFingerPrint(), key.GetPublicKey(), path.Item1, path.Item2);
            }
            return(this);
        }
Ejemplo n.º 7
0
        /// <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="newRoot">The KeyPath with the fingerprint of the new root key</param>
        /// <returns>This PSBT</returns>
        public PSBT RebaseKeyPaths(IHDKey accountKey, RootedKeyPath newRoot)
        {
            if (accountKey == null)
            {
                throw new ArgumentNullException(nameof(accountKey));
            }
            if (newRoot == null)
            {
                throw new ArgumentNullException(nameof(newRoot));
            }
            accountKey = accountKey.AsHDKeyCache();
            var accountKeyFP = accountKey.GetPublicKey().GetHDFingerPrint();

            foreach (var o in HDKeysFor(accountKey).GroupBy(c => c.Coin))
            {
                foreach (var keyPath in o)
                {
                    o.Key.HDKeyPaths.Remove(keyPath.PubKey);
                    o.Key.HDKeyPaths.Add(keyPath.PubKey, newRoot.Derive(keyPath.RootedKeyPath.KeyPath));
                }
            }
            return(this);
        }
        /// <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);
        }