예제 #1
0
        public KeyManager(BitcoinEncryptedSecretNoEC encryptedSecret, byte[] chainCode, HDFingerprint?masterFingerprint, ExtPubKey extPubKey, bool?passwordVerified, int?minGapLimit, BlockchainState blockchainState, string filePath = null, KeyPath accountKeyPath = null)
        {
            HdPubKeys               = new List <HdPubKey>();
            HdPubKeyScriptBytes     = new List <byte[]>();
            ScriptHdPubKeyMap       = new Dictionary <Script, HdPubKey>();
            HdPubKeysLock           = new object();
            HdPubKeyScriptBytesLock = new object();
            ScriptHdPubKeyMapLock   = new object();
            BlockchainStateLock     = new object();

            EncryptedSecret   = encryptedSecret;
            ChainCode         = chainCode;
            MasterFingerprint = masterFingerprint;
            ExtPubKey         = Guard.NotNull(nameof(extPubKey), extPubKey);

            PasswordVerified = passwordVerified;
            SetMinGapLimit(minGapLimit);

            BlockchainState    = blockchainState ?? new BlockchainState();
            HardwareWalletInfo = null;
            AccountKeyPath     = accountKeyPath ?? DefaultAccountKeyPath;

            SetFilePath(filePath);
            ToFileLock = new object();
            ToFile();
        }
예제 #2
0
        public KeyManager(BitcoinEncryptedSecretNoEC encryptedSecret, byte[] chainCode, string password, int minGapLimit = AbsoluteMinGapLimit, string filePath = null, KeyPath accountKeyPath = null)
        {
            HdPubKeys               = new List <HdPubKey>();
            HdPubKeyScriptBytes     = new List <byte[]>();
            ScriptHdPubKeyMap       = new Dictionary <Script, HdPubKey>();
            HdPubKeysLock           = new object();
            HdPubKeyScriptBytesLock = new object();
            ScriptHdPubKeyMapLock   = new object();
            BlockchainState         = new BlockchainState();
            BlockchainStateLock     = new object();
            HardwareWalletInfo      = null;

            if (password is null)
            {
                password = "";
            }

            SetMinGapLimit(minGapLimit);

            EncryptedSecret = Guard.NotNull(nameof(encryptedSecret), encryptedSecret);
            ChainCode       = Guard.NotNull(nameof(chainCode), chainCode);
            var extKey = new ExtKey(encryptedSecret.GetKey(password), chainCode);

            MasterFingerprint = extKey.Neuter().PubKey.GetHDFingerPrint();
            AccountKeyPath    = accountKeyPath ?? DefaultAccountKeyPath;
            ExtPubKey         = extKey.Derive(AccountKeyPath).Neuter();

            SetFilePath(filePath);
            ToFileLock = new object();
            ToFile();
        }
예제 #3
0
        public static async Task <PSBT> SignTxAsync(HardwareWalletInfo hardwareWalletInfo, PSBT psbt)
        {
            var psbtString    = psbt.ToBase64();
            var networkString = Network == Network.Main ? "" : "--testnet";

            try
            {
                JToken jtok = null;
                using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMinutes(3)))
                {
                    jtok = await SendCommandAsync($"{networkString} --device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" signtx {psbtString}", cts.Token, isMutexPriority : true);
                }
                JObject json             = jtok as JObject;
                var     signedPsbtString = json.Value <string>("psbt");
                var     signedPsbt       = PSBT.Parse(signedPsbtString, Network);

                if (!signedPsbt.IsAllFinalized())
                {
                    signedPsbt.Finalize();
                }

                return(signedPsbt);
            }
            catch (IOException ex) when(hardwareWalletInfo.Type == HardwareWalletType.Ledger &&
                                        (ex.Message.Contains("sign_tx cancelled", StringComparison.OrdinalIgnoreCase) ||
                                         ex.Message.Contains("open failed", StringComparison.OrdinalIgnoreCase)))
            {
                throw new IOException("Log into your Bitcoin account on your Ledger. If you're already logged in, log out and log in again.");
            }
            catch (IOException ex) when(hardwareWalletInfo.Type == HardwareWalletType.Ledger &&
                                        ex.Message.Contains("Bad argument", StringComparison.OrdinalIgnoreCase))
            {
                throw new IOException("Ledger refused to sign the transaction.");
            }
        }
