diff --git a/NBitcoin.Tests/NetworkTests.cs b/NBitcoin.Tests/NetworkTests.cs old mode 100644 new mode 100755 index 391bfaf81..0c4008cc9 --- a/NBitcoin.Tests/NetworkTests.cs +++ b/NBitcoin.Tests/NetworkTests.cs @@ -81,5 +81,48 @@ public void ReadMagicByteWithFirstByteDuplicated() Assert.True(found); } } + + [Fact] + [Trait("UnitTest", "UnitTest")] + public void CanGetDefaultSignet() + { + var signet = Network.GetNetwork("signet"); + + Assert.NotNull(signet); + + var consensusFactory = new ConsensusFactory(); + var block = consensusFactory.CreateBlock(); + block.ReadWrite(DataEncoders.Encoders.Hex.DecodeData(SignetSettings.DEFAULT_SIGNET_GENESIS_BLOCK), consensusFactory); + + Assert.Equal(block.GetHash(), signet.GenesisHash); + } + + [Fact] + [Trait("UnitTest", "UnitTest")] + public void CanGetCustomSignet() + { + var customSignetName = "signet-custom"; + var customSignetChallenge = "5121033da06bd7068e9859ee902a0608df9b948829718c60c587f2e497ad4d7420e43151AE"; + var customSignetGenesisBlock = "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a008f4d5fae77031e8ad222030101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"; + var customSignetSeeds = new[] + { + "127.0.0.1", + "[::1]" + }; + + var signetSettings = new SignetSettings(customSignetName, customSignetChallenge, customSignetGenesisBlock, customSignetSeeds); + + var initSignet = Bitcoin.Instance.InitCustomSignet(signetSettings); + + Assert.NotNull(initSignet); + + var customSignet = Network.GetNetwork(customSignetName); + + var consensusFactory = new ConsensusFactory(); + var block = consensusFactory.CreateBlock(); + block.ReadWrite(DataEncoders.Encoders.Hex.DecodeData(customSignetGenesisBlock), consensusFactory); + + Assert.Equal(block.GetHash(), customSignet.GenesisHash); + } } } diff --git a/NBitcoin/Bitcoin.Signet.cs b/NBitcoin/Bitcoin.Signet.cs old mode 100644 new mode 100755 index aea1e4ba5..8adfea3ed --- a/NBitcoin/Bitcoin.Signet.cs +++ b/NBitcoin/Bitcoin.Signet.cs @@ -5,16 +5,40 @@ namespace NBitcoin { + public record struct SignetSettings(string Name, string Challenge, string GenesisBlock, string[] NetworkSeeds) + { + public const string DEFAULT_SIGNET_NAME = "signet"; + + public const string DEFAULT_SIGNET_CHALLENGE = + "512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae"; + + public const string DEFAULT_SIGNET_GENESIS_BLOCK = "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a008f4d5fae77031e8ad222030101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"; + + public static readonly string[] DEFAULT_SIGNET_NETWORK_SEEDS = new[] + { + "178.128.221.177", + "2a01:7c8:d005:390::5" + }; + + public static readonly SignetSettings Default = + new(DEFAULT_SIGNET_NAME, DEFAULT_SIGNET_CHALLENGE, DEFAULT_SIGNET_GENESIS_BLOCK, DEFAULT_SIGNET_NETWORK_SEEDS); + } + public partial class Bitcoin { - static readonly ChainName SignetName = new ChainName("Signet"); + static readonly ChainName SignetName = new ChainName(SignetSettings.DEFAULT_SIGNET_NAME); public Network Signet => _Networks[SignetName]; - private Network CreateSignet() + private Network CreateSignet( + string name = SignetSettings.DEFAULT_SIGNET_NAME, + string challenge = SignetSettings.DEFAULT_SIGNET_CHALLENGE, + string genesisBlock = SignetSettings.DEFAULT_SIGNET_GENESIS_BLOCK, + string[] networkSeeds = null) { + networkSeeds ??= SignetSettings.DEFAULT_SIGNET_NETWORK_SEEDS; NetworkBuilder builder = new NetworkBuilder(); - builder.SetChainName(SignetName); + builder.SetChainName(name == SignetSettings.DEFAULT_SIGNET_NAME ? SignetName : new ChainName(name)); builder.SetNetworkSet(this); builder.SetConsensus(new Consensus() { @@ -43,28 +67,35 @@ private Network CreateSignet() .SetBech32(Bech32Type.WITNESS_PUBKEY_ADDRESS, "tb") .SetBech32(Bech32Type.WITNESS_SCRIPT_ADDRESS, "tb") .SetBech32(Bech32Type.TAPROOT_ADDRESS, "tb") - .SetMagic(GetSignetMagic()) + .SetMagic(GetSignetMagic(challenge)) .SetPort(38333) .SetRPCPort(38332) - .SetName("signet") - .AddAlias("bitcoin-signet") - .AddAlias("btc-signet") + .SetName(name) + .SetGenesis(genesisBlock); + + if (name == SignetSettings.DEFAULT_SIGNET_NAME) + { + builder.AddAlias("bitcoin-signet"); + builder.AddAlias("btc-signet"); + } + #if !NOSOCKET - .AddSeeds(new[] - { - "178.128.221.177", - "2a01:7c8:d005:390::5" - }.Select(o => new Protocol.NetworkAddress(System.Net.IPAddress.Parse(o)))) + if (networkSeeds != null) + { + builder.AddSeeds(networkSeeds.Select(o => new Protocol.NetworkAddress(System.Net.IPAddress.Parse(o)))); + } + else if (name == SignetSettings.DEFAULT_SIGNET_NAME) + { + builder.AddSeeds(SignetSettings.DEFAULT_SIGNET_NETWORK_SEEDS.Select(o => new Protocol.NetworkAddress(System.Net.IPAddress.Parse(o)))); + } #endif - .SetGenesis( - "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a008f4d5fae77031e8ad222030101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"); var network = builder.BuildAndRegister(); #if !NOFILEIO var data = Network.GetDefaultDataFolder("bitcoin"); if (data != null) { - var signetCookie = Path.Combine(data, "signet", ".cookie"); + var signetCookie = Path.Combine(data, name, ".cookie"); RPC.RPCClient.RegisterDefaultCookiePath(network, signetCookie); } #endif @@ -72,10 +103,9 @@ private Network CreateSignet() return network; } - private static uint GetSignetMagic() + private static uint GetSignetMagic(string challengeHex) { - var challengeBytes = DataEncoders.Encoders.Hex.DecodeData( - "512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae"); + var challengeBytes = DataEncoders.Encoders.Hex.DecodeData(challengeHex); var challenge = new Script(challengeBytes); MemoryStream ms = new MemoryStream(); BitcoinStream bitcoinStream = new BitcoinStream(ms, true); @@ -84,5 +114,16 @@ private static uint GetSignetMagic() return Utils.ToUInt32(h, true); } + public Network InitCustomSignet(SignetSettings? settings = null) + { + var s = settings ?? SignetSettings.Default; + + if (_Networks.TryGetValue(new ChainName(string.IsNullOrWhiteSpace(s.Name) ? SignetSettings.DEFAULT_SIGNET_NAME : s.Name), out var network)) + return network; + + var customSignet = CreateSignet(s.Name, s.Challenge, s.GenesisBlock, s.NetworkSeeds); + _Networks.TryAdd(customSignet.ChainName, customSignet); + return customSignet; + } } }