Commit 80032683 authored by Pavel Pavlov's avatar Pavel Pavlov

Adding transaction to block and adding block to chain (test)

parent c6f578c0
...@@ -17,6 +17,7 @@ using Stratis.Bitcoin.Features.BlockStore; ...@@ -17,6 +17,7 @@ using Stratis.Bitcoin.Features.BlockStore;
using Stratis.Bitcoin.Features.Consensus; using Stratis.Bitcoin.Features.Consensus;
using Stratis.Bitcoin.Features.MemoryPool; using Stratis.Bitcoin.Features.MemoryPool;
using Stratis.Bitcoin.Features.Miner; using Stratis.Bitcoin.Features.Miner;
using Stratis.Bitcoin.Features.Miner.Interfaces;
using Stratis.Bitcoin.Features.RPC; using Stratis.Bitcoin.Features.RPC;
using Stratis.Bitcoin.Features.Wallet; using Stratis.Bitcoin.Features.Wallet;
using Stratis.Bitcoin.Features.Wallet.Controllers; using Stratis.Bitcoin.Features.Wallet.Controllers;
...@@ -38,46 +39,6 @@ namespace DeStream.DeStreamD.ForTest ...@@ -38,46 +39,6 @@ namespace DeStream.DeStreamD.ForTest
MainAsync(args).Wait(); MainAsync(args).Wait();
} }
#region Test
public static DataFolder CreateDataFolder(object caller, [System.Runtime.CompilerServices.CallerMemberName] string callingMethod = "")
{
string directoryPath = GetTestDirectoryPath(caller, callingMethod);
var dataFolder = new DataFolder(new NodeSettings(args: new string[] { $"-datadir={AssureEmptyDir(directoryPath)}" }).DataDir);
return dataFolder;
}
public static string GetTestDirectoryPath(object caller, [System.Runtime.CompilerServices.CallerMemberName] string callingMethod = "")
{
return GetTestDirectoryPath(Path.Combine(caller.GetType().Name, callingMethod));
}
public static string AssureEmptyDir(string dir)
{
int deleteAttempts = 0;
while (deleteAttempts < 50)
{
if (Directory.Exists(dir))
{
try
{
Directory.Delete(dir, true);
break;
}
catch
{
deleteAttempts++;
Thread.Sleep(200);
}
}
else
break;
}
if (deleteAttempts >= 50)
throw new Exception(string.Format("The test folder: {0} could not be deleted.", dir));
Directory.CreateDirectory(dir);
return dir;
}
#endregion
public static async Task MainAsync(string[] args) public static async Task MainAsync(string[] args)
{ {
...@@ -101,76 +62,35 @@ namespace DeStream.DeStreamD.ForTest ...@@ -101,76 +62,35 @@ namespace DeStream.DeStreamD.ForTest
.UseBlockStore() .UseBlockStore()
.UsePosConsensus() .UsePosConsensus()
.UseMempool() .UseMempool()
.UseWallet() .UseWalletDeStream()
.AddPowPosMining() .AddPowPosMining()
.UseApi() .UseApi()
.AddRPC() .AddRPC()
.Build(); .Build();
var walletManager = node.WalletManager(); node.Services.ServiceProvider.GetService<IPowMining>().GenerateBlocks(new ReserveScript { ReserveFullNodeScript = MinerSecret.ScriptPubKey }, 3, uint.MaxValue);
var walletManager = (DeStreamWalletManager)node.WalletManager();
Wallet wallet = TestClassHelper.CreateFirstTransaction(nodeSettings, walletManager);
walletManager.Wallets.Add(wallet);
//var x= node.WalletManager().CreateWallet("password", "MyWallet"); //Wallet wallet = TestClassHelper.CreateFirstTransaction(nodeSettings, ref walletManager, node.NodeService<WalletSettings>(),
//Wallet MyWallet = null; // node.NodeService<IWalletFeePolicy>());
//try //(Wallet wallet, Block block, ChainedHeader chainedHeader) test = TestClassHelper.CreateFirstTransaction(nodeSettings, ref walletManager, node.NodeService<WalletSettings>(),
//{ // node.NodeService<IWalletFeePolicy>());
// MyWallet = node.NodeService<IWalletManager>().LoadWallet("password", "MyWallet"); //((WalletManager)node.NodeService<IWalletManager>()).Wallets.Add(test.wallet);
//}
//catch (Exception ex) //((WalletManager)node.NodeService<IWalletManager>()).LoadKeysLookupLock();
//{ //((WalletManager)node.NodeService<IWalletManager>()).WalletTipHash = test.block.Header.GetHash();
// node.WalletManager().CreateWallet("password", "MyWallet");
//} //((WalletManager)node.NodeService<IWalletManager>()).ProcessBlock(test.block, test.chainedHeader);
//TestClassHelper.CreateFirstTransaction(MyWallet, nodeSettings);
//walletManager.SaveWallets();
//walletManager.Wallets.Add(wallet);
//node.NodeService<IWalletManager>().SaveWallet(MyWallet);
int qwe0 = 1;
//(ExtKey ExtKey, string ExtPubKey) accountKeys = TestClassHelper.GenerateAccountKeys(MyWallet, "password", "m/44'/0'/0'");
//(PubKey PubKey, BitcoinPubKeyAddress Address) spendingKeys = TestClassHelper.GenerateAddressKeys(MyWallet, accountKeys.ExtPubKey, "0/0");
//(PubKey PubKey, BitcoinPubKeyAddress Address) destinationKeys = TestClassHelper.GenerateAddressKeys(MyWallet, accountKeys.ExtPubKey, "0/1");
//(PubKey PubKey, BitcoinPubKeyAddress Address) changeKeys = TestClassHelper.GenerateAddressKeys(MyWallet, accountKeys.ExtPubKey, "1/0");
//var spendingAddress = new HdAddress
//{
// Index = 0,
// HdPath = $"m/44'/0'/0'/0/0",
// Address = spendingKeys.Address.ToString(),
// Pubkey = spendingKeys.PubKey.ScriptPubKey,
// ScriptPubKey = spendingKeys.Address.ScriptPubKey,
// Transactions = new List<TransactionData>()
//};
//var destinationAddress = new HdAddress
//{
// Index = 1,
// HdPath = $"m/44'/0'/0'/0/1",
// Address = destinationKeys.Address.ToString(),
// Pubkey = destinationKeys.PubKey.ScriptPubKey,
// ScriptPubKey = destinationKeys.Address.ScriptPubKey,
// Transactions = new List<TransactionData>()
//};
//var changeAddress = new HdAddress
//{
// Index = 0,
// HdPath = $"m/44'/0'/0'/1/0",
// Address = changeKeys.Address.ToString(),
// Pubkey = changeKeys.PubKey.ScriptPubKey,
// ScriptPubKey = changeKeys.Address.ScriptPubKey,
// Transactions = new List<TransactionData>()
//};
//(ConcurrentChain chain, uint256 blockhash, Block block) chainInfo = TestClassHelper.CreateChainAndCreateFirstBlockWithPaymentToAddress(MyWallet.Network, spendingAddress);
//var transaction = chainInfo.block.Transactions[0];
//int blockHeight = chainInfo.chain.GetBlock(chainInfo.block.GetHash()).Height;
//var walletManager = node.WalletManager();
//walletManager.ProcessTransaction(transaction, blockHeight);
//ChainedHeader chainedBlock = chainInfo.chain.GetBlock(chainInfo.block.GetHash());
//walletManager.ProcessBlock(chainInfo.block, chainedBlock);
int qwe = 1;
if (node != null) if (node != null)
await node.RunAsync(); await node.RunAsync();
int qwe = 1;
} }
catch (Exception ex) catch (Exception ex)
{ {
......
...@@ -2,12 +2,16 @@ ...@@ -2,12 +2,16 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading;
using DeStream.Stratis.Bitcoin.Configuration; using DeStream.Stratis.Bitcoin.Configuration;
using Moq; using Moq;
using NBitcoin; using NBitcoin;
using Stratis.Bitcoin;
using Stratis.Bitcoin.Features.Wallet; using Stratis.Bitcoin.Features.Wallet;
using Stratis.Bitcoin.Features.Wallet.Interfaces; using Stratis.Bitcoin.Features.Wallet.Interfaces;
using Stratis.Bitcoin.IntegrationTests.Common.EnvironmentMockUpHelpers;
using Stratis.Bitcoin.Utilities; using Stratis.Bitcoin.Utilities;
using static Stratis.Bitcoin.BlockPulling.BlockPuller;
namespace DeStream.DeStreamD.ForTest namespace DeStream.DeStreamD.ForTest
{ {
...@@ -29,11 +33,15 @@ namespace DeStream.DeStreamD.ForTest ...@@ -29,11 +33,15 @@ namespace DeStream.DeStreamD.ForTest
} }
public static (ConcurrentChain chain, uint256 blockhash, Block block) CreateChainAndCreateFirstBlockWithPaymentToAddress(Network network, HdAddress address) public static (ConcurrentChain chain, uint256 blockhash, Block block) CreateChainAndCreateFirstBlockWithPaymentToAddress(DeStreamWalletManager walletManager, Network network, HdAddress address)
{ {
var chain = new ConcurrentChain(network); var chain = new ConcurrentChain(network);
//var chain = walletManager.Chain;
var block = new Block(); var block = new Block();
//var block = network.GetGenesis().Header;
block.Header.HashPrevBlock = chain.Tip.HashBlock; block.Header.HashPrevBlock = chain.Tip.HashBlock;
block.Header.Bits = block.Header.GetWorkRequired(network, chain.Tip); block.Header.Bits = block.Header.GetWorkRequired(network, chain.Tip);
block.Header.UpdateTime(DateTimeOffset.UtcNow, network, chain.Tip); block.Header.UpdateTime(DateTimeOffset.UtcNow, network, chain.Tip);
...@@ -126,7 +134,10 @@ namespace DeStream.DeStreamD.ForTest ...@@ -126,7 +134,10 @@ namespace DeStream.DeStreamD.ForTest
return (walletFile, extendedKey); return (walletFile, extendedKey);
} }
public static Wallet CreateFirstTransaction(DeStreamNodeSettings nodeSettings, WalletManager walletManager) //public static Wallet CreateFirstTransaction(DeStreamNodeSettings nodeSettings, ref DeStreamWalletManager walletManager, WalletSettings walletSettings,
// IWalletFeePolicy _walletFeePolicy)
public static (Wallet wallet, Block block, ChainedHeader chainedHeader) CreateFirstTransaction(DeStreamNodeSettings nodeSettings, ref DeStreamWalletManager walletManager, WalletSettings walletSettings,
IWalletFeePolicy _walletFeePolicy)
{ {
Wallet wallet = GenerateBlankWalletWithExtKey("myWallet1", "password").wallet; Wallet wallet = GenerateBlankWalletWithExtKey("myWallet1", "password").wallet;
(ExtKey ExtKey, string ExtPubKey) accountKeys = GenerateAccountKeys(wallet, "password", "m/44'/0'/0'"); (ExtKey ExtKey, string ExtPubKey) accountKeys = GenerateAccountKeys(wallet, "password", "m/44'/0'/0'");
...@@ -165,7 +176,7 @@ namespace DeStream.DeStreamD.ForTest ...@@ -165,7 +176,7 @@ namespace DeStream.DeStreamD.ForTest
}; };
//Generate a spendable transaction //Generate a spendable transaction
(ConcurrentChain chain, uint256 blockhash, Block block) chainInfo = CreateChainAndCreateFirstBlockWithPaymentToAddress(wallet.Network, spendingAddress); (ConcurrentChain chain, uint256 blockhash, Block block) chainInfo = CreateChainAndCreateFirstBlockWithPaymentToAddress(walletManager, wallet.Network, spendingAddress);
TransactionData spendingTransaction = CreateTransactionDataFromFirstBlock(chainInfo); TransactionData spendingTransaction = CreateTransactionDataFromFirstBlock(chainInfo);
spendingAddress.Transactions.Add(spendingTransaction); spendingAddress.Transactions.Add(spendingTransaction);
...@@ -176,13 +187,14 @@ namespace DeStream.DeStreamD.ForTest ...@@ -176,13 +187,14 @@ namespace DeStream.DeStreamD.ForTest
wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount
{ {
Index = 0, Index = 1,
Name = "account1", Name = "account1",
HdPath = "m/44'/0'/0'", HdPath = "m/44'/0'/0'",
ExtendedPubKey = accountKeys.ExtPubKey, ExtendedPubKey = accountKeys.ExtPubKey,
//ExternalAddresses = new List<HdAddress> { spendingAddress, destinationAddress }, //ExternalAddresses = new List<HdAddress> { spendingAddress, destinationAddress },
ExternalAddresses = new List<HdAddress> { spendingAddress }, ExternalAddresses = new List<HdAddress> { spendingAddress },
InternalAddresses = new List<HdAddress> { changeAddress } //InternalAddresses = new List<HdAddress> { changeAddress }
InternalAddresses = new List<HdAddress> { destinationAddress }
}); });
var walletFeePolicy = new Mock<IWalletFeePolicy>(); var walletFeePolicy = new Mock<IWalletFeePolicy>();
...@@ -190,19 +202,24 @@ namespace DeStream.DeStreamD.ForTest ...@@ -190,19 +202,24 @@ namespace DeStream.DeStreamD.ForTest
.Returns(new Money(5000)); .Returns(new Money(5000));
HdAddress spentAddressResult0 = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0); HdAddress spentAddressResult0 = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
//var walletManager = new WalletManager(nodeSettings.LoggerFactory, Network.Main, chainInfo.chain, nodeSettings, new Mock<WalletSettings>().Object, //var _walletManager = new WalletManager(nodeSettings.LoggerFactory, Network.Main, chainInfo.chain, nodeSettings, new Mock<WalletSettings>().Object,
// nodeSettings.DataFolder, walletFeePolicy.Object, new Mock<IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default); // nodeSettings.DataFolder, walletFeePolicy.Object, new Mock<IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default);
walletManager = new DeStreamWalletManager(nodeSettings.LoggerFactory, nodeSettings.Network, chainInfo.chain, nodeSettings,
walletSettings,
nodeSettings.DataFolder, walletFeePolicy.Object, walletManager.AsyncLoopFactory, walletManager.NodeLifetime, walletManager.DateTimeProvider);
walletManager.Wallets.Add(wallet); walletManager.Wallets.Add(wallet);
walletManager.LoadKeysLookupLock(); walletManager.LoadKeysLookupLock();
walletManager.WalletTipHash = block.Header.GetHash(); walletManager.WalletTipHash = block.Header.GetHash();
ChainedHeader chainedBlock = chainInfo.chain.GetBlock(block.GetHash()); ChainedHeader chainedBlock = chainInfo.chain.GetBlock(block.GetHash());
walletManager.ProcessTransaction(transaction, null, block, false); //walletManager.ProcessTransaction(transaction, null, block, false);
//walletManager.ProcessBlock(block, chainedBlock); walletManager.ProcessBlock(block, chainedBlock);
return (wallet, block, chainedBlock);
//HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0); //return wallet;
return wallet;
} }
public static Money Get9Billion() public static Money Get9Billion()
...@@ -210,5 +227,91 @@ namespace DeStream.DeStreamD.ForTest ...@@ -210,5 +227,91 @@ namespace DeStream.DeStreamD.ForTest
return new Money(9000000000); return new Money(9000000000);
} }
public static void CreateTestBlock(FullNode fullNode, BitcoinSecret minerSecret)
{
//FullNode fullNode = (this.runner as StratisBitcoinPowRunner).FullNode;
BitcoinSecret dest = minerSecret;
var blocks = new List<Block>();
List<Transaction> passedTransactions = null;
for (int i = 0; i < 3; i++)
{
uint nonce = 0;
var block = new Block();
block.Header.HashPrevBlock = fullNode.Chain.Tip.HashBlock;
block.Header.Bits = block.Header.GetWorkRequired(fullNode.Network, fullNode.Chain.Tip);
block.Header.UpdateTime(DateTimeOffset.UtcNow, fullNode.Network, fullNode.Chain.Tip);
var coinbase = new Transaction();
coinbase.AddInput(TxIn.CreateCoinbase(fullNode.Chain.Height + 1));
coinbase.AddOutput(new TxOut(fullNode.Network.GetReward(fullNode.Chain.Height + 1), dest.GetAddress()));
block.AddTransaction(coinbase);
if (passedTransactions?.Any() ?? false)
{
passedTransactions = Reorder(passedTransactions);
block.Transactions.AddRange(passedTransactions);
}
block.UpdateMerkleRoot();
while (!block.CheckProofOfWork())
block.Header.Nonce = ++nonce;
blocks.Add(block);
uint256 blockHash = block.GetHash();
var newChain = new ChainedHeader(block.Header, blockHash, fullNode.Chain.Tip);
ChainedHeader oldTip = fullNode.Chain.SetTip(newChain);
fullNode.ConsensusLoop().Puller.InjectBlock(blockHash, new DownloadedBlock { Length = block.GetSerializedSize(), Block = block }, CancellationToken.None);
}
}
private class TransactionNode
{
public uint256 Hash = null;
public Transaction Transaction = null;
public List<TransactionNode> DependsOn = new List<TransactionNode>();
public TransactionNode(Transaction tx)
{
this.Transaction = tx;
this.Hash = tx.GetHash();
}
}
private static List<Transaction> Reorder(List<Transaction> transactions)
{
if (transactions.Count == 0)
return transactions;
var result = new List<Transaction>();
Dictionary<uint256, TransactionNode> dictionary = transactions.ToDictionary(t => t.GetHash(), t => new TransactionNode(t));
foreach (TransactionNode transaction in dictionary.Select(d => d.Value))
{
foreach (TxIn input in transaction.Transaction.Inputs)
{
TransactionNode node = dictionary.TryGet(input.PrevOut.Hash);
if (node != null)
{
transaction.DependsOn.Add(node);
}
}
}
while (dictionary.Count != 0)
{
foreach (TransactionNode node in dictionary.Select(d => d.Value).ToList())
{
foreach (TransactionNode parent in node.DependsOn.ToList())
{
if (!dictionary.ContainsKey(parent.Hash))
node.DependsOn.Remove(parent);
}
if (node.DependsOn.Count == 0)
{
result.Add(node.Transaction);
dictionary.Remove(node.Hash);
}
}
}
return result;
}
} }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment