private static async Task <KeyPath> GetKeyPath(LedgerClient ledger, BTCPayNetwork network, DirectDerivationStrategy directStrategy)
        {
            KeyPath foundKeyPath = null;

            foreach (var account in
                     new[] { new KeyPath("49'"), new KeyPath("44'") }
                     .Select(purpose => purpose.Derive(network.CoinType))
                     .SelectMany(coinType => Enumerable.Range(0, 5).Select(i => coinType.Derive(i, true))))
            {
                try
                {
                    var extpubkey = await GetExtPubKey(ledger, network, account, true);

                    if (directStrategy.Root.PubKey == extpubkey.ExtPubKey.PubKey)
                    {
                        foundKeyPath = account;
                        break;
                    }
                }
                catch (FormatException)
                {
                    throw new Exception($"The opened ledger app does not support {network.NBitcoinNetwork.Name}");
                }
            }

            return(foundKeyPath);
        }
Ejemplo n.º 2
0
        private static async Task <BitcoinExtPubKey> GetExtPubKey(LedgerClient ledger, BTCPayNetwork network, KeyPath account, bool onlyChaincode)
        {
            try
            {
                var pubKey = await ledger.GetWalletPubKeyAsync(account);

                try
                {
                    pubKey.GetAddress(network.NBitcoinNetwork);
                }
                catch
                {
                    if (network.NBitcoinNetwork.NetworkType == NetworkType.Mainnet)
                    {
                        throw new Exception($"The opened ledger app does not seems to support {network.NBitcoinNetwork.Name}.");
                    }
                }
                var fingerprint = onlyChaincode ? new byte[4] : (await ledger.GetWalletPubKeyAsync(account.Parent)).UncompressedPublicKey.Compress().Hash.ToBytes().Take(4).ToArray();
                var extpubkey   = new ExtPubKey(pubKey.UncompressedPublicKey.Compress(), pubKey.ChainCode, (byte)account.Indexes.Length, fingerprint, account.Indexes.Last()).GetWif(network.NBitcoinNetwork);
                return(extpubkey);
            }
            catch (FormatException)
            {
                throw new HardwareWalletException("Unsupported ledger app");
            }
        }
Ejemplo n.º 3
0
 public HardwareWalletService(System.Net.WebSockets.WebSocket ledgerWallet)
 {
     if (ledgerWallet == null)
     {
         throw new ArgumentNullException(nameof(ledgerWallet));
     }
     _Transport = new WebSocketTransport(ledgerWallet);
     _Ledger    = new LedgerClient(_Transport);
 }
Ejemplo n.º 4
0
        public async Task CanGetWalletPubKey()
        {
            var ledger          = (await LedgerClient.GetHIDLedgersAsync()).First();
            var firmwareVersion = await ledger.GetFirmwareVersionAsync();

            var path = new KeyPath("1'/0");
            var walletPubKeyResponse = await ledger.GetWalletPubKeyAsync(path, LedgerClient.AddressType.Legacy, true);

            await ledger.GetWalletPubKeyAsync(path, LedgerClient.AddressType.NativeSegwit, false);

            await ledger.GetWalletPubKeyAsync(path, LedgerClient.AddressType.Segwit, false);
        }
Ejemplo n.º 5
0
        public async Task CanSignTransactionStandardModeConcurrently()
        {
            var ledger = (await LedgerClient.GetHIDLedgersAsync()).First();

            var walletPubKey = await ledger.GetWalletPubKeyAsync(new KeyPath("1'/0"));

            var address = walletPubKey.GetAddress(network);

            var walletPubKey2 = await ledger.GetWalletPubKeyAsync(new KeyPath("1'/1"));

            var changeAddress = walletPubKey2.GetAddress(network);

            Transaction funding = network.Consensus.ConsensusFactory.CreateTransaction();

            funding.AddInput(network.GetGenesis().Transactions[0].Inputs[0]);
            funding.Outputs.Add(new TxOut(Money.Coins(1.1m), address));
            funding.Outputs.Add(new TxOut(Money.Coins(1.0m), address));
            funding.Outputs.Add(new TxOut(Money.Coins(1.2m), address));

            var coins = funding.Outputs.AsCoins();

            var spending = network.Consensus.ConsensusFactory.CreateTransaction();

            spending.LockTime = 1;
            spending.Inputs.AddRange(coins.Select(o => new TxIn(o.Outpoint, o.ScriptPubKey)));
            spending.Outputs.Add(new TxOut(Money.Coins(0.5m), BitcoinAddress.Create("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe", Network.Main)));
            spending.Outputs.Add(new TxOut(Money.Coins(0.8m), changeAddress));
            spending.Outputs.Add(new TxOut(Money.Zero, TxNullDataTemplate.Instance.GenerateScriptPubKey(new byte[] { 1, 2 })));

            var tasks = new List <Task>();

            for (var i = 0; i < 5; i++)
            {
                //should show 0.5 and 2.0 btc in fee
                var signed = ledger.SignTransactionAsync(
                    new KeyPath("1'/0"),
                    new Coin[]
                {
                    new Coin(funding, 0),
                    new Coin(funding, 1),
                    new Coin(funding, 2),
                }, new Transaction[]
                {
                    funding
                }, spending, new KeyPath("1'/1"));

                tasks.Add(signed);
            }

            await Task.WhenAll(tasks);
        }