예제 #4
0
        public static async Task <IEnumerable <HardwareWalletInfo> > EnumerateAsync()
        {
            JToken jtok = null;

            using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)))
            {
                jtok = await SendCommandAsync("enumerate", cts.Token);
            }
            JArray jarr = jtok as JArray;
            var    hwis = new List <HardwareWalletInfo>();

            foreach (JObject json in jarr)
            {
                var fingerprint  = json.Value <string>("fingerprint");
                var serialNumber = json.Value <string>("serial_number");
                var typeString   = json.Value <string>("type");
                var path         = json.Value <string>("path");
                var error        = json.Value <string>("error");

                var type = (HardwareWalletType)Enum.Parse(typeof(HardwareWalletType), typeString, ignoreCase: true);

                var hwi = new HardwareWalletInfo(fingerprint, serialNumber, type, path, error);
                hwis.Add(hwi);
            }

            return(hwis);
        }
예제 #5
0
        public LoadWalletEntry(HardwareWalletInfo hwi)
        {
            if (string.IsNullOrWhiteSpace(hwi.Error))
            {
                WalletName = hwi.Type.ToString();
            }
            else if (!hwi.Initialized)
            {
                WalletName = hwi.Type.ToString() + $" - Not Initialized";
            }
            else if (!hwi.Ready)
            {
                WalletName = hwi.Type.ToString() + $" - Device Not Ready";
            }
            else if (hwi.NeedPin)
            {
                WalletName = hwi.Type.ToString();
            }
            else
            {
                WalletName = hwi.Type.ToString() + $" - Error: {hwi.Error}";
            }

            HardwareWalletInfo = hwi;
        }
예제 #6
0
        public KeyManager(BitcoinEncryptedSecretNoEC encryptedSecret, byte[] chainCode, string password, string filePath = null)
        {
            HdPubKeys               = new List <HdPubKey>();
            HdPubKeyScriptBytes     = new List <byte[]>();
            ScriptHdPubkeyMap       = new Dictionary <Script, HdPubKey>();
            HdPubKeysLock           = new object();
            HdPubKeyScriptBytesLock = new object();
            ScriptHdPubkeyMapLock   = new object();
            BlockchainState         = new BlockchainState();
            BlockchainStateLock     = new object();
            HardwareWalletInfo      = null;

            if (password is null)
            {
                password = "";
            }

            EncryptedSecret = Guard.NotNull(nameof(encryptedSecret), encryptedSecret);
            IsWatchOnly     = false;
            ChainCode       = Guard.NotNull(nameof(chainCode), chainCode);
            var extKey = new ExtKey(encryptedSecret.GetKey(password), chainCode);

            ExtPubKey = extKey.Derive(AccountKeyPath).Neuter();

            SetFilePath(filePath);
            ToFileLock = new object();
            ToFile();
        }
