Commit 64caca76 authored by Pavel Pavlov's avatar Pavel Pavlov

Сreate a test transaction in the block and add it to the chain

- created transaction
- created wallet
- created block and added transaction
parent 94a5c7f6
......@@ -93,6 +93,8 @@ namespace DeStream.DeStreamD.ForTest
Console.WriteLine($"current network: {network.Name}");
// NOTES: running BTC and STRAT side by side is not possible yet as the flags for serialization are static
FullNode node = (FullNode)new FullNodeBuilder()
.UseNodeSettings(nodeSettings)
......@@ -105,28 +107,40 @@ namespace DeStream.DeStreamD.ForTest
.AddRPC()
.Build();
////node.NodeService<IWalletManager>().LoadWallet("password", "mywallet123");
var walletManager = node.WalletManager();
//DataFolder dataFolder = CreateDataFolder(node);
//Directory.CreateDirectory(dataFolder.WalletPath);
Wallet wallet = TestClassHelper.CreateFirstTransaction(nodeSettings, walletManager);
walletManager.Wallets.Add(wallet);
//var x= node.WalletManager().CreateWallet("password", "MyWallet");
//Wallet MyWallet = null;
//try
//{
// MyWallet = node.NodeService<IWalletManager>().LoadWallet("password", "MyWallet");
//}
//catch (Exception ex)
//{
// node.WalletManager().CreateWallet("password", "MyWallet");
//}
//TestClassHelper.CreateFirstTransaction(MyWallet, nodeSettings);
//var wallet = node.WalletManager().CreateWallet("password", "MyWallet");
Wallet wallet = node.NodeService<IWalletManager>().LoadWallet("password", "MyWallet");
(ExtKey ExtKey, string ExtPubKey) accountKeys = WalletTestsHelpers.GenerateAccountKeys(wallet, "password", "m/44'/0'/0'");
(PubKey PubKey, BitcoinPubKeyAddress Address) spendingKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0");
(PubKey PubKey, BitcoinPubKeyAddress Address) destinationKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1");
(PubKey PubKey, BitcoinPubKeyAddress Address) changeKeys = WalletTestsHelpers.GenerateAddressKeys(wallet, 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>()
};
//node.NodeService<IWalletManager>().SaveWallet(MyWallet);
//(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,
......@@ -137,133 +151,24 @@ namespace DeStream.DeStreamD.ForTest
// 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>()
};
//Generate a spendable transaction
(ConcurrentChain chain, uint256 blockhash, Block block) chainInfo = WalletTestsHelpers.CreateChainAndCreateFirstBlockWithPaymentToAddress(wallet.Network, spendingAddress);
/* CreateChainAndCreateFirstBlockWithPaymentToAddress */
var chain = new ConcurrentChain(network);
var _block = new Block();
_block.Header.HashPrevBlock = chain.Tip.HashBlock;
_block.Header.Bits = _block.Header.GetWorkRequired(network, chain.Tip);
_block.Header.UpdateTime(DateTimeOffset.UtcNow, network, chain.Tip);
var coinbase = new Transaction();
coinbase.AddInput(TxIn.CreateCoinbase(chain.Height + 1));
coinbase.AddOutput(new TxOut(network.GetReward(chain.Height + 1), spendingAddress.ScriptPubKey));
_block.AddTransaction(coinbase);
_block.Header.Nonce = 0;
_block.UpdateMerkleRoot();
_block.Header.PrecomputeHash();
chain.SetTip(_block.Header);
/* CreateChainAndCreateFirstBlockWithPaymentToAddress */
//TransactionData spendingTransaction = WalletTestsHelpers.CreateTransactionDataFromFirstBlock(chainInfo);
/*CreateTransactionDataFromFirstBlock*/
//public static TransactionData CreateTransactionDataFromFirstBlock((ConcurrentChain chain, uint256 blockHash, Block block) chainInfo)
//var changeAddress = new HdAddress
//{
Transaction _transaction = _block.Transactions[0];
var addressTransaction = new TransactionData
{
Amount = _transaction.TotalOut,
BlockHash = _block.GetHash(),
BlockHeight = chainInfo.chain.GetBlock(_block.GetHash()).Height,
CreationTime = DateTimeOffset.FromUnixTimeSeconds(chainInfo.block.Header.Time),
Id = _transaction.GetHash(),
Index = 0,
ScriptPubKey = _transaction.Outputs[0].ScriptPubKey,
};
//return addressTransaction;
//}
/*CreateTransactionDataFromFirstBlock*/
spendingAddress.Transactions.Add(addressTransaction);
// setup a payment to yourself in a new block.
//Transaction transaction = WalletTestsHelpers.SetupValidTransaction(wallet, "password", spendingAddress, destinationKeys.PubKey, changeAddress, new Money(7500), new Money(5000));
#region SetupValidTransaction
//Transaction SetupValidTransaction(Features.Wallet.Wallet wallet, string password, HdAddress spendingAddress, PubKey destinationPubKey,
//HdAddress changeAddress, Money amount, Money fee)
TransactionData spendingTransaction = spendingAddress.Transactions.ElementAt(0);
var coin = new Coin(spendingTransaction.Id, (uint)spendingTransaction.Index, spendingTransaction.Amount, spendingTransaction.ScriptPubKey);
Key privateKey = Key.Parse(wallet.EncryptedSeed, "password", wallet.Network);
var scriptPubKey = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0).ScriptPubKey;
var builder = new TransactionBuilder(wallet.Network);
Transaction tx = builder
.AddCoins(new List<Coin> { coin })
.AddKeys(new ExtKey(privateKey, wallet.ChainCode).Derive(new KeyPath(spendingAddress.HdPath)).GetWif(wallet.Network))
.Send(scriptPubKey, new Money(7500))
.SetChange(changeAddress.ScriptPubKey)
.SendFees(new Money(5000))
.BuildTransaction(true);
if (!builder.Verify(tx))
{
throw new WalletException("Could not build transaction, please make sure you entered the correct data.");
}
#endregion
//Block block = WalletTestsHelpers.AppendTransactionInNewBlockToChain(chainInfo.chain, transaction);
Block block = WalletTestsHelpers.AppendTransactionInNewBlockToChain(chainInfo.chain, tx);
HdAddress _addr = node.NodeService<IWalletManager>().GetUnusedAddress(new WalletAccountReference("MyWallet", "account 0"));
wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount
{
Index = 0,
Name = "account1",
HdPath = "m/44'/0'/0'",
ExtendedPubKey = accountKeys.ExtPubKey,
ExternalAddresses = new List<HdAddress> { spendingAddress, _addr },
InternalAddresses = new List<HdAddress> { changeAddress }
});
var walletFeePolicy = new Mock<IWalletFeePolicy>();
walletFeePolicy.Setup(w => w.GetMinimumFee(258, 50))
.Returns(new Money(5000));
var walletManager = new WalletManager(nodeSettings.LoggerFactory, Network.DeStreamTest, chainInfo.chain, NodeSettings.Default(), new Mock<WalletSettings>().Object,
nodeSettings.DataFolder, walletFeePolicy.Object, new Mock<IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default);
walletManager.Wallets.Add(wallet);
walletManager.LoadKeysLookupLock();
walletManager.WalletTipHash = block.Header.GetHash();
ChainedHeader chainedBlock = chainInfo.chain.GetBlock(block.GetHash());
walletManager.ProcessBlock(block, chainedBlock);
HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
int qwe123 = 1;
//HdAddress address = WalletTestsHelpers.CreateAddress(false);
//this.walletManager.Setup(w => w.GetUnusedAddress(It.IsAny<WalletAccountReference>()))
// .Returns(address);
//HdAddress _addr = node.NodeService<IWalletManager>().GetUnusedAddress(new WalletAccountReference("mywallet", "account 0"));
//var _key0 = wallet.GetAllPubKeysByCoinType(CoinType.Stratis).FirstOrDefault();
//Key _key = wallet.GetExtendedPrivateKeyForAddress("123456", _addr).PrivateKey;
//var _walletTransactionHandler = ((FullNode)node).NodeService<IWalletTransactionHandler>() as WalletTransactionHandler;
// 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>()
//};
//var chain = new ConcurrentChain(_wallet.Network);
//WalletTestsHelpers.AddBlocksWithCoinbaseToChain(_wallet.Network, chain, _addr);
////var walletAccountReference = new WalletAccountReference()
//var account = _wallet.AccountsRoot.FirstOrDefault();
//TransactionBuildContext context = CreateContext(new WalletAccountReference("mywallet", "account 0"), "123456", _key.PubKey.ScriptPubKey, new Money(777), FeeType.Low, 0);
//Transaction transactionResult = _walletTransactionHandler.BuildTransaction(context);
//(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)
await node.RunAsync();
}
......@@ -273,17 +178,5 @@ namespace DeStream.DeStreamD.ForTest
}
}
public static TransactionBuildContext CreateContext(WalletAccountReference accountReference, string password,
Script destinationScript, Money amount, FeeType feeType, int minConfirmations)
{
return new TransactionBuildContext(accountReference,
new[] { new Recipient { Amount = amount, ScriptPubKey = destinationScript } }.ToList(), password)
{
MinConfirmations = minConfirmations,
FeeType = feeType
};
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DeStream.Stratis.Bitcoin.Configuration;
using Moq;
using NBitcoin;
using Stratis.Bitcoin.Features.Wallet;
using Stratis.Bitcoin.Features.Wallet.Interfaces;
using Stratis.Bitcoin.Utilities;
namespace DeStream.DeStreamD.ForTest
{
public class TestClassHelper
{
public static (ExtKey ExtKey, string ExtPubKey) GenerateAccountKeys(Wallet wallet, string password, string keyPath)
{
var accountExtKey = new ExtKey(Key.Parse(wallet.EncryptedSeed, password, wallet.Network), wallet.ChainCode);
string accountExtendedPubKey = accountExtKey.Derive(new KeyPath(keyPath)).Neuter().ToString(wallet.Network);
return (accountExtKey, accountExtendedPubKey);
}
public static (PubKey PubKey, BitcoinPubKeyAddress Address) GenerateAddressKeys(Wallet wallet, string accountExtendedPubKey, string keyPath)
{
PubKey addressPubKey = ExtPubKey.Parse(accountExtendedPubKey).Derive(new KeyPath(keyPath)).PubKey;
BitcoinPubKeyAddress address = addressPubKey.GetAddress(wallet.Network);
return (addressPubKey, address);
}
public static (ConcurrentChain chain, uint256 blockhash, Block block) CreateChainAndCreateFirstBlockWithPaymentToAddress(Network network, HdAddress address)
{
var chain = new ConcurrentChain(network);
var block = new Block();
block.Header.HashPrevBlock = chain.Tip.HashBlock;
block.Header.Bits = block.Header.GetWorkRequired(network, chain.Tip);
block.Header.UpdateTime(DateTimeOffset.UtcNow, network, chain.Tip);
var coinbase = new Transaction();
coinbase.AddInput(TxIn.CreateCoinbase(chain.Height + 1));
coinbase.AddOutput(new TxOut(Get9Billion(), address.ScriptPubKey));
block.AddTransaction(coinbase);
block.Header.Nonce = 0;
block.UpdateMerkleRoot();
block.Header.PrecomputeHash();
chain.SetTip(block.Header);
return (chain, block.GetHash(), block);
}
public static TransactionData CreateTransactionDataFromFirstBlock((ConcurrentChain chain, uint256 blockHash, Block block) chainInfo)
{
Transaction transaction = chainInfo.block.Transactions[0];
var addressTransaction = new TransactionData
{
Amount = transaction.TotalOut,
BlockHash = chainInfo.blockHash,
BlockHeight = chainInfo.chain.GetBlock(chainInfo.blockHash).Height,
CreationTime = DateTimeOffset.FromUnixTimeSeconds(chainInfo.block.Header.Time),
Id = transaction.GetHash(),
Index = 0,
ScriptPubKey = transaction.Outputs[0].ScriptPubKey,
};
return addressTransaction;
}
public static Transaction SetupValidTransaction(Wallet wallet, string password, HdAddress spendingAddress, PubKey destinationPubKey, HdAddress changeAddress, Money amount, Money fee)
{
TransactionData spendingTransaction = spendingAddress.Transactions.ElementAt(0);
var coin = new Coin(spendingTransaction.Id, (uint)spendingTransaction.Index, spendingTransaction.Amount, spendingTransaction.ScriptPubKey);
Key privateKey = Key.Parse(wallet.EncryptedSeed, password, wallet.Network);
var builder = new TransactionBuilder(wallet.Network);
Transaction tx = builder
.AddCoins(new List<Coin> { coin })
.AddKeys(new ExtKey(privateKey, wallet.ChainCode).Derive(new KeyPath(spendingAddress.HdPath)).GetWif(wallet.Network))
.Send(destinationPubKey.ScriptPubKey, amount)
.SetChange(changeAddress.ScriptPubKey)
.SendFees(fee)
.BuildTransaction(true);
if (!builder.Verify(tx))
{
throw new WalletException("Could not build transaction, please make sure you entered the correct data.");
}
return tx;
}
public static Block AppendTransactionInNewBlockToChain(ConcurrentChain chain, Transaction transaction)
{
ChainedHeader last = null;
uint nonce = RandomUtils.GetUInt32();
Block block = chain.Network.Consensus.ConsensusFactory.CreateBlock();
block.AddTransaction(transaction);
block.UpdateMerkleRoot();
block.Header.HashPrevBlock = chain.Tip.HashBlock;
block.Header.Nonce = nonce;
if (!chain.TrySetTip(block.Header, out last))
throw new InvalidOperationException("Previous not existing");
return block;
}
public static (Wallet wallet, ExtKey key) GenerateBlankWalletWithExtKey(string name, string password)
{
var mnemonic = new Mnemonic("grass industry beef stereo soap employ million leader frequent salmon crumble banana");
ExtKey extendedKey = mnemonic.DeriveExtKey(password);
var walletFile = new Wallet
{
Name = name,
EncryptedSeed = extendedKey.PrivateKey.GetEncryptedBitcoinSecret(password, Network.DeStreamTest).ToWif(),
ChainCode = extendedKey.ChainCode,
CreationTime = DateTimeOffset.Now,
Network = Network.DeStreamTest,
AccountsRoot = new List<AccountRoot> { new AccountRoot() { Accounts = new List<HdAccount>(), CoinType = (CoinType)Network.DeStreamTest.Consensus.CoinType } },
};
return (walletFile, extendedKey);
}
public static Wallet CreateFirstTransaction(DeStreamNodeSettings nodeSettings, WalletManager walletManager)
{
Wallet wallet = GenerateBlankWalletWithExtKey("myWallet1", "password").wallet;
(ExtKey ExtKey, string ExtPubKey) accountKeys = GenerateAccountKeys(wallet, "password", "m/44'/0'/0'");
(PubKey PubKey, BitcoinPubKeyAddress Address) spendingKeys = GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/0");
(PubKey PubKey, BitcoinPubKeyAddress Address) destinationKeys = GenerateAddressKeys(wallet, accountKeys.ExtPubKey, "0/1");
(PubKey PubKey, BitcoinPubKeyAddress Address) changeKeys = GenerateAddressKeys(wallet, 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>()
};
//Generate a spendable transaction
(ConcurrentChain chain, uint256 blockhash, Block block) chainInfo = CreateChainAndCreateFirstBlockWithPaymentToAddress(wallet.Network, spendingAddress);
TransactionData spendingTransaction = CreateTransactionDataFromFirstBlock(chainInfo);
spendingAddress.Transactions.Add(spendingTransaction);
// setup a payment to yourself in a new block.
Transaction transaction = SetupValidTransaction(wallet, "password", spendingAddress, destinationKeys.PubKey, changeAddress, new Money(7500), new Money(5000));
Block block = AppendTransactionInNewBlockToChain(chainInfo.chain, transaction);
wallet.AccountsRoot.ElementAt(0).Accounts.Add(new HdAccount
{
Index = 0,
Name = "account1",
HdPath = "m/44'/0'/0'",
ExtendedPubKey = accountKeys.ExtPubKey,
//ExternalAddresses = new List<HdAddress> { spendingAddress, destinationAddress },
ExternalAddresses = new List<HdAddress> { spendingAddress },
InternalAddresses = new List<HdAddress> { changeAddress }
});
var walletFeePolicy = new Mock<IWalletFeePolicy>();
walletFeePolicy.Setup(w => w.GetMinimumFee(258, 50))
.Returns(new Money(5000));
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,
// nodeSettings.DataFolder, walletFeePolicy.Object, new Mock<IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default);
walletManager.Wallets.Add(wallet);
walletManager.LoadKeysLookupLock();
walletManager.WalletTipHash = block.Header.GetHash();
ChainedHeader chainedBlock = chainInfo.chain.GetBlock(block.GetHash());
walletManager.ProcessTransaction(transaction, null, block, false);
//walletManager.ProcessBlock(block, chainedBlock);
HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
return wallet;
}
public static Money Get9Billion()
{
return new Money(9000000000);
}
}
}
......@@ -2430,7 +2430,7 @@ namespace Stratis.Bitcoin.Features.Wallet.Tests
var walletFeePolicy = new Mock<IWalletFeePolicy>();
walletFeePolicy.Setup(w => w.GetMinimumFee(258, 50))
.Returns(new Money(5000));
HdAddress spentAddressResult0 = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
var walletManager = new WalletManager(this.LoggerFactory.Object, Network.Main, chainInfo.chain, NodeSettings.Default(), new Mock<WalletSettings>().Object,
dataFolder, walletFeePolicy.Object, new Mock<IAsyncLoopFactory>().Object, new NodeLifetime(), DateTimeProvider.Default);
walletManager.Wallets.Add(wallet);
......
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