2026-06-15 12:03:46 +02:00
|
|
|
using NBitcoin;
|
|
|
|
|
using PalladiumWallet.Core.Chain;
|
|
|
|
|
using PalladiumWallet.Core.Crypto;
|
|
|
|
|
|
|
|
|
|
namespace PalladiumWallet.Tests.Crypto;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-06-16 14:40:06 +02:00
|
|
|
/// BIP86 test vectors (abandon-about mnemonic, no passphrase).
|
|
|
|
|
/// The tweaked public key (output key, 32-byte x-only) is chain-independent:
|
|
|
|
|
/// verified against the official Bitcoin vectors, then checked that the PLM
|
|
|
|
|
/// address starts with plm1p (witness v1, bech32m).
|
|
|
|
|
/// The path m/86'/0'/0' uses coin_type=0 (not 746) to match the BIP86 vectors.
|
2026-06-15 12:03:46 +02:00
|
|
|
/// </summary>
|
|
|
|
|
public class Bip86TaprootTests
|
|
|
|
|
{
|
|
|
|
|
private static HdAccount Account()
|
|
|
|
|
{
|
|
|
|
|
Assert.True(Bip39.TryParse(
|
|
|
|
|
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
|
|
|
|
out var mnemonic));
|
|
|
|
|
return HdAccount.FromSeed(
|
|
|
|
|
Bip39.ToSeed(mnemonic!),
|
|
|
|
|
ScriptKind.Taproot,
|
|
|
|
|
ChainProfiles.Mainnet,
|
|
|
|
|
new KeyPath("86'/0'/0'"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Il_derivation_path_di_un_account_taproot_usa_purpose_86()
|
|
|
|
|
{
|
|
|
|
|
var path = DerivationPaths.AccountPath(ScriptKind.Taproot, ChainProfiles.Mainnet, 0);
|
|
|
|
|
Assert.Equal($"86'/{ChainProfiles.Mainnet.Bip44CoinType}'/0'", path.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Gli_indirizzi_plm_taproot_iniziano_con_plm1p()
|
|
|
|
|
{
|
|
|
|
|
var account = Account();
|
|
|
|
|
var addr0 = account.GetReceiveAddress(0).ToString();
|
|
|
|
|
var addr1 = account.GetReceiveAddress(1).ToString();
|
|
|
|
|
var change0 = account.GetChangeAddress(0).ToString();
|
|
|
|
|
|
|
|
|
|
Assert.StartsWith("plm1p", addr0);
|
|
|
|
|
Assert.StartsWith("plm1p", addr1);
|
|
|
|
|
Assert.StartsWith("plm1p", change0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-06-16 14:40:06 +02:00
|
|
|
/// The output key (tweaked x-only pubkey, 32 bytes) matches the BIP86 vector
|
|
|
|
|
/// regardless of network: the network changes only HRP and checksum, not the program.
|
|
|
|
|
/// Bitcoin addresses from https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
|
2026-06-15 12:03:46 +02:00
|
|
|
/// </summary>
|
|
|
|
|
[Theory]
|
|
|
|
|
[InlineData(false, 0, "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr")]
|
|
|
|
|
[InlineData(false, 1, "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh")]
|
|
|
|
|
[InlineData(true, 0, "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7")]
|
|
|
|
|
public void L_output_key_coincide_col_vettore_bip86(
|
|
|
|
|
bool isChange, int index, string bitcoinAddress)
|
|
|
|
|
{
|
|
|
|
|
var account = Account();
|
|
|
|
|
var plmAddr = account.GetAddress(isChange, index);
|
|
|
|
|
|
2026-06-16 14:40:06 +02:00
|
|
|
// The witness program (tweaked output key) is chain-independent.
|
2026-06-15 12:03:46 +02:00
|
|
|
var btcAddr = (TaprootAddress)BitcoinAddress.Create(bitcoinAddress, Network.Main);
|
|
|
|
|
var plmTaproot = (TaprootAddress)plmAddr;
|
|
|
|
|
Assert.Equal(btcAddr.PubKey, plmTaproot.PubKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Il_wallet_taproot_e_watch_only_se_creato_da_xpub()
|
|
|
|
|
{
|
|
|
|
|
var full = Account();
|
|
|
|
|
var watchOnly = HdAccount.FromAccountXpub(
|
|
|
|
|
full.AccountXpub, ScriptKind.Taproot, ChainProfiles.Mainnet);
|
|
|
|
|
Assert.True(watchOnly.IsWatchOnly);
|
|
|
|
|
Assert.Equal(
|
|
|
|
|
full.GetReceiveAddress(0).ToString(),
|
|
|
|
|
watchOnly.GetReceiveAddress(0).ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void I_tipi_multisig_lanciano_not_supported()
|
|
|
|
|
{
|
|
|
|
|
Assert.Throws<NotSupportedException>(
|
|
|
|
|
() => DerivationPaths.ScriptPubKeyTypeFor(ScriptKind.WrappedSegwitMultisig));
|
|
|
|
|
Assert.Throws<NotSupportedException>(
|
|
|
|
|
() => DerivationPaths.ScriptPubKeyTypeFor(ScriptKind.NativeSegwitMultisig));
|
|
|
|
|
}
|
|
|
|
|
}
|