/// <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); }
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); }
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); } } }
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); }
/// <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); }