feat(wallet): add P2PKH, P2SH-P2WPKH, and P2TR (Taproot/BIP86) address types
- ScriptKind.Taproot (BIP86, purpose 86', P2WPKH → witness v1 bech32m plm1p) derivation wired in DerivationPaths and ChainProfiles (xprv/xpub headers, no SLIP-132 standard for P2TR); NBitcoin ScriptPubKeyType.TaprootBIP86 - Wizard step StepScriptType inserted between passphrase and password: 4 radio buttons (Legacy / Wrapped SegWit / Native SegWit★ / Taproot), localized in 6 languages; CreateOrRestore now uses SelectedScriptKind instead of hardcoded NativeSegwit; back navigation updated accordingly - BIP86 golden-vector tests (Bip86TaprootTests): output key verified against official Bitcoin BIP86 addresses, plm1p prefix asserted
This commit is contained in:
@@ -23,6 +23,7 @@ public partial class MainWindowViewModel
|
||||
public const string StepConfirmSeed = "confirm-seed";
|
||||
public const string StepWords = "words";
|
||||
public const string StepPassphrase = "passphrase";
|
||||
public const string StepScriptType = "script-type";
|
||||
public const string StepPassword = "password";
|
||||
|
||||
[ObservableProperty]
|
||||
@@ -34,18 +35,37 @@ public partial class MainWindowViewModel
|
||||
[NotifyPropertyChangedFor(nameof(IsStepConfirmSeed))]
|
||||
[NotifyPropertyChangedFor(nameof(IsStepWords))]
|
||||
[NotifyPropertyChangedFor(nameof(IsStepPassphrase))]
|
||||
[NotifyPropertyChangedFor(nameof(IsStepScriptType))]
|
||||
[NotifyPropertyChangedFor(nameof(IsStepPassword))]
|
||||
private string setupStep = StepStart;
|
||||
|
||||
public bool IsStepDataLocation => SetupStep == StepDataLocation;
|
||||
public bool IsStepStart => SetupStep == StepStart;
|
||||
public bool IsStepStart => SetupStep == StepStart;
|
||||
public bool IsStepChooseWallet => SetupStep == StepChooseWallet;
|
||||
public bool IsStepOpen => SetupStep == StepOpen;
|
||||
public bool IsStepShowSeed => SetupStep == StepShowSeed;
|
||||
public bool IsStepConfirmSeed => SetupStep == StepConfirmSeed;
|
||||
public bool IsStepWords => SetupStep == StepWords;
|
||||
public bool IsStepPassphrase => SetupStep == StepPassphrase;
|
||||
public bool IsStepPassword => SetupStep == StepPassword;
|
||||
public bool IsStepOpen => SetupStep == StepOpen;
|
||||
public bool IsStepShowSeed => SetupStep == StepShowSeed;
|
||||
public bool IsStepConfirmSeed => SetupStep == StepConfirmSeed;
|
||||
public bool IsStepWords => SetupStep == StepWords;
|
||||
public bool IsStepPassphrase => SetupStep == StepPassphrase;
|
||||
public bool IsStepScriptType => SetupStep == StepScriptType;
|
||||
public bool IsStepPassword => SetupStep == StepPassword;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(IsLegacySelected))]
|
||||
[NotifyPropertyChangedFor(nameof(IsWrappedSegwitSelected))]
|
||||
[NotifyPropertyChangedFor(nameof(IsNativeSegwitSelected))]
|
||||
[NotifyPropertyChangedFor(nameof(IsTaprootSelected))]
|
||||
private ScriptKind selectedScriptKind = ScriptKind.NativeSegwit;
|
||||
|
||||
public bool IsLegacySelected => SelectedScriptKind == ScriptKind.Legacy;
|
||||
public bool IsWrappedSegwitSelected => SelectedScriptKind == ScriptKind.WrappedSegwit;
|
||||
public bool IsNativeSegwitSelected => SelectedScriptKind == ScriptKind.NativeSegwit;
|
||||
public bool IsTaprootSelected => SelectedScriptKind == ScriptKind.Taproot;
|
||||
|
||||
[RelayCommand] private void SelectLegacy() => SelectedScriptKind = ScriptKind.Legacy;
|
||||
[RelayCommand] private void SelectWrappedSegwit() => SelectedScriptKind = ScriptKind.WrappedSegwit;
|
||||
[RelayCommand] private void SelectNativeSegwit() => SelectedScriptKind = ScriptKind.NativeSegwit;
|
||||
[RelayCommand] private void SelectTaproot() => SelectedScriptKind = ScriptKind.Taproot;
|
||||
|
||||
public string DefaultDataPath => AppPaths.DefaultDataRoot();
|
||||
|
||||
@@ -96,6 +116,7 @@ public partial class MainWindowViewModel
|
||||
private void RefreshSetupState()
|
||||
{
|
||||
SetupStep = StepStart;
|
||||
SelectedScriptKind = ScriptKind.NativeSegwit;
|
||||
MnemonicInput = ConfirmMnemonicInput = PassphraseInput = PasswordInput = ConfirmPasswordInput = "";
|
||||
WalletFileExists = AppPaths.WalletFiles(Net).Count > 0;
|
||||
StatusMessage = "";
|
||||
@@ -192,6 +213,13 @@ public partial class MainWindowViewModel
|
||||
|
||||
[RelayCommand]
|
||||
private void WizardNextFromPassphrase()
|
||||
{
|
||||
SetupStep = StepScriptType;
|
||||
StatusMessage = "";
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void WizardNextFromScriptType()
|
||||
{
|
||||
PasswordInput = ConfirmPasswordInput = "";
|
||||
EncryptWallet = true;
|
||||
@@ -208,7 +236,8 @@ public partial class MainWindowViewModel
|
||||
StepChooseWallet or StepShowSeed or StepWords => StepStart,
|
||||
StepConfirmSeed => StepShowSeed,
|
||||
StepPassphrase => _isRestoreFlow ? StepWords : StepConfirmSeed,
|
||||
StepPassword => StepPassphrase,
|
||||
StepScriptType => StepPassphrase,
|
||||
StepPassword => StepScriptType,
|
||||
_ => StepStart,
|
||||
};
|
||||
if (SetupStep == StepStart)
|
||||
@@ -243,7 +272,7 @@ public partial class MainWindowViewModel
|
||||
var (doc, account) = WalletLoader.NewFromMnemonic(
|
||||
MnemonicInput,
|
||||
string.IsNullOrEmpty(PassphraseInput) ? null : PassphraseInput,
|
||||
ScriptKind.NativeSegwit,
|
||||
SelectedScriptKind,
|
||||
Profile);
|
||||
var path = AppPaths.DefaultWalletPath(Net);
|
||||
for (var n = 2; WalletStore.Exists(path); n++)
|
||||
|
||||
Reference in New Issue
Block a user