예제 #1
0
        public async Task <IActionResult> SignWithSeed([ModelBinder(typeof(WalletIdModelBinder))]
                                                       WalletId walletId, SignWithSeedViewModel viewModel)
        {
            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }
            var network = NetworkProvider.GetNetwork <BTCPayNetwork>(walletId.CryptoCode);

            if (network == null)
            {
                throw new FormatException("Invalid value for crypto code");
            }

            ExtKey extKey = viewModel.GetExtKey(network.NBitcoinNetwork);

            if (extKey == null)
            {
                ModelState.AddModelError(nameof(viewModel.SeedOrKey),
                                         "Seed or Key was not in a valid format. It is either the 12/24 words or starts with xprv");
            }

            var psbt = PSBT.Parse(viewModel.PSBT, network.NBitcoinNetwork);

            if (!psbt.IsReadyToSign())
            {
                ModelState.AddModelError(nameof(viewModel.PSBT), "PSBT is not ready to be signed");
            }

            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }

            ExtKey signingKey         = null;
            var    settings           = GetDerivationSchemeSettings(walletId);
            var    signingKeySettings = settings.GetSigningAccountKeySettings();

            if (signingKeySettings.RootFingerprint is null)
            {
                signingKeySettings.RootFingerprint = extKey.GetPublicKey().GetHDFingerPrint();
            }

            RootedKeyPath rootedKeyPath = signingKeySettings.GetRootedKeyPath();

            // The user gave the root key, let's try to rebase the PSBT, and derive the account private key
            if (rootedKeyPath?.MasterFingerprint == extKey.GetPublicKey().GetHDFingerPrint())
            {
                psbt.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath);
                signingKey = extKey.Derive(rootedKeyPath.KeyPath);
            }
            // The user maybe gave the account key, let's try to sign with it
            else
            {
                signingKey = extKey;
            }
            var balanceChange = psbt.GetBalance(settings.AccountDerivation, signingKey, rootedKeyPath);

            if (balanceChange == Money.Zero)
            {
                ModelState.AddModelError(nameof(viewModel.SeedOrKey), "This seed is unable to sign this transaction. Either the seed is incorrect, or the account path has not been properly configured in the Wallet Settings.");
                return(View(viewModel));
            }
            psbt.SignAll(settings.AccountDerivation, signingKey, rootedKeyPath);
            ModelState.Remove(nameof(viewModel.PSBT));
            return(await WalletPSBTReady(walletId, psbt.ToBase64(), signingKey.GetWif(network.NBitcoinNetwork).ToString(), rootedKeyPath?.ToString()));
        }
