From f0fc34901d9a12efd7e4b682a62a30ee68747742 Mon Sep 17 00:00:00 2001 From: SondreB Date: Thu, 8 Sep 2022 13:06:46 +0200 Subject: [PATCH 001/194] Update DNS and seed nodes for City Chain --- src/Networks/Blockcore.Networks.City/CitySetup.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Networks/Blockcore.Networks.City/CitySetup.cs b/src/Networks/Blockcore.Networks.City/CitySetup.cs index a22fa243b..f366f7ea4 100644 --- a/src/Networks/Blockcore.Networks.City/CitySetup.cs +++ b/src/Networks/Blockcore.Networks.City/CitySetup.cs @@ -45,8 +45,8 @@ internal class CitySetup GenesisReward = Money.Zero, HashGenesisBlock = "00000b0517068e602ed5279c20168cfa1e69884ee4e784909652da34c361bff2", HashMerkleRoot = "b3425d46594a954b141898c7eebe369c6e6a35d2dab393c1f495504d2147883b", - DNS = new[] { "seed.city-chain.org", "seed.citychain.foundation", "seed.city-coin.org", "seed.liberstad.com", "city.seed.blockcore.net" }, - Nodes = new[] { "23.97.234.230", "13.73.143.193", "89.10.227.34" }, + DNS = new[] { "seed.city-chain.org", "seed.city-coin.org", "seed.liberstad.com", "city.seed.blockcore.net" }, + Nodes = new[] { "95.217.210.139", "195.201.16.145", "89.10.224.54" }, Checkpoints = new Dictionary { { 0, new CheckpointInfo(new uint256("0x00000b0517068e602ed5279c20168cfa1e69884ee4e784909652da34c361bff2"), new uint256("0x0000000000000000000000000000000000000000000000000000000000000000")) }, From f928dabeb73de41da990bfabf02bbce90445799e Mon Sep 17 00:00:00 2001 From: SondreB Date: Thu, 8 Sep 2022 13:08:19 +0200 Subject: [PATCH 002/194] Add additional checkpoint for City Chain --- src/Networks/Blockcore.Networks.City/CitySetup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Networks/Blockcore.Networks.City/CitySetup.cs b/src/Networks/Blockcore.Networks.City/CitySetup.cs index f366f7ea4..9fef78a34 100644 --- a/src/Networks/Blockcore.Networks.City/CitySetup.cs +++ b/src/Networks/Blockcore.Networks.City/CitySetup.cs @@ -57,6 +57,7 @@ internal class CitySetup { 800000, new CheckpointInfo(new uint256("0xaf94ebd59507829e82d2e98e75f8777224bf54e2f4ad76ff7bdc2ebebc634cb9"), new uint256("0xbe19a177b90653ee3a654e7fd307e93410db3478dbc28225e24aea9d2087d04b")) }, { 1060000, new CheckpointInfo(new uint256("0xea17e88ff533ca71dbaf0a8772d1f680845371e774250e35251671227fdcb699"), new uint256("0xfc4d6eec52900c6623711427d11357afe6becc6aafa71ed3ade3fe3128d9f23f")) }, { 1125570, new CheckpointInfo(new uint256("0x1295cd37612f19ad8847531f84489f25fa1612a0cb91e95bff44b566a0de2cfa"), new uint256("0xa62070bd16f609f33b724e2de7bd555fcef28161a6146e6270dfcaf784b21d61")) }, + { 1764800, new CheckpointInfo(new uint256("0xbec401a33c003c5949658afa253f73369ed3b2b8c9d9b067c589befaf33ec727"), new uint256("0xf0f969a1ab26187c01fd71e9b5955d5923d6b4f7dece270c1f3d1705d330210b")) }, } }; From 885634a99c6b243ea25906ef1306c43f6b0a0411 Mon Sep 17 00:00:00 2001 From: SondreB Date: Fri, 9 Sep 2022 12:33:02 +0200 Subject: [PATCH 003/194] Define a maximum tx fee or else zero few is required --- src/Networks/Blockcore.Networks.Strax/StraxRegTest.cs | 1 + src/Networks/Blockcore.Networks.Strax/StraxTest.cs | 1 + src/Node/Blockcore.Node/Properties/launchSettings.json | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Networks/Blockcore.Networks.Strax/StraxRegTest.cs b/src/Networks/Blockcore.Networks.Strax/StraxRegTest.cs index 63e96dc46..113d02c13 100644 --- a/src/Networks/Blockcore.Networks.Strax/StraxRegTest.cs +++ b/src/Networks/Blockcore.Networks.Strax/StraxRegTest.cs @@ -32,6 +32,7 @@ public StraxRegTest() //this.DefaultSignalRPort = 37102; this.MaxTipAge = 2 * 60 * 60; this.MinTxFee = 10000; + this.MaxTxFee = Money.Coins(1).Satoshi; this.FallbackFee = 10000; this.MinRelayTxFee = 10000; this.RootFolderName = StraxNetwork.StraxRootFolderName; diff --git a/src/Networks/Blockcore.Networks.Strax/StraxTest.cs b/src/Networks/Blockcore.Networks.Strax/StraxTest.cs index dce39cbb8..cee23f13f 100644 --- a/src/Networks/Blockcore.Networks.Strax/StraxTest.cs +++ b/src/Networks/Blockcore.Networks.Strax/StraxTest.cs @@ -32,6 +32,7 @@ public StraxTest() //this.DefaultSignalRPort = 27102; this.MaxTipAge = 2 * 60 * 60; this.MinTxFee = 10000; + this.MaxTxFee = Money.Coins(1).Satoshi; this.FallbackFee = 10000; this.MinRelayTxFee = 10000; this.RootFolderName = StraxNetwork.StraxRootFolderName; diff --git a/src/Node/Blockcore.Node/Properties/launchSettings.json b/src/Node/Blockcore.Node/Properties/launchSettings.json index a790891df..f6dd751a5 100644 --- a/src/Node/Blockcore.Node/Properties/launchSettings.json +++ b/src/Node/Blockcore.Node/Properties/launchSettings.json @@ -174,7 +174,7 @@ }, "STRAX (TEST)": { "commandName": "Project", - "commandLineArgs": "--chain=STRAX -server -iprangefiltering=0 -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser -testnet" + "commandLineArgs": "--chain=STRAX -txindex=1 -server -iprangefiltering=0 -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser -testnet" }, "STRAX (MAIN/LOCAL)": { "commandName": "Project", From 229a3ed65eb4dab98d1e644a42fdfac4251c31f4 Mon Sep 17 00:00:00 2001 From: SondreB Date: Sun, 25 Sep 2022 11:31:11 +0200 Subject: [PATCH 004/194] Configure reloadOnChange to be false - This was previously done to allow reload while running, but it causes issues running under docker. - Related to #418 --- src/Features/Blockcore.Features.NodeHost/Startup.cs | 2 +- src/Node/Blockcore.Node/Properties/launchSettings.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Features/Blockcore.Features.NodeHost/Startup.cs b/src/Features/Blockcore.Features.NodeHost/Startup.cs index a4a8d5f4c..ead9aa340 100644 --- a/src/Features/Blockcore.Features.NodeHost/Startup.cs +++ b/src/Features/Blockcore.Features.NodeHost/Startup.cs @@ -34,7 +34,7 @@ public Startup(IWebHostEnvironment env, IFullNode fullNode) IConfigurationBuilder builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) - .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); diff --git a/src/Node/Blockcore.Node/Properties/launchSettings.json b/src/Node/Blockcore.Node/Properties/launchSettings.json index f6dd751a5..6c60def56 100644 --- a/src/Node/Blockcore.Node/Properties/launchSettings.json +++ b/src/Node/Blockcore.Node/Properties/launchSettings.json @@ -170,7 +170,7 @@ }, "STRAX (MAIN)": { "commandName": "Project", - "commandLineArgs": "--chain=STRAX -server -iprangefiltering=0 -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser" + "commandLineArgs": "--chain=STRAX -txindex=1 -server -iprangefiltering=0 -rpcallowip=127.0.0.1 -rpcbind=127.0.0.1 -rpcpassword=rpcpassword -rpcuser=rpcuser" }, "STRAX (TEST)": { "commandName": "Project", From 3ef32a7befaa5912cd6a7dc6d19fd1f02f6f6a56 Mon Sep 17 00:00:00 2001 From: Dan Gershony Date: Thu, 29 Sep 2022 10:44:24 +0100 Subject: [PATCH 005/194] Fix wallet to use segwit in the correct derivation path (#415) * Preparing to remove the Bech32Address field * Remove the IsSegwit flag and fixing all errors * fix build errors and enable legacy wallets to work side by side * Working coed plus UI * fix api error message * Make the wallet version an integer and backwards compatible * Fix build errors on tests * Fix incorrect script pubkey when creating an address * Fix some more wallet tests * All tests passing * use select instead of drop down * clean some comments * remove the IsSegwit flag from the rpc client * delete forgotten segwit flag * fix build --- .../Api/Controllers/ColdStakingController.cs | 4 +- .../Api/Models/ColdStakingModels.cs | 10 -- .../ColdStakingManager.cs | 25 ++--- .../UI/Pages/ColdStakeDelegate.razor | 13 +-- .../UI/Pages/ColdStakeSetup.razor | 10 +- .../UI/Pages/ColdStakeWithdraw.razor | 4 +- .../Api/Controllers/StakingController.cs | 6 +- .../Api/Models/RequestModels.cs | 2 - .../Blockcore.Features.RPC/RPCClient.cs | 9 +- .../Api/Controllers/WalletController.cs | 16 ++- .../Api/Controllers/WalletModelBuilder.cs | 2 +- .../Api/Controllers/WalletRPCController.cs | 11 +-- .../Api/Models/RequestModels.cs | 50 ++++++---- .../Api/Models/SpendableTransactionsModel.cs | 6 ++ .../Helpers/HdOperations.cs | 15 +-- .../Interfaces/IWalletManager.cs | 15 ++- .../Blockcore.Features.Wallet/Types/Wallet.cs | 99 ++++++++++++++----- .../UI/Pages/Accounts.razor | 15 +++ .../ModalViewSpendableTransactions.razor | 6 ++ .../UI/Pages/Modal/ModalWalletCreate.razor | 25 ++++- .../UI/Pages/Modal/ModalWalletRecover.razor | 26 ++++- .../UI/Pages/UTXOList.razor | 1 + .../UI/Pages/WalletReceive.razor | 16 +-- .../UI/Pages/WalletSend.razor | 1 - .../WalletManager.cs | 60 ++++++++--- .../WalletTransactionHandler.cs | 14 +-- .../ColdStakingControllerTest.cs | 45 ++++++--- .../ColdStakingManagerTest.cs | 3 + .../WalletControllerTest.cs | 24 ++--- .../WalletManagerTest.cs | 60 +++++++++-- .../WalletTransactionHandlerTest.cs | 2 + .../EnvironmentMockUpHelpers/CoreNode.cs | 24 ++++- .../API/ApiSteps.cs | 2 +- .../RPC/RPCTestsMutable.cs | 14 +-- .../Blockcore.IntegrationTests/SegWitTests.cs | 25 ++--- ...dressGenerationAndFundsVisibility_Steps.cs | 2 +- .../WalletTestsHelpers.cs | 12 ++- 37 files changed, 439 insertions(+), 235 deletions(-) diff --git a/src/Features/Blockcore.Features.ColdStaking/Api/Controllers/ColdStakingController.cs b/src/Features/Blockcore.Features.ColdStaking/Api/Controllers/ColdStakingController.cs index cb3411c01..01c8b98e0 100644 --- a/src/Features/Blockcore.Features.ColdStaking/Api/Controllers/ColdStakingController.cs +++ b/src/Features/Blockcore.Features.ColdStaking/Api/Controllers/ColdStakingController.cs @@ -148,7 +148,7 @@ public IActionResult GetColdStakingAddress([FromQuery]GetColdStakingAddressReque var model = new GetColdStakingAddressResponse { - Address = request.Segwit ? address?.Bech32Address : address?.Address + Address = address?.Address }; if (model.Address == null) @@ -213,7 +213,7 @@ private IActionResult SetupColdStakingInternal(SetupColdStakingRequest request, Transaction transaction = this.ColdStakingManager.GetColdStakingSetupTransaction( this.walletTransactionHandler, request.ColdWalletAddress, request.HotWalletAddress, - request.WalletName, request.WalletAccount, request.WalletPassword, amount, feeAmount, request.SegwitChangeAddress, request.PayToScript, createHotAccount); + request.WalletName, request.WalletAccount, request.WalletPassword, amount, feeAmount, request.PayToScript, createHotAccount); var model = new SetupColdStakingResponse { diff --git a/src/Features/Blockcore.Features.ColdStaking/Api/Models/ColdStakingModels.cs b/src/Features/Blockcore.Features.ColdStaking/Api/Models/ColdStakingModels.cs index bd705ef07..7f445a7cd 100644 --- a/src/Features/Blockcore.Features.ColdStaking/Api/Models/ColdStakingModels.cs +++ b/src/Features/Blockcore.Features.ColdStaking/Api/Models/ColdStakingModels.cs @@ -108,11 +108,6 @@ public class GetColdStakingAddressRequest [JsonProperty(PropertyName = "isColdWalletAddress")] public bool IsColdWalletAddress { get; set; } - /// - /// Whether to return the P2WPKH (segwit bech32) addresses, or a regular P2PKH address - /// - public bool Segwit { get; set; } - /// Creates a string containing the properties of this object. /// A string containing the properties of the object. public override string ToString() @@ -241,11 +236,6 @@ public class SetupColdStakingRequest [JsonProperty(PropertyName = "fees")] public string Fees { get; set; } - /// - /// Whether to send the change to a P2WPKH (segwit bech32) addresses, or a regular P2PKH address - /// - public bool SegwitChangeAddress { get; set; } - /// /// Use script outputs (P2SH and P2WSH) for cold staking /// diff --git a/src/Features/Blockcore.Features.ColdStaking/ColdStakingManager.cs b/src/Features/Blockcore.Features.ColdStaking/ColdStakingManager.cs index 000e3b11c..5ba47656e 100644 --- a/src/Features/Blockcore.Features.ColdStaking/ColdStakingManager.cs +++ b/src/Features/Blockcore.Features.ColdStaking/ColdStakingManager.cs @@ -240,7 +240,10 @@ public HdAccount GetOrCreateColdStakingAccount(string walletName, bool isColdWal accountName = HotWalletAccountName; } - account = wallet.AddNewAccount(walletPassword, this.dateTimeProvider.GetTimeOffset(), accountIndex, accountName); + HdAccount defaultAccount = wallet.GetAccount(0); + int purposeField = defaultAccount.Purpose; + + account = wallet.AddNewAccount(walletPassword, this.dateTimeProvider.GetTimeOffset(), purposeField, accountIndex, accountName); // Maintain at least one unused address at all times. This will ensure that wallet recovery will also work. IEnumerable newAddresses = account.CreateAddresses(wallet.Network, 1, false); @@ -258,9 +261,9 @@ public HdAccount GetOrCreateColdStakingAccount(string walletName, bool isColdWal /// track addresses under the HD account. /// /// - public override Wallet.Types.Wallet RecoverWallet(string password, string name, string mnemonic, DateTime creationTime, string passphrase, int? coinType = null, bool? isColdStakingWallet = false) + public override Wallet.Types.Wallet RecoverWallet(string password, string name, string mnemonic, DateTime creationTime, string passphrase, int? purpose = null, int? coinType = null, bool? isColdStakingWallet = false) { - Wallet.Types.Wallet wallet = base.RecoverWallet(password, name, mnemonic, creationTime, passphrase, coinType); + Wallet.Types.Wallet wallet = base.RecoverWallet(password, name, mnemonic, creationTime, passphrase, purpose, coinType); if (isColdStakingWallet.HasValue && isColdStakingWallet == true) { @@ -324,7 +327,6 @@ internal HdAddress GetFirstUnusedColdStakingAddress(string walletName, bool isCo /// The wallet password. /// The amount to cold stake. /// The fee to pay for the cold staking setup transaction. - /// Use a segwit style change address. /// Indicate script staking (P2SH or P2WSH outputs). /// The for setting up cold staking. /// Thrown if any of the rules listed in the remarks section of this method are broken. @@ -332,7 +334,7 @@ internal HdAddress GetFirstUnusedColdStakingAddress(string walletName, bool isCo internal Transaction GetColdStakingSetupTransaction(IWalletTransactionHandler walletTransactionHandler, string coldWalletAddress, string hotWalletAddress, string walletName, string walletAccount, - string walletPassword, Money amount, Money feeAmount, bool useSegwitChangeAddress = false, bool payToScript = false, bool createHotAccount = true) + string walletPassword, Money amount, Money feeAmount, bool payToScript = false, bool createHotAccount = true) { Guard.NotNull(walletTransactionHandler, nameof(walletTransactionHandler)); Guard.NotEmpty(coldWalletAddress, nameof(coldWalletAddress)); @@ -357,8 +359,8 @@ internal Transaction GetColdStakingSetupTransaction(IWalletTransactionHandler wa hotAccount = this.GetColdStakingAccount(this.GetWalletByName(walletName), false); } - HdAddress coldAddress = coldAccount?.ExternalAddresses.FirstOrDefault(s => s.Address == coldWalletAddress || s.Bech32Address == coldWalletAddress); - HdAddress hotAddress = hotAccount?.ExternalAddresses.FirstOrDefault(s => s.Address == hotWalletAddress || s.Bech32Address == hotWalletAddress); + HdAddress coldAddress = coldAccount?.ExternalAddresses.FirstOrDefault(s => s.Address == coldWalletAddress); + HdAddress hotAddress = hotAccount?.ExternalAddresses.FirstOrDefault(s => s.Address == hotWalletAddress); bool thisIsColdWallet = coldAddress != null; bool thisIsHotWallet = hotAddress != null; @@ -383,7 +385,7 @@ internal Transaction GetColdStakingSetupTransaction(IWalletTransactionHandler wa KeyId coldPubKeyHash = null; // Check if this is a segwit address - if (coldAddress?.Bech32Address == coldWalletAddress || hotAddress?.Bech32Address == hotWalletAddress) + if ((coldAddress != null && coldAddress.IsBip84()) || (hotAddress != null && hotAddress.IsBip84())) { hotPubKeyHash = new BitcoinWitPubKeyAddress(hotWalletAddress, wallet.Network).Hash.AsKeyId(); coldPubKeyHash = new BitcoinWitPubKeyAddress(coldWalletAddress, wallet.Network).Hash.AsKeyId(); @@ -427,7 +429,6 @@ internal Transaction GetColdStakingSetupTransaction(IWalletTransactionHandler wa TransactionFee = feeAmount, MinConfirmations = 0, Shuffle = false, - UseSegwitChangeAddress = useSegwitChangeAddress, WalletPassword = walletPassword, Recipients = new List() { new Recipient { Amount = amount, ScriptPubKey = destination } } }; @@ -500,14 +501,14 @@ internal Transaction GetColdStakingWithdrawalTransaction(IWalletTransactionHandl } // Prevent reusing cold stake addresses as regular withdrawal addresses. - if (coldAccount.ExternalAddresses.Concat(coldAccount.InternalAddresses).Any(s => s.Address == receivingAddress || s.Bech32Address == receivingAddress)) + if (coldAccount.ExternalAddresses.Concat(coldAccount.InternalAddresses).Any(s => s.Address == receivingAddress )) { this.logger.LogTrace("(-)[COLDSTAKE_INVALID_COLD_WALLET_ADDRESS_USAGE]"); throw new WalletException("You can't send the money to a cold staking cold wallet account."); } HdAccount hotAccount = this.GetColdStakingAccount(wallet, false); - if (hotAccount != null && hotAccount.ExternalAddresses.Concat(hotAccount.InternalAddresses).Any(s => s.Address == receivingAddress || s.Bech32Address == receivingAddress)) + if (hotAccount != null && hotAccount.ExternalAddresses.Concat(hotAccount.InternalAddresses).Any(s => s.Address == receivingAddress)) { this.logger.LogTrace("(-)[COLDSTAKE_INVALID_HOT_WALLET_ADDRESS_USAGE]"); throw new WalletException("You can't send the money to a cold staking hot wallet account."); @@ -531,7 +532,7 @@ internal Transaction GetColdStakingWithdrawalTransaction(IWalletTransactionHandl { AccountReference = accountReference, // Specify a dummy change address to prevent a change (internal) address from being created. - // Will be changed after the transacton is built and before it is signed. + // Will be changed after the transaction is built and before it is signed. ChangeAddress = coldAccount.ExternalAddresses.First(), TransactionFee = feeAmount, MinConfirmations = 0, diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor index a88751a3d..c0cfd5735 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeDelegate.razor @@ -159,8 +159,6 @@ private decimal Fee { get; set; } - public bool SegwitChangeAddress { get; set; } - public bool PayToScript { get; set; } protected override Task OnInitializedAsync() @@ -202,8 +200,6 @@ this.Alert = "Segwit is not activated, can't use segwit address."; return; } - - this.SegwitChangeAddress = true; } else { @@ -226,13 +222,7 @@ return; } - if (this.SegwitChangeAddress != address.IsBip84()) - { - this.Alert = "Trying to send to a segwit address from a non segwit wallet."; - return; - } - - this.ColdWalletAddress = this.SegwitChangeAddress ? address?.Bech32Address : address?.Address; + this.ColdWalletAddress = address?.Address; if (this.ColdWalletAddress == null) { this.Alert = "The cold staking account does not exist."; @@ -252,7 +242,6 @@ this.Password, new Money(this.Amount, MoneyUnit.BTC), new Money(this.Fee, MoneyUnit.BTC), - this.SegwitChangeAddress, this.PayToScript); await this.BroadcasterManager.BroadcastTransactionAsync(transaction); diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor index 4a4e348dc..f685b746f 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeSetup.razor @@ -179,8 +179,6 @@ private decimal Fee { get; set; } - public bool SegwitChangeAddress { get; set; } - public bool PayToScript { get; set; } protected override Task OnInitializedAsync() @@ -191,10 +189,7 @@ var address = this.ColdStakingManager.GetFirstUnusedColdStakingAddress(this.walletname, true); - // this.SegwitChangeAddress = this.NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.Witness); - this.SegwitChangeAddress = address.IsBip84(); - - this.ColdWalletAddress = this.SegwitChangeAddress ? address?.Bech32Address : address?.Address; + this.ColdWalletAddress = address?.Address; if (this.ColdWalletAddress == null) { @@ -209,7 +204,7 @@ { var address = this.ColdStakingManager.GetFirstUnusedColdStakingAddress(hotWalletName, false); - this.HotWalletAddress = this.SegwitChangeAddress ? address?.Bech32Address : address?.Address; + this.HotWalletAddress = address?.Address; if (this.HotWalletAddress == null) { @@ -261,7 +256,6 @@ this.Password, new Money(this.Amount, MoneyUnit.BTC), new Money(this.Fee, MoneyUnit.BTC), - this.SegwitChangeAddress, this.PayToScript); await this.BroadcasterManager.BroadcastTransactionAsync(transaction); diff --git a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor index ce24301b2..5163b00cf 100644 --- a/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor +++ b/src/Features/Blockcore.Features.ColdStaking/UI/Pages/ColdStakeWithdraw.razor @@ -180,9 +180,7 @@ { var result = this.WalletManager.GetUnusedAddress(new Wallet.Types.WalletAccountReference(this.walletname, "account 0")); - var segwit = this.NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.Witness); - - this.Address = segwit ? result.Bech32Address : result.Address; + this.Address = result.Address; } public void MaxAmount() { diff --git a/src/Features/Blockcore.Features.Miner/Api/Controllers/StakingController.cs b/src/Features/Blockcore.Features.Miner/Api/Controllers/StakingController.cs index 62b46f890..fc38ff0b2 100644 --- a/src/Features/Blockcore.Features.Miner/Api/Controllers/StakingController.cs +++ b/src/Features/Blockcore.Features.Miner/Api/Controllers/StakingController.cs @@ -206,7 +206,7 @@ public IActionResult StakingExpiry([FromBody] StakingExpiryRequest request) { foreach (HdAddress address in account.GetCombinedAddresses()) { - if ((address.Address == request.Address) || address.Bech32Address == request.Address) + if ((address.Address == request.Address)) { address.StakingExpiry = request.StakingExpiry; } @@ -272,7 +272,7 @@ public IActionResult GetStakingNotExpired([FromBody] StakingNotExpiredRequest re { addressItem = new GetStakingAddressesModelItem { - Addresses = request.Segwit ? address.Bech32Address : address.Address, + Addresses = address.Address, Expiry = address.StakingExpiry, Expired = address.StakingExpiry < DateTime.UtcNow, }; @@ -288,7 +288,7 @@ public IActionResult GetStakingNotExpired([FromBody] StakingNotExpiredRequest re { addressItem = new GetStakingAddressesModelItem { - Addresses = request.Segwit ? address.Bech32Address : address.Address, + Addresses = address.Address, Expiry = address.StakingExpiry, Expired = address.StakingExpiry < DateTime.UtcNow, }; diff --git a/src/Features/Blockcore.Features.Miner/Api/Models/RequestModels.cs b/src/Features/Blockcore.Features.Miner/Api/Models/RequestModels.cs index 71da1a627..d82223af9 100644 --- a/src/Features/Blockcore.Features.Miner/Api/Models/RequestModels.cs +++ b/src/Features/Blockcore.Features.Miner/Api/Models/RequestModels.cs @@ -92,7 +92,5 @@ public class StakingNotExpiredRequest : RequestModel /// [Required(ErrorMessage = "Name of wallet.")] public string WalletName { get; set; } - - public bool Segwit { get; set; } } } diff --git a/src/Features/Blockcore.Features.RPC/RPCClient.cs b/src/Features/Blockcore.Features.RPC/RPCClient.cs index dd1922ed3..f92b112df 100644 --- a/src/Features/Blockcore.Features.RPC/RPCClient.cs +++ b/src/Features/Blockcore.Features.RPC/RPCClient.cs @@ -1403,11 +1403,11 @@ public async Task EstimatePriorityAsync(int nblock) /// A locally-stored (not broadcast) comment assigned to this transaction. Default is no comment /// A locally-stored (not broadcast) comment assigned to this transaction. Meant to be used for describing who the payment was sent to. Default is no comment /// The TXID of the sent transaction - public uint256 SendToAddress(BitcoinAddress address, Money amount, string commentTx = null, string commentDest = null, decimal? fee = null, bool isSegwit = false) + public uint256 SendToAddress(BitcoinAddress address, Money amount, string commentTx = null, string commentDest = null, decimal? fee = null) { uint256 txid = null; - txid = SendToAddressAsync(address, amount, commentTx, commentDest, fee, isSegwit).GetAwaiter().GetResult(); + txid = SendToAddressAsync(address, amount, commentTx, commentDest, fee).GetAwaiter().GetResult(); return txid; } @@ -1419,7 +1419,7 @@ public uint256 SendToAddress(BitcoinAddress address, Money amount, string commen /// A locally-stored (not broadcast) comment assigned to this transaction. Default is no comment /// A locally-stored (not broadcast) comment assigned to this transaction. Meant to be used for describing who the payment was sent to. Default is no comment /// The TXID of the sent transaction - public async Task SendToAddressAsync(BitcoinAddress address, Money amount, string commentTx = null, string commentDest = null, decimal? fee = null, bool isSegwit = false) + public async Task SendToAddressAsync(BitcoinAddress address, Money amount, string commentTx = null, string commentDest = null, decimal? fee = null) { var parameters = new List(); parameters.Add(address.ToString()); @@ -1434,9 +1434,6 @@ public async Task SendToAddressAsync(BitcoinAddress address, Money amou if (fee != null) parameters.Add(fee.ToString()); - if (isSegwit) - parameters.Add(isSegwit.ToString()); - RPCResponse resp = await SendCommandAsync(RPCOperations.sendtoaddress, parameters.ToArray()).ConfigureAwait(false); return uint256.Parse(resp.Result.ToString()); } diff --git a/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletController.cs b/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletController.cs index a1f22b765..b5c3d830c 100644 --- a/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletController.cs +++ b/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletController.cs @@ -128,7 +128,7 @@ public IActionResult Create([FromBody] WalletCreationRequest request) { Mnemonic requestMnemonic = string.IsNullOrEmpty(request.Mnemonic) ? null : new Mnemonic(request.Mnemonic); - Mnemonic mnemonic = this.walletManager.CreateWallet(request.Password, request.Name, request.Passphrase, mnemonic: requestMnemonic); + Mnemonic mnemonic = this.walletManager.CreateWallet(request.Password, request.Name, request.Passphrase, mnemonic: requestMnemonic, purpose: request.Purpose); // start syncing the wallet from the creation date this.walletSyncManager.SyncFromDate(this.dateTimeProvider.GetUtcNow()); @@ -264,7 +264,7 @@ public IActionResult Recover([FromBody] WalletRecoveryRequest request) try { - Types.Wallet wallet = this.walletManager.RecoverWallet(request.Password, request.Name, request.Mnemonic, request.CreationDate, passphrase: request.Passphrase, request.CoinType, request.IsColdStakingWallet); + Types.Wallet wallet = this.walletManager.RecoverWallet(request.Password, request.Name, request.Mnemonic, request.CreationDate, passphrase: request.Passphrase, purpose: request.Purpose, request.CoinType, request.IsColdStakingWallet); this.SyncFromBestHeightForRecoveredWallets(request.CreationDate); @@ -314,8 +314,7 @@ public IActionResult RecoverViaExtPubKey([FromBody] WalletExtPubRecoveryRequest ? request.ExtPubKey : LegacyExtPubKeyConverter.ConvertIfInLegacyStratisFormat(request.ExtPubKey, this.network); - this.walletManager.RecoverWallet(request.Name, ExtPubKey.Parse(accountExtPubKey), request.AccountIndex, - request.CreationDate); + this.walletManager.RecoverWallet(request.Name, ExtPubKey.Parse(accountExtPubKey), request.AccountIndex, request.CreationDate, request.Purpose); this.SyncFromBestHeightForRecoveredWallets(request.CreationDate); @@ -751,7 +750,6 @@ public IActionResult BuildTransaction([FromBody] BuildTransactionRequest request AllowOtherInputs = false, Recipients = recipients, ChangeAddress = changeAddress, - UseSegwitChangeAddress = request.SegwitChangeAddress }; if (!string.IsNullOrEmpty(request.FeeType)) @@ -952,7 +950,7 @@ public IActionResult CreateNewAccount([FromBody] GetUnusedAccountModel request) try { - HdAccount result = this.walletManager.GetUnusedAccount(request.WalletName, request.Password); + HdAccount result = this.walletManager.GetUnusedAccount(request.WalletName, request.Password, request.Purpose); return this.Json(result.Name); } catch (CannotAddAccountToXpubKeyWalletException e) @@ -1018,7 +1016,7 @@ public IActionResult GetUnusedAddress([FromQuery] GetUnusedAddressModel request) try { HdAddress result = this.walletManager.GetUnusedAddress(new WalletAccountReference(request.WalletName, request.AccountName)); - return this.Json(request.Segwit ? result.Bech32Address : result.Address); + return this.Json(result.Address); } catch (Exception e) { @@ -1051,7 +1049,7 @@ public IActionResult GetUnusedAddresses([FromQuery] GetUnusedAddressesModel requ try { IEnumerable result = this.walletManager.GetUnusedAddresses(new WalletAccountReference(request.WalletName, request.AccountName), count); - return this.Json(result.Select(x => request.Segwit ? x.Bech32Address : x.Address).ToArray()); + return this.Json(result.Select(x => x.Address).ToArray()); } catch (Exception e) { @@ -1093,7 +1091,7 @@ public IActionResult GetAllAddresses([FromQuery] GetAllAddressesModel request) return new AddressModel { - Address = request.Segwit ? address.Bech32Address : address.Address, + Address = address.Address, IsUsed = anyTrx, IsChange = address.IsChangeAddress(), AmountConfirmed = confirmedAmount, diff --git a/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletModelBuilder.cs b/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletModelBuilder.cs index 4a7a02095..9c71a5860 100644 --- a/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletModelBuilder.cs +++ b/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletModelBuilder.cs @@ -172,7 +172,7 @@ public static WalletHistoryModel GetHistory(IWalletManager walletManager, Networ if (!string.IsNullOrEmpty(request.Address)) { - query = query.Where(x => x.Address.Address == request.Address || x.Address.Bech32Address == request.Address); + query = query.Where(x => x.Address.Address == request.Address); } // Sorting the history items by descending dates. That includes received and sent dates. diff --git a/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletRPCController.cs b/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletRPCController.cs index 10480c54c..63392d76c 100644 --- a/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletRPCController.cs +++ b/src/Features/Blockcore.Features.Wallet/Api/Controllers/WalletRPCController.cs @@ -125,7 +125,7 @@ public bool LockWallet() [ActionName("sendtoaddress")] [ActionDescription("Sends money to an address. Requires wallet to be unlocked using walletpassphrase.")] - public async Task SendToAddressAsync(BitcoinAddress address, decimal amount, string commentTx, string commentDest, decimal? fee = null, bool isSegwit = false) + public async Task SendToAddressAsync(BitcoinAddress address, decimal amount, string commentTx, string commentDest, decimal? fee = null) { decimal transactionFee = fee ?? Money.Satoshis(this.FullNode.Network.MinTxFee).ToDecimal(MoneyUnit.BTC); @@ -135,7 +135,6 @@ public async Task SendToAddressAsync(BitcoinAddress address, decimal am Recipients = new[] { new Recipient { Amount = Money.Coins(amount), ScriptPubKey = address.ScriptPubKey } }.ToList(), CacheSecret = false, TransactionFee = Money.Coins(transactionFee), - UseSegwitChangeAddress = isSegwit }; try @@ -223,9 +222,7 @@ public NewAddressModel GetNewAddress(string account = "", string addressType = " HdAddress hdAddress = this.walletManager.GetUnusedAddresses(accountReference, 1, alwaysnew: true).Single(); - string address = hdAddress.Address; // legacy address - if (addressType != null && addressType.Equals("bech32", StringComparison.InvariantCultureIgnoreCase)) - address = hdAddress.Bech32Address; + string address = hdAddress.Address; return new NewAddressModel(address); } @@ -252,9 +249,7 @@ public NewAddressModel GetUnusedAddress(string account, string addressType) } HdAddress hdAddress = this.walletManager.GetUnusedAddress(this.GetWalletAccountReference()); - string address = hdAddress.Address; // legacy address - if (addressType != null && addressType.Equals("bech32", StringComparison.InvariantCultureIgnoreCase)) - address = hdAddress.Bech32Address; + string address = hdAddress.Address; return new NewAddressModel(address); } diff --git a/src/Features/Blockcore.Features.Wallet/Api/Models/RequestModels.cs b/src/Features/Blockcore.Features.Wallet/Api/Models/RequestModels.cs index 384c1be31..2c8f0d284 100644 --- a/src/Features/Blockcore.Features.Wallet/Api/Models/RequestModels.cs +++ b/src/Features/Blockcore.Features.Wallet/Api/Models/RequestModels.cs @@ -64,6 +64,12 @@ public class WalletCreationRequest : RequestModel /// [Required(ErrorMessage = "The name of the wallet to create is missing.")] public string Name { get; set; } + + /// + /// Optional BIP44 Purpose field, this can be either 44 or 48 (default to 44). + /// + [EnumDataType(typeof(BIP44Purpose),ErrorMessage = "The Purpose must be 44 (legacy) or 84 (segwit)")] + public int? Purpose { get; set; } } /// @@ -125,12 +131,24 @@ public class WalletRecoveryRequest : RequestModel /// public int? CoinType { get; set; } + /// + /// Optional BIP44 Purpose field, this can be either 44 or 48 (default to 44). + /// + [EnumDataType(typeof(BIP44Purpose), ErrorMessage = "The Purpose must be 44 (legacy) or 84 (segwit)")] + public int? Purpose { get; set; } + /// /// Optional flag that indicates if the "coldStakingColdAddresses" and "coldStakingHotAddresses" accounts should be restored. /// public bool? IsColdStakingWallet { get; set; } } + public enum BIP44Purpose + { + Bip44 = 44, + Bip84 = 84, + } + /// /// A class containing the necessary parameters for a wallet recovery request using its extended public key. /// Note that the recovered wallet will not have a private key and is @@ -163,6 +181,12 @@ public class WalletExtPubRecoveryRequest : RequestModel /// [JsonConverter(typeof(IsoDateTimeConverter))] public DateTime CreationDate { get; set; } + + /// + /// Optional BIP44 Purpose field, this can be either 44 or 48 (default to 44). + /// + [EnumDataType(typeof(BIP44Purpose), ErrorMessage = "The Purpose must be 44 (legacy) or 84 (segwit)")] + public int? Purpose { get; set; } } /// @@ -422,11 +446,6 @@ public class BuildTransactionRequest : TxFeeEstimateRequest, IValidatableObject [Required(ErrorMessage = "A password is required.")] public string Password { get; set; } - /// - /// Whether to send the change to a P2WPKH (segwit bech32) addresses, or a regular P2PKH address - /// - public bool SegwitChangeAddress { get; set; } - /// public IEnumerable Validate(ValidationContext validationContext) { @@ -575,11 +594,6 @@ public GetUnusedAddressModel() /// The name of the account for which to get the address. /// public string AccountName { get; set; } - - /// - /// Whether to return the P2WPKH (segwit bech32) addresses, or a regular P2PKH address - /// - public bool Segwit { get; set; } } /// @@ -608,11 +622,6 @@ public GetUnusedAddressesModel() /// [Required] public string Count { get; set; } - - /// - /// Whether to return the P2WPKH (segwit bech32) addresses, or a regular P2PKH address - /// - public bool Segwit { get; set; } } /// @@ -635,11 +644,6 @@ public GetAllAddressesModel() /// The name of the account for which to get the addresses. /// public string AccountName { get; set; } - - /// - /// Whether to return the P2WPKH (segwit bech32) addresses, or a regular P2PKH address - /// - public bool Segwit { get; set; } } /// @@ -714,6 +718,12 @@ public class GetUnusedAccountModel : RequestModel /// [Required] public string Password { get; set; } + + /// + /// Optional BIP44 Purpose field, this can be either 44 or 48 (default to 44). + /// + [EnumDataType(typeof(BIP44Purpose), ErrorMessage = "The Purpose must be 44 (legacy) or 84 (segwit)")] + public int? Purpose { get; set; } } /// diff --git a/src/Features/Blockcore.Features.Wallet/Api/Models/SpendableTransactionsModel.cs b/src/Features/Blockcore.Features.Wallet/Api/Models/SpendableTransactionsModel.cs index 478b69f7c..3b83544b6 100644 --- a/src/Features/Blockcore.Features.Wallet/Api/Models/SpendableTransactionsModel.cs +++ b/src/Features/Blockcore.Features.Wallet/Api/Models/SpendableTransactionsModel.cs @@ -38,6 +38,12 @@ public class SpendableTransactionModel [JsonProperty(PropertyName = "address")] public string Address { get; set; } + /// + /// The script. + /// + [JsonProperty(PropertyName = "script")] + public string Script { get; set; } + /// /// A value indicating whether this address is a change address. /// diff --git a/src/Features/Blockcore.Features.Wallet/Helpers/HdOperations.cs b/src/Features/Blockcore.Features.Wallet/Helpers/HdOperations.cs index a2732e86d..09af96217 100644 --- a/src/Features/Blockcore.Features.Wallet/Helpers/HdOperations.cs +++ b/src/Features/Blockcore.Features.Wallet/Helpers/HdOperations.cs @@ -57,15 +57,16 @@ public static ISecret GetExtendedPrivateKey(Key privateKey, byte[] chainCode, st /// /// The private key from which to generate the extended public key. /// The chain code used in creating the extended public key. + /// Purpose of the coin this account is in. /// Type of the coin of the account for which to generate an extended public key. /// Index of the account for which to generate an extended public key. /// The extended public key for an account, used to derive child keys. - public static ExtPubKey GetExtendedPublicKey(Key privateKey, byte[] chainCode, int coinType, int accountIndex) + public static ExtPubKey GetExtendedPublicKey(Key privateKey, byte[] chainCode, int purpose, int coinType, int accountIndex) { Guard.NotNull(privateKey, nameof(privateKey)); Guard.NotNull(chainCode, nameof(chainCode)); - string accountHdPath = GetAccountHdPath(coinType, accountIndex); + string accountHdPath = GetAccountHdPath(purpose, coinType, accountIndex); return GetExtendedPublicKey(privateKey, chainCode, accountHdPath); } @@ -92,12 +93,13 @@ public static ExtPubKey GetExtendedPublicKey(Key privateKey, byte[] chainCode, s /// /// Gets the HD path of an account. /// + /// Purpose of the coin this account is in. /// Type of the coin this account is in. /// Index of the account. /// The HD path of an account. - public static string GetAccountHdPath(int coinType, int accountIndex) + public static string GetAccountHdPath(int purpose, int coinType, int accountIndex) { - return $"m/44'/{coinType}'/{accountIndex}'"; + return $"m/{purpose}'/{coinType}'/{accountIndex}'"; } /// @@ -131,16 +133,17 @@ public static ExtKey GetExtendedKey(Mnemonic mnemonic, string passphrase = null) /// /// Creates an address' HD path, according to BIP 44. /// + /// Purpose of the coin this account is in. /// Type of coin in the HD path. /// Index of the account in the HD path. /// A value indicating whether the HD path to generate corresponds to a change address. /// Index of the address in the HD path. /// The HD path. /// Refer to for the format of the HD path. - public static string CreateHdPath(int coinType, int accountIndex, bool isChange, int addressIndex) + public static string CreateHdPath(int purpose, int coinType, int accountIndex, bool isChange, int addressIndex) { int change = isChange ? 1 : 0; - return $"m/44'/{coinType}'/{accountIndex}'/{change}/{addressIndex}"; + return $"m/{purpose}'/{coinType}'/{accountIndex}'/{change}/{addressIndex}"; } /// diff --git a/src/Features/Blockcore.Features.Wallet/Interfaces/IWalletManager.cs b/src/Features/Blockcore.Features.Wallet/Interfaces/IWalletManager.cs index f1a37e1fe..c55c9eb9b 100644 --- a/src/Features/Blockcore.Features.Wallet/Interfaces/IWalletManager.cs +++ b/src/Features/Blockcore.Features.Wallet/Interfaces/IWalletManager.cs @@ -82,8 +82,9 @@ public interface IWalletManager /// The passphrase used in the seed. /// The user's mnemonic for the wallet. /// Allow to override the default BIP44 cointype. + /// An optional BIP44 purpose (also used in BIP84 and BIP49), this means specifying BIP84 to create a segwit wallet. /// A mnemonic defining the wallet's seed used to generate addresses. - Mnemonic CreateWallet(string password, string name, string passphrase = null, Mnemonic mnemonic = null, int? coinType = null); + Mnemonic CreateWallet(string password, string name, string passphrase = null, Mnemonic mnemonic = null, int? coinType = null, int? purpose = null); /// @@ -146,9 +147,10 @@ public interface IWalletManager /// The user's mnemonic for the wallet. /// The passphrase used in the seed. /// The date and time this wallet was created. + /// An optional BIP44 purpose (also used in BIP84 and BIP49), this means specifying BIP84 to create a segwit wallet. /// Allow to override the default BIP44 cointype. /// The recovered wallet. - Types.Wallet RecoverWallet(string password, string name, string mnemonic, DateTime creationTime, string passphrase = null, int? coinType = null, bool? isColdStakingWallet = false); + Types.Wallet RecoverWallet(string password, string name, string mnemonic, DateTime creationTime, string passphrase = null, int? purpose = null, int? coinType = null, bool? isColdStakingWallet = false); /// /// Recovers a wallet using extended public key and account index. @@ -157,8 +159,9 @@ public interface IWalletManager /// The extended public key. /// The account number. /// The date and time this wallet was created. + /// An optional BIP44 purpose (also used in BIP84 and BIP49), this means specifying BIP84 to create a segwit wallet. /// - Types.Wallet RecoverWallet(string name, ExtPubKey extPubKey, int accountIndex, DateTime creationTime); + Types.Wallet RecoverWallet(string name, ExtPubKey extPubKey, int accountIndex, DateTime creationTime, int? purpose = null); /// /// Deletes a wallet. @@ -170,24 +173,26 @@ public interface IWalletManager /// /// The name of the wallet from which to get an account. /// The password used to decrypt the private key. + /// An optional BIP44 purpose (also used in BIP84 and BIP49), this means specifying BIP84 to create a segwit wallet. /// /// According to BIP44, an account at index (i) can only be created when the account /// at index (i - 1) contains transactions. /// /// An unused account. - HdAccount GetUnusedAccount(string walletName, string password); + HdAccount GetUnusedAccount(string walletName, string password, int? purpose = null); /// /// Gets an account that contains no transactions. /// /// The wallet from which to get an account. /// The password used to decrypt the private key. + /// An optional BIP44 purpose (also used in BIP84 and BIP49), this means specifying BIP84 to create a segwit wallet. /// /// According to BIP44, an account at index (i) can only be created when the account /// at index (i - 1) contains transactions. /// /// An unused account. - HdAccount GetUnusedAccount(Types.Wallet wallet, string password); + HdAccount GetUnusedAccount(Types.Wallet wallet, string password, int? purpose = null); /// /// Gets an address that contains no transaction. diff --git a/src/Features/Blockcore.Features.Wallet/Types/Wallet.cs b/src/Features/Blockcore.Features.Wallet/Types/Wallet.cs index 850611490..8872a62fa 100644 --- a/src/Features/Blockcore.Features.Wallet/Types/Wallet.cs +++ b/src/Features/Blockcore.Features.Wallet/Types/Wallet.cs @@ -43,6 +43,12 @@ public Wallet() [JsonIgnore] public IWalletStore walletStore { get; set; } + /// + /// The wallet version. + /// + [JsonProperty(PropertyName = "version")] + public int Version { get; set; } + /// /// The name of this wallet. /// @@ -115,6 +121,16 @@ public HdAccount GetAccount(string accountName) return this.AccountsRoot.SingleOrDefault()?.GetAccountByName(accountName); } + /// + /// Gets an account from the wallet's accounts. + /// + /// The index of the account to retrieve. + /// The requested account or null if the account does not exist. + public HdAccount GetAccount(int index) + { + return this.AccountsRoot.SingleOrDefault()?.GetAccountByIndex(index); + } + /// /// Update the last block synced height and hash in the wallet. /// @@ -221,15 +237,16 @@ public IEnumerable GetAllAddresses(Func accountFilte /// /// The password used to decrypt the wallet's . /// Creation time of the account to be created. + /// A BIP44 purpose (also used in BIP84 and BIP49), this will allow to overwrite the default BIP44 purpose. /// The index at which an account will be created. If left null, a new account will be created after the last used one. /// The name of the account to be created. If left null, an account will be created according to the . /// A new HD account. - public HdAccount AddNewAccount(string password, DateTimeOffset accountCreationTime, int? accountIndex = null, string accountName = null) + public HdAccount AddNewAccount(string password, DateTimeOffset accountCreationTime, int purpose, int? accountIndex = null, string accountName = null) { Guard.NotEmpty(password, nameof(password)); AccountRoot accountRoot = this.AccountsRoot.Single(); - return accountRoot.AddNewAccount(password, this.EncryptedSeed, this.ChainCode, this.Network, accountCreationTime, accountIndex, accountName); + return accountRoot.AddNewAccount(password, this.EncryptedSeed, this.ChainCode, this.Network, accountCreationTime, purpose, accountIndex, accountName); } /// @@ -243,11 +260,12 @@ public HdAccount AddNewAccount(string password, DateTimeOffset accountCreationTi /// The extended public key for the wallet. /// Zero-based index of the account to add. /// Creation time of the account to be created. + /// A BIP44 purpose (also used in BIP84 and BIP49), this will allow to overwrite the default BIP44 purpose. /// A new HD account. - public HdAccount AddNewAccount(ExtPubKey extPubKey, int accountIndex, DateTimeOffset accountCreationTime) + public HdAccount AddNewAccount(ExtPubKey extPubKey, int accountIndex, DateTimeOffset accountCreationTime, int purpose) { AccountRoot accountRoot = this.AccountsRoot.Single(); - return accountRoot.AddNewAccount(extPubKey, accountIndex, this.Network, accountCreationTime); + return accountRoot.AddNewAccount(extPubKey, accountIndex, this.Network, accountCreationTime, purpose); } /// @@ -383,7 +401,7 @@ public Money GetSentTransactionFee(uint256 transactionId) public HdAddress GetAddress(string address, Func accountFilter = null) { Guard.NotNull(address, nameof(address)); - return this.GetAllAddresses(accountFilter).SingleOrDefault(a => a.Address == address || a.Bech32Address == address); + return this.GetAllAddresses(accountFilter).SingleOrDefault(a => a.Address == address); } } @@ -461,6 +479,16 @@ public HdAccount GetAccountByName(string accountName) return this.Accounts?.SingleOrDefault(a => a.Name == accountName); } + /// + /// Gets the account matching the index passed as a parameter. + /// + /// The index of the account to get. + /// The HD account specified by the parameter or null if the account does not exist. + public HdAccount GetAccountByIndex(int index) + { + return this.Accounts?.SingleOrDefault(a => a.Index == index); + } + /// /// Adds an account to the current account root using encrypted seed and password. /// @@ -474,8 +502,9 @@ public HdAccount GetAccountByName(string accountName) /// Creation time of the account to be created. /// The index at which an account will be created. If left null, a new account will be created after the last used one. /// The name of the account to be created. If left null, an account will be created according to the . + /// A BIP44 purpose (also used in BIP84 and BIP49), this will allow to overwrite the default BIP44 purpose. /// A new HD account. - public HdAccount AddNewAccount(string password, string encryptedSeed, byte[] chainCode, Network network, DateTimeOffset accountCreationTime, int? accountIndex = null, string accountName = null) + public HdAccount AddNewAccount(string password, string encryptedSeed, byte[] chainCode, Network network, DateTimeOffset accountCreationTime, int purpose, int? accountIndex = null, string accountName = null) { Guard.NotEmpty(password, nameof(password)); Guard.NotEmpty(encryptedSeed, nameof(encryptedSeed)); @@ -502,7 +531,7 @@ public HdAccount AddNewAccount(string password, string encryptedSeed, byte[] cha } } - HdAccount newAccount = this.CreateAccount(password, encryptedSeed, chainCode, network, accountCreationTime, accountIndex.Value, accountName); + HdAccount newAccount = this.CreateAccount(password, encryptedSeed, chainCode, network, accountCreationTime, purpose, accountIndex.Value, accountName); hdAccounts.Add(newAccount); this.Accounts = hdAccounts; @@ -520,9 +549,10 @@ public HdAccount AddNewAccount(string password, string encryptedSeed, byte[] cha /// Creation time of the account to be created. /// The optional account index to use. /// The optional account name to use. + /// A BIP44 purpose (also used in BIP84 and BIP49), this will allow to overwrite the default BIP44 purpose. /// A new HD account. public HdAccount CreateAccount(string password, string encryptedSeed, byte[] chainCode, - Network network, DateTimeOffset accountCreationTime, + Network network, DateTimeOffset accountCreationTime, int purpose, int newAccountIndex, string newAccountName = null) { if (string.IsNullOrEmpty(newAccountName)) @@ -531,7 +561,7 @@ public HdAccount CreateAccount(string password, string encryptedSeed, byte[] cha } // Get the extended pub key used to generate addresses for this account. - string accountHdPath = HdOperations.GetAccountHdPath((int)this.CoinType, newAccountIndex); + string accountHdPath = HdOperations.GetAccountHdPath(purpose, this.CoinType, newAccountIndex); Key privateKey = HdOperations.DecryptSeed(encryptedSeed, password, network); ExtPubKey accountExtPubKey = HdOperations.GetExtendedPublicKey(privateKey, chainCode, accountHdPath); @@ -543,6 +573,7 @@ public HdAccount CreateAccount(string password, string encryptedSeed, byte[] cha InternalAddresses = new List(), Name = newAccountName, HdPath = accountHdPath, + Purpose = purpose, CreationTime = accountCreationTime }; } @@ -553,7 +584,8 @@ public HdAccount CreateAccount(string password, string encryptedSeed, byte[] cha /// /// The extended public key for the account. /// The zero-based account index. - public HdAccount AddNewAccount(ExtPubKey accountExtPubKey, int accountIndex, Network network, DateTimeOffset accountCreationTime) + /// A BIP44 purpose (also used in BIP84 and BIP49), this will allow to overwrite the default BIP44 purpose. + public HdAccount AddNewAccount(ExtPubKey accountExtPubKey, int accountIndex, Network network, DateTimeOffset accountCreationTime, int purpose) { ICollection hdAccounts = this.Accounts.ToList(); @@ -568,7 +600,7 @@ public HdAccount AddNewAccount(ExtPubKey accountExtPubKey, int accountIndex, Net accountExtPubKey.ToString(network)); } - string accountHdPath = HdOperations.GetAccountHdPath((int)this.CoinType, accountIndex); + string accountHdPath = HdOperations.GetAccountHdPath(purpose, this.CoinType, accountIndex); var newAccount = new HdAccount { @@ -578,6 +610,7 @@ public HdAccount AddNewAccount(ExtPubKey accountExtPubKey, int accountIndex, Net InternalAddresses = new List(), Name = $"account {accountIndex}", HdPath = accountHdPath, + Purpose = purpose, CreationTime = accountCreationTime }; @@ -609,6 +642,12 @@ public HdAccount() [JsonProperty(PropertyName = "index")] public int Index { get; set; } + /// + /// The purpose of the coin as described in BIP44. + /// + [JsonProperty(PropertyName = "purpose")] + public int Purpose { get; set; } + /// /// The name of this account. /// @@ -783,21 +822,35 @@ public IEnumerable CreateAddresses(Network network, int addressesQuan // Retrieve the pubkey associated with the private key of this address index. PubKey pubkey = HdOperations.GeneratePublicKey(this.ExtendedPubKey, i, isChange); - // Generate the P2PKH address corresponding to the pubkey. - BitcoinPubKeyAddress address = pubkey.GetAddress(network); - BitcoinWitPubKeyAddress witAddress = pubkey.GetSegwitAddress(network); - // Add the new address details to the list of addresses. var newAddress = new HdAddress { Index = i, - HdPath = HdOperations.CreateHdPath((int)this.GetCoinType(), this.Index, isChange, i), - ScriptPubKey = address.ScriptPubKey, - Pubkey = pubkey.ScriptPubKey, - Bech32Address = witAddress.ToString(), - Address = address.ToString(), + HdPath = HdOperations.CreateHdPath(this.Purpose, this.GetCoinType(), this.Index, isChange, i), + Pubkey = pubkey.ScriptPubKey, // this is a P2PK script type }; + if (newAddress.IsBip44()) + { + // Generate the P2PKH address corresponding to the pubkey. + BitcoinPubKeyAddress address = pubkey.GetAddress(network); + newAddress.ScriptPubKey = address.ScriptPubKey; + newAddress.Address = address.ToString(); + } + else if (newAddress.IsBip84()) + { + // Generate the PW2PKH address corresponding to the pubkey. + BitcoinWitPubKeyAddress witAddress = pubkey.GetSegwitAddress(network); + newAddress.ScriptPubKey = witAddress.ScriptPubKey; + newAddress.Address = witAddress.ToString(); + } + + // TODO: should we check this and throw or just skip if no derivation path is found (in that case we default to only P2PK) + if (newAddress.Address == null) + { + throw new WalletException("Unknown derivation path"); + } + addresses.Add(newAddress); addressesCreated.Add(newAddress); } @@ -915,12 +968,6 @@ public HdAddress() [JsonConverter(typeof(ScriptJsonConverter))] public Script Pubkey { get; set; } - /// - /// The base32 representation of a segwit (P2WPH) address. - /// - [JsonProperty(PropertyName = "bech32Address")] - public string Bech32Address { get; set; } - /// /// The Base58 representation of this address. /// diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Accounts.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Accounts.razor index 3e8b71dda..8a1e7acfe 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Accounts.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Accounts.razor @@ -120,6 +120,7 @@ Account Name + Format CONFIRMED BALANCE UNCONFIRMED BALANCE DETAILS @@ -134,6 +135,7 @@ + @ParseAccount(_account) @accountBalance.AmountConfirmed @accountBalance.AmountUnconfirmed @@ -175,7 +177,20 @@ { NavigationManager.NavigateTo("walletrecover"); } + private string ParseAccount(Blockcore.Features.Wallet.Types.HdAccount account) + { + if (account.Purpose == 44) + { + return "legacy"; + } + if (account.Purpose == 84) + { + return "segwit"; + } + + return "unknown"; + } private Dictionary ReadCurrentWallets() { var walletBalances = new Dictionary(); diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Modal/ModalViewSpendableTransactions.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Modal/ModalViewSpendableTransactions.razor index 03f175a70..f50002950 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Modal/ModalViewSpendableTransactions.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Modal/ModalViewSpendableTransactions.razor @@ -30,6 +30,12 @@
+ +
+ +
@*
diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/Modal/ModalWalletCreate.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/Modal/ModalWalletCreate.razor index 20ea5f1a7..95e33a805 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/Modal/ModalWalletCreate.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/Modal/ModalWalletCreate.razor @@ -42,6 +42,22 @@
+
+
+ +
+ +
+ +
+ +
+ +
+
- @if (NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.Witness)) - { -
Address:
-
- } - else - { -
Address:
-
- } +
Address:
+
@@ -60,9 +52,7 @@ return new AddressModel { - Address = (bool)(NodeDeployments.GetFlags().ScriptFlags.HasFlag(ScriptVerify.Witness)) ? address.Bech32Address : address.Address, - // Address = request.Segwit ? address.Bech32Address : address.Address, - // Address = address.Address, + Address = address.Address, IsUsed = anyTrx, IsChange = address.IsChangeAddress(), AmountConfirmed = confirmedAmount, diff --git a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor index 138dc04ff..00d119227 100644 --- a/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor +++ b/src/Features/Blockcore.Features.Wallet/UI/Pages/WalletSend.razor @@ -337,7 +337,6 @@ Shuffle = true, // We shuffle transaction outputs by default as it's better for anonymity. WalletPassword = Password, Recipients = recipients, - UseSegwitChangeAddress = recipients[0].ScriptPubKey.IsScriptType(ScriptType.Witness), TransactionFee = new Money(this.Fee, MoneyUnit.BTC) }; diff --git a/src/Features/Blockcore.Features.Wallet/WalletManager.cs b/src/Features/Blockcore.Features.Wallet/WalletManager.cs index 2992c3876..53a11c670 100644 --- a/src/Features/Blockcore.Features.Wallet/WalletManager.cs +++ b/src/Features/Blockcore.Features.Wallet/WalletManager.cs @@ -78,6 +78,9 @@ public class WalletManager : IWalletManager /// The type of coin used in this manager. protected readonly int coinType; + /// The purpose field as defined in BIP44, we default the value is regular derivation. + protected readonly int defaultPurpose = 44; + /// Specification of the network the node runs on - regtest/testnet/mainnet. protected readonly Network network; @@ -235,6 +238,7 @@ public void Start() foreach (Types.Wallet wallet in wallets) { this.Load(wallet); + foreach (HdAccount account in wallet.GetAccounts()) { this.AddAddressesToMaintainBuffer(wallet, account, false); @@ -290,7 +294,7 @@ public void Stop() } /// - public Mnemonic CreateWallet(string password, string name, string passphrase, Mnemonic mnemonic = null, int? coinType = null) + public Mnemonic CreateWallet(string password, string name, string passphrase, Mnemonic mnemonic = null, int? coinType = null, int? purpose = null) { Guard.NotEmpty(password, nameof(password)); Guard.NotEmpty(name, nameof(name)); @@ -309,7 +313,7 @@ public Mnemonic CreateWallet(string password, string name, string passphrase, Mn // Generate multiple accounts and addresses from the get-go. for (int i = 0; i < WalletCreationAccountsCount; i++) { - HdAccount account = wallet.AddNewAccount(password, this.dateTimeProvider.GetTimeOffset()); + HdAccount account = wallet.AddNewAccount(password, this.dateTimeProvider.GetTimeOffset(), purpose ?? this.defaultPurpose); IEnumerable newReceivingAddresses = account.CreateAddresses(this.network, this.walletSettings.UnusedAddressesBuffer); IEnumerable newChangeAddresses = account.CreateAddresses(this.network, this.walletSettings.UnusedAddressesBuffer, true); this.UpdateKeysLookup(wallet, newReceivingAddresses.Concat(newChangeAddresses)); @@ -461,7 +465,7 @@ private SecureString CacheSecret(string name, string walletPassword, TimeSpan du } /// - public virtual Types.Wallet RecoverWallet(string password, string name, string mnemonic, DateTime creationTime, string passphrase, int? coinType = null, bool? isColdStakingWallet = false) + public virtual Types.Wallet RecoverWallet(string password, string name, string mnemonic, DateTime creationTime, string passphrase, int? purpose = null, int? coinType = null, bool? isColdStakingWallet = false) { Guard.NotEmpty(password, nameof(password)); Guard.NotEmpty(name, nameof(name)); @@ -495,7 +499,7 @@ public virtual Types.Wallet RecoverWallet(string password, string name, string m HdAccount account; lock (this.lockObject) { - account = wallet.AddNewAccount(password, this.dateTimeProvider.GetTimeOffset()); + account = wallet.AddNewAccount(password, this.dateTimeProvider.GetTimeOffset(), purpose ?? this.defaultPurpose); } IEnumerable newReceivingAddresses = account.CreateAddresses(this.network, this.walletSettings.UnusedAddressesBuffer); @@ -523,7 +527,7 @@ public virtual Types.Wallet RecoverWallet(string password, string name, string m } /// - public Types.Wallet RecoverWallet(string name, ExtPubKey extPubKey, int accountIndex, DateTime creationTime) + public Types.Wallet RecoverWallet(string name, ExtPubKey extPubKey, int accountIndex, DateTime creationTime, int? purpose = null) { Guard.NotEmpty(name, nameof(name)); Guard.NotNull(extPubKey, nameof(extPubKey)); @@ -536,7 +540,7 @@ public Types.Wallet RecoverWallet(string name, ExtPubKey extPubKey, int accountI HdAccount account; lock (this.lockObject) { - account = wallet.AddNewAccount(extPubKey, accountIndex, this.dateTimeProvider.GetTimeOffset()); + account = wallet.AddNewAccount(extPubKey, accountIndex, this.dateTimeProvider.GetTimeOffset(), purpose ?? this.defaultPurpose); } IEnumerable newReceivingAddresses = account.CreateAddresses(this.network, this.walletSettings.UnusedAddressesBuffer); @@ -563,7 +567,7 @@ public Types.Wallet RecoverWallet(string name, ExtPubKey extPubKey, int accountI } /// - public HdAccount GetUnusedAccount(string walletName, string password) + public HdAccount GetUnusedAccount(string walletName, string password, int? purpose = null) { Guard.NotEmpty(walletName, nameof(walletName)); Guard.NotEmpty(password, nameof(password)); @@ -576,12 +580,12 @@ public HdAccount GetUnusedAccount(string walletName, string password) throw new CannotAddAccountToXpubKeyWalletException("Use recover-via-extpubkey instead."); } - HdAccount res = this.GetUnusedAccount(wallet, password); + HdAccount res = this.GetUnusedAccount(wallet, password, purpose ?? this.defaultPurpose); return res; } /// - public HdAccount GetUnusedAccount(Types.Wallet wallet, string password) + public HdAccount GetUnusedAccount(Types.Wallet wallet, string password, int? purpose = null) { Guard.NotNull(wallet, nameof(wallet)); Guard.NotEmpty(password, nameof(password)); @@ -599,7 +603,7 @@ public HdAccount GetUnusedAccount(Types.Wallet wallet, string password) } // No unused account was found, create a new one. - account = wallet.AddNewAccount(password, this.dateTimeProvider.GetTimeOffset()); + account = wallet.AddNewAccount(password, this.dateTimeProvider.GetTimeOffset(), purpose ?? this.defaultPurpose); IEnumerable newReceivingAddresses = account.CreateAddresses(this.network, this.walletSettings.UnusedAddressesBuffer); IEnumerable newChangeAddresses = account.CreateAddresses(this.network, this.walletSettings.UnusedAddressesBuffer, true); this.UpdateKeysLookup(wallet, newReceivingAddresses.Concat(newChangeAddresses)); @@ -887,7 +891,7 @@ public AddressBalance GetAddressBalance(string address) foreach (Types.Wallet wallet in this.Wallets) { - hdAddress = wallet.GetAllAddresses().FirstOrDefault(a => a.Address == address || a.Bech32Address == address); + hdAddress = wallet.GetAllAddresses().FirstOrDefault(a => a.Address == address); if (hdAddress == null) continue; // When this query to get balance on specific address, we will exclude the cold staking UTXOs. @@ -1613,6 +1617,7 @@ private Types.Wallet GenerateWalletFile(string name, string encryptedSeed, byte[ var walletFile = new Types.Wallet { + Version = 2, Name = name, EncryptedSeed = encryptedSeed, ChainCode = chainCode, @@ -1650,6 +1655,7 @@ private Types.Wallet GenerateExtPubKeyOnlyWalletFile(string name, DateTimeOffset var walletFile = new Types.Wallet { + Version = 2, Name = name, IsExtPubKeyWallet = true, CreationTime = creationTime ?? this.dateTimeProvider.GetTimeOffset(), @@ -1688,6 +1694,14 @@ internal void Load(Types.Wallet wallet) wallet.AccountsRoot.Single().LastBlockSyncedHash = wallet.walletStore.GetData().WalletTip.Hash; wallet.AccountsRoot.Single().LastBlockSyncedHeight = wallet.walletStore.GetData().WalletTip.Height; + if (wallet.Version < 2) + { + foreach (HdAccount hdAccount in wallet.GetAccounts()) + { + hdAccount.Purpose = 44; + } + } + this.Wallets.Add(wallet); } @@ -1742,16 +1756,30 @@ protected virtual void AddAddressToIndex(Types.Wallet wallet, HdAddress address) walletIndex = this.walletIndex[wallet.Name]; } - // Track the P2PKH of this pubic key - walletIndex.ScriptToAddressLookup[address.ScriptPubKey] = address; - // Track the P2PK of this public key if (address.Pubkey != null) walletIndex.ScriptToAddressLookup[address.Pubkey] = address; + // TODO: the address.ScriptPubKey should already reflect the bip44 or bip84 script so perhaps this test is not needed + + // Track the P2PKH of this pubic key + if (address.IsBip44()) + { + walletIndex.ScriptToAddressLookup[address.ScriptPubKey] = address; + + if (wallet.Version < 2 && address.Pubkey != null) + { + var pubkey = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(address.Pubkey); + BitcoinWitPubKeyAddress witAddress = pubkey.GetSegwitAddress(this.network); + walletIndex.ScriptToAddressLookup[witAddress.ScriptPubKey] = address; + } + } + // Track the P2WPKH of this pubic key - if (address.Bech32Address != null) - walletIndex.ScriptToAddressLookup[new BitcoinWitPubKeyAddress(address.Bech32Address, this.network).ScriptPubKey] = address; + if (address.IsBip84()) + { + walletIndex.ScriptToAddressLookup[address.ScriptPubKey] = address; + } } /// diff --git a/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs b/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs index dfde49fec..8df2471d4 100644 --- a/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs +++ b/src/Features/Blockcore.Features.Wallet/WalletTransactionHandler.cs @@ -281,14 +281,7 @@ protected void FindChangeAddress(TransactionBuildContext context) context.ChangeAddress = this.walletManager.GetUnusedChangeAddress(new WalletAccountReference(context.AccountReference.WalletName, context.AccountReference.AccountName)); } - if (context.UseSegwitChangeAddress) - { - context.TransactionBuilder.SetChange(new BitcoinWitPubKeyAddress(context.ChangeAddress.Bech32Address, this.network).ScriptPubKey); - } - else - { - context.TransactionBuilder.SetChange(context.ChangeAddress.ScriptPubKey); - } + context.TransactionBuilder.SetChange(context.ChangeAddress.ScriptPubKey); } /// @@ -570,10 +563,5 @@ public TransactionBuildContext(Network network) /// The timestamp to set on the transaction. /// public uint? Time { get; set; } - - /// - /// Whether to send the change to a P2WPKH (segwit bech32) addresses, or a regular P2PKH address - /// - public bool UseSegwitChangeAddress { get; set; } } } \ No newline at end of file diff --git a/src/Tests/Blockcore.Features.ColdStaking.Tests/ColdStakingControllerTest.cs b/src/Tests/Blockcore.Features.ColdStaking.Tests/ColdStakingControllerTest.cs index 2318e8996..4536eb10a 100644 --- a/src/Tests/Blockcore.Features.ColdStaking.Tests/ColdStakingControllerTest.cs +++ b/src/Tests/Blockcore.Features.ColdStaking.Tests/ColdStakingControllerTest.cs @@ -29,6 +29,7 @@ using Blockcore.Features.Wallet.Exceptions; using Blockcore.Features.Wallet.Interfaces; using Blockcore.Features.Wallet.Types; +using Blockcore.Networks; using Blockcore.Networks.Stratis.Deployments; using Blockcore.Networks.Stratis.Policies; using Blockcore.Signals; @@ -61,10 +62,10 @@ public class ColdStakingControllerTest : TestBase private const string hotWalletAddress1 = "SaVUwmJSvRiofghrePxrBQGoke1pLfmfXN"; private const string coldWalletAddress2 = "Sagbh9LuzNAV7y2FHyUQJcgmjcuogSssef"; private const string hotWalletAddress2 = "SVoMim67CMF1St6j6toAWnnQ2mCvb8V4mT"; - private const string coldWalletSegwitAddress1 = "strat1qp79yqxx44gza9mzmwjk25cxmyg6wdee4hnf7c9"; - private const string hotWalletSegwitAddress1 = "strat1qjrzc9ju366mdwa7rrjy36j2rlm2wmtp63vre6g"; - private const string coldWalletSegwitAddress2 = "strat1qjt0ms2wnrnh7dgrnru6r9h4yzkt2y7xedlgcp9"; - private const string hotWalletSegwitAddress2 = "strat1qt489d0ct9snhutaam7dmttrtf4f3hfk23xmn0s"; + private const string coldWalletSegwitAddress1 = "strat1qcspg2d96hl2e2xz8925jlzj4vwtuhrakyw0vam"; // "strat1qp79yqxx44gza9mzmwjk25cxmyg6wdee4hnf7c9"; + private const string hotWalletSegwitAddress1 = "strat1qf3s8ezwl6hwvwalevltuvzsgmgc2uzvcy9kgmf"; //"strat1qjrzc9ju366mdwa7rrjy36j2rlm2wmtp63vre6g"; + private const string coldWalletSegwitAddress2 = "strat1qymk6rq8cw2c5afeugd9wxq5g0zgw2y57q02nkq"; // "strat1qjt0ms2wnrnh7dgrnru6r9h4yzkt2y7xedlgcp9"; + private const string hotWalletSegwitAddress2 = "strat1qyegz7ed6asrsa7ycxac6xh7q6np4kfl3zffws8"; // "strat1qt489d0ct9snhutaam7dmttrtf4f3hfk23xmn0s"; private ColdStakingManager coldStakingManager; private ColdStakingController coldStakingController; @@ -147,6 +148,20 @@ private void MockCoinView() }); } + private class NodeDeploymentsWitnessMock : NodeDeployments + { + public NodeDeploymentsWitnessMock(Network network, ChainIndexer chainIndexer) : base(network, chainIndexer) + { + } + + public override DeploymentFlags GetFlags(ChainedHeader block) + { + var flags = base.GetFlags(block); + flags.ScriptFlags |= ScriptVerify.Witness; + return flags; + } + } + /// /// Create the MempoolManager used for testing whether transactions are accepted to the memory pool. /// @@ -157,7 +172,8 @@ private void CreateMempoolManager() this.txMemPool = new TxMempool(this.dateTimeProvider, new BlockPolicyEstimator( new MempoolSettings(this.nodeSettings), this.loggerFactory, this.nodeSettings), this.loggerFactory, this.nodeSettings); this.chainIndexer = new ChainIndexer(this.Network); - this.nodeDeployments = new NodeDeployments(this.Network, this.chainIndexer); + + this.nodeDeployments = new NodeDeploymentsWitnessMock(this.Network, this.chainIndexer); this.MockCoinView(); this.MockStakeChain(); @@ -563,7 +579,7 @@ public void SetupColdStakingWithHotWalletSegwitSucceeds() this.Initialize(); this.CreateMempoolManager(); - this.coldStakingManager.CreateWallet(walletPassword, walletName1, walletPassphrase, new Mnemonic(walletMnemonic1)); + this.coldStakingManager.CreateWallet(walletPassword, walletName1, walletPassphrase, new Mnemonic(walletMnemonic1), purpose: 84); Wallet.Types.Wallet wallet1 = this.coldStakingManager.GetWalletByName(walletName1); @@ -588,9 +604,9 @@ public void SetupColdStakingWithHotWalletSegwitSucceeds() Assert.Equal((uint)0, transaction.Inputs[0].PrevOut.N); Assert.Equal(2, transaction.Outputs.Count); Assert.Equal(Money.Coins(0.99m), transaction.Outputs[0].Value); - Assert.Equal("OP_DUP OP_HASH160 970e19fc2f6565b0b1c65fd88ef1512cb3da4d7b OP_EQUALVERIFY OP_CHECKSIG", transaction.Outputs[0].ScriptPubKey.ToString()); + Assert.Equal("0 124486fdd0c9f1dec0467c43596c5d59b4a869c6", transaction.Outputs[0].ScriptPubKey.ToString()); Assert.Equal(Money.Coins(100), transaction.Outputs[1].Value); - Assert.Equal("OP_DUP OP_HASH160 OP_ROT OP_IF OP_CHECKCOLDSTAKEVERIFY 90c582cb91d6b6d777c31c891d4943fed4edac3a OP_ELSE 92dfb829d31cefe6a0731f3432dea41596a278d9 OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG", transaction.Outputs[1].ScriptPubKey.ToString()); + Assert.Equal("OP_DUP OP_HASH160 OP_ROT OP_IF OP_CHECKCOLDSTAKEVERIFY 4c607c89dfd5dcc777f967d7c60a08da30ae0998 OP_ELSE 26eda180f872b14ea73c434ae302887890e5129e OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG", transaction.Outputs[1].ScriptPubKey.ToString()); Assert.False(transaction.IsCoinBase || transaction.IsCoinStake || transaction.IsColdCoinStake); // Record the spendable outputs. @@ -714,7 +730,7 @@ public void SetupColdStakingWithColdWalletSegwitSucceeds() this.Initialize(); this.CreateMempoolManager(); - this.coldStakingManager.CreateWallet(walletPassword, walletName2, walletPassphrase, new Mnemonic(walletMnemonic2)); + this.coldStakingManager.CreateWallet(walletPassword, walletName2, walletPassphrase, new Mnemonic(walletMnemonic2), purpose: 84); Wallet.Types.Wallet wallet2 = this.coldStakingManager.GetWalletByName(walletName2); @@ -740,9 +756,9 @@ public void SetupColdStakingWithColdWalletSegwitSucceeds() Assert.Equal((uint)0, transaction.Inputs[0].PrevOut.N); Assert.Equal(2, transaction.Outputs.Count); Assert.Equal(Money.Coins(0.99m), transaction.Outputs[0].Value); - Assert.Equal("OP_DUP OP_HASH160 3d36028dc0fd3d3e433c801d9ebfff05ea663816 OP_EQUALVERIFY OP_CHECKSIG", transaction.Outputs[0].ScriptPubKey.ToString()); + Assert.Equal("0 302fe798130e5bcec50fe69f2de4b6085305e50e", transaction.Outputs[0].ScriptPubKey.ToString()); Assert.Equal(Money.Coins(100), transaction.Outputs[1].Value); - Assert.Equal("OP_DUP OP_HASH160 OP_ROT OP_IF OP_CHECKCOLDSTAKEVERIFY 90c582cb91d6b6d777c31c891d4943fed4edac3a OP_ELSE 92dfb829d31cefe6a0731f3432dea41596a278d9 OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG", transaction.Outputs[1].ScriptPubKey.ToString()); + Assert.Equal("OP_DUP OP_HASH160 OP_ROT OP_IF OP_CHECKCOLDSTAKEVERIFY 4c607c89dfd5dcc777f967d7c60a08da30ae0998 OP_ELSE 26eda180f872b14ea73c434ae302887890e5129e OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG", transaction.Outputs[1].ScriptPubKey.ToString()); Assert.False(transaction.IsCoinBase || transaction.IsCoinStake || transaction.IsColdCoinStake); // Record the spendable outputs. @@ -759,7 +775,7 @@ public void SetupScriptColdStakingWithColdWalletSegwitSucceeds() this.Initialize(); this.CreateMempoolManager(); - this.coldStakingManager.CreateWallet(walletPassword, walletName2, walletPassphrase, new Mnemonic(walletMnemonic2)); + this.coldStakingManager.CreateWallet(walletPassword, walletName2, walletPassphrase, new Mnemonic(walletMnemonic2), purpose: 84); Wallet.Types.Wallet wallet2 = this.coldStakingManager.GetWalletByName(walletName2); @@ -785,10 +801,11 @@ public void SetupScriptColdStakingWithColdWalletSegwitSucceeds() Assert.Equal(prevTran.GetHash(), transaction.Inputs[0].PrevOut.Hash); Assert.Equal((uint)0, transaction.Inputs[0].PrevOut.N); Assert.Equal(3, transaction.Outputs.Count); + Assert.True(transaction.Outputs[2].ScriptPubKey.IsUnspendable); Assert.Equal(Money.Coins(0.99m), transaction.Outputs[0].Value); - Assert.Equal("OP_DUP OP_HASH160 3d36028dc0fd3d3e433c801d9ebfff05ea663816 OP_EQUALVERIFY OP_CHECKSIG", transaction.Outputs[0].ScriptPubKey.ToString()); + Assert.Equal("0 302fe798130e5bcec50fe69f2de4b6085305e50e", transaction.Outputs[0].ScriptPubKey.ToString()); Assert.Equal(Money.Coins(100), transaction.Outputs[1].Value); - Assert.Equal("0 344874146cfe398540d00bf978e747781f29a77ff586049ad23d2fe6df4f458b", transaction.Outputs[1].ScriptPubKey.ToString()); + Assert.Equal("0 01c4750fa7241ffe09e42a4d0225c08ae4748cf6e2c7d7bd1d6bb15d01f0610f", transaction.Outputs[1].ScriptPubKey.ToString()); Assert.False(transaction.IsCoinBase || transaction.IsCoinStake || transaction.IsColdCoinStake); // Record the spendable outputs. diff --git a/src/Tests/Blockcore.Features.ColdStaking.Tests/ColdStakingManagerTest.cs b/src/Tests/Blockcore.Features.ColdStaking.Tests/ColdStakingManagerTest.cs index ca8adefc0..b5bbe6d84 100644 --- a/src/Tests/Blockcore.Features.ColdStaking.Tests/ColdStakingManagerTest.cs +++ b/src/Tests/Blockcore.Features.ColdStaking.Tests/ColdStakingManagerTest.cs @@ -162,6 +162,7 @@ public void ProcessTransactionWithValidColdStakingSetupLoadsTransactionsIntoWall wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account 0", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -172,6 +173,7 @@ public void ProcessTransactionWithValidColdStakingSetupLoadsTransactionsIntoWall coldWallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = ColdStakingManager.ColdWalletAccountIndex, + Purpose = 44, Name = ColdStakingManager.ColdWalletAccountName, HdPath = $"m/44'/0'/{ColdStakingManager.ColdWalletAccountIndex}'", ExtendedPubKey = accountColdKeys.ExtPubKey, @@ -182,6 +184,7 @@ public void ProcessTransactionWithValidColdStakingSetupLoadsTransactionsIntoWall hotWallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = ColdStakingManager.HotWalletAccountIndex, + Purpose = 44, Name = ColdStakingManager.HotWalletAccountName, HdPath = $"m/44'/0'/{ColdStakingManager.HotWalletAccountIndex}'", ExtendedPubKey = accountHotKeys.ExtPubKey, diff --git a/src/Tests/Blockcore.Features.Wallet.Tests/WalletControllerTest.cs b/src/Tests/Blockcore.Features.Wallet.Tests/WalletControllerTest.cs index c7016e29b..b5b30e0d8 100644 --- a/src/Tests/Blockcore.Features.Wallet.Tests/WalletControllerTest.cs +++ b/src/Tests/Blockcore.Features.Wallet.Tests/WalletControllerTest.cs @@ -226,7 +226,7 @@ public void CreateWalletSuccessfullyReturnsMnemonic() { var mnemonic = new Mnemonic(Wordlist.English, WordCount.Twelve); var mockWalletCreate = new Mock(); - mockWalletCreate.Setup(wallet => wallet.CreateWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null)).Returns(mnemonic); + mockWalletCreate.Setup(wallet => wallet.CreateWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null)).Returns(mnemonic); var controller = new WalletController(this.LoggerFactory.Object, mockWalletCreate.Object, new Mock().Object, new Mock().Object, It.IsAny(), this.Network, this.chainIndexer, new Mock().Object, DateTimeProvider.Default); @@ -272,7 +272,7 @@ public void CreateWalletWithInvalidOperationExceptionReturnsConflict() { string errorMessage = "An error occurred."; var mockWalletCreate = new Mock(); - mockWalletCreate.Setup(wallet => wallet.CreateWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null)) + mockWalletCreate.Setup(wallet => wallet.CreateWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null)) .Throws(new WalletException(errorMessage)); var controller = new WalletController(this.LoggerFactory.Object, mockWalletCreate.Object, new Mock().Object, new Mock().Object, It.IsAny(), this.Network, this.chainIndexer, new Mock().Object, DateTimeProvider.Default); @@ -298,7 +298,7 @@ public void CreateWalletWithInvalidOperationExceptionReturnsConflict() public void CreateWalletWithNotSupportedExceptionExceptionReturnsBadRequest() { var mockWalletCreate = new Mock(); - mockWalletCreate.Setup(wallet => wallet.CreateWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null)) + mockWalletCreate.Setup(wallet => wallet.CreateWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null)) .Throws(new NotSupportedException("Not supported")); var controller = new WalletController(this.LoggerFactory.Object, mockWalletCreate.Object, new Mock().Object, new Mock().Object, It.IsAny(), this.Network, this.chainIndexer, new Mock().Object, DateTimeProvider.Default); @@ -330,7 +330,7 @@ public void RecoverWalletSuccessfullyReturnsWalletModel() }; var mockWalletManager = new Mock(); - mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)).Returns(wallet); + mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null, null)).Returns(wallet); Mock walletSyncManager = new Mock(); walletSyncManager.Setup(w => w.WalletTip).Returns(new ChainedHeader(this.Network.GetGenesis().Header, this.Network.GetGenesis().Header.GetHash(), 3)); @@ -368,7 +368,7 @@ public void RecoverWalletWithDatedAfterCurrentSyncHeightDoesNotMoveSyncHeight() DateTime lastBlockDateTime = chainIndexer.Tip.Header.BlockTime.DateTime; var mockWalletManager = new Mock(); - mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)).Returns(wallet); + mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null, null)).Returns(wallet); Mock walletSyncManager = new Mock(); walletSyncManager.Setup(w => w.WalletTip).Returns(new ChainedHeader(this.Network.GetGenesis().Header, this.Network.GetGenesis().Header.GetHash(), 3)); @@ -419,7 +419,7 @@ public void RecoverWalletWithInvalidOperationExceptionReturnsConflict() { string errorMessage = "An error occurred."; var mockWalletManager = new Mock(); - mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)) + mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null, null)) .Throws(new WalletException(errorMessage)); var controller = new WalletController(this.LoggerFactory.Object, mockWalletManager.Object, new Mock().Object, new Mock().Object, It.IsAny(), this.Network, this.chainIndexer, new Mock().Object, DateTimeProvider.Default); @@ -445,7 +445,7 @@ public void RecoverWalletWithInvalidOperationExceptionReturnsConflict() public void RecoverWalletWithFileNotFoundExceptionReturnsNotFound() { var mockWalletManager = new Mock(); - mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)) + mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null, null)) .Throws(new FileNotFoundException("File not found.")); var controller = new WalletController(this.LoggerFactory.Object, mockWalletManager.Object, new Mock().Object, new Mock().Object, It.IsAny(), this.Network, this.chainIndexer, new Mock().Object, DateTimeProvider.Default); @@ -472,7 +472,7 @@ public void RecoverWalletWithFileNotFoundExceptionReturnsNotFound() public void RecoverWalletWithExceptionReturnsBadRequest() { var mockWalletManager = new Mock(); - mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null)) + mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, null, null, null)) .Throws(new FormatException("Formatting failed.")); var controller = new WalletController(this.LoggerFactory.Object, mockWalletManager.Object, new Mock().Object, new Mock().Object, It.IsAny(), this.Network, this.chainIndexer, new Mock().Object, DateTimeProvider.Default); @@ -523,7 +523,7 @@ private void RecoverWithExtPubAndCheckSuccessfulResponse(string walletName, stri }; var walletManager = new Mock(); - walletManager.Setup(w => w.RecoverWallet(walletName, It.IsAny(), 1, It.IsAny())).Returns(wallet); + walletManager.Setup(w => w.RecoverWallet(walletName, It.IsAny(), 1, It.IsAny(), null)).Returns(wallet); Mock walletSyncManager = new Mock(); walletSyncManager.Setup(w => w.WalletTip).Returns(new ChainedHeader(this.Network.GetGenesis().Header, this.Network.GetGenesis().Header.GetHash(), 3)); @@ -569,7 +569,7 @@ public void RecoverWalletWithExtPubDatedAfterCurrentSyncHeightDoesNotMoveSyncHei DateTime lastBlockDateTime = chainIndexer.Tip.Header.BlockTime.DateTime; var walletManager = new Mock(); - walletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), 1, It.IsAny())).Returns(wallet); + walletManager.Setup(w => w.RecoverWallet(It.IsAny(), It.IsAny(), 1, It.IsAny(), null)).Returns(wallet); Mock walletSyncManager = new Mock(); walletSyncManager.Setup(w => w.WalletTip).Returns(new ChainedHeader(this.Network.GetGenesis().Header, this.Network.GetGenesis().Header.GetHash(), 3)); @@ -1922,7 +1922,7 @@ public void ListWalletFilesWithExceptionReturnsBadRequest() public void CreateNewAccountWithValidModelReturnsAccountName() { var mockWalletManager = new Mock(); - mockWalletManager.Setup(m => m.GetUnusedAccount("myWallet", "test")) + mockWalletManager.Setup(m => m.GetUnusedAccount("myWallet", "test", null)) .Returns(new HdAccount { Name = "Account 1" }); var controller = new WalletController(this.LoggerFactory.Object, mockWalletManager.Object, new Mock().Object, new Mock().Object, It.IsAny(), this.Network, this.chainIndexer, new Mock().Object, DateTimeProvider.Default); @@ -1963,7 +1963,7 @@ public void CreateNewAccountWithInvalidValidModelReturnsBadRequest() public void CreateNewAccountWithExceptionReturnsBadRequest() { var mockWalletManager = new Mock(); - mockWalletManager.Setup(m => m.GetUnusedAccount("myWallet", "test")) + mockWalletManager.Setup(m => m.GetUnusedAccount("myWallet", "test", null)) .Throws(new InvalidOperationException("Wallet not found.")); var controller = new WalletController(this.LoggerFactory.Object, mockWalletManager.Object, new Mock().Object, new Mock().Object, It.IsAny(), this.Network, this.chainIndexer, new Mock().Object, DateTimeProvider.Default); diff --git a/src/Tests/Blockcore.Features.Wallet.Tests/WalletManagerTest.cs b/src/Tests/Blockcore.Features.Wallet.Tests/WalletManagerTest.cs index 58a88d52d..8a7886d3f 100644 --- a/src/Tests/Blockcore.Features.Wallet.Tests/WalletManagerTest.cs +++ b/src/Tests/Blockcore.Features.Wallet.Tests/WalletManagerTest.cs @@ -627,7 +627,7 @@ public void CreateNewAccountGivenNoAccountsExistingInWalletCreatesNewAccount() Types.Wallet wallet = this.walletFixture.GenerateBlankWallet("testWallet", "password"); wallet.AccountsRoot.ElementAt(0).Accounts.Clear(); - HdAccount result = wallet.AddNewAccount("password", DateTimeOffset.UtcNow); + HdAccount result = wallet.AddNewAccount("password", DateTimeOffset.UtcNow, 44); Assert.Equal(1, wallet.AccountsRoot.ElementAt(0).Accounts.Count); var extKey = new ExtKey(Key.Parse(wallet.EncryptedSeed, "password", wallet.Network), wallet.ChainCode); @@ -640,6 +640,29 @@ public void CreateNewAccountGivenNoAccountsExistingInWalletCreatesNewAccount() Assert.Equal(0, result.ExternalAddresses.Count); } + [Fact] + public void CreateNewBIP84AccountGivenNoAccountsExistingInWalletCreatesNewAccount() + { + DataFolder dataFolder = CreateDataFolder(this); + + var walletManager = new WalletManager(this.LoggerFactory.Object, this.Network, new Mock().Object, new WalletSettings(NodeSettings.Default(this.Network)), + dataFolder, new Mock().Object, new Mock().Object, new NodeLifetime(), DateTimeProvider.Default, new ScriptAddressReader()); + Types.Wallet wallet = this.walletFixture.GenerateBlankWallet("testWallet", "password"); + wallet.AccountsRoot.ElementAt(0).Accounts.Clear(); + + HdAccount result = wallet.AddNewAccount("password", DateTimeOffset.UtcNow, 84); + + Assert.Equal(1, wallet.AccountsRoot.ElementAt(0).Accounts.Count); + var extKey = new ExtKey(Key.Parse(wallet.EncryptedSeed, "password", wallet.Network), wallet.ChainCode); + string expectedExtendedPubKey = extKey.Derive(new KeyPath($"m/84'/0'/0'")).Neuter().ToString(wallet.Network); + Assert.Equal($"account 0", result.Name); + Assert.Equal(0, result.Index); + Assert.Equal($"m/84'/0'/0'", result.HdPath); + Assert.Equal(expectedExtendedPubKey, result.ExtendedPubKey); + Assert.Equal(0, result.InternalAddresses.Count); + Assert.Equal(0, result.ExternalAddresses.Count); + } + [Fact] public void CreateNewAccountGivenExistingAccountInWalletCreatesNewAccount() { @@ -651,7 +674,7 @@ public void CreateNewAccountGivenExistingAccountInWalletCreatesNewAccount() Types.Wallet wallet = this.walletFixture.GenerateBlankWallet("testWallet", "password"); wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Name = "unused" }); - HdAccount result = wallet.AddNewAccount("password", DateTimeOffset.UtcNow); + HdAccount result = wallet.AddNewAccount("password", DateTimeOffset.UtcNow, 44); Assert.Equal(2, wallet.AccountsRoot.ElementAt(0).Accounts.Count); var extKey = new ExtKey(Key.Parse(wallet.EncryptedSeed, "password", wallet.Network), wallet.ChainCode); @@ -784,6 +807,7 @@ public void GetOrCreateChangeAddressWithWalletNotHavingUnusedAddressReturnsAddre wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "myAccount", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountExtendedPubKey, @@ -810,6 +834,7 @@ public void GetUnusedAddressWithoutWalletHavingUnusedAddressCreatesAddressAndSav wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "myAccount", HdPath = "m/44'/0'/0'", ExternalAddresses = new List @@ -855,6 +880,7 @@ public void GetHistoryByNameWithExistingWalletReturnsAllAddressesWithTransaction wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "myAccount", HdPath = "m/44'/0'/0'", ExternalAddresses = new List @@ -898,6 +924,7 @@ public void GetHistorySlimByNameWithExistingWalletReturnsAllAddressesWithTransac wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "myAccount", HdPath = "m/44'/0'/0'", ExternalAddresses = new List @@ -940,6 +967,7 @@ public void GetHistoryByAccountWithExistingAccountReturnsAllAddressesWithTransac var account = new HdAccount { Index = 0, + Purpose = 44, Name = "myAccount", HdPath = "m/44'/0'/0'", ExternalAddresses = new List @@ -985,6 +1013,7 @@ public void GetHistoryByAccountWithoutHavingAddressesWithTransactionsReturnsEmpt var account = new HdAccount { Index = 0, + Purpose = 44, Name = "myAccount", HdPath = "m/44'/0'/0'", ExternalAddresses = new List(), @@ -1328,6 +1357,7 @@ public void GetKeyForAddressWithWalletReturnsAddressExtPrivateKey() data.wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, ExternalAddresses = new List { address }, @@ -1359,6 +1389,7 @@ public void GetKeyForAddressWitoutAddressOnWalletThrowsWalletException() data.wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, ExternalAddresses = new List(), InternalAddresses = new List(), Name = "savings account" @@ -1420,6 +1451,7 @@ public void ProcessTransactionWithValidTransactionLoadsTransactionsIntoWalletIfM wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -1510,6 +1542,7 @@ public void ProcessTransactionWithEmptyScriptInTransactionDoesNotAddTransactionT wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -1597,6 +1630,7 @@ public void ProcessTransactionWithDestinationToChangeAddressDoesNotAddTransactio wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -1679,6 +1713,7 @@ public void ProcessTransactionWithDestinationAsMultisigAddTransactionAsPayment() wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -1764,6 +1799,7 @@ public void ProcessTransactionWithBlockHeightSetsBlockHeightOnTransactionData() wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -1861,6 +1897,7 @@ public void ProcessTransactionWithBlockSetsBlockHash() wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -2253,6 +2290,7 @@ public void RemoveBlocksRemovesTransactionsWithHigherBlockHeightAndUpdatesLastSy wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Name = "First account", + Purpose = 44, ExternalAddresses = WalletTestsHelpers.CreateSpentTransactionsOfBlockHeights((WalletMemoryStore)wallet.walletStore, this.Network, 1, 2, 3, 4, 5).ToList(), InternalAddresses = WalletTestsHelpers.CreateSpentTransactionsOfBlockHeights((WalletMemoryStore)wallet.walletStore, this.Network, 1, 2, 3, 4, 5).ToList() }); @@ -2361,6 +2399,7 @@ public void ProcessBlockWithWalletsProcessesTransactionsOfBlockToWallet() wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -2823,7 +2862,7 @@ public void LoadKeysLookupWithoutWalletsInitializesEmptyDictionary() [Fact] public void CreateBip44PathWithChangeAddressReturnsPath() { - string result = HdOperations.CreateHdPath((int)KnownCoinTypes.Stratis, 4, true, 3); + string result = HdOperations.CreateHdPath(44, (int)KnownCoinTypes.Stratis, 4, true, 3); Assert.Equal("m/44'/105'/4'/1/3", result); } @@ -2831,11 +2870,19 @@ public void CreateBip44PathWithChangeAddressReturnsPath() [Fact] public void CreateBip44PathWithoutChangeAddressReturnsPath() { - string result = HdOperations.CreateHdPath((int)KnownCoinTypes.Stratis, 4, false, 3); + string result = HdOperations.CreateHdPath(44, (int)KnownCoinTypes.Stratis, 4, false, 3); Assert.Equal("m/44'/105'/4'/0/3", result); } + [Fact] + public void CreateBip84PathWithoutChangeAddressReturnsPath() + { + string result = HdOperations.CreateHdPath(84, (int)KnownCoinTypes.Stratis, 4, false, 3); + + Assert.Equal("m/84'/105'/4'/0/3", result); + } + [Fact] public void StopSavesWallets() { @@ -3101,6 +3148,7 @@ public void ConfirmedTransactionsShouldWipeOutUnconfirmedWithSameInputs() wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -3262,7 +3310,7 @@ public void AddNewAccount_via_xpubkey_prevents_adding_an_account_as_an_existing_ try { - wallet.AddNewAccount(ExtPubKey.Parse(stratisAccount1ExtPubKey), 0, DateTime.Now.AddHours(-2)); + wallet.AddNewAccount(ExtPubKey.Parse(stratisAccount1ExtPubKey), 0, DateTime.Now.AddHours(-2), 44); Assert.True(false, "should have thrown exception but didn't."); } @@ -3281,7 +3329,7 @@ public void AddNewAccount_via_xpubkey_prevents_adding_the_same_xpub_key_as_diffe var walletManager = this.CreateWalletManager(dataFolder, KnownNetworks.StratisMain); var wallet = walletManager.RecoverWallet("wallet1", ExtPubKey.Parse(stratisAccount0ExtPubKey), 0, DateTime.Now.AddHours(-2)); - var addNewAccount = new Action(() => wallet.AddNewAccount(ExtPubKey.Parse(stratisAccount0ExtPubKey), 1, DateTime.Now.AddHours(-2))); + var addNewAccount = new Action(() => wallet.AddNewAccount(ExtPubKey.Parse(stratisAccount0ExtPubKey), 1, DateTime.Now.AddHours(-2), 44)); addNewAccount.Should().Throw() .WithMessage("There is already an account in this wallet with this xpubkey: " + stratisAccount0ExtPubKey); diff --git a/src/Tests/Blockcore.Features.Wallet.Tests/WalletTransactionHandlerTest.cs b/src/Tests/Blockcore.Features.Wallet.Tests/WalletTransactionHandlerTest.cs index de8718c4d..2927c2f88 100644 --- a/src/Tests/Blockcore.Features.Wallet.Tests/WalletTransactionHandlerTest.cs +++ b/src/Tests/Blockcore.Features.Wallet.Tests/WalletTransactionHandlerTest.cs @@ -340,6 +340,7 @@ public void FundTransaction_Given__a_wallet_has_enough_inputs__When__adding_inpu wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, @@ -701,6 +702,7 @@ private WalletTransactionHandlerTestContext SetupWallet() wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount { Index = 0, + Purpose = 44, Name = "account1", HdPath = "m/44'/0'/0'", ExtendedPubKey = accountKeys.ExtPubKey, diff --git a/src/Tests/Blockcore.IntegrationTests.Common/EnvironmentMockUpHelpers/CoreNode.cs b/src/Tests/Blockcore.IntegrationTests.Common/EnvironmentMockUpHelpers/CoreNode.cs index 3acdcda0f..6c08a9132 100644 --- a/src/Tests/Blockcore.IntegrationTests.Common/EnvironmentMockUpHelpers/CoreNode.cs +++ b/src/Tests/Blockcore.IntegrationTests.Common/EnvironmentMockUpHelpers/CoreNode.cs @@ -77,6 +77,7 @@ public class CoreNode private bool builderOverrideDateTimeProvider; private bool builderWithDummyWallet; private bool builderWithWallet; + private bool builderWithSegwitWallet; private string builderWalletName; private string builderWalletPassword; private string builderWalletPassphrase; @@ -224,6 +225,27 @@ public CoreNode WithWallet(string walletPassword = "password", string walletName return this; } + /// + /// Adds a segwit wallet to this node with defaulted parameters under the BIP84 derivation path. + /// + /// Wallet password defaulted to "password". + /// Wallet name defaulted to "mywallet". + /// Wallet passphrase defaulted to "passphrase". + /// Optional wallet mnemonic. + /// This node. + public CoreNode WithSegwitWallet(string walletPassword = "password", string walletName = "mywallet", string walletPassphrase = "passphrase", string walletMnemonic = null) + { + this.builderWithDummyWallet = false; + this.builderWithWallet = true; + this.builderWithSegwitWallet = true; + this.builderWalletName = walletName; + this.builderWalletPassphrase = walletPassphrase; + this.builderWalletPassword = walletPassword; + this.builderWalletMnemonic = walletMnemonic; + + return this; + } + public CoreNode WithReadyBlockchainData(string readyDataName) { // Extract the zipped blockchain data to the node's DataFolder. @@ -445,7 +467,7 @@ private void StartStratisRunner() this.builderWalletPassword, this.builderWalletName, this.builderWalletPassphrase, - string.IsNullOrEmpty(this.builderWalletMnemonic) ? null : new Mnemonic(this.builderWalletMnemonic)); + string.IsNullOrEmpty(this.builderWalletMnemonic) ? null : new Mnemonic(this.builderWalletMnemonic), purpose: this.builderWithSegwitWallet ? 84 : null); } } diff --git a/src/Tests/Blockcore.IntegrationTests/API/ApiSteps.cs b/src/Tests/Blockcore.IntegrationTests/API/ApiSteps.cs index fb6ee0768..4cf0c243e 100644 --- a/src/Tests/Blockcore.IntegrationTests/API/ApiSteps.cs +++ b/src/Tests/Blockcore.IntegrationTests/API/ApiSteps.cs @@ -458,7 +458,7 @@ private void a_full_list_of_available_commands_is_returned() commands.Should().Contain(x => x.Command == "walletpassphrase "); commands.Should().Contain(x => x.Command == "walletlock"); commands.Should().Contain(x => x.Command == "getwalletinfo"); - commands.Should().Contain(x => x.Command == "sendtoaddress
[] []"); + commands.Should().Contain(x => x.Command == "sendtoaddress
[]"); commands.Should().Contain(x => x.Command == "sendrawtransaction "); commands.Should().Contain(x => x.Command == "getnewaddress [] []"); commands.Should().Contain(x => x.Command == "getunusedaddress "); diff --git a/src/Tests/Blockcore.IntegrationTests/RPC/RPCTestsMutable.cs b/src/Tests/Blockcore.IntegrationTests/RPC/RPCTestsMutable.cs index 8dbce08db..081685b30 100644 --- a/src/Tests/Blockcore.IntegrationTests/RPC/RPCTestsMutable.cs +++ b/src/Tests/Blockcore.IntegrationTests/RPC/RPCTestsMutable.cs @@ -134,7 +134,7 @@ public void TestRpcSendToAddressIsSuccessful() var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); rpcClient.WalletPassphrase("password", 60); - var txid = rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m, false); + var txid = rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m); rpcClient.SendCommand(RPCOperations.walletlock); // Check the hash calculated correctly. @@ -159,19 +159,19 @@ public void TestRpcSendToAddressCantSpendWhenLocked() RPCClient rpcClient = node.CreateRPCClient(); // Not unlocked case. - Action action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m, false); + Action action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m); action.Should().Throw().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED); // Unlock and lock case. rpcClient.WalletPassphrase("password", 60); rpcClient.SendCommand(RPCOperations.walletlock); - action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m, false); + action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m); action.Should().Throw().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED); // Unlock timesout case. rpcClient.WalletPassphrase("password", 5); Thread.Sleep(10 * 1000); // 10 seconds. - action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m, false); + action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m); action.Should().Throw().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED); } } @@ -294,17 +294,17 @@ public void TestRpcSendToAddressSpendRefreshesTimeout() rpcClient.WalletPassphrase("password", 20); // Send a transaction. - rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m, false).Should().NotBeNull(); + rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m).Should().NotBeNull(); // Wait 10 seconds and then send another transaction, should still be unlocked. Thread.Sleep(10 * 1000); var bobAddress = new Key().GetBitcoinSecret(network).GetAddress(); - rpcClient.SendToAddress(bobAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m, false).Should().NotBeNull(); + rpcClient.SendToAddress(bobAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m).Should().NotBeNull(); // Now wait 10 seconds so the wallet should be back locked and a transaction should fail. Thread.Sleep(10 * 1000); - Action action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m, false); + Action action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m), "CommentTX", "CommentDest", 0.01m); action.Should().Throw().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED); } } diff --git a/src/Tests/Blockcore.IntegrationTests/SegWitTests.cs b/src/Tests/Blockcore.IntegrationTests/SegWitTests.cs index 815c51754..aa4ad0a22 100644 --- a/src/Tests/Blockcore.IntegrationTests/SegWitTests.cs +++ b/src/Tests/Blockcore.IntegrationTests/SegWitTests.cs @@ -363,9 +363,9 @@ public void StakeSegwitBlock_UsingOnlySegwitUTXOs() using (NodeBuilder builder = NodeBuilder.Create(this)) { // Even though we are mining, we still want to use PoS consensus rules. - CoreNode node = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithWallet().Start(); + CoreNode node = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithSegwitWallet().Start(); - var address = BitcoinWitPubKeyAddress.Create(node.FullNode.WalletManager().GetUnusedAddress().Bech32Address, KnownNetworks.StratisRegTest); + var address = BitcoinWitPubKeyAddress.Create(node.FullNode.WalletManager().GetUnusedAddress().Address, KnownNetworks.StratisRegTest); // A P2WPKH scriptPubKey - so that funds get mined into the node's wallet as segwit UTXOs var script = address.ScriptPubKey; @@ -529,8 +529,8 @@ public void SegwitWalletTransactionBuildingAndPropagationTest() { using (NodeBuilder builder = NodeBuilder.Create(this)) { - CoreNode node = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithWallet().Start(); - CoreNode listener = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithWallet().Start(); + CoreNode node = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithSegwitWallet().Start(); + CoreNode listener = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithSegwitWallet().Start(); IConnectionManager listenerConnMan = listener.FullNode.NodeService(); listenerConnMan.Parameters.TemplateBehaviors.Add(new TestBehavior()); @@ -549,7 +549,7 @@ public void SegwitWalletTransactionBuildingAndPropagationTest() // Send a transaction from first node to itself so that it has a proper segwit input to spend. var destinationAddress = node.FullNode.WalletManager().GetUnusedAddress(); - var witAddress = destinationAddress.Bech32Address; + var witAddress = destinationAddress.Address; IActionResult transactionResult = node.FullNode.NodeController() .BuildTransaction(new BuildTransactionRequest @@ -632,8 +632,8 @@ public void SegwitWalletTransactionBuildingTest_SpendP2WPKHAndNormalUTXOs() { using (NodeBuilder builder = NodeBuilder.Create(this)) { - CoreNode node = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithWallet().Start(); - CoreNode listener = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithWallet().Start(); + CoreNode node = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithSegwitWallet().Start(); + CoreNode listener = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithSegwitWallet().Start(); TestHelper.Connect(listener, node); @@ -648,7 +648,7 @@ public void SegwitWalletTransactionBuildingTest_SpendP2WPKHAndNormalUTXOs() // Send a transaction from first node to itself so that it has a proper segwit input to spend. var destinationAddress = node.FullNode.WalletManager().GetUnusedAddress(); - var witAddress = destinationAddress.Bech32Address; + var witAddress = destinationAddress.Address; var p2wpkhAmount = Money.Coins(1); @@ -683,7 +683,7 @@ public void SegwitWalletTransactionBuildingTest_SpendP2WPKHAndNormalUTXOs() // Make sure wallet is synced. TestBase.WaitLoop(() => node.CreateRPCClient().GetBlockCount() == node.FullNode.WalletManager().LastBlockHeight(), cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token); - var spendable = node.FullNode.WalletManager().GetSpendableTransactionsInWallet(node.WalletName).Where(t => t.Address.Bech32Address != witAddress); + var spendable = node.FullNode.WalletManager().GetSpendableTransactionsInWallet(node.WalletName).Where(t => t.Address.Address != witAddress); // By sending more than the size of the P2WPKH UTXO, we guarantee that at least one non-P2WPKH UTXO gets included transactionResult = node.FullNode.NodeController() @@ -721,7 +721,7 @@ public void SegwitWalletTransactionBuildingTest_SendToBech32AndNormalDestination { using (NodeBuilder builder = NodeBuilder.Create(this)) { - CoreNode node = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithWallet().Start(); + CoreNode node = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithSegwitWallet().Start(); CoreNode listener = builder.CreateStratisPosNode(KnownNetworks.StratisRegTest).WithWallet().Start(); TestHelper.Connect(listener, node); @@ -736,8 +736,9 @@ public void SegwitWalletTransactionBuildingTest_SendToBech32AndNormalDestination TestBase.WaitLoop(() => TestHelper.AreNodesSynced(node, listener)); var destinationAddress = node.FullNode.WalletManager().GetUnusedAddress(); - var witAddress = destinationAddress.Bech32Address; - var nonWitAddress = destinationAddress.Address; + var destinationAddress1 = listener.FullNode.WalletManager().GetUnusedAddress(); + var witAddress = destinationAddress.Address; + var nonWitAddress = destinationAddress1.Address; IActionResult transactionResult = node.FullNode.NodeController() .BuildTransaction(new BuildTransactionRequest diff --git a/src/Tests/Blockcore.IntegrationTests/Wallet/WalletAddressGenerationAndFundsVisibility_Steps.cs b/src/Tests/Blockcore.IntegrationTests/Wallet/WalletAddressGenerationAndFundsVisibility_Steps.cs index b4a192a50..b8556dada 100644 --- a/src/Tests/Blockcore.IntegrationTests/Wallet/WalletAddressGenerationAndFundsVisibility_Steps.cs +++ b/src/Tests/Blockcore.IntegrationTests/Wallet/WalletAddressGenerationAndFundsVisibility_Steps.cs @@ -109,7 +109,7 @@ private ExtPubKey GetExtendedPublicKey(CoreNode node) { ExtKey xPrivKey = node.Mnemonic.DeriveExtKey(WalletPassphrase); Key privateKey = xPrivKey.PrivateKey; - ExtPubKey xPublicKey = HdOperations.GetExtendedPublicKey(privateKey, xPrivKey.ChainCode, KnownCoinTypes.Bitcoin, 0); + ExtPubKey xPublicKey = HdOperations.GetExtendedPublicKey(privateKey, xPrivKey.ChainCode, 44, KnownCoinTypes.Bitcoin, 0); return xPublicKey; } diff --git a/src/Tests/Blockcore.Tests.Wallet.Common/WalletTestsHelpers.cs b/src/Tests/Blockcore.Tests.Wallet.Common/WalletTestsHelpers.cs index 8afd85c52..553120d37 100644 --- a/src/Tests/Blockcore.Tests.Wallet.Common/WalletTestsHelpers.cs +++ b/src/Tests/Blockcore.Tests.Wallet.Common/WalletTestsHelpers.cs @@ -245,11 +245,13 @@ public static void AddAddressesToWallet(WalletManager walletManager, int count) { new HdAccount { + Purpose = 44, ExternalAddresses = GenerateAddresses(count), InternalAddresses = GenerateAddresses(count) }, new HdAccount { + Purpose = 44, ExternalAddresses = GenerateAddresses(count), InternalAddresses = GenerateAddresses(count) } } @@ -262,8 +264,9 @@ public static HdAddress CreateAddressWithoutTransaction(int index, string addres return new HdAddress { Index = index, + HdPath = "m/44'/0'/0'/0/0", Address = addressName, - ScriptPubKey = new Script(), + ScriptPubKey = new Script() //Transactions = new List() }; } @@ -273,8 +276,9 @@ public static HdAddress CreateAddressWithEmptyTransaction(int index, string addr return new HdAddress { Index = index, + HdPath = "m/44'/0'/0'/0/0", Address = addressName, - ScriptPubKey = new Script(), + ScriptPubKey = new Script() //Transactions = new List { new TransactionData() } }; } @@ -289,7 +293,8 @@ public static List GenerateAddresses(int count) var address = new HdAddress { Address = key.ToString(), - ScriptPubKey = key + ScriptPubKey = key, + HdPath = $"m/44'/0'/0'/0/{count}", }; addresses.Add(address); } @@ -440,6 +445,7 @@ public static ICollection CreateSpentTransactionsOfBlockHeights(Walle { Address = key.PubKey.GetAddress(network).ToString(), ScriptPubKey = key.ScriptPubKey, + HdPath = "m/44'/0'/0'/0/0", }; store.Add(new List { From d6f143abf7efaab0951474c73fe26580b8f70286 Mon Sep 17 00:00:00 2001 From: dangershony Date: Thu, 29 Sep 2022 11:43:43 +0100 Subject: [PATCH 006/194] Bump version and update change log --- CHANGELOG.md | 11 +++++++++++ src/Directory.Build.props | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43e5e8c2a..27564440d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## (2022-09-29) + +* Add additional checkpoint for City Chain ([f928dab](https://github.com/block-core/blockcore/commit/f928dab)) +* Configure reloadOnChange to be false ([229a3ed](https://github.com/block-core/blockcore/commit/229a3ed)), closes [#418](https://github.com/block-core/blockcore/issues/418) +* Define a maximum tx fee or else zero few is required ([885634a](https://github.com/block-core/blockcore/commit/885634a)) +* Fix wallet to use segwit in the correct derivation path (#415) ([3ef32a7](https://github.com/block-core/blockcore/commit/3ef32a7)), closes [#415](https://github.com/block-core/blockcore/issues/415) +* Update DNS and seed nodes for City Chain ([f0fc349](https://github.com/block-core/blockcore/commit/f0fc349)) +* Update version ([c36bf5e](https://github.com/block-core/blockcore/commit/c36bf5e)) + + + ## (2022-08-26) * add changelog ([5e5cde6](https://github.com/block-core/blockcore/commit/5e5cde6)) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e0a31d69c..b79a192ed 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@ - 1.1.36 + 1.1.37 net6.0 false Blockcore From 68291686fefb2b2d59926e1aac9ff0deb2cc2be7 Mon Sep 17 00:00:00 2001 From: Dan Gershony Date: Mon, 10 Oct 2022 13:37:57 +0100 Subject: [PATCH 007/194] Enable blazor (#419) * first push * Solution compiles * delete blazor project * remove from solution * remove commented code * Fix rpc feature * Fix rpc tests * Bring back the disable logs on tests --- src/Blockcore/Base/BaseFeature.cs | 4 - src/Blockcore/Blockcore.csproj | 7 +- src/Blockcore/Connection/PeerNodeModel.cs | 52 +++++------ src/Blockcore/EventBus/EventBase.cs | 1 - src/Blockcore/FullNode.cs | 7 -- src/Blockcore/IFullNode.cs | 4 - .../Blockcore.Features.Consensus.csproj | 1 + .../Blockcore.Features.Diagnostic.csproj | 1 + .../Blockcore.Features.NodeHost.csproj | 1 + .../Broadcasters/BroadcasterBase.cs | 1 - .../ClientEventBroadcasterSettings.cs | 0 .../Broadcasters/IClientEventBroadcaster.cs | 1 - .../IEventsSubscriptionService.cs | 0 .../ConnectionManagerController.cs | 4 +- .../Controller/ConnectionManagerHelper.cs | 90 +++++++++++++++++++ .../Converters/BtcDecimalJsonConverter.cs | 0 .../Converters/ToStringJsonConverter.cs | 0 .../Controller}/DashboardController.cs | 0 .../Controller}/FeatureController.cs | 0 .../Models/AddressBalancesResult.cs | 0 .../Controller}/Models/AsyncLoopModel.cs | 0 .../Controller}/Models/BannedPeerModel.cs | 0 .../Controller}/Models/BlockHeaderModel.cs | 0 .../Controller}/Models/BlockModel.cs | 0 .../Controller}/Models/ConnectedPeerModel.cs | 0 .../Models/DecodeRawTransactionModel.cs | 0 .../Models/DisconnectPeerViewModel.cs | 0 .../Controller}/Models/GetTxOutModel.cs | 0 .../Controller}/Models/LogRuleModel.cs | 0 .../Controller}/Models/LogRulesRequest.cs | 0 .../Controller}/Models/SetBanPeerViewModel.cs | 0 .../Controller}/Models/StatusModel.cs | 0 .../Controller}/Models/TransactionModel.cs | 0 .../Controller}/Models/ValidatedAddress.cs | 0 .../Controller}/NetworkController.cs | 0 .../Controller}/NodeController.cs | 0 .../Controller}/RestApiClientBase.cs | 0 .../JsonErrors/ErrorHelpers.cs | 0 .../JsonErrors/ErrorResponse.cs | 0 .../JsonErrors/ErrorResult.cs | 3 +- .../ModelStateErrors/ModelStateErrors.cs | 0 .../NodeHostFeature.cs | 4 + .../UI/BlazorModal/ModalService.cs | 0 .../Blockcore.Features.Notifications.csproj | 1 + .../ConnectionManagerRPCController.cs | 0 .../Controllers/RPCController.cs | 7 +- .../Blockcore.Features.RPC/RPCFeature.cs | 36 +++++++- .../Controller/RPCControllerTest.cs | 10 ++- 48 files changed, 177 insertions(+), 58 deletions(-) rename src/{Blockcore => Features/Blockcore.Features.NodeHost}/Broadcasters/BroadcasterBase.cs (98%) rename src/{Blockcore => Features/Blockcore.Features.NodeHost}/Broadcasters/ClientEventBroadcasterSettings.cs (100%) rename src/{Blockcore => Features/Blockcore.Features.NodeHost}/Broadcasters/IClientEventBroadcaster.cs (82%) rename src/{Blockcore => Features/Blockcore.Features.NodeHost}/Broadcasters/IEventsSubscriptionService.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/ConnectionManagerController.cs (93%) create mode 100644 src/Features/Blockcore.Features.NodeHost/Controller/ConnectionManagerHelper.cs rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Converters/BtcDecimalJsonConverter.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Converters/ToStringJsonConverter.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/DashboardController.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/FeatureController.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/AddressBalancesResult.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/AsyncLoopModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/BannedPeerModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/BlockHeaderModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/BlockModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/ConnectedPeerModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/DecodeRawTransactionModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/DisconnectPeerViewModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/GetTxOutModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/LogRuleModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/LogRulesRequest.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/SetBanPeerViewModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/StatusModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/TransactionModel.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/Models/ValidatedAddress.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/NetworkController.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/NodeController.cs (100%) rename src/{Blockcore/Controllers => Features/Blockcore.Features.NodeHost/Controller}/RestApiClientBase.cs (100%) rename src/{Blockcore/Utilities => Features/Blockcore.Features.NodeHost}/JsonErrors/ErrorHelpers.cs (100%) rename src/{Blockcore/Utilities => Features/Blockcore.Features.NodeHost}/JsonErrors/ErrorResponse.cs (100%) rename src/{Blockcore/Utilities => Features/Blockcore.Features.NodeHost}/JsonErrors/ErrorResult.cs (87%) rename src/{Blockcore/Utilities => Features/Blockcore.Features.NodeHost}/ModelStateErrors/ModelStateErrors.cs (100%) rename src/{Blockcore => Features/Blockcore.Features.NodeHost}/UI/BlazorModal/ModalService.cs (100%) rename src/{Blockcore => Features/Blockcore.Features.RPC}/Controllers/ConnectionManagerRPCController.cs (100%) diff --git a/src/Blockcore/Base/BaseFeature.cs b/src/Blockcore/Base/BaseFeature.cs index c19affaae..95161ff44 100644 --- a/src/Blockcore/Base/BaseFeature.cs +++ b/src/Blockcore/Base/BaseFeature.cs @@ -17,7 +17,6 @@ using Blockcore.Consensus.Checkpoints; using Blockcore.Consensus.Rules; using Blockcore.Consensus.Validators; -using Blockcore.Controllers; using Blockcore.EventBus; using Blockcore.Interfaces; using Blockcore.Networks; @@ -502,9 +501,6 @@ public static IFullNodeBuilder UseBaseFeature(this IFullNodeBuilder fullNodeBuil // Console services.AddSingleton(); - - // Controller - services.AddTransient(); }); }); diff --git a/src/Blockcore/Blockcore.csproj b/src/Blockcore/Blockcore.csproj index 9830c2961..89c36a49a 100644 --- a/src/Blockcore/Blockcore.csproj +++ b/src/Blockcore/Blockcore.csproj @@ -25,7 +25,7 @@ - + @@ -56,6 +56,11 @@ + + + + + Library diff --git a/src/Blockcore/Connection/PeerNodeModel.cs b/src/Blockcore/Connection/PeerNodeModel.cs index 6be8db0b7..8b9407174 100644 --- a/src/Blockcore/Connection/PeerNodeModel.cs +++ b/src/Blockcore/Connection/PeerNodeModel.cs @@ -11,173 +11,173 @@ public class PeerNodeModel /// Peer index. ///
[JsonProperty(PropertyName = "id")] - public int Id { get; internal set; } + public int Id { get; set; } /// /// The IP address and port of the peer. /// [JsonProperty(PropertyName = "addr")] - public string Address { get; internal set; } + public string Address { get; set; } /// /// Local address as reported by the peer. /// [JsonProperty(PropertyName = "addrlocal")] - public string LocalAddress { get; internal set; } + public string LocalAddress { get; set; } /// /// The services offered. /// [JsonProperty(PropertyName = "services")] - public string Services { get; internal set; } + public string Services { get; set; } /// /// Whether the peer has asked us to relay transactions to it. /// Currently not populated. /// [JsonProperty(PropertyName = "relaytxes")] - public bool IsRelayTransactions { get; internal set; } + public bool IsRelayTransactions { get; set; } ///   ///  The Unix epoch time of the last send from this node. /// Currently not populated. ///   [JsonProperty(PropertyName = "lastsend")] - public int LastSend { get; internal set; } + public int LastSend { get; set; } ///   ///  The Unix epoch time when we last received data from this node. /// Currently not populated. ///   [JsonProperty(PropertyName = "lastrecv")] - public int LastReceive { get; internal set; } + public int LastReceive { get; set; } ///   ///  The total number of bytes we’ve sent to this node. ///  Currently not populated. ///   [JsonProperty(PropertyName = "bytessent")] - public long BytesSent { get; internal set; } + public long BytesSent { get; set; } ///   ///  The total number of bytes we’ve received from this node. ///  Currently not populated. ///   [JsonProperty(PropertyName = "bytesrecv")] - public long BytesReceived { get; internal set; } + public long BytesReceived { get; set; } ///   ///  The connection time in seconds since epoch. ///  Currently not populated. ///   [JsonProperty(PropertyName = "conntime")] - public int ConnectionTime { get; internal set; } + public int ConnectionTime { get; set; } /// /// The time offset in seconds. /// [JsonProperty(PropertyName = "timeoffset")] - public int TimeOffset { get; internal set; } + public int TimeOffset { get; set; } /// /// The ping time to the node in seconds. /// Currently not populated. /// [JsonProperty(PropertyName = "pingtime")] - public double PingTime { get; internal set; } + public double PingTime { get; set; } /// /// The minimum observed ping time. /// Currently not populated. /// [JsonProperty(PropertyName = "minping")] - public double MinPing { get; internal set; } + public double MinPing { get; set; } /// /// The number of seconds waiting for a ping. /// Currently not populated. /// [JsonProperty(PropertyName = "pingwait")] - public double PingWait { get; internal set; } + public double PingWait { get; set; } /// /// The protocol version number used by this node. /// [JsonProperty(PropertyName = "version")] - public uint Version { get; internal set; } + public uint Version { get; set; } /// /// The user agent this node sends in its version message. /// [JsonProperty(PropertyName = "subver")] - public string SubVersion { get; internal set; } + public string SubVersion { get; set; } /// /// Whether node is inbound or outbound connection. /// Currently not populated. /// [JsonProperty(PropertyName = "inbound")] - public bool Inbound { get; internal set; } + public bool Inbound { get; set; } /// /// Whether connection was due to addnode. /// Currently not populated. /// [JsonProperty(PropertyName = "addnode")] - public bool IsAddNode { get; internal set; } + public bool IsAddNode { get; set; } /// /// The starting height (block) of the peer. /// [JsonProperty(PropertyName = "startingheight")] - public int StartingHeight { get; internal set; } + public int StartingHeight { get; set; } /// /// The ban score for the node. /// Currently not populated. /// [JsonProperty(PropertyName = "banscore")] - public int BanScore { get; internal set; } + public int BanScore { get; set; } ///   ///  The last header we have in common with this peer. ///  Currently not populated. ///   [JsonProperty(PropertyName = "synced_headers")] - public int SynchronizedHeaders { get; internal set; } + public int SynchronizedHeaders { get; set; } /// /// The last block we have in common with this peer. /// Currently not populated. /// [JsonProperty(PropertyName = "synced_blocks")] - public int SynchronizedBlocks { get; internal set; } + public int SynchronizedBlocks { get; set; } /// /// Whether the peer is whitelisted. /// [JsonProperty(PropertyName = "whitelisted")] - public bool IsWhiteListed { get; internal set; } + public bool IsWhiteListed { get; set; } /// /// The heights of blocks we're currently asking from this peer. /// Currently not populated. /// [JsonProperty(PropertyName = "inflight")] - public uint[] Inflight { get; internal set; } + public uint[] Inflight { get; set; } /// /// Total sent bytes aggregated by message type. /// Currently not populated. /// [JsonProperty(PropertyName = "bytessent_per_msg")] - public uint[] BytesSentPerMessage { get; internal set; } + public uint[] BytesSentPerMessage { get; set; } /// /// Total received bytes aggregated by message type. /// Currently not populated. /// [JsonProperty(PropertyName = "bytesrecv_per_msg")] - public uint[] BytesReceivedPerMessage { get; internal set; } + public uint[] BytesReceivedPerMessage { get; set; } } } diff --git a/src/Blockcore/EventBus/EventBase.cs b/src/Blockcore/EventBus/EventBase.cs index ebcf1a86a..7c4630bbc 100644 --- a/src/Blockcore/EventBus/EventBase.cs +++ b/src/Blockcore/EventBus/EventBase.cs @@ -1,5 +1,4 @@ using System; -using Blockcore.Broadcasters; namespace Blockcore.EventBus { diff --git a/src/Blockcore/FullNode.cs b/src/Blockcore/FullNode.cs index 58cfb0951..220310d42 100644 --- a/src/Blockcore/FullNode.cs +++ b/src/Blockcore/FullNode.cs @@ -12,7 +12,6 @@ using Blockcore.Interfaces; using Blockcore.Networks; using Blockcore.Utilities; -using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NBitcoin; @@ -45,9 +44,6 @@ public class FullNode : IFullNode /// Provider of notification about newly available blocks and transactions. public Signals.ISignals Signals { get; set; } - /// ASP.NET Core host for RPC server. - public IWebHost RPCHost { get; set; } - /// public FullNodeState State { get; private set; } @@ -284,9 +280,6 @@ public void Dispose() this.logger.LogInformation("Disposing connection manager."); this.ConnectionManager.Dispose(); - this.logger.LogInformation("Disposing RPC host."); - this.RPCHost?.Dispose(); - this.logger.LogInformation("Disposing periodic logging loops."); this.periodicLogLoop?.Dispose(); this.periodicBenchmarkLoop?.Dispose(); diff --git a/src/Blockcore/IFullNode.cs b/src/Blockcore/IFullNode.cs index 7feb8e219..43791ae87 100644 --- a/src/Blockcore/IFullNode.cs +++ b/src/Blockcore/IFullNode.cs @@ -2,7 +2,6 @@ using Blockcore.Builder; using Blockcore.Networks; using Blockcore.Utilities; -using Microsoft.AspNetCore.Hosting; namespace Blockcore { @@ -26,9 +25,6 @@ public interface IFullNode : IDisposable /// Software version of the full node. Version Version { get; } - /// ASP.NET Core host for RPC server. - IWebHost RPCHost { get; set; } - /// Provides current state of the node. FullNodeState State { get; } diff --git a/src/Features/Blockcore.Features.Consensus/Blockcore.Features.Consensus.csproj b/src/Features/Blockcore.Features.Consensus/Blockcore.Features.Consensus.csproj index b2cb86705..0fbf17908 100644 --- a/src/Features/Blockcore.Features.Consensus/Blockcore.Features.Consensus.csproj +++ b/src/Features/Blockcore.Features.Consensus/Blockcore.Features.Consensus.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Features/Blockcore.Features.Diagnostic/Blockcore.Features.Diagnostic.csproj b/src/Features/Blockcore.Features.Diagnostic/Blockcore.Features.Diagnostic.csproj index ffcda1524..269bd0355 100644 --- a/src/Features/Blockcore.Features.Diagnostic/Blockcore.Features.Diagnostic.csproj +++ b/src/Features/Blockcore.Features.Diagnostic/Blockcore.Features.Diagnostic.csproj @@ -6,6 +6,7 @@ + diff --git a/src/Features/Blockcore.Features.NodeHost/Blockcore.Features.NodeHost.csproj b/src/Features/Blockcore.Features.NodeHost/Blockcore.Features.NodeHost.csproj index 498aaa959..11d5487bc 100644 --- a/src/Features/Blockcore.Features.NodeHost/Blockcore.Features.NodeHost.csproj +++ b/src/Features/Blockcore.Features.NodeHost/Blockcore.Features.NodeHost.csproj @@ -22,6 +22,7 @@ + all diff --git a/src/Blockcore/Broadcasters/BroadcasterBase.cs b/src/Features/Blockcore.Features.NodeHost/Broadcasters/BroadcasterBase.cs similarity index 98% rename from src/Blockcore/Broadcasters/BroadcasterBase.cs rename to src/Features/Blockcore.Features.NodeHost/Broadcasters/BroadcasterBase.cs index a1779b921..eab3c3a26 100644 --- a/src/Blockcore/Broadcasters/BroadcasterBase.cs +++ b/src/Features/Blockcore.Features.NodeHost/Broadcasters/BroadcasterBase.cs @@ -4,7 +4,6 @@ using Blockcore.AsyncWork; using Blockcore.EventBus; using Blockcore.Utilities; -using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; namespace Blockcore.Broadcasters diff --git a/src/Blockcore/Broadcasters/ClientEventBroadcasterSettings.cs b/src/Features/Blockcore.Features.NodeHost/Broadcasters/ClientEventBroadcasterSettings.cs similarity index 100% rename from src/Blockcore/Broadcasters/ClientEventBroadcasterSettings.cs rename to src/Features/Blockcore.Features.NodeHost/Broadcasters/ClientEventBroadcasterSettings.cs diff --git a/src/Blockcore/Broadcasters/IClientEventBroadcaster.cs b/src/Features/Blockcore.Features.NodeHost/Broadcasters/IClientEventBroadcaster.cs similarity index 82% rename from src/Blockcore/Broadcasters/IClientEventBroadcaster.cs rename to src/Features/Blockcore.Features.NodeHost/Broadcasters/IClientEventBroadcaster.cs index 7c89798bd..f42598e18 100644 --- a/src/Blockcore/Broadcasters/IClientEventBroadcaster.cs +++ b/src/Features/Blockcore.Features.NodeHost/Broadcasters/IClientEventBroadcaster.cs @@ -1,4 +1,3 @@ -using Microsoft.AspNetCore.SignalR; namespace Blockcore.Broadcasters { diff --git a/src/Blockcore/Broadcasters/IEventsSubscriptionService.cs b/src/Features/Blockcore.Features.NodeHost/Broadcasters/IEventsSubscriptionService.cs similarity index 100% rename from src/Blockcore/Broadcasters/IEventsSubscriptionService.cs rename to src/Features/Blockcore.Features.NodeHost/Broadcasters/IEventsSubscriptionService.cs diff --git a/src/Blockcore/Controllers/ConnectionManagerController.cs b/src/Features/Blockcore.Features.NodeHost/Controller/ConnectionManagerController.cs similarity index 93% rename from src/Blockcore/Controllers/ConnectionManagerController.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/ConnectionManagerController.cs index 246339b85..2d10ce129 100644 --- a/src/Blockcore/Controllers/ConnectionManagerController.cs +++ b/src/Features/Blockcore.Features.NodeHost/Controller/ConnectionManagerController.cs @@ -52,7 +52,7 @@ public IActionResult AddNode([FromQuery] string endpoint, string command) Guard.NotEmpty(endpoint, nameof(endpoint)); Guard.NotEmpty(command, nameof(command)); - return this.Json(ConnectionManagerRPCController.AddNode(this.ConnectionManager, this.peerBanning, endpoint, command)); + return this.Json(ConnectionManagerHelper.AddNode(this.ConnectionManager, this.peerBanning, endpoint, command)); } catch (Exception e) { @@ -74,7 +74,7 @@ public IActionResult GetPeerInfo() { try { - return this.Json(ConnectionManagerRPCController.GetPeerInfo(this.ConnectionManager)); + return this.Json(ConnectionManagerHelper.GetPeerInfo(this.ConnectionManager)); } catch (Exception e) { diff --git a/src/Features/Blockcore.Features.NodeHost/Controller/ConnectionManagerHelper.cs b/src/Features/Blockcore.Features.NodeHost/Controller/ConnectionManagerHelper.cs new file mode 100644 index 000000000..ed14eb8df --- /dev/null +++ b/src/Features/Blockcore.Features.NodeHost/Controller/ConnectionManagerHelper.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using Blockcore.Connection; +using Blockcore.P2P.Peer; +using Blockcore.Utilities; +using Blockcore.Utilities.Extensions; +using Blockcore.Utilities.JsonErrors; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace Blockcore.Controllers +{ + public class ConnectionManagerHelper + { + public static bool AddNode(IConnectionManager connectionManager, IPeerBanning peerBanning, string endpointStr, string command) + { + IPEndPoint endpoint = endpointStr.ToIPEndPoint(connectionManager.Network.DefaultPort); + switch (command) + { + case "add": + if (peerBanning.IsBanned(endpoint)) + throw new InvalidOperationException("Can't perform 'add' for a banned peer."); + + connectionManager.AddNodeAddress(endpoint); + break; + + case "remove": + connectionManager.RemoveNodeAddress(endpoint); + break; + + case "onetry": + if (peerBanning.IsBanned(endpoint)) + throw new InvalidOperationException("Can't connect to a banned peer."); + + connectionManager.ConnectAsync(endpoint).GetAwaiter().GetResult(); + break; + + default: + throw new ArgumentException("command"); + } + + return true; + } + + public static List GetPeerInfo(IConnectionManager connectionManager) + { + var peerList = new List(); + + List peers = connectionManager.ConnectedPeers.ToList(); + foreach (INetworkPeer peer in peers) + { + if ((peer != null) && (peer.RemoteSocketAddress != null)) + { + var peerNode = new PeerNodeModel + { + Id = peers.IndexOf(peer), + Address = peer.RemoteSocketEndpoint.ToString() + }; + + if (peer.PeerVersion != null) + { + peerNode.LocalAddress = peer.PeerVersion.AddressReceiver?.ToString(); + peerNode.Services = ((ulong)peer.PeerVersion.Services).ToString("X"); + peerNode.Version = (uint)peer.PeerVersion.Version; + peerNode.SubVersion = peer.PeerVersion.UserAgent; + peerNode.StartingHeight = peer.PeerVersion.StartHeight; + } + + var connectionManagerBehavior = peer.Behavior(); + if (connectionManagerBehavior != null) + { + peerNode.Inbound = peer.Inbound; + peerNode.IsWhiteListed = connectionManagerBehavior.Whitelisted; + } + + if (peer.TimeOffset != null) + { + peerNode.TimeOffset = peer.TimeOffset.Value.Seconds; + } + + peerList.Add(peerNode); + } + } + + return peerList; + } + } +} \ No newline at end of file diff --git a/src/Blockcore/Controllers/Converters/BtcDecimalJsonConverter.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Converters/BtcDecimalJsonConverter.cs similarity index 100% rename from src/Blockcore/Controllers/Converters/BtcDecimalJsonConverter.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Converters/BtcDecimalJsonConverter.cs diff --git a/src/Blockcore/Controllers/Converters/ToStringJsonConverter.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Converters/ToStringJsonConverter.cs similarity index 100% rename from src/Blockcore/Controllers/Converters/ToStringJsonConverter.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Converters/ToStringJsonConverter.cs diff --git a/src/Blockcore/Controllers/DashboardController.cs b/src/Features/Blockcore.Features.NodeHost/Controller/DashboardController.cs similarity index 100% rename from src/Blockcore/Controllers/DashboardController.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/DashboardController.cs diff --git a/src/Blockcore/Controllers/FeatureController.cs b/src/Features/Blockcore.Features.NodeHost/Controller/FeatureController.cs similarity index 100% rename from src/Blockcore/Controllers/FeatureController.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/FeatureController.cs diff --git a/src/Blockcore/Controllers/Models/AddressBalancesResult.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/AddressBalancesResult.cs similarity index 100% rename from src/Blockcore/Controllers/Models/AddressBalancesResult.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/AddressBalancesResult.cs diff --git a/src/Blockcore/Controllers/Models/AsyncLoopModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/AsyncLoopModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/AsyncLoopModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/AsyncLoopModel.cs diff --git a/src/Blockcore/Controllers/Models/BannedPeerModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/BannedPeerModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/BannedPeerModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/BannedPeerModel.cs diff --git a/src/Blockcore/Controllers/Models/BlockHeaderModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/BlockHeaderModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/BlockHeaderModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/BlockHeaderModel.cs diff --git a/src/Blockcore/Controllers/Models/BlockModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/BlockModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/BlockModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/BlockModel.cs diff --git a/src/Blockcore/Controllers/Models/ConnectedPeerModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/ConnectedPeerModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/ConnectedPeerModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/ConnectedPeerModel.cs diff --git a/src/Blockcore/Controllers/Models/DecodeRawTransactionModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/DecodeRawTransactionModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/DecodeRawTransactionModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/DecodeRawTransactionModel.cs diff --git a/src/Blockcore/Controllers/Models/DisconnectPeerViewModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/DisconnectPeerViewModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/DisconnectPeerViewModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/DisconnectPeerViewModel.cs diff --git a/src/Blockcore/Controllers/Models/GetTxOutModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/GetTxOutModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/GetTxOutModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/GetTxOutModel.cs diff --git a/src/Blockcore/Controllers/Models/LogRuleModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/LogRuleModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/LogRuleModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/LogRuleModel.cs diff --git a/src/Blockcore/Controllers/Models/LogRulesRequest.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/LogRulesRequest.cs similarity index 100% rename from src/Blockcore/Controllers/Models/LogRulesRequest.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/LogRulesRequest.cs diff --git a/src/Blockcore/Controllers/Models/SetBanPeerViewModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/SetBanPeerViewModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/SetBanPeerViewModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/SetBanPeerViewModel.cs diff --git a/src/Blockcore/Controllers/Models/StatusModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/StatusModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/StatusModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/StatusModel.cs diff --git a/src/Blockcore/Controllers/Models/TransactionModel.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/TransactionModel.cs similarity index 100% rename from src/Blockcore/Controllers/Models/TransactionModel.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/TransactionModel.cs diff --git a/src/Blockcore/Controllers/Models/ValidatedAddress.cs b/src/Features/Blockcore.Features.NodeHost/Controller/Models/ValidatedAddress.cs similarity index 100% rename from src/Blockcore/Controllers/Models/ValidatedAddress.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/Models/ValidatedAddress.cs diff --git a/src/Blockcore/Controllers/NetworkController.cs b/src/Features/Blockcore.Features.NodeHost/Controller/NetworkController.cs similarity index 100% rename from src/Blockcore/Controllers/NetworkController.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/NetworkController.cs diff --git a/src/Blockcore/Controllers/NodeController.cs b/src/Features/Blockcore.Features.NodeHost/Controller/NodeController.cs similarity index 100% rename from src/Blockcore/Controllers/NodeController.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/NodeController.cs diff --git a/src/Blockcore/Controllers/RestApiClientBase.cs b/src/Features/Blockcore.Features.NodeHost/Controller/RestApiClientBase.cs similarity index 100% rename from src/Blockcore/Controllers/RestApiClientBase.cs rename to src/Features/Blockcore.Features.NodeHost/Controller/RestApiClientBase.cs diff --git a/src/Blockcore/Utilities/JsonErrors/ErrorHelpers.cs b/src/Features/Blockcore.Features.NodeHost/JsonErrors/ErrorHelpers.cs similarity index 100% rename from src/Blockcore/Utilities/JsonErrors/ErrorHelpers.cs rename to src/Features/Blockcore.Features.NodeHost/JsonErrors/ErrorHelpers.cs diff --git a/src/Blockcore/Utilities/JsonErrors/ErrorResponse.cs b/src/Features/Blockcore.Features.NodeHost/JsonErrors/ErrorResponse.cs similarity index 100% rename from src/Blockcore/Utilities/JsonErrors/ErrorResponse.cs rename to src/Features/Blockcore.Features.NodeHost/JsonErrors/ErrorResponse.cs diff --git a/src/Blockcore/Utilities/JsonErrors/ErrorResult.cs b/src/Features/Blockcore.Features.NodeHost/JsonErrors/ErrorResult.cs similarity index 87% rename from src/Blockcore/Utilities/JsonErrors/ErrorResult.cs rename to src/Features/Blockcore.Features.NodeHost/JsonErrors/ErrorResult.cs index 0776a73ff..7e276cdfd 100644 --- a/src/Blockcore/Utilities/JsonErrors/ErrorResult.cs +++ b/src/Features/Blockcore.Features.NodeHost/JsonErrors/ErrorResult.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc; + +using Microsoft.AspNetCore.Mvc; namespace Blockcore.Utilities.JsonErrors { diff --git a/src/Blockcore/Utilities/ModelStateErrors/ModelStateErrors.cs b/src/Features/Blockcore.Features.NodeHost/ModelStateErrors/ModelStateErrors.cs similarity index 100% rename from src/Blockcore/Utilities/ModelStateErrors/ModelStateErrors.cs rename to src/Features/Blockcore.Features.NodeHost/ModelStateErrors/ModelStateErrors.cs diff --git a/src/Features/Blockcore.Features.NodeHost/NodeHostFeature.cs b/src/Features/Blockcore.Features.NodeHost/NodeHostFeature.cs index 0866ad67b..f2d3de458 100644 --- a/src/Features/Blockcore.Features.NodeHost/NodeHostFeature.cs +++ b/src/Features/Blockcore.Features.NodeHost/NodeHostFeature.cs @@ -129,6 +129,10 @@ public static IFullNodeBuilder UseNodeHost(this IFullNodeBuilder fullNodeBuilder services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + + // Controller + services.AddTransient(); + }); }); diff --git a/src/Blockcore/UI/BlazorModal/ModalService.cs b/src/Features/Blockcore.Features.NodeHost/UI/BlazorModal/ModalService.cs similarity index 100% rename from src/Blockcore/UI/BlazorModal/ModalService.cs rename to src/Features/Blockcore.Features.NodeHost/UI/BlazorModal/ModalService.cs diff --git a/src/Features/Blockcore.Features.Notifications/Blockcore.Features.Notifications.csproj b/src/Features/Blockcore.Features.Notifications/Blockcore.Features.Notifications.csproj index 2f11ef460..2333c7fe0 100644 --- a/src/Features/Blockcore.Features.Notifications/Blockcore.Features.Notifications.csproj +++ b/src/Features/Blockcore.Features.Notifications/Blockcore.Features.Notifications.csproj @@ -8,6 +8,7 @@ + diff --git a/src/Blockcore/Controllers/ConnectionManagerRPCController.cs b/src/Features/Blockcore.Features.RPC/Controllers/ConnectionManagerRPCController.cs similarity index 100% rename from src/Blockcore/Controllers/ConnectionManagerRPCController.cs rename to src/Features/Blockcore.Features.RPC/Controllers/ConnectionManagerRPCController.cs diff --git a/src/Features/Blockcore.Features.RPC/Controllers/RPCController.cs b/src/Features/Blockcore.Features.RPC/Controllers/RPCController.cs index 8470f86c3..eb2e9bd7f 100644 --- a/src/Features/Blockcore.Features.RPC/Controllers/RPCController.cs +++ b/src/Features/Blockcore.Features.RPC/Controllers/RPCController.cs @@ -35,6 +35,7 @@ public class RPCController : Controller /// RPC Client Factory. private readonly IRPCClientFactory rpcClientFactory; + private readonly IRPCFeature rpcFeature; /// ControllerActionDescriptor dictionary. private Dictionary ActionDescriptors { get; set; } @@ -45,7 +46,7 @@ public class RPCController : Controller /// The full node. /// Factory to be used to create logger for the node. /// The RPC Settings of the full node. - public RPCController(IFullNode fullNode, ILoggerFactory loggerFactory, RpcSettings rpcSettings, IRPCClientFactory rpcClientFactory) + public RPCController(IFullNode fullNode, ILoggerFactory loggerFactory, RpcSettings rpcSettings, IRPCClientFactory rpcClientFactory, IRPCFeature rpcFeature) { Guard.NotNull(fullNode, nameof(fullNode)); Guard.NotNull(loggerFactory, nameof(loggerFactory)); @@ -56,6 +57,7 @@ public RPCController(IFullNode fullNode, ILoggerFactory loggerFactory, RpcSettin this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.rpcSettings = rpcSettings; this.rpcClientFactory = rpcClientFactory; + this.rpcFeature = rpcFeature; } /// @@ -66,7 +68,8 @@ private Dictionary GetActionDescriptors() if (this.ActionDescriptors == null) { this.ActionDescriptors = new Dictionary(); - var actionDescriptorProvider = this.fullNode?.RPCHost.Services.GetService(typeof(IActionDescriptorCollectionProvider)) as IActionDescriptorCollectionProvider; + var host = this.rpcFeature.RPCHost; + var actionDescriptorProvider = host?.Services.GetService(typeof(IActionDescriptorCollectionProvider)) as IActionDescriptorCollectionProvider; // This approach is similar to the one used by RPCRouteHandler so should only give us the descriptors // that RPC would normally act on subject to the method name matching the "ActionName". foreach (ControllerActionDescriptor actionDescriptor in actionDescriptorProvider?.ActionDescriptors.Items.OfType()) diff --git a/src/Features/Blockcore.Features.RPC/RPCFeature.cs b/src/Features/Blockcore.Features.RPC/RPCFeature.cs index e4d736ffb..735536832 100644 --- a/src/Features/Blockcore.Features.RPC/RPCFeature.cs +++ b/src/Features/Blockcore.Features.RPC/RPCFeature.cs @@ -14,8 +14,16 @@ namespace Blockcore.Features.RPC { - public class RPCFeature : FullNodeFeature + public interface IRPCFeature { + IWebHost RPCHost { get; set; } + } + + public class RPCFeature : FullNodeFeature, IRPCFeature + { + /// How long we are willing to wait for the NodeHost to stop. + private const int NodeHostStopTimeoutSeconds = 10; + private readonly FullNode fullNode; private readonly NodeSettings nodeSettings; @@ -26,6 +34,8 @@ public class RPCFeature : FullNodeFeature private readonly RpcSettings rpcSettings; + public IWebHost RPCHost { get; set; } + public RPCFeature(IFullNodeBuilder fullNodeBuilder, FullNode fullNode, NodeSettings nodeSettings, ILoggerFactory loggerFactory, RpcSettings rpcSettings) { this.fullNodeBuilder = fullNodeBuilder; @@ -69,7 +79,8 @@ public override Task InitializeAsync() { // TODO: The web host wants to create IServiceProvider, so build (but not start) // earlier, if you want to use dependency injection elsewhere - this.fullNode.RPCHost = new WebHostBuilder() + + var webHost = new WebHostBuilder() .UseKestrel(o => o.AllowSynchronousIO = true) .ForFullNode(this.fullNode) .UseUrls(this.rpcSettings.GetUrls()) @@ -105,7 +116,8 @@ public override Task InitializeAsync() .UseStartup() .Build(); - this.fullNode.RPCHost.Start(); + webHost.Start(); + this.RPCHost = webHost; this.logger.LogInformation("RPC listening on: " + Environment.NewLine + string.Join(Environment.NewLine, this.rpcSettings.GetUrls())); } else @@ -115,6 +127,18 @@ public override Task InitializeAsync() return Task.CompletedTask; } + + /// + public override void Dispose() + { + // Make sure we are releasing the listening ip address / port. + if (this.RPCHost != null) + { + this.logger.LogInformation("Disposing RPC host."); + this.RPCHost.StopAsync(TimeSpan.FromSeconds(NodeHostStopTimeoutSeconds)).Wait(); + this.RPCHost = null; + } + } } /// @@ -131,7 +155,11 @@ public static IFullNodeBuilder AddRPC(this IFullNodeBuilder fullNodeBuilder) features .AddFeature() .DependOn() - .FeatureServices(services => services.AddSingleton(fullNodeBuilder)); + .FeatureServices(services => + { + services.AddSingleton(fullNodeBuilder); + services.AddSingleton(provider => provider.GetService()); + }); }); fullNodeBuilder.ConfigureServices(service => diff --git a/src/Tests/Blockcore.Features.RPC.Tests/Controller/RPCControllerTest.cs b/src/Tests/Blockcore.Features.RPC.Tests/Controller/RPCControllerTest.cs index 77a56269d..2aade58f6 100644 --- a/src/Tests/Blockcore.Features.RPC.Tests/Controller/RPCControllerTest.cs +++ b/src/Tests/Blockcore.Features.RPC.Tests/Controller/RPCControllerTest.cs @@ -35,6 +35,7 @@ public class RPCControllerTest : LogsTestBase private readonly RPCController controller; private readonly Mock rpcClientFactory; private readonly Mock rpcHost; + private readonly Mock rpcFeature; private readonly Mock serviceProvider; private readonly Mock actionDescriptorCollectionProvider; private readonly Mock rpcClient; @@ -58,7 +59,8 @@ public RPCControllerTest() this.rpcClientFactory.Setup(r => r.Create(It.IsAny(), It.Is(u => u.ToString() == "http://127.0.0.1:0/"), It.IsAny())) .Returns(this.rpcClient.Object); - this.fullNode.Setup(f => f.RPCHost) + this.rpcFeature = new Mock(); + this.rpcFeature.Setup(f => f.RPCHost) .Returns(this.rpcHost.Object); this.rpcHost.Setup(c => c.Services) .Returns(this.serviceProvider.Object); @@ -72,7 +74,7 @@ public RPCControllerTest() return new ActionDescriptorCollection(this.descriptors, 0); }); - this.controller = new RPCController(this.fullNode.Object, this.LoggerFactory.Object, this.rpcSettings, this.rpcClientFactory.Object); + this.controller = new RPCController(this.fullNode.Object, this.LoggerFactory.Object, this.rpcSettings, this.rpcClientFactory.Object, this.rpcFeature.Object); } [Fact] @@ -120,7 +122,7 @@ public void ListMethods_NoDescriptors_ReturnsEmptyModel() [Fact] public void ListMethods_WithException_ReturnsErrorResult() { - this.fullNode.Setup(f => f.RPCHost) + this.rpcFeature.Setup(f => f.RPCHost) .Throws(new InvalidOperationException("Could not find RPCHost")); IActionResult controllerResult = this.controller.ListMethods(); @@ -201,7 +203,7 @@ public void CallByName_RpcMethodNotFound_ReturnsErrorResult() [Fact] public void CallByName_WithException_ReturnsErrorResult() { - this.fullNode.Setup(f => f.RPCHost) + this.rpcFeature.Setup(f => f.RPCHost) .Throws(new InvalidOperationException("Could not find RPCHost")); var body = JObject.FromObject(new { methodName = "getblockheader" }); From 4ab57b201a1897b4e9e92ab84a41063148d404f0 Mon Sep 17 00:00:00 2001 From: dangershony Date: Mon, 10 Oct 2022 20:43:34 +0100 Subject: [PATCH 008/194] Remove empty solution folder --- src/Blockcore/Blockcore.csproj | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Blockcore/Blockcore.csproj b/src/Blockcore/Blockcore.csproj index 89c36a49a..1fd4bc49c 100644 --- a/src/Blockcore/Blockcore.csproj +++ b/src/Blockcore/Blockcore.csproj @@ -56,11 +56,6 @@ - - - - - Library From 09be90ae0f6dc04a980cf7aa3572ec1fa82afd46 Mon Sep 17 00:00:00 2001 From: SondreB Date: Thu, 20 Oct 2022 12:42:00 +0200 Subject: [PATCH 009/194] Remove the reload on change to reduce listeners handlers (OS resources) --- src/Features/Blockcore.Features.NodeHost/Startup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/Blockcore.Features.NodeHost/Startup.cs b/src/Features/Blockcore.Features.NodeHost/Startup.cs index ead9aa340..aba1699f4 100644 --- a/src/Features/Blockcore.Features.NodeHost/Startup.cs +++ b/src/Features/Blockcore.Features.NodeHost/Startup.cs @@ -35,7 +35,7 @@ public Startup(IWebHostEnvironment env, IFullNode fullNode) IConfigurationBuilder builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false) - .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false) .AddEnvironmentVariables(); this.Configuration = builder.Build(); From 62f41df7accb3fc888f6f8fa5c3fb536040c9981 Mon Sep 17 00:00:00 2001 From: dangershony Date: Sun, 23 Oct 2022 20:48:06 +0100 Subject: [PATCH 010/194] Adding BC flags for SHA512 hashes --- src/Blockcore/NBitcoin/BIP32/ExtKey.cs | 16 ++++++++++++++++ src/Blockcore/NBitcoin/Crypto/Hashes.cs | 15 ++++++++++++++- .../Helpers/HdOperations.cs | 18 +++++++++++++++++- .../WalletSyncManagerTest.cs | 2 +- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/Blockcore/NBitcoin/BIP32/ExtKey.cs b/src/Blockcore/NBitcoin/BIP32/ExtKey.cs index 398ebfc71..93fc8d6bd 100644 --- a/src/Blockcore/NBitcoin/BIP32/ExtKey.cs +++ b/src/Blockcore/NBitcoin/BIP32/ExtKey.cs @@ -13,6 +13,8 @@ namespace NBitcoin /// public class ExtKey : IBitcoinSerializable, IDestination, ISecret { + public static bool UseBCForHMACSHA512 = false; + /// /// Parses the Base58 data (checking the network if specified), checks it represents the /// correct type of item, and then returns the corresponding ExtKey. @@ -167,6 +169,20 @@ public ExtKey(byte[] seed) private void SetMaster(byte[] seed) { + if (UseBCForHMACSHA512) + { + var mac = new NBitcoin.BouncyCastle.Crypto.Macs.HMac(new NBitcoin.BouncyCastle.Crypto.Digests.Sha512Digest()); + mac.Init(new NBitcoin.BouncyCastle.Crypto.Parameters.KeyParameter(hashkey)); + byte[] hashMACBC = new byte[mac.GetMacSize()]; + byte[] hash = new byte[mac.GetMacSize()]; + mac.BlockUpdate(seed, 0, seed.Length); + mac.DoFinal(hash, 0); + Array.Copy(hash, hashMACBC, hashMACBC.Length); + this.key = new Key(hashMACBC.SafeSubarray(0, 32)); + Buffer.BlockCopy(hashMACBC, 32, this.vchChainCode, 0, ChainCodeLength); + return; + } + byte[] hashMAC = Hashes.HMACSHA512(hashkey, seed); this.key = new Key(hashMAC.SafeSubarray(0, 32)); diff --git a/src/Blockcore/NBitcoin/Crypto/Hashes.cs b/src/Blockcore/NBitcoin/Crypto/Hashes.cs index f6bc93356..7869282de 100644 --- a/src/Blockcore/NBitcoin/Crypto/Hashes.cs +++ b/src/Blockcore/NBitcoin/Crypto/Hashes.cs @@ -3,11 +3,14 @@ using System.Linq; using NBitcoin.BouncyCastle.Crypto.Digests; using System.Security.Cryptography; +using NBitcoin.BouncyCastle.Crypto.Parameters; namespace NBitcoin.Crypto { public static class Hashes { + public static bool UseBCForHMACSHA512 = false; + #region Hash256 public static uint256 Hash256(byte[] data) @@ -65,7 +68,7 @@ public static uint160 Hash160(byte[] data, int offset, int count) #region RIPEMD160 - private static byte[] RIPEMD160(byte[] data) + public static byte[] RIPEMD160(byte[] data) { return RIPEMD160(data, 0, data.Length); } @@ -380,6 +383,16 @@ public static uint MurmurHash3(uint nHashSeed, byte[] vDataToHash) public static byte[] HMACSHA512(byte[] key, byte[] data) { + if (UseBCForHMACSHA512) + { + var mac = new NBitcoin.BouncyCastle.Crypto.Macs.HMac(new Sha512Digest()); + mac.Init(new KeyParameter(key)); + mac.BlockUpdate(data, 0, data.Length); + byte[] result = new byte[mac.GetMacSize()]; + mac.DoFinal(result, 0); + return result; + } + return new HMACSHA512(key).ComputeHash(data); } diff --git a/src/Features/Blockcore.Features.Wallet/Helpers/HdOperations.cs b/src/Features/Blockcore.Features.Wallet/Helpers/HdOperations.cs index 09af96217..53ae8bb99 100644 --- a/src/Features/Blockcore.Features.Wallet/Helpers/HdOperations.cs +++ b/src/Features/Blockcore.Features.Wallet/Helpers/HdOperations.cs @@ -24,10 +24,26 @@ public static PubKey GeneratePublicKey(string accountExtPubKey, int index, bool { Guard.NotEmpty(accountExtPubKey, nameof(accountExtPubKey)); + return GeneratePublicKey(ExtPubKey.Parse(accountExtPubKey), index, isChange); + } + + /// + /// Generates an HD public key derived from an extended public key. + /// + /// The extended public key used to generate child keys. + /// The index of the child key to generate. + /// A value indicating whether the public key to generate corresponds to a change address. + /// + /// An HD public key derived from an extended public key. + /// + public static PubKey GeneratePublicKey(ExtPubKey accountExtPubKey, int index, bool isChange) + { + Guard.NotNull(accountExtPubKey, nameof(accountExtPubKey)); + int change = isChange ? 1 : 0; var keyPath = new KeyPath($"{change}/{index}"); // TODO: Should probably explicitly be passing the network into Parse - ExtPubKey extPubKey = ExtPubKey.Parse(accountExtPubKey).Derive(keyPath); + ExtPubKey extPubKey = accountExtPubKey.Derive(keyPath); return extPubKey.PubKey; } diff --git a/src/Tests/Blockcore.Features.Wallet.Tests/WalletSyncManagerTest.cs b/src/Tests/Blockcore.Features.Wallet.Tests/WalletSyncManagerTest.cs index f043e636e..6508835f2 100644 --- a/src/Tests/Blockcore.Features.Wallet.Tests/WalletSyncManagerTest.cs +++ b/src/Tests/Blockcore.Features.Wallet.Tests/WalletSyncManagerTest.cs @@ -51,7 +51,7 @@ public WalletSyncManagerTest() this.walletManager.Setup(w => w.ContainsWallets).Returns(true); } - [Fact(Skip = "Enables this whwn wallet can support prunning")] + [Fact(Skip = "Enables this when wallet can support pruning")] public void Start_HavingPrunedStoreSetting_ThrowsWalletException() { this.storeSettings.AmountOfBlocksToKeep = 1; From 91eaea8862629295ade673edaaf9fca3fcfe44a1 Mon Sep 17 00:00:00 2001 From: implx <1c@ua.fm> Date: Mon, 24 Oct 2022 18:33:18 +0400 Subject: [PATCH 011/194] Adding MOL blockchain (#423) * readme * added impleum network * build removed * build removed * Impleum network new settings prepared * Merged with blockcore. Fixing Impleum network params * Impleum update mamx supply * Impleum magic comment added * temporary remove workflows * Fix for impleum bad address * Update DNSSeedData * Updates static Nodes * Update ImpleumSetup.cs * Update ImpleumSetup.cs * Update ImpleumSetup.cs * Upate MinTxFee * Upate MinTxFee TestNet * Upate MinTxFee TestNet * Impleum: Fix for MaxTxFee * fix bip 9 deployments * Ass mainnet nodes * Add mainnet nodes * cd /Users/elenabulanova/IMPL/D/ddd/blockcore * Workflows add * Fix DefaultThreshold * Update ImpleumSetup.cs * Add IMPLX seed Nodes * Add checkpoints for City Chain network * Added Tech Molie network * fix MOL commandline arg * MOL checkpoints * Blockore merge * Add Molie network to Network folder * Update launchSettings.json * Impleum Logo and new IMPLX and MOL Seed Nodes * Add IMPL and MOL checkpoints Co-authored-by: Anton Yaroshenko Co-authored-by: Elena Bulanova Co-authored-by: Yurii Bulakh Co-authored-by: yuriy.bulah Co-authored-by: Milad --- src/Blockcore.sln | 7 + .../ImpleumSetup.cs | 23 +- .../Blockcore.Networks.Impleum/icon.png | Bin 1419 -> 310973 bytes .../Blockcore.Networks.Molie.csproj | 34 +++ .../Deployments/MolieBIP9Deployments.cs | 58 ++++ .../Blockcore.Networks.Molie/MolieMain.cs | 263 ++++++++++++++++++ .../Blockcore.Networks.Molie/MolieRegTest.cs | 129 +++++++++ .../Blockcore.Networks.Molie/MolieSetup.cs | 191 +++++++++++++ .../Blockcore.Networks.Molie/MolieTest.cs | 127 +++++++++ .../Blockcore.Networks.Molie/Networks.cs | 14 + .../Policies/MollieStandardScriptsRegistry.cs | 44 +++ .../Rules/MollieHeaderVersionRule.cs | 49 ++++ .../Blockcore.Networks.Molie/icon.png | Bin 0 -> 23600 bytes .../Blockcore.Networks.Molie/icon_mes.png | Bin 0 -> 23424 bytes src/Node/Blockcore.Node/Blockcore.Node.csproj | 9 + src/Node/Blockcore.Node/NetworkSelector.cs | 4 + src/Node/Blockcore.Node/NodeBuilder.cs | 1 + .../Properties/launchSettings.json | 30 +- 18 files changed, 954 insertions(+), 29 deletions(-) create mode 100644 src/Networks/Blockcore.Networks.Molie/Blockcore.Networks.Molie.csproj create mode 100644 src/Networks/Blockcore.Networks.Molie/Deployments/MolieBIP9Deployments.cs create mode 100644 src/Networks/Blockcore.Networks.Molie/MolieMain.cs create mode 100644 src/Networks/Blockcore.Networks.Molie/MolieRegTest.cs create mode 100644 src/Networks/Blockcore.Networks.Molie/MolieSetup.cs create mode 100644 src/Networks/Blockcore.Networks.Molie/MolieTest.cs create mode 100644 src/Networks/Blockcore.Networks.Molie/Networks.cs create mode 100644 src/Networks/Blockcore.Networks.Molie/Policies/MollieStandardScriptsRegistry.cs create mode 100644 src/Networks/Blockcore.Networks.Molie/Rules/MollieHeaderVersionRule.cs create mode 100644 src/Networks/Blockcore.Networks.Molie/icon.png create mode 100644 src/Networks/Blockcore.Networks.Molie/icon_mes.png 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 73ce872131d0c9ea6ad0bb20b702ed1166faffe6..dd033186181c81a1e0556b727233c381fb01b8c3 100644 GIT binary patch literal 310973 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

s-Tj+jFZ@PME@vsOH~xpOPU)JMir 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 !9Dokn=kKv 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 z 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 literal 1419 zcmV;61$6p}P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1t3X8K~z{r?N@DU zTtyThW(ZVlM zQOv^nohbM!;KvQFLxep% zR=JCXqi@7%>TMv}npTC4|Gs*n?hH{I)*2yEQOL==*Rb`+LNAI>g-Q)NLHb!gl94m^ zr=-`<2eIfx-g=B^FiRv*_=TgAno>mXK5N!Z%n`l!RWx4%6L%8;`A*%PQDz}&2f9cl z7$rEPnRRBjCt558-#`naByz6dMJnR*?91Y_S_fQS)?{%M@VcLK0#InDE9xcA7BK;I zaAcO~=&T{u;t&haiLs|^4cVm?6Ypyc1^l*T*F^CPBVO<)uuGF7Xkf_3S0(M87PN0l z(B(BHs&bV5O=?11lg(T=zP>Gr96n6t(!5$1hs=NRewws^jvoqX2*_z=2nP26&K~XC zk)*?qr|6xbBnnIFYhbj0cZ&A!NzrpXT;~n6a@#GZnMFzUIFMagBj^UUWCdp@Dq7di zD{d_SA0C0K8m-JbTs@l@?b(u`Tr;PZ8ngdTb>K4yw*d(pF_pi)&5#Mn==W=qdT<^# zAzyFFq8_(iYoN&`_WyJ!0Q+zD#dNNq#0+IjVTFkmBkW<@nZo3vpv`!8w;11*RiX_X z!1-lKA098!fv-#S={F_Ukk{NSm+X&FK(PM`HdzT8YEGcA8SjPbf|A&hT$}OT5$JYV z(1Xp4>S~k#PSX&i#NW6n>G;oOI&rp43z&$jZGoKpkq;X6Zvx(VqQK!CcIv#uL5!a1 zn*tM95_JD&PT6{pse^@yY}_H*)~*C$BJfSksTzhbn52eo$Xreei0l1V#*xs4ed!1j z4bqrRZ=)U%Efgdztw}w8WlGeOe_fc_F_qQSGXnV;+&w<_+$swE(sM_y#lzqspx>4*2~^RS^75 z9P9G|xiWPIa?xZ@wO`1)0i%M#S69Qu?CAX%fI25Fw>FM~TqPPpkmw|fz#oY6V;XlE zao`VfB5^s-B>U2GYf}?AqZ0ks#6kJ}4kPg@9r_bgP(BSQaQnS-Xe6_4xwWYYyp2U7 zO!QE_n2pB~+YSZzA@(-@eu*}4dbhuztNio}QZd!piTm*XJe`wrK} z6Ne5r9XL1=9=^czJ*RBw;94sdJPBk0hW}#X#VkC3^;b>;H-VpUbxn_aoN@n({clkt Z`U|%{ysOGk>7oDt002ovPDHLkV1l?Fr$GP! 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,