public void TrySign(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, RootedKeyPath accountKeyPath, SigHash sigHash = SigHash.All) { if (accountKey == null) { throw new ArgumentNullException(nameof(accountKey)); } if (accountHDScriptPubKey == null) { throw new ArgumentNullException(nameof(accountHDScriptPubKey)); } var cache = accountKey.AsHDKeyCache(); accountHDScriptPubKey = accountHDScriptPubKey.AsHDKeyCache(); foreach (var hdk in this.HDKeysFor(accountHDScriptPubKey, cache, accountKeyPath)) { if (((HDKeyCache)cache.Derive(hdk.AddressKeyPath)).Inner is ISecret k) { Sign(k.PrivateKey, sigHash); } else { throw new ArgumentException(paramName: nameof(accountKey), message: "This should be a private key"); } } }
/// <summary> /// Deriving an IHDScriptPubKey is normally time consuming, this wrap the IHDScriptPubKey in a new IHDScriptPubKey object which can cache derivations /// </summary> /// <param name="hdScriptPubKey">The hdScriptPubKey to wrap</param> /// <returns>An hdkey which cache derivations, of the parameter if it is already itself a cache</returns> public static IHDScriptPubKey AsHDKeyCache(this IHDScriptPubKey hdScriptPubKey) { if (hdScriptPubKey == null) { throw new ArgumentNullException(nameof(hdScriptPubKey)); } if (hdScriptPubKey is HDScriptPubKeyCache c) { return(c); } return(new HDScriptPubKeyCache(hdScriptPubKey)); }
/// <summary> /// Filter the keys which contains the <paramref name="accountKey"/> and <paramref name="accountKeyPath"/> in the HDKeys and whose input/output /// the same scriptPubKeys as <paramref name="accountHDScriptPubKey"/>. /// </summary> /// <param name="accountHDScriptPubKey">The hdScriptPubKey used to generate addresses</param> /// <param name="accountKey">The account key that will be used to sign (ie. 49'/0'/0')</param> /// <param name="accountKeyPath">The account key path</param> /// <returns>HD Keys matching master root key</returns> public IEnumerable <PSBTHDKeyMatch> HDKeysFor(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, RootedKeyPath accountKeyPath = null) { if (accountKey == null) { throw new ArgumentNullException(nameof(accountKey)); } if (accountHDScriptPubKey == null) { throw new ArgumentNullException(nameof(accountHDScriptPubKey)); } accountHDScriptPubKey = accountHDScriptPubKey.AsHDKeyCache(); accountKey = accountKey.AsHDKeyCache(); return(Inputs.HDKeysFor(accountHDScriptPubKey, accountKey, accountKeyPath).OfType <PSBTHDKeyMatch>().Concat(Outputs.HDKeysFor(accountHDScriptPubKey, accountKey, accountKeyPath))); }
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> /// Get the balance change if you were signing this transaction. /// </summary> /// <param name="accountHDScriptPubKey">The hdScriptPubKey used to generate addresses</param> /// <param name="accountKey">The account key that will be used to sign (ie. 49'/0'/0')</param> /// <param name="accountKeyPath">The account key path</param> /// <returns>The balance change</returns> public Money GetBalance(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, RootedKeyPath accountKeyPath = null) { if (accountHDScriptPubKey == null) { throw new ArgumentNullException(nameof(accountHDScriptPubKey)); } Money total = Money.Zero; foreach (var o in CoinsFor(accountHDScriptPubKey, accountKey, accountKeyPath)) { var amount = o.GetCoin()?.Amount; if (amount == null) { continue; } total += o is PSBTInput ? -amount : amount; } return(total); }
/// <summary> /// Sign all inputs which derive addresses from <paramref name="accountHDScriptPubKey"/> and that need to be signed by <paramref name="accountKey"/>. /// </summary> /// <param name="accountHDScriptPubKey">The address generator</param> /// <param name="accountKey">The account key with which to sign</param> /// <param name="accountKeyPath">The account key path (eg. [masterFP]/49'/0'/0')</param> /// <param name="sigHash">The SigHash</param> /// <returns>This PSBT</returns> public PSBT SignAll(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, RootedKeyPath accountKeyPath, SigHash sigHash = SigHash.All) { if (accountKey == null) { throw new ArgumentNullException(nameof(accountKey)); } if (accountHDScriptPubKey == null) { throw new ArgumentNullException(nameof(accountHDScriptPubKey)); } accountHDScriptPubKey = accountHDScriptPubKey.AsHDKeyCache(); accountKey = accountKey.AsHDKeyCache(); Money total = Money.Zero; foreach (var o in Inputs.CoinsFor(accountHDScriptPubKey, accountKey, accountKeyPath)) { o.TrySign(accountHDScriptPubKey, accountKey, accountKeyPath, sigHash); } return(this); }
public void TrySign(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, SigHash sigHash = SigHash.All) { TrySign(accountHDScriptPubKey, accountKey, null, sigHash); }
internal IEnumerable <T> GetPSBTCoins(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, RootedKeyPath accountKeyPath = null) { return(GetHDKeys(accountHDScriptPubKey, accountKey, accountKeyPath) .Select(c => c.Coin) .Distinct()); }
/// <summary> /// Filter the keys which contains the <paramref name="accountKey"/> and <paramref name="accountKeyPath"/> in the HDKeys and whose input/output /// the same scriptPubKeys as <paramref name="accountHDScriptPubKey"/>. /// </summary> /// <param name="accountHDScriptPubKey">The hdScriptPubKey used to generate addresses</param> /// <param name="accountKey">The account key that will be used to sign (ie. 49'/0'/0')</param> /// <param name="accountKeyPath">The account key path</param> /// <returns>HD Keys matching master root key</returns> public IEnumerable <PSBTHDKeyMatch <T> > HDKeysFor(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, RootedKeyPath accountKeyPath = null) { return(GetHDKeys(accountHDScriptPubKey, accountKey, accountKeyPath)); }
/// <summary> /// Filter the coins which contains the <paramref name="accountKey"/> and <paramref name="accountKeyPath"/> in the HDKeys and derive /// the same scriptPubKeys as <paramref name="accountHDScriptPubKey"/>. /// </summary> /// <param name="accountHDScriptPubKey">The hdScriptPubKey used to generate addresses</param> /// <param name="accountKey">The account key that will be used to sign (ie. 49'/0'/0')</param> /// <param name="accountKeyPath">The account key path</param> /// <returns>Inputs with HD keys matching masterFingerprint and account key</returns> public IEnumerable <T> CoinsFor(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, RootedKeyPath accountKeyPath = null) { return(GetPSBTCoins(accountHDScriptPubKey, accountKey, accountKeyPath)); }
public void TrySign(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, RootedKeyPath accountKeyPath, SigHash sigHash = SigHash.All) { TrySign(accountHDScriptPubKey, accountKey, accountKeyPath, Parent.Normalize(new SigningOptions(sigHash))); }
/// <summary> /// Sign all inputs which derive addresses from <paramref name="accountHDScriptPubKey"/> and that need to be signed by <paramref name="accountKey"/>. /// </summary> /// <param name="accountHDScriptPubKey">The address generator</param> /// <param name="accountKey">The account key with which to sign</param> /// <param name="sigHash">The SigHash</param> /// <returns>This PSBT</returns> public PSBT SignAll(IHDScriptPubKey accountHDScriptPubKey, IHDKey accountKey, SigHash sigHash = SigHash.All) { return(SignAll(accountHDScriptPubKey, accountKey, null, sigHash)); }
HDScriptPubKeyCache(IHDScriptPubKey hdKey, KeyPath childPath, ConcurrentDictionary <KeyPath, IHDScriptPubKey> cache) { this.derivationCache = cache; _PathFromRoot = childPath; this.hdKey = hdKey; }
internal HDScriptPubKeyCache(IHDScriptPubKey masterKey) { this.hdKey = masterKey; _PathFromRoot = new KeyPath(); derivationCache = new ConcurrentDictionary <KeyPath, IHDScriptPubKey>(); }