예제 #2
0
        public async Task <IActionResult> SignWithSeed([ModelBinder(typeof(WalletIdModelBinder))]
                                                       WalletId walletId, SignWithSeedViewModel viewModel)
        {
            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }
            var network = NetworkProvider.GetNetwork <BTCPayNetwork>(walletId.CryptoCode);

            if (network == null)
            {
                throw new FormatException("Invalid value for crypto code");
            }

            ExtKey extKey = viewModel.GetExtKey(network.NBitcoinNetwork);

            if (extKey == null)
            {
                ModelState.AddModelError(nameof(viewModel.SeedOrKey),
                                         "Seed or Key was not in a valid format. It is either the 12/24 words or starts with xprv");
            }

            var psbt = PSBT.Parse(viewModel.PSBT, network.NBitcoinNetwork);

            if (!psbt.IsReadyToSign())
            {
                ModelState.AddModelError(nameof(viewModel.PSBT), "PSBT is not ready to be signed");
            }

            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }

            ExtKey signingKey         = null;
            var    settings           = GetDerivationSchemeSettings(walletId);
            var    signingKeySettings = settings.GetSigningAccountKeySettings();

            if (signingKeySettings.RootFingerprint is null)
            {
                signingKeySettings.RootFingerprint = extKey.GetPublicKey().GetHDFingerPrint();
            }

            RootedKeyPath rootedKeyPath = signingKeySettings.GetRootedKeyPath();

            if (rootedKeyPath == null)
            {
                ModelState.AddModelError(nameof(viewModel.SeedOrKey), "The master fingerprint and/or account key path of your seed are not set in the wallet settings.");
                return(View(viewModel));
            }
            // The user gave the root key, let's try to rebase the PSBT, and derive the account private key
            if (rootedKeyPath.MasterFingerprint == extKey.GetPublicKey().GetHDFingerPrint())
            {
                psbt.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath);
                signingKey = extKey.Derive(rootedKeyPath.KeyPath);
            }
            else
            {
                ModelState.AddModelError(nameof(viewModel.SeedOrKey), "The master fingerprint does not match the one set in your wallet settings. Probable cause are: wrong seed, wrong passphrase or wrong fingerprint in your wallet settings.");
                return(View(viewModel));
            }

            var changed = PSBTChanged(psbt, () => psbt.SignAll(settings.AccountDerivation, signingKey, rootedKeyPath));

            if (!changed)
            {
                ModelState.AddModelError(nameof(viewModel.SeedOrKey), "Impossible to sign the transaction. Probable cause: Incorrect account key path in wallet settings, PSBT already signed.");
                return(View(viewModel));
            }
            ModelState.Remove(nameof(viewModel.PSBT));
            return(await WalletPSBTReady(walletId, psbt.ToBase64(), signingKey.GetWif(network.NBitcoinNetwork).ToString(), rootedKeyPath?.ToString()));
        }
        public async Task <IActionResult> SignWithSeed([ModelBinder(typeof(WalletIdModelBinder))]
                                                       WalletId walletId, SignWithSeedViewModel viewModel)
        {
            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }
            var network = NetworkProvider.GetNetwork(walletId.CryptoCode);

            if (network == null)
            {
                throw new FormatException("Valor no válido para el código criptográfico");
            }

            ExtKey extKey = viewModel.GetExtKey(network.NBitcoinNetwork);

            if (extKey == null)
            {
                ModelState.AddModelError(nameof(viewModel.SeedOrKey),
                                         "La seed o la clave no estaban en un formato válido. Es el 12/24 palabras o comienza con xprv");
            }

            var psbt = PSBT.Parse(viewModel.PSBT, network.NBitcoinNetwork);

            if (!psbt.IsReadyToSign())
            {
                ModelState.AddModelError(nameof(viewModel.PSBT), "PSBT no está listo para ser firmado");
            }

            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }

            ExtKey signingKey         = null;
            var    settings           = (await GetDerivationSchemeSettings(walletId));
            var    signingKeySettings = settings.GetSigningAccountKeySettings();

            if (signingKeySettings.RootFingerprint is null)
            {
                signingKeySettings.RootFingerprint = extKey.GetPublicKey().GetHDFingerPrint();
            }

            RootedKeyPath rootedKeyPath = signingKeySettings.GetRootedKeyPath();

            // The user gave the root key, let's try to rebase the PSBT, and derive the account private key
            if (rootedKeyPath?.MasterFingerprint == extKey.GetPublicKey().GetHDFingerPrint())
            {
                psbt.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath);
                signingKey = extKey.Derive(rootedKeyPath.KeyPath);
            }
            // The user maybe gave the account key, let's try to sign with it
            else
            {
                signingKey = extKey;
            }
            var balanceChange = psbt.GetBalance(settings.AccountDerivation, signingKey, rootedKeyPath);

            if (balanceChange == Money.Zero)
            {
                ModelState.AddModelError(nameof(viewModel.SeedOrKey), "Esta seed no parece poder firmar esta transacción. Esta es la clave incorrecta o la configuración de la cartera no tiene la ruta de cuenta correcta en la configuración de la cartera.");
                return(View(viewModel));
            }
            psbt.SignAll(settings.AccountDerivation, signingKey, rootedKeyPath);
            ModelState.Remove(nameof(viewModel.PSBT));
            return(await WalletPSBTReady(walletId, psbt.ToBase64(), signingKey.GetWif(network.NBitcoinNetwork).ToString(), rootedKeyPath.ToString()));
        }