Ejemplo n.º 6
0
        public async Task LedgerIsThreadSafe()
        {
            var ledger = (await LedgerClient.GetHIDLedgersAsync()).First();

            var tasks = new List <Task>();

            for (int i = 0; i < 50; i++)
            {
                tasks.Add(ledger.GetWalletPubKeyAsync(new KeyPath("1'/0")));
                tasks.Add(ledger.GetFirmwareVersionAsync());
            }

            await Task.WhenAll(tasks);
        }
        public override async Task Initialize()
        {
            var ledgerClient = (await LedgerClient.GetHIDLedgersAsync()).First();

            AddressDeriver = new LedgerDotNetApiWrapper(ledgerClient);
        }
Ejemplo n.º 8
0
        private static LedgerClient GetLedger()
        {
            var ledger = LedgerClient.GetHIDLedgers().First();

            return(ledger);
        }
 public LedgerDotNetApiWrapper(LedgerClient ledgerClient)
 {
     _LedgerClient = ledgerClient;
 }
Ejemplo n.º 10
0
        private async Task CanSignTransactionStandardModeCore(bool segwit)
        {
            var ledger       = (await LedgerClient.GetHIDLedgersAsync()).First();
            var walletPubKey = await ledger.GetWalletPubKeyAsync(new KeyPath("1'/0"));

            var address = segwit ? walletPubKey.UncompressedPublicKey.Compress().WitHash.ScriptPubKey : walletPubKey.GetAddress(network).ScriptPubKey;

            var response = await ledger.GetWalletPubKeyAsync(new KeyPath("1'/1"));

            var changeAddress = response.GetAddress(network);

            Transaction funding = network.Consensus.ConsensusFactory.CreateTransaction();

            funding.AddInput(Network.Main.GetGenesis().Transactions[0].Inputs[0]);
            funding.Outputs.Add(new TxOut(Money.Coins(1.1m), address));
            funding.Outputs.Add(new TxOut(Money.Coins(1.0m), address));
            funding.Outputs.Add(new TxOut(Money.Coins(1.2m), address));

            var coins = funding.Outputs.AsCoins();

            var spending = network.Consensus.ConsensusFactory.CreateTransaction();

            spending.LockTime = 1;
            spending.Inputs.AddRange(coins.Select(o => new TxIn(o.Outpoint, Script.Empty)));
            spending.Inputs[0].Sequence = 1;
            spending.Outputs.Add(new TxOut(Money.Coins(0.5m), BitcoinAddress.Create("15sYbVpRh6dyWycZMwPdxJWD4xbfxReeHe", Network.Main)));
            spending.Outputs.Add(new TxOut(Money.Coins(0.8m), changeAddress));
            spending.Outputs.Add(new TxOut(Money.Zero, TxNullDataTemplate.Instance.GenerateScriptPubKey(new byte[] { 1, 2 })));


            var requests = new SignatureRequest[] {
                new SignatureRequest()
                {
                    InputCoin        = new Coin(funding, 0),
                    InputTransaction = funding,
                    KeyPath          = new KeyPath("1'/0")
                },
                new SignatureRequest()
                {
                    InputCoin        = new Coin(funding, 1),
                    InputTransaction = funding,
                    KeyPath          = new KeyPath("1'/0")
                },
                new SignatureRequest()
                {
                    InputCoin        = new Coin(funding, 2),
                    InputTransaction = funding,
                    KeyPath          = new KeyPath("1'/0")
                },
            };

            if (segwit)
            {
                foreach (var req in requests)
                {
                    req.InputTransaction = null;
                }
            }

            //should show 0.5 and 2.0 btc in fee
            var signed = await ledger.SignTransactionAsync(requests, spending, new KeyPath("1'/1"));

            //Assert.Equal(Script.Empty, spending.Inputs.Last().ScriptSig);
            Assert.NotNull(signed);
        }
Ejemplo n.º 11
0
 public async Task GetCoinVersion()
 {
     var ledger      = (await LedgerClient.GetHIDLedgersAsync()).First();
     var coinVersion = await ledger.GetCoinVersion();
 }
Ejemplo n.º 12
0
 private static LedgerClient GetLedger()
 {
     return(LedgerClient.GetHIDLedgers().First());
 }
 public void TestInitialize()
 {
     processor = new LedgerClient(new LedgerDatabase());
 }