예제 #7
0
        public static async Task <bool> SetupAsync(HardwareWalletInfo hardwareWalletInfo)
        {
            var    networkString = Network == Network.Main ? "" : "--testnet";
            JToken jtok          = await SendCommandAsync($"{networkString} --device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" --interactive setup");

            JObject json    = jtok as JObject;
            var     success = json.Value <bool>("success");

            return(success);
        }
예제 #8
0
        /// <summary>
        /// Acquire bech32 xpub on path: m/84h/0h/0h
        /// https://github.com/bitcoin-core/HWI/blob/master/docs/examples.md
        /// </summary>
        public static async Task <ExtPubKey> GetXpubAsync(HardwareWalletInfo hardwareWalletInfo)
        {
            var    networkString = Network == Network.Main ? "" : "--testnet ";
            JToken jtok          = await SendCommandAsync($"{networkString}--device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" getxpub m/84h/0h/0h");

            JObject json = jtok as JObject;
            string  xpub = json.Value <string>("xpub");

            ExtPubKey extpub = NBitcoinHelpers.BetterParseExtPubKey(xpub);

            return(extpub);
        }
예제 #9
0
        public static string GetNextHardwareWalletName(HardwareWalletInfo hwi)
        {
            for (int i = 0; i < int.MaxValue; i++)
            {
                var name = $"{hwi.Type}{i}";
                if (!File.Exists(Path.Combine(Global.WalletsDir, $"{name}.json")))
                {
                    return(name);
                }
            }

            throw new NotSupportedException("This is impossible.");
        }
예제 #10
0
        public static async Task <bool> SetupAsync(HardwareWalletInfo hardwareWalletInfo)
        {
            var    networkString = Network == Network.Main ? "" : "--testnet";
            JToken jtok          = null;

            using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMinutes(3)))
            {
                jtok = await SendCommandAsync($"{networkString} --device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" --interactive setup", cts.Token);
            }
            JObject json    = jtok as JObject;
            var     success = json.Value <bool>("success");

            return(success);
        }
예제 #11
0
        public static async Task <PSBT> SignTxAsync(HardwareWalletInfo hardwareWalletInfo, PSBT psbt)
        {
            var    psbtString    = psbt.ToBase64();
            var    networkString = Network == Network.Main ? "" : "--testnet";
            JToken jtok          = await SendCommandAsync($"{networkString} --device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" signtx {psbtString}");

            JObject json             = jtok as JObject;
            var     signedPsbtString = json.Value <string>("psbt");
            var     signedPsbt       = PSBT.Parse(signedPsbtString, Network);

            signedPsbt.Finalize();

            return(signedPsbt);
        }
예제 #12
0
        /// <summary>
        /// Acquire bech32 xpub on path: m/84h/0h/0h
        /// https://github.com/bitcoin-core/HWI/blob/master/docs/examples.md
        /// </summary>
        public static async Task <ExtPubKey> GetXpubAsync(HardwareWalletInfo hardwareWalletInfo)
        {
            var    networkString = Network == Network.Main ? "" : "--testnet ";
            JToken jtok          = null;

            using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)))
            {
                jtok = await SendCommandAsync($"{networkString}--device-type \"{hardwareWalletInfo.Type.ToString().ToLowerInvariant()}\" --device-path \"{hardwareWalletInfo.Path}\" getxpub m/84h/0h/0h", cts.Token);
            }
            JObject json = jtok as JObject;
            string  xpub = json.Value <string>("xpub");

            ExtPubKey extpub = NBitcoinHelpers.BetterParseExtPubKey(xpub);

            return(extpub);
        }
예제 #13
0
        public KeyManager(BitcoinEncryptedSecretNoEC encryptedSecret, byte[] chainCode, ExtPubKey extPubKey, bool?passwordVerified, BlockchainState blockchainState, string filePath = null)
        {
            HdPubKeys               = new List <HdPubKey>();
            HdPubKeyScriptBytes     = new List <byte[]>();
            ScriptHdPubkeyMap       = new Dictionary <Script, HdPubKey>();
            HdPubKeysLock           = new object();
            HdPubKeyScriptBytesLock = new object();
            ScriptHdPubkeyMapLock   = new object();
            BlockchainStateLock     = new object();

            EncryptedSecret = encryptedSecret;
            IsWatchOnly     = EncryptedSecret is null;
            ChainCode       = chainCode;
            ExtPubKey       = Guard.NotNull(nameof(extPubKey), extPubKey);

            PasswordVerified = passwordVerified;

            BlockchainState    = blockchainState ?? new BlockchainState();
            HardwareWalletInfo = null;

            SetFilePath(filePath);
            ToFileLock = new object();
            ToFile();
        }
예제 #14
0
 public LoadWalletEntry(string walletName)
 {
     WalletName         = walletName;
     HardwareWalletInfo = null;
 }
예제 #15
0
 public LoadWalletEntry(HardwareWalletInfo hwi)
 {
     WalletName         = hwi.Type.ToString();
     HardwareWalletInfo = hwi;
 }