public void SetUp() { _defaultWallet = new DefaultWallet(_params); _blockStore = new MemoryBlockStore(_params); var chain = new BlockChain(_params, _defaultWallet, _blockStore); _peerGroup = new PeerGroup(_blockStore, _params, chain); }
public void SetUp() { _unitTestParams = NetworkParameters.UnitTests(); _defaultWallet = new DefaultWallet(_unitTestParams); _defaultWallet.AddKey(new EcKey()); _chainBlockStore = new MemoryBlockStore(_unitTestParams); _chain = new BlockChain(_unitTestParams, _defaultWallet, _chainBlockStore); _coinbaseTo = _defaultWallet.Keychain[0].ToAddress(_unitTestParams); _someOtherGuy = new EcKey().ToAddress(_unitTestParams); }
public static void Run(string[] args) { var wallet = new DefaultWallet(NetworkParameters); using (var blockStore = new MemoryBlockStore(NetworkParameters)) { var chain = new BlockChain(NetworkParameters, wallet, blockStore); var peerGroup = new PeerGroup(blockStore, NetworkParameters, chain); //peerGroup.AddAddress(new PeerAddress(new IPAddress(new byte[]{ 192, 168, 1, 136 }), 18333)); peerGroup.AddPeerDiscovery(new DnsDiscovery(NetworkParameters)); peerGroup.Start(); // Act peerGroup.DownloadBlockChain(); peerGroup.Stop(); } //var file = new FileInfo(args[0]); //var wallet = Wallet.LoadFromFile(file); //Console.WriteLine(wallet.ToString()); //// Set up the components and link them together. //var @params = NetworkParameters.TestNet(); //using (var blockStore = new MemoryBlockStore(@params)) //{ // var chain = new BlockChain(@params, wallet, blockStore); // var peerGroup = new PeerGroup(blockStore, @params, chain); // peerGroup.AddAddress(new PeerAddress(IPAddress.Loopback)); // peerGroup.Start(); // wallet.CoinsReceived += // (sender, e) => // { // Console.WriteLine(); // Console.WriteLine("Received tx " + e.Transaction.HashAsString); // Console.WriteLine(e.Transaction.ToString()); // }; // // Now download and process the block chain. // peerGroup.DownloadBlockChain(); // peerGroup.Stop(); //} //wallet.SaveToFile(file); Console.WriteLine(); Console.WriteLine("Done!"); Console.WriteLine(); Console.WriteLine(wallet.ToString()); }
public static void Run(string[] args) { // TODO: Assumes production network not testnet. Make it selectable. var @params = NetworkParameters.ProdNet(); try { // Decode the private key from Satoshi's Base58 variant. If 51 characters long then it's from BitCoins // "dumpprivkey" command and includes a version byte and checksum. Otherwise assume it's a raw key. EcKey key; if (args[0].Length == 51) { var dumpedPrivateKey = new DumpedPrivateKey(@params, args[0]); key = dumpedPrivateKey.Key; } else { var privKey = Base58.DecodeToBigInteger(args[0]); key = new EcKey(privKey); } Console.WriteLine("Address from private key is: " + key.ToAddress(@params)); // And the address ... var destination = new Address(@params, args[1]); // Import the private key to a fresh wallet. var wallet = new DefaultWallet(@params); wallet.AddKey(key); // Find the transactions that involve those coins. using (var blockStore = new MemoryBlockStore(@params)) { var chain = new BlockChain(@params, wallet, blockStore); var peerGroup = new PeerGroup(blockStore, @params, chain); peerGroup.AddAddress(new PeerAddress(IPAddress.Loopback)); peerGroup.Start(); peerGroup.DownloadBlockChain(); peerGroup.Stop(); // And take them! Console.WriteLine("Claiming " + Utils.BitcoinValueToFriendlyString(wallet.GetBalance()) + " coins"); wallet.SendCoins(peerGroup, destination, wallet.GetBalance()); // Wait a few seconds to let the packets flush out to the network (ugly). Thread.Sleep(5000); } } catch (IndexOutOfRangeException) { Console.WriteLine("First arg should be private key in Base58 format. Second argument should be address to send to."); } }
public static void Run(string[] args) { Console.WriteLine("Connecting to node"); var @params = NetworkParameters.ProdNet(); using (var blockStore = new MemoryBlockStore(@params)) { var chain = new BlockChain(@params, blockStore); var peer = new Peer(@params, new PeerAddress(IPAddress.Loopback), chain); peer.Connect(); new Thread(peer.Run).Start(); var blockHash = new Sha256Hash(args[0]); var future = peer.BeginGetBlock(blockHash, null, null); Console.WriteLine("Waiting for node to send us the requested block: " + blockHash); var block = peer.EndGetBlock(future); Console.WriteLine(block); peer.Disconnect(); } }
public void SetUp() { _testNetChainBlockStore = new MemoryBlockStore(_testNet); _testNetChain = new BlockChain(_testNet, new DefaultWallet(_testNet), _testNetChainBlockStore); _unitTestParams = NetworkParameters.UnitTests(); _defaultWallet = new DefaultWallet(_unitTestParams); _defaultWallet.AddKey(new EcKey()); ResetBlockStore(); _chain = new BlockChain(_unitTestParams, _defaultWallet, _blockStore); _coinbaseTo = _defaultWallet.Keychain[0].ToAddress(_unitTestParams); }
public static void Run(string[] args) { var testNet = args.Length > 0 && string.Equals(args[0], "testnet", StringComparison.InvariantCultureIgnoreCase); var @params = testNet ? NetworkParameters.TestNet() : NetworkParameters.ProdNet(); var filePrefix = testNet ? "pingservice-testnet" : "pingservice-prodnet"; // Try to read the wallet from storage, create a new one if not possible. IDefaultWallet defaultWallet; var walletFile = new FileInfo(filePrefix + ".wallet"); try { defaultWallet = DefaultWallet.LoadFromFile(walletFile); } catch (IOException) { defaultWallet = new DefaultWallet(@params); defaultWallet.Keychain.Add(new EcKey()); defaultWallet.SaveToFile(walletFile); } // Fetch the first key in the wallet (should be the only key). var key = defaultWallet.Keychain[0]; Console.WriteLine(defaultWallet); // Load the block chain, if there is one stored locally. Console.WriteLine("Reading block store from disk"); using (var blockStore = new BoundedOverheadBlockStore(@params, new FileInfo(filePrefix + ".blockchain"))) { // Connect to the localhost node. One minute timeout since we won't try any other peers Console.WriteLine("Connecting ..."); var chain = new BlockChain(@params, defaultWallet, blockStore); var peerGroup = new PeerGroup(blockStore, @params, chain); peerGroup.AddAddress(new PeerAddress(IPAddress.Loopback)); peerGroup.Start(); // We want to know when the balance changes. defaultWallet.CoinsReceived += (sender, e) => { // Running on a peer thread. Debug.Assert(!e.NewBalance.Equals(0)); // It's impossible to pick one specific identity that you receive coins from in BitCoin as there // could be inputs from many addresses. So instead we just pick the first and assume they were all // owned by the same person. var input = e.Transaction.TransactionInputs[0]; var from = input.FromAddress; var value = e.Transaction.GetValueSentToMe(defaultWallet); Console.WriteLine("Received " + Utils.BitcoinValueToFriendlyString(value) + " from " + from); // Now send the coins back! var sendTx = defaultWallet.SendCoins(peerGroup, from, value); Debug.Assert(sendTx != null); // We should never try to send more coins than we have! Console.WriteLine("Sent coins back! Transaction hash is " + sendTx.HashAsString); defaultWallet.SaveToFile(walletFile); }; peerGroup.DownloadBlockChain(); Console.WriteLine("Send coins to: " + key.ToAddress(@params)); Console.WriteLine("Waiting for coins to arrive. Press Ctrl-C to quit."); // The PeerGroup thread keeps us alive until something kills the process. } }
/// <exception cref="BitcoinSharp.Core.Exceptions.VerificationException"/> /// <exception cref="BitcoinSharp.Core.Exceptions.ScriptException"/> private void Receive(Transaction transaction, StoredBlock storedBlock, BlockChain.NewBlockType blockType, bool reorg) { lock (this) { // Runs in a peer thread. var previousBalance = GetBalance(); var transactionHash = transaction.Hash; var bestChain = blockType == BlockChain.NewBlockType.BestChain; var sideChain = blockType == BlockChain.NewBlockType.SideChain; var valueSentFromMe = transaction.GetValueSentFromMe(this); var valueSentToMe = transaction.GetValueSentToMe(this); var valueDifference = (long) (valueSentToMe - valueSentFromMe); if (!reorg) { Log.InfoFormat("Received tx{0} for {1} BTC: {2}", sideChain ? " on a side chain" : "", Utils.BitcoinValueToFriendlyString(valueDifference), transaction.HashAsString); } // If this transaction is already in the wallet we may need to move it into a different WalletPool. At the very // least we need to ensure we're manipulating the canonical object rather than a duplicate. Transaction walletTransaction; if (Pending.TryGetValue(transactionHash, out walletTransaction)) { Pending.Remove(transactionHash); Log.Info(" <-pending"); // A transaction we created appeared in a block. Probably this is a spend we broadcast that has been // accepted by the network. // // Mark the tx as appearing in this block so we can find it later after a re-org. walletTransaction.AddBlockAppearance(storedBlock); if (bestChain) { if (valueSentToMe.Equals(0)) { // There were no change transactions so this tx is fully spent. Log.Info(" ->spent"); Debug.Assert(!Spent.ContainsKey(walletTransaction.Hash), "TX in both pending and spent pools"); Spent[walletTransaction.Hash] = walletTransaction; } else { // There was change back to us, or this tx was purely a spend back to ourselves (perhaps for // anonymization purposes). Log.Info(" ->unspent"); Debug.Assert(!Unspent.ContainsKey(walletTransaction.Hash), "TX in both pending and unspent pools"); Unspent[walletTransaction.Hash] = walletTransaction; } } else if (sideChain) { // The transaction was accepted on an inactive side chain, but not yet by the best chain. Log.Info(" ->inactive"); // It's OK for this to already be in the inactive WalletPool because there can be multiple independent side // chains in which it appears: // // b1 --> b2 // \-> b3 // \-> b4 (at this point it's already present in 'inactive' if (_inactive.ContainsKey(walletTransaction.Hash)) Log.Info("Saw a transaction be incorporated into multiple independent side chains"); _inactive[walletTransaction.Hash] = walletTransaction; // Put it back into the pending WalletPool, because 'pending' means 'waiting to be included in best chain'. Pending[walletTransaction.Hash] = walletTransaction; } } else { if (!reorg) { // Mark the tx as appearing in this block so we can find it later after a re-org. transaction.AddBlockAppearance(storedBlock); } // This TX didn't originate with us. It could be sending us coins and also spending our own coins if keys // are being shared between different wallets. if (sideChain) { Log.Info(" ->inactive"); _inactive[transaction.Hash] = transaction; } else if (bestChain) { ProcessTransactionFromBestChain(transaction); } } Log.InfoFormat("Balance is now: {0}", Utils.BitcoinValueToFriendlyString(GetBalance())); // Inform anyone interested that we have new coins. Note: we may be re-entered by the event listener, // so we must not make assumptions about our state after this loop returns! For example, // the balance we just received might already be spent! if (!reorg && bestChain && valueDifference > 0 && CoinsReceived != null) { lock (CoinsReceived) { CoinsReceived(this, new WalletCoinsReceivedEventArgs(transaction, previousBalance, GetBalance())); } } } }
/// <summary> /// Called by the <see cref="BitcoinSharp.Core.BlockChain"/> when we receive a new block that sends coins to one of our addresses or /// spends coins from one of our addresses (note that a single transaction can do both). /// </summary> /// <remarks> /// This is necessary for the internal book-keeping Wallet does. When a transaction is received that sends us /// coins it is added to a WalletPool so we can use it later to create spends. When a transaction is received that /// consumes outputs they are marked as spent so they won't be used in future.<p/> /// A transaction that spends our own coins can be received either because a spend we created was accepted by the /// network and thus made it into a block, or because our keys are being shared between multiple instances and /// some other node spent the coins instead. We still have to know about that to avoid accidentally trying to /// double spend.<p/> /// A transaction may be received multiple times if is included into blocks in parallel chains. The blockType /// parameter describes whether the containing block is on the main/best chain or whether it's on a presently /// inactive side chain. We must still record these transactions and the blocks they appear in because a future /// block might change which chain is best causing a reorganize. A re-org can totally change our balance! /// </remarks> /// <exception cref="BitcoinSharp.Core.Exceptions.VerificationException"/> /// <exception cref="BitcoinSharp.Core.Exceptions.ScriptException"/> public void Receive(Transaction transaction, StoredBlock storedBlock, BlockChain.NewBlockType blockType) { lock (this) { Receive(transaction, storedBlock, blockType, false); } }