diff --git a/src/Blockcore.sln b/src/Blockcore.sln index 19ba8cfe1..b4d12ede9 100644 --- a/src/Blockcore.sln +++ b/src/Blockcore.sln @@ -154,6 +154,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Networks.SeniorBl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Networks.RoyalSportsCity", "Networks\Blockcore.Networks.RoyalSportsCity\Blockcore.Networks.RoyalSportsCity.csproj", "{D176C98F-E2EF-49C6-B073-32F08889BD27}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blockcore.Networks.Molie", "Networks\Blockcore.Networks.Molie\Blockcore.Networks.Molie.csproj", "{876BAE76-9A83-4757-9688-84E3692134FE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -404,6 +406,10 @@ Global {D176C98F-E2EF-49C6-B073-32F08889BD27}.Debug|Any CPU.Build.0 = Debug|Any CPU {D176C98F-E2EF-49C6-B073-32F08889BD27}.Release|Any CPU.ActiveCfg = Release|Any CPU {D176C98F-E2EF-49C6-B073-32F08889BD27}.Release|Any CPU.Build.0 = Release|Any CPU + {876BAE76-9A83-4757-9688-84E3692134FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {876BAE76-9A83-4757-9688-84E3692134FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {876BAE76-9A83-4757-9688-84E3692134FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {876BAE76-9A83-4757-9688-84E3692134FE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -472,6 +478,7 @@ Global {2834DEF2-0CF7-4012-A73D-07F06256CC75} = {3B56C02B-4468-4268-B797-851562789FCC} {9C962CB5-A11B-47F1-A5D3-2AD2215CF100} = {3B56C02B-4468-4268-B797-851562789FCC} {D176C98F-E2EF-49C6-B073-32F08889BD27} = {3B56C02B-4468-4268-B797-851562789FCC} + {876BAE76-9A83-4757-9688-84E3692134FE} = {3B56C02B-4468-4268-B797-851562789FCC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6C780ABA-5872-4B83-AD3F-A5BD423AD907} diff --git a/src/Networks/Blockcore.Networks.Impleum/ImpleumSetup.cs b/src/Networks/Blockcore.Networks.Impleum/ImpleumSetup.cs index 126044505..3be1bf8ec 100644 --- a/src/Networks/Blockcore.Networks.Impleum/ImpleumSetup.cs +++ b/src/Networks/Blockcore.Networks.Impleum/ImpleumSetup.cs @@ -50,10 +50,10 @@ internal class Main public static List DNS = new List { - new DNSSeedData("seed1", "mn1.uh420058.ukrdomen.com"), - new DNSSeedData("seed2", "mn2.uh420058.ukrdomen.com"), - new DNSSeedData("seed3", "mn3.uh420058.ukrdomen.com"), - new DNSSeedData("seed4", "mn4.uh420058.ukrdomen.com"), + new DNSSeedData("seed1", "mol.molie.net"), + new DNSSeedData("seed2", "mol1.molie.net"), + new DNSSeedData("seed3", "mol2.molie.net"), + new DNSSeedData("seed4", "mol3.molie.net"), new DNSSeedData("seed5", "impleum.com"), new DNSSeedData("seed6", "seed1.impleum.com"), new DNSSeedData("seed7", "seed2.impleum.com"), @@ -69,7 +69,7 @@ internal class Main public static Dictionary Checkpoints = new Dictionary { - { 0, new CheckpointInfo(new uint256("0x000002e1a5c2361c43f5d76b7d77cd52c2866b391c59867ad79de49795ed7361"), new uint256("0x0000000000000000000000000000000000000000000000000000000000000000")) }, + { 0, new CheckpointInfo(new uint256("0x000002e1a5c2361c43f5d76b7d77cd52c2866b391c59867ad79de49795ed7361"), new uint256("0x0000000000000000000000000000000000000000000000000000000000000000")) }, { 675, new CheckpointInfo(new uint256("0x228fe79897e110963fb1c39fc87f8627b51b37151d2184178139960b9ddc902a"), new uint256("0xb6191b4b733d38c0d3a7d1bcf95009bc8b173fc9dd435165bf08cde2eef33918")) }, { 1000, new CheckpointInfo(new uint256("0x6637657c16eb9ce7b99d09f41c0e12054dc0c47fd566f69af7778770bd5107f9"), new uint256("0x00eb64d91bb3dade131e3baf57fd40120586c0b08eea1852a2268b4eb4d87787")) }, { 1500, new CheckpointInfo(new uint256("0x21215e41cfa79a83b32c34419c9ff24712d5be48e2753ea58c80422432198f93"), new uint256("0x23e3130f9b7d4101a129c03792ac565f0850a6df475ac59bae77ae4761c6dc98")) }, @@ -80,7 +80,18 @@ internal class Main { 20000, new CheckpointInfo(new uint256("0xb24fca13c138617da441b4a983e582557cda12fb778d7fae0994af01e3f3d252"), new uint256("0x35c3f5856f36fdc43ee7da31530e649966b924cf59e1fddd87d7ed7837b63073")) }, { 30000, new CheckpointInfo(new uint256("0x8e7f225cb9eed57d578a6edf98a61f4120d20f0b41032eef35b557c2ae3b1c5e"), new uint256("0xd204fc2c31a15f5e3c02a178d100d88d1c10d21087c7a321594590f471ea6e51")) }, { 50000, new CheckpointInfo(new uint256("0x6d0541ad988fb15b9b59a291f0beca1cd147dcc60e7503d4610f21aedeee4053"), new uint256("0x9fdfb977228155cb14c814e463f6280ece1961e873165dd9eadabbc523ee35fe")) }, - { 70000, new CheckpointInfo(new uint256("0x3f3d906896235395d6e203a1967875ba9408cc56d9a49b75503ef507712a7642"), new uint256("0x989fe82bec93afd796121443e62dab9a20fdb81764f5b52fceff05b05b4a781a")) } + { 70000, new CheckpointInfo(new uint256("0x3f3d906896235395d6e203a1967875ba9408cc56d9a49b75503ef507712a7642"), new uint256("0x989fe82bec93afd796121443e62dab9a20fdb81764f5b52fceff05b05b4a781a")) }, + { 100000, new CheckpointInfo(new uint256("0x17ecd5212e991836759d0968195ddc16580813ac13fb0a70b4983f589fb365ee"), new uint256("9d72ec78c445f07aec12c6996eed44363e0c31008517bc78e418ef4a6b5e5677")) }, + { 150000, new CheckpointInfo(new uint256("0x97681da29d982934108a4668bdcfd6606656e3e5a7bc84f50c64780bd8fe451c"), new uint256("0xa1663164c8ffc87da70754258fe7c8cadd982619d51257df37dc52e8b648f2ad")) }, + { 200000, new CheckpointInfo(new uint256("0xddd353e1ca10ddc0d0bb42a09e8448e7a08ad7fae954b7358e8a5ecb827a81c9"), new uint256("0xebfafd00ebedabe40401ecaae263b585146c797d33c4c7c793a4233e5c8b88fa")) }, + { 250000, new CheckpointInfo(new uint256("0x06fea4881b80be581b5876353019dc3e8429c7321c71f2a1d0791ad4d15828e4"), new uint256("0x5d0aa1166d2c83cf8dc73142cb028a26c568b91c14566f35fdfaaba678d1fd99")) }, + { 300000, new CheckpointInfo(new uint256("0x822e30a8b4ad4b6792c34ffbc397090ca59b52e2ac1cd4299f24afc2ffe38fb2"), new uint256("0x276f1f116a1c5332927a7585859fedadf7cee36099995e7a7b4ee1a19dc048b0")) }, + { 400000, new CheckpointInfo(new uint256("0x67890776bfe224a098cbf90bb0b7b7e2ffe33acd2c34158a77d462a08f21a751"), new uint256("0x582ee64a508f319c4d9208de1ceb91649cebf8a691b6d95573f1ebb1951c5e31")) }, + { 500000, new CheckpointInfo(new uint256("0x84b7e38b779365b3daa1d11007bfc4e155022a06da85e1be66885ae5b59aa9bf"), new uint256("0x9fc920ab363e4d916b4060e734de7f9be84dd4777f7b00d059848174381ff5e9")) }, + { 600000, new CheckpointInfo(new uint256("0xac64cb247ccbc3b4077c7c6489124ec8895ca33dac39ac5ab0c833657e6c9df6"), new uint256("0xe2a8cc402d5f30eaa18f4591533fc17bc0f36874bc52f011723b8f786d4d6022")) }, + { 700000, new CheckpointInfo(new uint256("0xec96224f7ea2352a158ec3af7415e37e86356951661c6d6456a998b6684c5c91"), new uint256("0xb36136b9a92fe62b8f76dd4d7df59c7ca85efd49bb8f4154f6b159926c590e7b")) }, + { 800000, new CheckpointInfo(new uint256("0x8c72571334c5ed51e9332e1ba457cff5c920d54ef9b92a36602a350ca326790d"), new uint256("0xdce78ac613c81bc1908defcd674cfe32de5186db7c0635f1789eea7a5f9a0850")) }, + { 900000, new CheckpointInfo(new uint256("0x9856449c51c92cba7a2d4ee505650b18e044e2eb8b56c300fe5700eabed9049e"), new uint256("0x89d63290966eeca6dca6144672f894bfde5b4894dd89e0f2f7cd8a94f77543de")) } }; } diff --git a/src/Networks/Blockcore.Networks.Impleum/icon.png b/src/Networks/Blockcore.Networks.Impleum/icon.png index 73ce87213..dd0331861 100644 Binary files a/src/Networks/Blockcore.Networks.Impleum/icon.png and b/src/Networks/Blockcore.Networks.Impleum/icon.png differ diff --git a/src/Networks/Blockcore.Networks.Molie/Blockcore.Networks.Molie.csproj b/src/Networks/Blockcore.Networks.Molie/Blockcore.Networks.Molie.csproj new file mode 100644 index 000000000..c17d7a117 --- /dev/null +++ b/src/Networks/Blockcore.Networks.Molie/Blockcore.Networks.Molie.csproj @@ -0,0 +1,34 @@ + + + + Blockcore + Blockcore.Networks.Molie + Blockcore.Networks.Molie + Blockcore.Networks.Molie + False + true + + + + latest + icon.png + + + + + + + + + True + + + + + + + + + + + diff --git a/src/Networks/Blockcore.Networks.Molie/Deployments/MolieBIP9Deployments.cs b/src/Networks/Blockcore.Networks.Molie/Deployments/MolieBIP9Deployments.cs new file mode 100644 index 000000000..42882ba74 --- /dev/null +++ b/src/Networks/Blockcore.Networks.Molie/Deployments/MolieBIP9Deployments.cs @@ -0,0 +1,58 @@ +using Blockcore.Base.Deployments; +using Blockcore.Consensus.ScriptInfo; +using Blockcore.Consensus.TransactionInfo; + +namespace Blockcore.Networks.Molie.Deployments +{ + /// + /// BIP9 deployments for the Blockcore sample coin network. + /// + public class MolieBIP9Deployments : BIP9DeploymentsArray + { + // The position of each deployment in the deployments array. Note that this is decoupled from the actual position of the flag bit for the deployment in the block version. + public const int CSV = 0; + public const int Segwit = 1; + public const int ColdStaking = 2; // TODO: Move this to the end of the deployments to leave room for others from Bitcoin? + + // The number of deployments. + public const int NumberOfDeployments = 3; + + /// + /// Constructs the BIP9 deployments array. + /// + public MolieBIP9Deployments() : base(NumberOfDeployments) + { + } + + /// + /// Gets the deployment flags to set when the deployment activates. + /// + /// The deployment number. + /// The deployment flags. + public override BIP9DeploymentFlags GetFlags(int deployment) + { + // The flags get combined in the caller, so it is ok to make a fresh object here. + var flags = new BIP9DeploymentFlags(); + + switch (deployment) + { + case ColdStaking: + flags.ScriptFlags = ScriptVerify.CheckColdStakeVerify; + break; + + case CSV: + // Start enforcing BIP68 (sequence locks), BIP112 (CHECKSEQUENCEVERIFY) and BIP113 (Median Time Past) using versionbits logic. + flags.ScriptFlags = ScriptVerify.CheckSequenceVerify; + flags.LockTimeFlags = Transaction.LockTimeFlags.VerifySequence | Transaction.LockTimeFlags.MedianTimePast; + break; + + case Segwit: + // Start enforcing WITNESS rules using versionbits logic. + flags.ScriptFlags = ScriptVerify.Witness; + break; + } + + return flags; + } + } +} diff --git a/src/Networks/Blockcore.Networks.Molie/MolieMain.cs b/src/Networks/Blockcore.Networks.Molie/MolieMain.cs new file mode 100644 index 000000000..1920ef136 --- /dev/null +++ b/src/Networks/Blockcore.Networks.Molie/MolieMain.cs @@ -0,0 +1,263 @@ +using System; +using System.Collections.Generic; +using Blockcore.Base.Deployments; +using Blockcore.Consensus; +using Blockcore.Consensus.BlockInfo; +using Blockcore.Consensus.ScriptInfo; +using Blockcore.Consensus.TransactionInfo; +using Blockcore.Features.Consensus.Rules.CommonRules; +using Blockcore.Features.Consensus.Rules.ProvenHeaderRules; +using Blockcore.Features.Consensus.Rules.UtxosetRules; +using Blockcore.Features.MemoryPool.Rules; +using Blockcore.Networks.Molie.Deployments; +using Blockcore.Networks.Molie.Policies; +using Blockcore.Networks.Molie.Rules; +using NBitcoin; +using NBitcoin.BouncyCastle.Math; +using NBitcoin.DataEncoders; + +namespace Blockcore.Networks.Molie +{ + public class MolieMain : Network + { + public MolieMain() + { + this.NetworkType = NetworkType.Mainnet; + this.DefaultConfigFilename = MolieSetup.ConfigFileName; // The default name used for the Molie configuration file. + + this.Name = MolieSetup.Main.Name; + this.CoinTicker = MolieSetup.Main.CoinTicker; + this.Magic = MolieSetup.Main.Magic; + this.RootFolderName = MolieSetup.Main.RootFolderName; + this.DefaultPort = MolieSetup.Main.DefaultPort; + this.DefaultRPCPort = MolieSetup.Main.DefaultRPCPort; + this.DefaultAPIPort = MolieSetup.Main.DefaultAPIPort; + + this.DefaultMaxOutboundConnections = 16; + this.DefaultMaxInboundConnections = 109; + this.MaxTipAge = 2 * 60 * 60; + this.MinTxFee = 10000; + this.MaxTxFee = Money.Coins(0.1m); + this.FallbackFee = 10000; + this.MinRelayTxFee = 10000; + this.MaxTimeOffsetSeconds = 25 * 60; + this.DefaultBanTimeSeconds = 11250; // 500 (MaxReorg) * 45 (TargetSpacing) / 2 = 3 hours, 7 minutes and 30 seconds + + var consensusFactory = new PosConsensusFactory(); + + Block genesisBlock = CreateGenesisBlock(consensusFactory, + MolieSetup.Main.GenesisTime, + MolieSetup.Main.GenesisNonce, + MolieSetup.Main.GenesisBits, + MolieSetup.Main.GenesisVersion, + MolieSetup.Main.GenesisReward, + MolieSetup.GenesisText); + + this.Genesis = genesisBlock; + + // Taken from StratisX. + var consensusOptions = new PosConsensusOptions() + { + MaxBlockBaseSize = 1_000_000, + MaxStandardVersion = 2, + MaxStandardTxWeight = 100_000, + MaxBlockSigopsCost = 20_000, + MaxStandardTxSigopsCost = 20_000 / 5, + WitnessScaleFactor = 4 + }; + + var buriedDeployments = new BuriedDeploymentsArray + { + [BuriedDeployments.BIP34] = 0, + [BuriedDeployments.BIP65] = 0, + [BuriedDeployments.BIP66] = 0 + }; + + var bip9Deployments = new MolieBIP9Deployments() + { + // Always active. + [MolieBIP9Deployments.CSV] = new BIP9DeploymentsParameters("CSV", 0, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultMainnetThreshold), + [MolieBIP9Deployments.Segwit] = new BIP9DeploymentsParameters("Segwit", 1, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultMainnetThreshold), + [MolieBIP9Deployments.ColdStaking] = new BIP9DeploymentsParameters("ColdStaking", 2, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultMainnetThreshold) + }; + + this.Consensus = new Consensus.Consensus( + consensusFactory: consensusFactory, + consensusOptions: consensusOptions, + coinType: MolieSetup.CoinType, + hashGenesisBlock: genesisBlock.GetHash(), + subsidyHalvingInterval: 210000, + majorityEnforceBlockUpgrade: 750, + majorityRejectBlockOutdated: 950, + majorityWindow: 1000, + buriedDeployments: buriedDeployments, + bip9Deployments: bip9Deployments, + bip34Hash: null, + minerConfirmationWindow: 2016, // nPowTargetTimespan / nPowTargetSpacing + maxReorgLength: 500, + defaultAssumeValid: null, + maxMoney: Money.Coins(MolieSetup.MaxSupply), + coinbaseMaturity: 50, + premineHeight: 2, + premineReward: Money.Coins(MolieSetup.PremineReward), + proofOfWorkReward: Money.Coins(MolieSetup.PoWBlockReward), + targetTimespan: TimeSpan.FromSeconds(14 * 24 * 60 * 60), // two weeks + targetSpacing: MolieSetup.TargetSpacing, + powAllowMinDifficultyBlocks: false, + posNoRetargeting: false, + powNoRetargeting: false, + powLimit: new Target(new uint256("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), + minimumChainWork: null, + isProofOfStake: true, + lastPowBlock: MolieSetup.Main.LastPowBlock, + proofOfStakeLimit: new BigInteger(uint256 + .Parse("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), + proofOfStakeLimitV2: new BigInteger(uint256 + .Parse("000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), + proofOfStakeReward: Money.Coins(MolieSetup.PoSBlockReward), + proofOfStakeTimestampMask: MolieSetup.ProofOfStakeTimestampMask + ) + { + PosEmptyCoinbase = MolieSetup.IsPoSv3(), + PosUseTimeFieldInKernalHash = MolieSetup.IsPoSv3() + }; + + + // TODO: Set your Base58Prefixes + this.Base58Prefixes = new byte[12][]; + this.Base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS] = new byte[] { (MolieSetup.Main.PubKeyAddress) }; + this.Base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS] = new byte[] { (MolieSetup.Main.ScriptAddress) }; + this.Base58Prefixes[(int)Base58Type.SECRET_KEY] = new byte[] { (MolieSetup.Main.SecretAddress) }; + + this.Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_NO_EC] = new byte[] { 0x01, 0x42 }; + this.Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_EC] = new byte[] { 0x01, 0x43 }; + this.Base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY] = new byte[] { (0x04), (0x88), (0xB2), (0x1E) }; + this.Base58Prefixes[(int)Base58Type.EXT_SECRET_KEY] = new byte[] { (0x04), (0x88), (0xAD), (0xE4) }; + this.Base58Prefixes[(int)Base58Type.PASSPHRASE_CODE] = new byte[] { 0x2C, 0xE9, 0xB3, 0xE1, 0xFF, 0x39, 0xE2 }; + this.Base58Prefixes[(int)Base58Type.CONFIRMATION_CODE] = new byte[] { 0x64, 0x3B, 0xF6, 0xA8, 0x9A }; + this.Base58Prefixes[(int)Base58Type.ASSET_ID] = new byte[] { 23 }; + + this.Bech32Encoders = new Bech32Encoder[2]; + var encoder = new Bech32Encoder(MolieSetup.Main.CoinTicker.ToLowerInvariant()); + this.Bech32Encoders[(int)Bech32Type.WITNESS_PUBKEY_ADDRESS] = encoder; + this.Bech32Encoders[(int)Bech32Type.WITNESS_SCRIPT_ADDRESS] = encoder; + + this.Checkpoints = MolieSetup.Main.Checkpoints; + this.DNSSeeds = MolieSetup.Main.DNS; + this.SeedNodes = MolieSetup.Main.Nodes; + + this.StandardScriptsRegistry = new MolieStandardScriptsRegistry(); + + // 64 below should be changed to TargetSpacingSeconds when we move that field. + Assert(this.DefaultBanTimeSeconds <= this.Consensus.MaxReorgLength * 64 / 2); + + Assert(this.Consensus.HashGenesisBlock == uint256.Parse(MolieSetup.Main.HashGenesisBlock)); + Assert(this.Genesis.Header.HashMerkleRoot == uint256.Parse(MolieSetup.Main.HashMerkleRoot)); + + RegisterRules(this.Consensus); + RegisterMempoolRules(this.Consensus); + } + + protected void RegisterRules(IConsensus consensus) + { + consensus.ConsensusRules + .Register() + .Register() + .Register() + .Register() + .Register() + .Register() + .Register(); + + consensus.ConsensusRules + .Register() + .Register() + .Register(); + + consensus.ConsensusRules + .Register() + .Register() + + // rules that are inside the method ContextualCheckBlock + .Register() + .Register() + .Register() + .Register() + + // rules that are inside the method CheckBlock + .Register() + .Register() + .Register() + .Register() + .Register(); + + consensus.ConsensusRules + .Register() + + .Register() + + // rules that require the store to be loaded (coinview) + .Register() + .Register() + .Register() // implements BIP68, MaxSigOps and BlockReward calculation + // Place the PosColdStakingRule after the PosCoinviewRule to ensure that all input scripts have been evaluated + // and that the "IsColdCoinStake" flag would have been set by the OP_CHECKCOLDSTAKEVERIFY opcode if applicable. + .Register() + .Register() + .Register(); + } + + protected void RegisterMempoolRules(IConsensus consensus) + { + consensus.MempoolRules = new List() + { + typeof(CheckConflictsMempoolRule), + typeof(CheckCoinViewMempoolRule), + typeof(CreateMempoolEntryMempoolRule), + typeof(CheckSigOpsMempoolRule), + typeof(CheckFeeMempoolRule), + typeof(CheckRateLimitMempoolRule), + typeof(CheckAncestorsMempoolRule), + typeof(CheckReplacementMempoolRule), + typeof(CheckAllInputsMempoolRule), + typeof(CheckTxOutDustRule) + }; + } + + protected static Block CreateGenesisBlock(ConsensusFactory consensusFactory, uint nTime, uint nNonce, uint nBits, int nVersion, Money genesisReward, string genesisText) + { + Transaction txNew = consensusFactory.CreateTransaction(); + txNew.Version = 1; + + if (txNew is IPosTransactionWithTime posTx) + { + posTx.Time = nTime; + } + + txNew.AddInput(new TxIn() + { + ScriptSig = new Script(Op.GetPushOp(0), new Op() + { + Code = (OpcodeType)0x1, + PushData = new[] { (byte)42 } + }, Op.GetPushOp(Encoders.ASCII.DecodeData(genesisText))) + }); + + txNew.AddOutput(new TxOut() + { + Value = genesisReward, + }); + + Block genesis = consensusFactory.CreateBlock(); + genesis.Header.BlockTime = Utils.UnixTimeToDateTime(nTime); + genesis.Header.Bits = nBits; + genesis.Header.Nonce = nNonce; + genesis.Header.Version = nVersion; + genesis.Transactions.Add(txNew); + genesis.Header.HashPrevBlock = uint256.Zero; + genesis.UpdateMerkleRoot(); + + return genesis; + } + } +} diff --git a/src/Networks/Blockcore.Networks.Molie/MolieRegTest.cs b/src/Networks/Blockcore.Networks.Molie/MolieRegTest.cs new file mode 100644 index 000000000..9a04855ef --- /dev/null +++ b/src/Networks/Blockcore.Networks.Molie/MolieRegTest.cs @@ -0,0 +1,129 @@ +using System; +using Blockcore.Base.Deployments; +using Blockcore.Consensus; +using Blockcore.Consensus.BlockInfo; +using Blockcore.Networks.Molie.Deployments; +using Blockcore.Networks.Molie.Policies; +using NBitcoin; +using NBitcoin.BouncyCastle.Math; +using NBitcoin.DataEncoders; + +namespace Blockcore.Networks.Molie +{ + public class MolieRegTest : MolieMain + { + public MolieRegTest() + { + this.NetworkType = NetworkType.Regtest; + + this.Name = MolieSetup.RegTest.Name; + this.CoinTicker = MolieSetup.RegTest.CoinTicker; + this.Magic = MolieSetup.RegTest.Magic; + this.RootFolderName = MolieSetup.RegTest.RootFolderName; + this.DefaultPort = MolieSetup.RegTest.DefaultPort; + this.DefaultRPCPort = MolieSetup.RegTest.DefaultRPCPort; + this.DefaultAPIPort = MolieSetup.RegTest.DefaultAPIPort; + + var consensusFactory = new PosConsensusFactory(); + + Block genesisBlock = CreateGenesisBlock(consensusFactory, + MolieSetup.RegTest.GenesisTime, + MolieSetup.RegTest.GenesisNonce, + MolieSetup.RegTest.GenesisBits, + MolieSetup.RegTest.GenesisVersion, + MolieSetup.RegTest.GenesisReward, + MolieSetup.GenesisText); + + this.Genesis = genesisBlock; + + // Taken from StratisX. + var consensusOptions = new PosConsensusOptions() + { + MaxBlockBaseSize = 1_000_000, + MaxStandardVersion = 2, + MaxStandardTxWeight = 100_000, + MaxBlockSigopsCost = 20_000, + MaxStandardTxSigopsCost = 20_000 / 5, + WitnessScaleFactor = 4 + }; + + var buriedDeployments = new BuriedDeploymentsArray + { + [BuriedDeployments.BIP34] = 0, + [BuriedDeployments.BIP65] = 0, + [BuriedDeployments.BIP66] = 0 + }; + + + var bip9Deployments = new MolieBIP9Deployments() + { + // Always active. + [MolieBIP9Deployments.CSV] = new BIP9DeploymentsParameters("CSV", 0, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultRegTestThreshold), + [MolieBIP9Deployments.Segwit] = new BIP9DeploymentsParameters("Segwit", 1, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultRegTestThreshold), + [MolieBIP9Deployments.ColdStaking] = new BIP9DeploymentsParameters("ColdStaking", 2, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultRegTestThreshold) + }; + + this.Consensus = new Consensus.Consensus( + consensusFactory: consensusFactory, + consensusOptions: consensusOptions, + coinType: 1, + hashGenesisBlock: genesisBlock.GetHash(), + subsidyHalvingInterval: 210000, + majorityEnforceBlockUpgrade: 750, + majorityRejectBlockOutdated: 950, + majorityWindow: 1000, + buriedDeployments: buriedDeployments, + bip9Deployments: bip9Deployments, + bip34Hash: null, + minerConfirmationWindow: 2016, // nPowTargetTimespan / nPowTargetSpacing + maxReorgLength: 500, + defaultAssumeValid: null, + maxMoney: Money.Coins(MolieSetup.MaxSupply), + coinbaseMaturity: 10, + premineHeight: 2, + premineReward: Money.Coins(MolieSetup.PremineReward), + proofOfWorkReward: Money.Coins(MolieSetup.PoWBlockReward), + targetTimespan: TimeSpan.FromSeconds(14 * 24 * 60 * 60), // two weeks + targetSpacing: MolieSetup.TargetSpacing, + powAllowMinDifficultyBlocks: true, + posNoRetargeting: true, + powNoRetargeting: true, + powLimit: new Target(new uint256("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), + minimumChainWork: null, + isProofOfStake: true, + lastPowBlock: MolieSetup.RegTest.LastPowBlock, + proofOfStakeLimit: new BigInteger(uint256.Parse("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), + proofOfStakeLimitV2: new BigInteger(uint256.Parse("000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), + proofOfStakeReward: Money.Coins(MolieSetup.PoSBlockReward), + proofOfStakeTimestampMask: MolieSetup.ProofOfStakeTimestampMask + ); + + this.Base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS] = new byte[] { (MolieSetup.RegTest.PubKeyAddress) }; + this.Base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS] = new byte[] { (MolieSetup.RegTest.ScriptAddress) }; + this.Base58Prefixes[(int)Base58Type.SECRET_KEY] = new byte[] { (MolieSetup.RegTest.SecretAddress) }; + this.Base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY] = new byte[] { (0x04), (0x35), (0x87), (0xCF) }; + this.Base58Prefixes[(int)Base58Type.EXT_SECRET_KEY] = new byte[] { (0x04), (0x35), (0x83), (0x94) }; + this.Base58Prefixes[(int)Base58Type.ASSET_ID] = new byte[] { 115 }; + + this.Bech32Encoders = new Bech32Encoder[2]; + var encoder = new Bech32Encoder(MolieSetup.RegTest.CoinTicker.ToLowerInvariant()); + this.Bech32Encoders[(int)Bech32Type.WITNESS_PUBKEY_ADDRESS] = encoder; + this.Bech32Encoders[(int)Bech32Type.WITNESS_SCRIPT_ADDRESS] = encoder; + + this.Checkpoints = MolieSetup.RegTest.Checkpoints; + this.DNSSeeds = MolieSetup.RegTest.DNS; + this.SeedNodes = MolieSetup.RegTest.Nodes; + + this.StandardScriptsRegistry = new MolieStandardScriptsRegistry(); + + // 64 below should be changed to TargetSpacingSeconds when we move that field. + Assert(this.DefaultBanTimeSeconds <= this.Consensus.MaxReorgLength * 64 / 2); + + Assert(this.Consensus.HashGenesisBlock == uint256.Parse(MolieSetup.RegTest.HashGenesisBlock)); + Assert(this.Genesis.Header.HashMerkleRoot == uint256.Parse(MolieSetup.RegTest.HashMerkleRoot)); + + RegisterRules(this.Consensus); + RegisterMempoolRules(this.Consensus); + } + } +} diff --git a/src/Networks/Blockcore.Networks.Molie/MolieSetup.cs b/src/Networks/Blockcore.Networks.Molie/MolieSetup.cs new file mode 100644 index 000000000..2f861c944 --- /dev/null +++ b/src/Networks/Blockcore.Networks.Molie/MolieSetup.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Blockcore.Consensus.Checkpoints; +using Blockcore.P2P; +using NBitcoin; +using NBitcoin.Protocol; + +namespace Blockcore.Networks.Molie +{ + public class MolieSetup + { + public const string ConfigFileName = "Molie.conf"; + + /// + /// Molie cointype. For Molie it was 769 + /// + public const int CoinType = 772; // SLIP-0044: https://github.com/satoshilabs/slips/blob/master/slip-0044.md + + public const decimal PremineReward = 1049966250; + public const decimal PoWBlockReward = 50; + public const decimal PoSBlockReward = 0; + public const long MaxSupply = 10500000000; + public const string GenesisText = "Multifunctional decentralized messenger and multi-currency wallet"; + public static TimeSpan TargetSpacing = TimeSpan.FromSeconds(45); + public const uint ProofOfStakeTimestampMask = 0x0000000F; // 0x0000003F // 64 sec + public const int PoSVersion = 4; + + internal class Main + { + public const string Name = "MolieMain"; + public const string RootFolderName = "Molie"; + public const string CoinTicker = "MOL"; + public const int DefaultPort = 22105; + public const int DefaultRPCPort = 22104; + public const int DefaultAPIPort = 22103; + public const int PubKeyAddress = 51; // X https://en.bitcoin.it/wiki/List_of_address_prefixes + public const int ScriptAddress = 141; // y or z + public const int SecretAddress = PubKeyAddress + ScriptAddress; + public static readonly uint Magic = BitConverter.ToUInt32(Encoding.ASCII.GetBytes("Molie")); //1483763017 + public const int LastPowBlock = 675; + + public const uint GenesisTime = 1619257421; // ~11 December 2020 - https://www.unixtimestamp.com/ + public const uint GenesisNonce = 222768; // Set to 1 until correct value found + public const uint GenesisBits = 0x1E0FFFFF; // The difficulty target + public const int GenesisVersion = 1; // 'Empty' BIP9 deployments as they are all activated from genesis already + public static Money GenesisReward = Money.Zero; + public const string HashGenesisBlock = "0x000002a1ad0e9fa339c1074f97f7f7de25dac50865966c6d8d8a075026373a5c"; + public const string HashMerkleRoot = "0x9f9930c2112eb4fc90d4abfa4085708d2e913c8cd638335be715e48601292bed"; + + public static List DNS = new List + { + new DNSSeedData("seed1", "mol.molie.net"), + new DNSSeedData("seed2", "mol1.molie.net"), + new DNSSeedData("seed3", "mol2.molie.net"), + new DNSSeedData("seed4", "mol3.molie.net"), + new DNSSeedData("seed5", "impleum.com"), + new DNSSeedData("seed6", "seed1.impleum.com"), + new DNSSeedData("seed7", "seed2.impleum.com"), + new DNSSeedData("seed8", "seed3.impleum.com"), + new DNSSeedData("seed9", "seed4.impleum.com") + }; + + public static List Nodes = new List + { + // new NetworkAddress(IPAddress.Parse("109.108.77.134"), DefaultPort), + // new NetworkAddress(IPAddress.Parse("62.80.181.141"), DefaultPort) + }; + + public static Dictionary Checkpoints = new Dictionary + { + { 0, new CheckpointInfo(new uint256("0x000002a1ad0e9fa339c1074f97f7f7de25dac50865966c6d8d8a075026373a5c"), new uint256("0x0000000000000000000000000000000000000000000000000000000000000000")) }, + { 10, new CheckpointInfo(new uint256("0x4d1c528735266dbf999d070b5a18f54e535f87084bbe92e8febaa5bb2db6c74b"), new uint256("0xd50af11c4d301bfec5a4b5d1f46e0a751aac640da1bbbc31ac0db1af5b585f44")) }, + { 100, new CheckpointInfo(new uint256("0xd2fe88d6e4f56a4b55a27e3fc8e0257adc4497e5ec5ccaa64075b9ff007d3eff"), new uint256("0x2c783e2d5c82e4f42c7def4451e8236cf44ef7594fa37da3f7ca65ebb66911e2")) }, + { 1000, new CheckpointInfo(new uint256("0x994bda728098cfa6b815d8cf5bd29aa3d0b1d6a4e421b9d7460b56c5e7ecb9a2"), new uint256("0x54676536898e94ec1fada28d45eb0b5ec4dfc9f7e6d8a4b999d3593ad53f5ab1")) }, + { 2000, new CheckpointInfo(new uint256("0x291652a0e4712729ea82f60dee6b0127f25d2271cf0216b924f858e30a97e291"), new uint256("0x0eb067d54218fb3f488ed67d97ee82bdc7c4641718948761bbff7e83a1217603")) }, + { 5000, new CheckpointInfo(new uint256("0xf1a228bc882042d190a674fe69b50f76da8649bfc6005b05bfcf3f12674ba724"), new uint256("0x90e53f8e32bfdfed191fbf4f3eb6b8ae0b9f797071a9cc457c9698ee7bd5d684")) }, + { 10000, new CheckpointInfo(new uint256("0xe496c00c50b0176c6695ed303d4dcb44ed78ea16221fece64cc86054c0243630"), new uint256("0x38a01ba181957490efd395169f66a2fc62ac525ca584a0f54bd239abf6e0f931")) }, + { 20000, new CheckpointInfo(new uint256("0x6db25eeb5034b2831635abe5e986f86f7dd41064c6840bd5e141c3d28c2c3396"), new uint256("0xb264ac835c1c5fee9bc4ef7712d01ca652cd0a966e363e574998b58d245ee9f8")) }, + { 30000, new CheckpointInfo(new uint256("0x73c188629decfb81a4236d2f7c581a855aa9d7aa4b44533b7311a23f35a11ef7"), new uint256("0xd6ca6c00e58d47919d4b4c06711887664be3d1a753ca1af3e6a02486a525f4ce")) }, + { 50000, new CheckpointInfo(new uint256("0xf55e286d695b6e28dc1cea55db23e2c8f4e282db4d58f3cef2a9963785d760eb"), new uint256("0xb7ca872b75e9ee41a6d1f848fd67847211d31b9b3bfefce1a829e21db30394e6")) }, + { 100000, new CheckpointInfo(new uint256("0x4cba2e2b952ecf0f3671c17d4468800005db24d117315d1cff9cefbad5e85a79"), new uint256("0x34f0dfd00940e7724a4c89773775fc039e8d37155f29ea7cd1133e3e1eb4826a")) }, + { 150000, new CheckpointInfo(new uint256("0x9da6c50706dccb8eddee2dbf8bfd401be6d991e4b65bd09bbfd8fcd9f3e14214"), new uint256("0xd110b60a280b829bd370fc5a9388345c835db61638507ba56304d9a5c59c922c")) }, + { 200000, new CheckpointInfo(new uint256("0xfc9380c469d3f09aa0638ce6f6b2344322694c0958cbb7b36e80ee0e993b68d1"), new uint256("0x66156e9f4f09d69a3cee9bed6ddbdf0deac42251fa77b82c1dac558fef668275")) }, + { 300000, new CheckpointInfo(new uint256("0x398986ca2d89f7c267253e5d814663b56962fdf94f87a26c1311ec15638d81bb"), new uint256("0x50e45783c89c58cdd7a33f4823cdc49aad266d3ac110ac68825b2eea0a833bea")) }, + { 400000, new CheckpointInfo(new uint256("0x5811caef1f89a497f55135bbc244bdfc9f50c21ca9ff906f7762e81fb5eddeee"), new uint256("0x69daf3b1547b33a5b2b19ef28274054a31fcc879148c1cc4c29857e76bfb1966")) }, + { 500000, new CheckpointInfo(new uint256("0x91132a91aa24a6c2bebf90c02acbfe58def98cbab1072e0d3aec6f6873c3d7a9"), new uint256("0x902ee692a6a9f92d9eb32632f8e58399c5a4cbb256864b346e39965ea80c4135")) } + }; + } + + + internal class Test + { + public const string Name = "MolieTest"; + public const string RootFolderName = "MolieTest"; + public const string CoinTicker = "TMOL"; + public const int DefaultPort = 32105; + public const int DefaultRPCPort = 32104; + public const int DefaultAPIPort = 32103; + public const int PubKeyAddress = 105; + public const int ScriptAddress = 129; + public const int SecretAddress = PubKeyAddress + ScriptAddress; + public static readonly uint Magic = BitConverter.ToUInt32(Encoding.ASCII.GetBytes("Molie")); + public const int LastPowBlock = 12500; + + public const uint GenesisTime = 1619257450; + public const uint GenesisNonce = 1127; + public const uint GenesisBits = 0x1F0FFFFF; + public const int GenesisVersion = 1; + public static Money GenesisReward = Money.Zero; + public const string HashGenesisBlock = "0x000e5a32f82051916e14cdb9ccc4c7146c106349a0622df5d122410934554912"; + public const string HashMerkleRoot = "0x15a4348986e906634ff05ae5cdf208d0c297b3542b86a2919cbf03c7b5bddace"; + + public static List DNS = new List + { + new DNSSeedData("seed1", "mol.molie.net"), + new DNSSeedData("seed2", "mol1.molie.net"), + new DNSSeedData("seed3", "mol2.molie.net"), + new DNSSeedData("seed4", "mol3.molie.net"), + new DNSSeedData("seed5", "impleum.com"), + new DNSSeedData("seed6", "seed1.impleum.com"), + new DNSSeedData("seed7", "seed2.impleum.com"), + new DNSSeedData("seed8", "seed3.impleum.com"), + new DNSSeedData("seed9", "seed4.impleum.com") + }; + + public static List Nodes = new List + { + //new NetworkAddress(IPAddress.Parse("109.108.77.134"), DefaultPort), + //new NetworkAddress(IPAddress.Parse("62.80.181.141"), DefaultPort), + }; + + public static Dictionary Checkpoints = new Dictionary + { + + }; + } + + internal class RegTest + { + public const string Name = "MolieRegTest"; + public const string RootFolderName = "MolieRegTest"; + public const string CoinTicker = "TMOL"; + public const int DefaultPort = 42105; + public const int DefaultRPCPort = 42104; + public const int DefaultAPIPort = 42103; + public const int PubKeyAddress = 105; + public const int ScriptAddress = 129; + public const int SecretAddress = PubKeyAddress + ScriptAddress; + public static readonly uint Magic = BitConverter.ToUInt32(Encoding.ASCII.GetBytes("Rolie")); + public const int LastPowBlock = 12500; + + public const uint GenesisTime = 1619257448; + public const uint GenesisNonce = 11588; + public const uint GenesisBits = 0x1F00FFFF; + public const int GenesisVersion = 1; + public static Money GenesisReward = Money.Zero; + public const string HashGenesisBlock = "0x000083c58f9fc90470670c6ccee600f8db5837fc38f6b0d19d3984234d2ec8e3"; + public const string HashMerkleRoot = "0x81ff297a766f945a1c4c536969900ca4fa5f3bd359d567ada6adb1accf063626"; + + public static List DNS = new List + { + new DNSSeedData("seed1", "mol.molie.net"), + new DNSSeedData("seed2", "mol1.molie.net"), + new DNSSeedData("seed3", "mol2.molie.net"), + new DNSSeedData("seed4", "mol3.molie.net"), + new DNSSeedData("seed5", "impleum.com"), + new DNSSeedData("seed6", "seed1.impleum.com"), + new DNSSeedData("seed7", "seed2.impleum.com"), + new DNSSeedData("seed8", "seed3.impleum.com"), + new DNSSeedData("seed9", "seed4.impleum.com") + }; + + public static List Nodes = new List + { + //new NetworkAddress(IPAddress.Parse("109.108.77.134"), DefaultPort), + //new NetworkAddress(IPAddress.Parse("62.80.181.141"), DefaultPort) + }; + + public static Dictionary Checkpoints = new Dictionary + { + // TODO: Add checkpoints as the network progresses. + }; + } + + public static bool IsPoSv3() => PoSVersion == 3; + + public static bool IsPoSv4() => PoSVersion == 4; + + } +} diff --git a/src/Networks/Blockcore.Networks.Molie/MolieTest.cs b/src/Networks/Blockcore.Networks.Molie/MolieTest.cs new file mode 100644 index 000000000..b4196f5a9 --- /dev/null +++ b/src/Networks/Blockcore.Networks.Molie/MolieTest.cs @@ -0,0 +1,127 @@ +using System; +using Blockcore.Base.Deployments; +using Blockcore.Consensus; +using Blockcore.Consensus.BlockInfo; +using Blockcore.Networks.Molie.Deployments; +using Blockcore.Networks.Molie.Policies; +using NBitcoin; +using NBitcoin.BouncyCastle.Math; +using NBitcoin.DataEncoders; + +namespace Blockcore.Networks.Molie +{ + public class MolieTest : MolieMain + { + public MolieTest() + { + this.NetworkType = NetworkType.Testnet; + + this.Name = MolieSetup.Test.Name; + this.CoinTicker = MolieSetup.Test.CoinTicker; + this.Magic = MolieSetup.Test.Magic; + this.RootFolderName = MolieSetup.Test.RootFolderName; + this.DefaultPort = MolieSetup.Test.DefaultPort; + this.DefaultRPCPort = MolieSetup.Test.DefaultRPCPort; + this.DefaultAPIPort = MolieSetup.Test.DefaultAPIPort; + + var consensusFactory = new PosConsensusFactory(); + + Block genesisBlock = CreateGenesisBlock(consensusFactory, + MolieSetup.Test.GenesisTime, + MolieSetup.Test.GenesisNonce, + MolieSetup.Test.GenesisBits, + MolieSetup.Test.GenesisVersion, + MolieSetup.Test.GenesisReward, + MolieSetup.GenesisText); + + this.Genesis = genesisBlock; + + // Taken from StratisX. + var consensusOptions = new PosConsensusOptions() + { + MaxBlockBaseSize = 1_000_000, + MaxStandardVersion = 2, + MaxStandardTxWeight = 100_000, + MaxBlockSigopsCost = 20_000, + MaxStandardTxSigopsCost = 20_000 / 5, + WitnessScaleFactor = 4 + }; + var buriedDeployments = new BuriedDeploymentsArray + { + [BuriedDeployments.BIP34] = 0, + [BuriedDeployments.BIP65] = 0, + [BuriedDeployments.BIP66] = 0 + }; + + var bip9Deployments = new MolieBIP9Deployments() + { + // Always active. + [MolieBIP9Deployments.CSV] = new BIP9DeploymentsParameters("CSV", 0, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultTestnetThreshold), + [MolieBIP9Deployments.Segwit] = new BIP9DeploymentsParameters("Segwit", 1, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultTestnetThreshold), + [MolieBIP9Deployments.ColdStaking] = new BIP9DeploymentsParameters("ColdStaking", 2, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultTestnetThreshold) + }; + + this.Consensus = new Consensus.Consensus( + consensusFactory: consensusFactory, + consensusOptions: consensusOptions, + coinType: 1, + hashGenesisBlock: genesisBlock.GetHash(), + subsidyHalvingInterval: 210000, + majorityEnforceBlockUpgrade: 750, + majorityRejectBlockOutdated: 950, + majorityWindow: 1000, + buriedDeployments: buriedDeployments, + bip9Deployments: bip9Deployments, + bip34Hash: null, + minerConfirmationWindow: 2016, // nPowTargetTimespan / nPowTargetSpacing + maxReorgLength: 500, + defaultAssumeValid: null, + maxMoney: Money.Coins(MolieSetup.MaxSupply), + coinbaseMaturity: 10, + premineHeight: 2, + premineReward: Money.Coins(MolieSetup.PremineReward), + proofOfWorkReward: Money.Coins(MolieSetup.PoWBlockReward), + targetTimespan: TimeSpan.FromSeconds(14 * 24 * 60 * 60), // two weeks + targetSpacing: MolieSetup.TargetSpacing, + powAllowMinDifficultyBlocks: false, + posNoRetargeting: false, + powNoRetargeting: false, + powLimit: new Target(new uint256("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), + minimumChainWork: null, + isProofOfStake: true, + lastPowBlock: MolieSetup.Test.LastPowBlock, + proofOfStakeLimit: new BigInteger(uint256.Parse("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), + proofOfStakeLimitV2: new BigInteger(uint256.Parse("000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), + proofOfStakeReward: Money.Coins(MolieSetup.PoSBlockReward), + proofOfStakeTimestampMask: MolieSetup.ProofOfStakeTimestampMask + ); + + this.Base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS] = new byte[] { (MolieSetup.Test.PubKeyAddress) }; + this.Base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS] = new byte[] { (MolieSetup.Test.ScriptAddress) }; + this.Base58Prefixes[(int)Base58Type.SECRET_KEY] = new byte[] { (MolieSetup.Test.SecretAddress) }; + this.Base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY] = new byte[] { (0x04), (0x35), (0x87), (0xCF) }; + this.Base58Prefixes[(int)Base58Type.EXT_SECRET_KEY] = new byte[] { (0x04), (0x35), (0x83), (0x94) }; + this.Base58Prefixes[(int)Base58Type.ASSET_ID] = new byte[] { 115 }; + + this.Bech32Encoders = new Bech32Encoder[2]; + var encoder = new Bech32Encoder(MolieSetup.Test.CoinTicker.ToLowerInvariant()); + this.Bech32Encoders[(int)Bech32Type.WITNESS_PUBKEY_ADDRESS] = encoder; + this.Bech32Encoders[(int)Bech32Type.WITNESS_SCRIPT_ADDRESS] = encoder; + + this.Checkpoints = MolieSetup.Test.Checkpoints; + this.DNSSeeds = MolieSetup.Test.DNS; + this.SeedNodes = MolieSetup.Test.Nodes; + + this.StandardScriptsRegistry = new MolieStandardScriptsRegistry(); + + // 64 below should be changed to TargetSpacingSeconds when we move that field. + Assert(this.DefaultBanTimeSeconds <= this.Consensus.MaxReorgLength * 64 / 2); + + Assert(this.Consensus.HashGenesisBlock == uint256.Parse(MolieSetup.Test.HashGenesisBlock)); + Assert(this.Genesis.Header.HashMerkleRoot == uint256.Parse(MolieSetup.Test.HashMerkleRoot)); + + RegisterRules(this.Consensus); + RegisterMempoolRules(this.Consensus); + } + } +} diff --git a/src/Networks/Blockcore.Networks.Molie/Networks.cs b/src/Networks/Blockcore.Networks.Molie/Networks.cs new file mode 100644 index 000000000..765eb1f7b --- /dev/null +++ b/src/Networks/Blockcore.Networks.Molie/Networks.cs @@ -0,0 +1,14 @@ +namespace Blockcore.Networks.Molie +{ + public static class Networks + { + public static NetworksSelector Molie + { + get + { + return new NetworksSelector(() => new MolieMain(), () => new MolieTest(), + () => new MolieRegTest()); + } + } + } +} diff --git a/src/Networks/Blockcore.Networks.Molie/Policies/MollieStandardScriptsRegistry.cs b/src/Networks/Blockcore.Networks.Molie/Policies/MollieStandardScriptsRegistry.cs new file mode 100644 index 000000000..8e4e294f6 --- /dev/null +++ b/src/Networks/Blockcore.Networks.Molie/Policies/MollieStandardScriptsRegistry.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Linq; +using Blockcore.Consensus.ScriptInfo; + +namespace Blockcore.Networks.Molie.Policies +{ + /// + /// Blockcore sample coin-specific standard transaction definitions. + /// + public class MolieStandardScriptsRegistry : StandardScriptsRegistry + { + // See MAX_OP_RETURN_RELAY in Bitcoin Core,