56ce1d4259
- AppPaths: data-root resolution, per-network paths, wallet file listing. - TransactionFactory: legacy/P2SH/segwit destinations, multi-UTXO selection, dust change absorbed into fee, and a golden txid for the PSBT signing path (RFC 6979 makes it deterministic; the builder's own output shuffling for privacy makes anchoring the vector at the top-level Build() unreliable). - PropertyTests: Slip132 roundtrip for every script kind and network, WalletDocument JSON roundtrip with arbitrary labels/contacts, Scripthash cross-checked against an independent SHA-256 computation. - StorageTests: regression cases for the IsEncrypted fix. - Removed CS8602/CS8604 nullable warnings from existing address/loader tests.
97 lines
4.1 KiB
C#
97 lines
4.1 KiB
C#
using NBitcoin;
|
|
using PalladiumWallet.Core.Chain;
|
|
using PalladiumWallet.Core.Crypto;
|
|
|
|
namespace PalladiumWallet.Tests.Crypto;
|
|
|
|
public class AddressDerivationTests
|
|
{
|
|
private static byte[] AbandonAboutSeed()
|
|
{
|
|
Assert.True(Bip39.TryParse(
|
|
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
|
out var mnemonic));
|
|
return Bip39.ToSeed(mnemonic!);
|
|
}
|
|
|
|
[Fact]
|
|
public void Il_vettore_bip44_produce_lo_stesso_hash_su_bitcoin_e_plm()
|
|
{
|
|
// Known abandon-about address at m/44'/0'/0'/0/0 (public reference).
|
|
var account = HdAccount.FromSeed(AbandonAboutSeed(), ScriptKind.Legacy,
|
|
ChainProfiles.Mainnet, new KeyPath("44'/0'/0'"));
|
|
var pubKey = account.GetPublicKey(isChange: false, 0)!;
|
|
|
|
var bitcoinAddr = pubKey.GetAddress(ScriptPubKeyType.Legacy, Network.Main);
|
|
Assert.Equal("1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA", bitcoinAddr.ToString());
|
|
|
|
var plmAddr = account.GetReceiveAddress(0);
|
|
Assert.StartsWith("P", plmAddr.ToString());
|
|
// Same hash160 under the two prefixes: the derivation is identical,
|
|
// only the network dress changes.
|
|
Assert.Equal(pubKey.Hash, ((BitcoinPubKeyAddress)plmAddr).Hash);
|
|
}
|
|
|
|
[Fact]
|
|
public void Il_vettore_bip49_produce_lo_stesso_script_hash_su_bitcoin_e_plm()
|
|
{
|
|
var account = HdAccount.FromSeed(AbandonAboutSeed(), ScriptKind.WrappedSegwit,
|
|
ChainProfiles.Mainnet, new KeyPath("49'/0'/0'"));
|
|
var pubKey = account.GetPublicKey(isChange: false, 0)!;
|
|
|
|
var bitcoinAddr = pubKey.GetAddress(ScriptPubKeyType.SegwitP2SH, Network.Main);
|
|
Assert.Equal("37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf", bitcoinAddr.ToString());
|
|
|
|
var plmAddr = account.GetReceiveAddress(0);
|
|
Assert.StartsWith("3", plmAddr.ToString());
|
|
Assert.Equal(((BitcoinScriptAddress)bitcoinAddr).Hash, ((BitcoinScriptAddress)plmAddr).Hash);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(ScriptKind.Legacy, NetKind.Mainnet)]
|
|
[InlineData(ScriptKind.WrappedSegwit, NetKind.Mainnet)]
|
|
[InlineData(ScriptKind.NativeSegwit, NetKind.Mainnet)]
|
|
[InlineData(ScriptKind.Legacy, NetKind.Testnet)]
|
|
[InlineData(ScriptKind.WrappedSegwit, NetKind.Testnet)]
|
|
[InlineData(ScriptKind.NativeSegwit, NetKind.Testnet)]
|
|
[InlineData(ScriptKind.NativeSegwit, NetKind.Regtest)]
|
|
public void Ogni_indirizzo_derivato_fa_roundtrip_sulla_propria_rete(ScriptKind kind, NetKind net)
|
|
{
|
|
var profile = ChainProfiles.For(net);
|
|
var account = HdAccount.FromSeed(AbandonAboutSeed(), kind, profile);
|
|
|
|
var addr = account.GetReceiveAddress(0);
|
|
var parsed = BitcoinAddress.Create(addr.ToString(), PalladiumNetworks.For(net));
|
|
|
|
Assert.Equal(addr.ScriptPubKey, parsed.ScriptPubKey);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(NetKind.Mainnet, "tplm1")]
|
|
[InlineData(NetKind.Mainnet, "rplm1")]
|
|
public void Gli_indirizzi_segwit_mainnet_non_hanno_prefissi_di_altre_reti(NetKind net, string wrongPrefix)
|
|
{
|
|
var account = HdAccount.FromSeed(AbandonAboutSeed(), ScriptKind.NativeSegwit, ChainProfiles.For(net));
|
|
Assert.DoesNotContain(wrongPrefix, account.GetReceiveAddress(0).ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public void Il_path_di_account_usa_il_coin_type_del_profilo()
|
|
{
|
|
Assert.Equal("84'/746'/0'",
|
|
DerivationPaths.AccountPath(ScriptKind.NativeSegwit, ChainProfiles.Mainnet).ToString());
|
|
Assert.Equal("84'/1'/0'",
|
|
DerivationPaths.AccountPath(ScriptKind.NativeSegwit, ChainProfiles.Testnet).ToString());
|
|
Assert.Equal("44'/746'/2'",
|
|
DerivationPaths.AccountPath(ScriptKind.Legacy, ChainProfiles.Mainnet, account: 2).ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public void Receiving_e_change_derivano_indirizzi_diversi()
|
|
{
|
|
var account = HdAccount.FromSeed(AbandonAboutSeed(), ScriptKind.NativeSegwit, ChainProfiles.Mainnet);
|
|
Assert.NotEqual(account.GetReceiveAddress(0).ToString(), account.GetChangeAddress(0).ToString());
|
|
Assert.NotEqual(account.GetReceiveAddress(0).ToString(), account.GetReceiveAddress(1).ToString());
|
|
}
|
|
}
|