/// <summary>
        /// Connects this input to the relevant output of the referenced transaction if it's in the given map.
        /// Connecting means updating the internal pointers and spent flags.
        /// </summary>
        /// <param name="transactions">Map of txhash-&gt;transaction.</param>
        /// <param name="disconnect">Whether to abort if there's a pre-existing connection or not.</param>
        /// <returns>True if connection took place, false if the referenced transaction was not in the list.</returns>
        internal ConnectionResult Connect(IDictionary <Sha256Hash, Transaction> transactions, bool disconnect)
        {
            var         h = new Sha256Hash(Outpoint.Hash);
            Transaction tx;

            if (!transactions.TryGetValue(h, out tx))
            {
                return(ConnectionResult.NoSuchTx);
            }
            var @out = tx.Outputs[Outpoint.Index];

            if ([email protected])
            {
                if (disconnect)
                {
                    @out.MarkAsUnspent();
                }
                else
                {
                    return(ConnectionResult.AlreadySpent);
                }
            }
            Outpoint.FromTx = tx;
            @out.MarkAsSpent(this);
            return(ConnectionResult.Success);
        }
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 private void CreateNewStore(NetworkParameters @params, FileInfo file)
 {
     // Create a new block store if the file wasn't found or anything went wrong whilst reading.
     _blockCache.Clear();
     try
     {
         if (_channel != null)
         {
             _channel.Dispose();
             _channel = null;
         }
         file.Delete();
         _channel = file.Create(); // Create fresh.
         _channel.Write(_fileFormatVersion);
     }
     catch (IOException e1)
     {
         // We could not load a block store nor could we create a new one!
         throw new BlockStoreException(e1);
     }
     try
     {
         // Set up the genesis block. When we start out fresh, it is by definition the top of the chain.
         var genesis       = @params.GenesisBlock.CloneAsHeader();
         var storedGenesis = new StoredBlock(genesis, genesis.GetWork(), 0);
         _chainHead = new Sha256Hash(storedGenesis.Header.Hash);
         _channel.Write(_chainHead.Hash);
         Put(storedGenesis);
     }
     catch (IOException e)
     {
         throw new BlockStoreException(e);
     }
 }
        /// <exception cref="System.IO.IOException" />
        /// <exception cref="BitCoinSharp.BlockStoreException" />
        private void Load(FileInfo file)
        {
            _log.InfoFormat("Reading block store from {0}", file);
            if (_channel != null)
            {
                _channel.Dispose();
            }
            _channel = file.OpenRead();
            // Read a version byte.
            var version = _channel.Read();

            if (version == -1)
            {
                // No such file or the file was empty.
                throw new FileNotFoundException(file.Name + " does not exist or is empty");
            }
            if (version != _fileFormatVersion)
            {
                throw new BlockStoreException("Bad version number: " + version);
            }
            // Chain head pointer is the first thing in the file.
            var chainHeadHash = new byte[32];

            _channel.Read(chainHeadHash);
            _chainHead = new Sha256Hash(chainHeadHash);
            _log.InfoFormat("Read chain head from disk: {0}", _chainHead);
            _channel.Position = _channel.Length - Record.Size;
        }
示例#4
0
        /// <exception cref="ProtocolException"/>
        protected override void Parse()
        {
            _version          = ReadUint32();
            _prevBlockHash    = ReadHash();
            _merkleRoot       = ReadHash();
            _time             = ReadUint32();
            _difficultyTarget = ReadUint32();
            _nonce            = ReadUint32();

            _hash = new Sha256Hash(Utils.ReverseBytes(Utils.DoubleDigest(Bytes, 0, Cursor)));

            if (Cursor == Bytes.Length)
            {
                // This message is just a header, it has no transactions.
                return;
            }

            var numTransactions = (int)ReadVarInt();

            Transactions = new List <Transaction>(numTransactions);
            for (var i = 0; i < numTransactions; i++)
            {
                var tx = new Transaction(Params, Bytes, Cursor);
                Transactions.Add(tx);
                Cursor += tx.MessageSize;
            }
        }
示例#5
0
        /// <exception cref="BitCoinSharp.ProtocolException" />
        protected override void Parse()
        {
            _version = ReadUint32();
            // First come the inputs.
            var numInputs = ReadVarInt();

            _inputs = new List <TransactionInput>((int)numInputs);
            for (var i = 0UL; i < numInputs; i++)
            {
                var input = new TransactionInput(Params, this, Bytes, Cursor);
                _inputs.Add(input);
                Cursor += input.MessageSize;
            }
            // Now the outputs
            var numOutputs = ReadVarInt();

            _outputs = new List <TransactionOutput>((int)numOutputs);
            for (var i = 0UL; i < numOutputs; i++)
            {
                var output = new TransactionOutput(Params, this, Bytes, Cursor);
                _outputs.Add(output);
                Cursor += output.MessageSize;
            }
            _lockTime = ReadUint32();

            // Store a hash, it may come in useful later (want to avoid re-serialization costs).
            _hash = new Sha256Hash(Utils.ReverseBytes(Utils.DoubleDigest(Bytes, Offset, Cursor - Offset)));
        }
示例#6
0
 /// <summary>
 /// Special case constructor, used for the genesis node, cloneAsHeader and unit tests.
 /// </summary>
 internal Block(NetworkParameters @params)
     : base(@params)
 {
     // Set up a few basic things. We are not complete after this though.
     _version          = 1;
     _difficultyTarget = 0x1d07fff8;
     _time             = (uint)UnixTime.ToUnixTime(DateTime.UtcNow);
     _prevBlockHash    = Sha256Hash.ZeroHash;
 }
示例#7
0
 /// <summary>
 /// Adds a transaction to this block.
 /// </summary>
 internal void AddTransaction(Transaction t)
 {
     if (Transactions == null)
     {
         Transactions = new List <Transaction>();
     }
     Transactions.Add(t);
     // Force a recalculation next time the values are needed.
     _merkleRoot = null;
     _hash       = null;
 }
        // TODO: Clean all this up once TransactionOutPoint disappears.

        /// <summary>
        /// Locates the referenced output from the given pool of transactions.
        /// </summary>
        /// <returns>The TransactionOutput or null if the transactions map doesn't contain the referenced tx.</returns>
        internal TransactionOutput GetConnectedOutput(IDictionary <Sha256Hash, Transaction> transactions)
        {
            var         h = new Sha256Hash(Outpoint.Hash);
            Transaction tx;

            if (!transactions.TryGetValue(h, out tx))
            {
                return(null);
            }
            var @out = tx.Outputs[Outpoint.Index];

            return(@out);
        }
        /// <exception cref="BitCoinSharp.BlockStoreException" />
        public StoredBlock Get(byte[] hashBytes)
        {
            lock (this)
            {
                // Check the memory cache first.
                var         hash = new Sha256Hash(hashBytes);
                StoredBlock fromMem;
                if (_blockCache.TryGetValue(hash, out fromMem))
                {
                    return(fromMem);
                }
                if (_notFoundCache.TryGetValue(hash, out fromMem) && fromMem == _notFoundMarker)
                {
                    return(null);
                }

                try
                {
                    var         fromDisk = GetRecord(hash);
                    StoredBlock block    = null;
                    if (fromDisk == null)
                    {
                        _notFoundCache[hash] = _notFoundMarker;
                        while (_notFoundCache.Count > 100)
                        {
                            _notFoundCache.RemoveAt(0);
                        }
                    }
                    else
                    {
                        block             = fromDisk.ToStoredBlock(_params);
                        _blockCache[hash] = block;
                        while (_blockCache.Count > 100)
                        {
                            _blockCache.RemoveAt(0);
                        }
                    }
                    return(block);
                }
                catch (IOException e)
                {
                    throw new BlockStoreException(e);
                }
                catch (ProtocolException e)
                {
                    throw new BlockStoreException(e);
                }
            }
        }
示例#10
0
        /// <exception cref="IOException"/>
        private void BlockChainDownload(Sha256Hash toHash)
        {
            // This may run in ANY thread.

            // The block chain download process is a bit complicated. Basically, we start with zero or more blocks in a
            // chain that we have from a previous session. We want to catch up to the head of the chain BUT we don't know
            // where that chain is up to or even if the top block we have is even still in the chain - we
            // might have got ourselves onto a fork that was later resolved by the network.
            //
            // To solve this, we send the peer a block locator which is just a list of block hashes. It contains the
            // blocks we know about, but not all of them, just enough of them so the peer can figure out if we did end up
            // on a fork and if so, what the earliest still valid block we know about is likely to be.
            //
            // Once it has decided which blocks we need, it will send us an inv with up to 500 block messages. We may
            // have some of them already if we already have a block chain and just need to catch up. Once we request the
            // last block, if there are still more to come it sends us an "inv" containing only the hash of the head
            // block.
            //
            // That causes us to download the head block but then we find (in processBlock) that we can't connect
            // it to the chain yet because we don't have the intermediate blocks. So we rerun this function building a
            // new block locator describing where we're up to.
            //
            // The getblocks with the new locator gets us another inv with another bunch of blocks. We download them once
            // again. This time when the peer sends us an inv with the head block, we already have it so we won't download
            // it again - but we recognize this case as special and call back into blockChainDownload to continue the
            // process.
            //
            // So this is a complicated process but it has the advantage that we can download a chain of enormous length
            // in a relatively stateless manner and with constant/bounded memory usage.
            _log.InfoFormat("blockChainDownload({0})", toHash);

            // TODO: Block locators should be abstracted out rather than special cased here.
            var blockLocator = new LinkedList <Sha256Hash>();

            // We don't do the exponential thinning here, so if we get onto a fork of the chain we will end up
            // re-downloading the whole thing again.
            blockLocator.AddLast(_params.GenesisBlock.Hash);
            var topBlock = _blockChain.ChainHead.Header;

            if (!topBlock.Equals(_params.GenesisBlock))
            {
                blockLocator.AddFirst(topBlock.Hash);
            }
            var message = new GetBlocksMessage(_params, blockLocator.ToList(), toHash);

            _conn.WriteMessage(message);
        }
示例#11
0
        /// <summary>
        /// Asks the connected peer for the block of the given hash, and returns a Future representing the answer.
        /// If you want the block right away and don't mind waiting for it, just call .get() on the result. Your thread
        /// will block until the peer answers. You can also use the Future object to wait with a timeout, or just check
        /// whether it's done later.
        /// </summary>
        /// <param name="blockHash">Hash of the block you were requesting.</param>
        /// <exception cref="IOException"/>
        public IAsyncResult BeginGetBlock(Sha256Hash blockHash, AsyncCallback callback, object state)
        {
            var getdata       = new GetDataMessage(_params);
            var inventoryItem = new InventoryItem(InventoryItem.ItemType.Block, blockHash);

            getdata.AddItem(inventoryItem);
            var future = new GetDataFuture <Block>(inventoryItem, callback, state);

            // Add to the list of things we're waiting for. It's important this come before the network send to avoid
            // race conditions.
            lock (_pendingGetBlockFutures)
            {
                _pendingGetBlockFutures.Add(future);
            }
            _conn.WriteMessage(getdata);
            return(future);
        }
示例#12
0
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 public void SetChainHead(StoredBlock chainHead)
 {
     lock (this)
     {
         try
         {
             var hash = chainHead.Header.Hash;
             _chainHead = new Sha256Hash(hash);
             // Write out new hash to the first 32 bytes of the file past one (first byte is version number).
             _stream.Seek(1, SeekOrigin.Begin);
             _stream.Write(hash, 0, hash.Length);
         }
         catch (IOException e)
         {
             throw new BlockStoreException(e);
         }
     }
 }
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 public void SetChainHead(StoredBlock chainHead)
 {
     lock (this)
     {
         try
         {
             var hash = chainHead.Header.Hash;
             _chainHead = new Sha256Hash(hash);
             // Write out new hash to the first 32 bytes of the file past one (first byte is version number).
             var originalPos = _channel.Position;
             _channel.Position = 1;
             _channel.Write(hash, 0, hash.Length);
             _channel.Position = originalPos;
         }
         catch (IOException e)
         {
             throw new BlockStoreException(e);
         }
     }
 }
示例#14
0
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 public void Put(StoredBlock block)
 {
     lock (this)
     {
         try
         {
             var hash = new Sha256Hash(block.Header.Hash);
             Debug.Assert(!_blockMap.ContainsKey(hash), "Attempt to insert duplicate");
             // Append to the end of the file. The other fields in StoredBlock will be recalculated when it's reloaded.
             var bytes = block.Header.BitcoinSerialize();
             _stream.Write(bytes);
             _stream.Flush();
             _blockMap[hash] = block;
         }
         catch (IOException e)
         {
             throw new BlockStoreException(e);
         }
     }
 }
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 public void Put(StoredBlock block)
 {
     lock (this)
     {
         try
         {
             var hash = new Sha256Hash(block.Header.Hash);
             // Append to the end of the file.
             _dummyRecord.Write(_channel, block);
             _blockCache[hash] = block;
             while (_blockCache.Count > 100)
             {
                 _blockCache.RemoveAt(0);
             }
         }
         catch (IOException e)
         {
             throw new BlockStoreException(e);
         }
     }
 }
        /// <exception cref="BitCoinSharp.BlockStoreException" />
        /// <exception cref="System.IO.IOException" />
        /// <exception cref="BitCoinSharp.ProtocolException" />
        private Record GetRecord(Sha256Hash hash)
        {
            var startPos = _channel.Position;
            // Use our own file pointer within the tight loop as updating channel positions is really expensive.
            var pos    = startPos;
            var record = new Record();

            do
            {
                if (!record.Read(_channel, pos, _buf))
                {
                    throw new IOException("Failed to read buffer");
                }
                if (record.GetHeader(_params).Hash.SequenceEqual(hash.Hash))
                {
                    // Found it. Update file position for next time.
                    _channel.Position = pos;
                    return(record);
                }
                // Did not find it.
                if (pos == 1 + 32)
                {
                    // At the start so wrap around to the end.
                    pos = _channel.Length - Record.Size;
                }
                else
                {
                    // Move backwards.
                    pos = pos - Record.Size;
                    Debug.Assert(pos >= 1 + 32, pos.ToString());
                }
            } while (pos != startPos);
            // Was never stored.
            _channel.Position = pos;
            return(null);
        }
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 public void Put(StoredBlock block)
 {
     lock (this)
     {
         try
         {
             var hash = new Sha256Hash(block.Header.Hash);
             // Append to the end of the file.
             _dummyRecord.Write(_channel, block);
             _blockCache[hash] = block;
             while (_blockCache.Count > 100)
             {
                 _blockCache.RemoveAt(0);
             }
         }
         catch (IOException e)
         {
             throw new BlockStoreException(e);
         }
     }
 }
示例#18
0
        /// <exception cref="ProtocolException"/>
        protected override void Parse()
        {
            _version = ReadUint32();
            _prevBlockHash = ReadHash();
            _merkleRoot = ReadHash();
            _time = ReadUint32();
            _difficultyTarget = ReadUint32();
            _nonce = ReadUint32();

            _hash = new Sha256Hash(Utils.ReverseBytes(Utils.DoubleDigest(Bytes, 0, Cursor)));

            if (Cursor == Bytes.Length)
            {
                // This message is just a header, it has no transactions.
                return;
            }

            var numTransactions = (int) ReadVarInt();
            Transactions = new List<Transaction>(numTransactions);
            for (var i = 0; i < numTransactions; i++)
            {
                var tx = new Transaction(Params, Bytes, Cursor);
                Transactions.Add(tx);
                Cursor += tx.MessageSize;
            }
        }
示例#19
0
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 private void Load(FileInfo file)
 {
     _log.InfoFormat("Reading block store from {0}", file);
     using (var input = file.OpenRead())
     {
         // Read a version byte.
         var version = input.Read();
         if (version == -1)
         {
             // No such file or the file was empty.
             throw new FileNotFoundException(file.Name + " does not exist or is empty");
         }
         if (version != 1)
         {
             throw new BlockStoreException("Bad version number: " + version);
         }
         // Chain head pointer is the first thing in the file.
         var chainHeadHash = new byte[32];
         input.Read(chainHeadHash);
         _chainHead = new Sha256Hash(chainHeadHash);
         _log.InfoFormat("Read chain head from disk: {0}", _chainHead);
         var now = Environment.TickCount;
         // Rest of file is raw block headers.
         var headerBytes = new byte[Block.HeaderSize];
         try
         {
             while (true)
             {
                 // Read a block from disk.
                 if (input.Read(headerBytes) < 80)
                 {
                     // End of file.
                     break;
                 }
                 // Parse it.
                 var b = new Block(_params, headerBytes);
                 // Look up the previous block it connects to.
                 var prev = Get(b.PrevBlockHash);
                 StoredBlock s;
                 if (prev == null)
                 {
                     // First block in the stored chain has to be treated specially.
                     if (b.Equals(_params.GenesisBlock))
                     {
                         s = new StoredBlock(_params.GenesisBlock.CloneAsHeader(), _params.GenesisBlock.GetWork(), 0);
                     }
                     else
                     {
                         throw new BlockStoreException("Could not connect " + Utils.BytesToHexString(b.Hash) + " to "
                                                       + Utils.BytesToHexString(b.PrevBlockHash));
                     }
                 }
                 else
                 {
                     // Don't try to verify the genesis block to avoid upsetting the unit tests.
                     b.Verify();
                     // Calculate its height and total chain work.
                     s = prev.Build(b);
                 }
                 // Save in memory.
                 _blockMap[new Sha256Hash(b.Hash)] = s;
             }
         }
         catch (ProtocolException e)
         {
             // Corrupted file.
             throw new BlockStoreException(e);
         }
         catch (VerificationException e)
         {
             // Should not be able to happen unless the file contains bad blocks.
             throw new BlockStoreException(e);
         }
         var elapsed = Environment.TickCount - now;
         _log.InfoFormat("Block chain read complete in {0}ms", elapsed);
     }
 }
 public GetBlocksMessage(NetworkParameters @params, IList<Sha256Hash> locator, Sha256Hash stopHash)
     : base(@params)
 {
     _locator = locator;
     _stopHash = stopHash;
 }
        public IList<Sha256Hash> Locator
        {
            get { return _locator; }
        }

        public Sha256Hash StopHash
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="BitCoinSharp.ProtocolException" />
 private Record GetRecord(Sha256Hash hash)
 {
     var startPos = _channel.Position;
     // Use our own file pointer within the tight loop as updating channel positions is really expensive.
     var pos = startPos;
     var record = new Record();
     do
     {
         if (!record.Read(_channel, pos, _buf))
             throw new IOException("Failed to read buffer");
         if (record.GetHeader(_params).Hash.SequenceEqual(hash.Hash))
         {
             // Found it. Update file position for next time.
             _channel.Position = pos;
             return record;
         }
         // Did not find it.
         if (pos == 1 + 32)
         {
             // At the start so wrap around to the end.
             pos = _channel.Length - Record.Size;
         }
         else
         {
             // Move backwards.
             pos = pos - Record.Size;
             Debug.Assert(pos >= 1 + 32, pos.ToString());
         }
     } while (pos != startPos);
     // Was never stored.
     _channel.Position = pos;
     return null;
 }
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 private void Load(FileInfo file)
 {
     _log.InfoFormat("Reading block store from {0}", file);
     if (_channel != null)
     {
         _channel.Dispose();
     }
     _channel = file.OpenRead();
     // Read a version byte.
     var version = _channel.Read();
     if (version == -1)
     {
         // No such file or the file was empty.
         throw new FileNotFoundException(file.Name + " does not exist or is empty");
     }
     if (version != _fileFormatVersion)
     {
         throw new BlockStoreException("Bad version number: " + version);
     }
     // Chain head pointer is the first thing in the file.
     var chainHeadHash = new byte[32];
     _channel.Read(chainHeadHash);
     _chainHead = new Sha256Hash(chainHeadHash);
     _log.InfoFormat("Read chain head from disk: {0}", _chainHead);
     _channel.Position = _channel.Length - Record.Size;
 }
示例#24
0
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 public void SetChainHead(StoredBlock chainHead)
 {
     lock (this)
     {
         try
         {
             var hash = chainHead.Header.Hash;
             _chainHead = new Sha256Hash(hash);
             // Write out new hash to the first 32 bytes of the file past one (first byte is version number).
             _stream.Seek(1, SeekOrigin.Begin);
             _stream.Write(hash, 0, hash.Length);
         }
         catch (IOException e)
         {
             throw new BlockStoreException(e);
         }
     }
 }
示例#25
0
 /// <summary>
 /// Adds a transaction to this block.
 /// </summary>
 internal void AddTransaction(Transaction t)
 {
     if (Transactions == null)
     {
         Transactions = new List<Transaction>();
     }
     Transactions.Add(t);
     // Force a recalculation next time the values are needed.
     _merkleRoot = null;
     _hash = null;
 }
示例#26
0
 /// <summary>
 /// Special case constructor, used for the genesis node, cloneAsHeader and unit tests.
 /// </summary>
 internal Block(NetworkParameters @params)
     : base(@params)
 {
     // Set up a few basic things. We are not complete after this though.
     _version = 1;
     _difficultyTarget = 0x1d07fff8;
     _time = (uint) UnixTime.ToUnixTime(DateTime.UtcNow);
     _prevBlockHash = Sha256Hash.ZeroHash;
 }
示例#27
0
 /// <exception cref="System.IO.IOException" />
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 private void Load(FileInfo file)
 {
     _log.InfoFormat("Reading block store from {0}", file);
     using (var input = file.OpenRead())
     {
         // Read a version byte.
         var version = input.Read();
         if (version == -1)
         {
             // No such file or the file was empty.
             throw new FileNotFoundException(file.Name + " does not exist or is empty");
         }
         if (version != 1)
         {
             throw new BlockStoreException("Bad version number: " + version);
         }
         // Chain head pointer is the first thing in the file.
         var chainHeadHash = new byte[32];
         input.Read(chainHeadHash);
         _chainHead = new Sha256Hash(chainHeadHash);
         _log.InfoFormat("Read chain head from disk: {0}", _chainHead);
         var now = Environment.TickCount;
         // Rest of file is raw block headers.
         var headerBytes = new byte[Block.HeaderSize];
         try
         {
             while (true)
             {
                 // Read a block from disk.
                 if (input.Read(headerBytes) < 80)
                 {
                     // End of file.
                     break;
                 }
                 // Parse it.
                 var b = new Block(_params, headerBytes);
                 // Look up the previous block it connects to.
                 var         prev = Get(b.PrevBlockHash);
                 StoredBlock s;
                 if (prev == null)
                 {
                     // First block in the stored chain has to be treated specially.
                     if (b.Equals(_params.GenesisBlock))
                     {
                         s = new StoredBlock(_params.GenesisBlock.CloneAsHeader(), _params.GenesisBlock.GetWork(), 0);
                     }
                     else
                     {
                         throw new BlockStoreException("Could not connect " + Utils.BytesToHexString(b.Hash) + " to "
                                                       + Utils.BytesToHexString(b.PrevBlockHash));
                     }
                 }
                 else
                 {
                     // Don't try to verify the genesis block to avoid upsetting the unit tests.
                     b.Verify();
                     // Calculate its height and total chain work.
                     s = prev.Build(b);
                 }
                 // Save in memory.
                 _blockMap[new Sha256Hash(b.Hash)] = s;
             }
         }
         catch (ProtocolException e)
         {
             // Corrupted file.
             throw new BlockStoreException(e);
         }
         catch (VerificationException e)
         {
             // Should not be able to happen unless the file contains bad blocks.
             throw new BlockStoreException(e);
         }
         var elapsed = Environment.TickCount - now;
         _log.InfoFormat("Block chain read complete in {0}ms", elapsed);
     }
 }
示例#28
0
 /// <summary>
 /// Connects this input to the relevant output of the referenced transaction if it's in the given map.
 /// Connecting means updating the internal pointers and spent flags.
 /// </summary>
 /// <param name="transactions">Map of txhash-&gt;transaction.</param>
 /// <param name="disconnect">Whether to abort if there's a pre-existing connection or not.</param>
 /// <returns>True if connection took place, false if the referenced transaction was not in the list.</returns>
 internal ConnectionResult Connect(IDictionary<Sha256Hash, Transaction> transactions, bool disconnect)
 {
     var h = new Sha256Hash(Outpoint.Hash);
     Transaction tx;
     if (!transactions.TryGetValue(h, out tx))
         return ConnectionResult.NoSuchTx;
     var @out = tx.Outputs[Outpoint.Index];
     if ([email protected])
     {
         if (disconnect)
             @out.MarkAsUnspent();
         else
             return ConnectionResult.AlreadySpent;
     }
     Outpoint.FromTx = tx;
     @out.MarkAsSpent(this);
     return ConnectionResult.Success;
 }
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 public void SetChainHead(StoredBlock chainHead)
 {
     lock (this)
     {
         try
         {
             var hash = chainHead.Header.Hash;
             _chainHead = new Sha256Hash(hash);
             // Write out new hash to the first 32 bytes of the file past one (first byte is version number).
             var originalPos = _channel.Position;
             _channel.Position = 1;
             _channel.Write(hash, 0, hash.Length);
             _channel.Position = originalPos;
         }
         catch (IOException e)
         {
             throw new BlockStoreException(e);
         }
     }
 }
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 private void CreateNewStore(NetworkParameters @params, FileInfo file)
 {
     // Create a new block store if the file wasn't found or anything went wrong whilst reading.
     _blockCache.Clear();
     try
     {
         if (_channel != null)
         {
             _channel.Dispose();
             _channel = null;
         }
         file.Delete();
         _channel = file.Create(); // Create fresh.
         _channel.Write(_fileFormatVersion);
     }
     catch (IOException e1)
     {
         // We could not load a block store nor could we create a new one!
         throw new BlockStoreException(e1);
     }
     try
     {
         // Set up the genesis block. When we start out fresh, it is by definition the top of the chain.
         var genesis = @params.GenesisBlock.CloneAsHeader();
         var storedGenesis = new StoredBlock(genesis, genesis.GetWork(), 0);
         _chainHead = new Sha256Hash(storedGenesis.Header.Hash);
         _channel.Write(_chainHead.Hash);
         Put(storedGenesis);
     }
     catch (IOException e)
     {
         throw new BlockStoreException(e);
     }
 }
示例#31
0
        /// <exception cref="BitCoinSharp.ProtocolException" />
        protected override void Parse()
        {
            _version = ReadUint32();
            // First come the inputs.
            var numInputs = ReadVarInt();
            _inputs = new List<TransactionInput>((int) numInputs);
            for (var i = 0UL; i < numInputs; i++)
            {
                var input = new TransactionInput(Params, this, Bytes, Cursor);
                _inputs.Add(input);
                Cursor += input.MessageSize;
            }
            // Now the outputs
            var numOutputs = ReadVarInt();
            _outputs = new List<TransactionOutput>((int) numOutputs);
            for (var i = 0UL; i < numOutputs; i++)
            {
                var output = new TransactionOutput(Params, this, Bytes, Cursor);
                _outputs.Add(output);
                Cursor += output.MessageSize;
            }
            _lockTime = ReadUint32();

            // Store a hash, it may come in useful later (want to avoid re-serialization costs).
            _hash = new Sha256Hash(Utils.ReverseBytes(Utils.DoubleDigest(Bytes, Offset, Cursor - Offset)));
        }
示例#32
0
 /// <exception cref="BitCoinSharp.BlockStoreException" />
 public void Put(StoredBlock block)
 {
     lock (this)
     {
         try
         {
             var hash = new Sha256Hash(block.Header.Hash);
             Debug.Assert(!_blockMap.ContainsKey(hash), "Attempt to insert duplicate");
             // Append to the end of the file. The other fields in StoredBlock will be recalculated when it's reloaded.
             var bytes = block.Header.BitcoinSerialize();
             _stream.Write(bytes);
             _stream.Flush();
             _blockMap[hash] = block;
         }
         catch (IOException e)
         {
             throw new BlockStoreException(e);
         }
     }
 }
示例#33
0
 // TODO: Clean all this up once TransactionOutPoint disappears.
 /// <summary>
 /// Locates the referenced output from the given pool of transactions.
 /// </summary>
 /// <returns>The TransactionOutput or null if the transactions map doesn't contain the referenced tx.</returns>
 internal TransactionOutput GetConnectedOutput(IDictionary<Sha256Hash, Transaction> transactions)
 {
     var h = new Sha256Hash(Outpoint.Hash);
     Transaction tx;
     if (!transactions.TryGetValue(h, out tx))
         return null;
     var @out = tx.Outputs[Outpoint.Index];
     return @out;
 }
        /// <exception cref="BitCoinSharp.BlockStoreException" />
        public StoredBlock Get(byte[] hashBytes)
        {
            lock (this)
            {
                // Check the memory cache first.
                var hash = new Sha256Hash(hashBytes);
                StoredBlock fromMem;
                if (_blockCache.TryGetValue(hash, out fromMem))
                {
                    return fromMem;
                }
                if (_notFoundCache.TryGetValue(hash, out fromMem) && fromMem == _notFoundMarker)
                {
                    return null;
                }

                try
                {
                    var fromDisk = GetRecord(hash);
                    StoredBlock block = null;
                    if (fromDisk == null)
                    {
                        _notFoundCache[hash] = _notFoundMarker;
                        while (_notFoundCache.Count > 100)
                        {
                            _notFoundCache.RemoveAt(0);
                        }
                    }
                    else
                    {
                        block = fromDisk.ToStoredBlock(_params);
                        _blockCache[hash] = block;
                        while (_blockCache.Count > 100)
                        {
                            _blockCache.RemoveAt(0);
                        }
                    }
                    return block;
                }
                catch (IOException e)
                {
                    throw new BlockStoreException(e);
                }
                catch (ProtocolException e)
                {
                    throw new BlockStoreException(e);
                }
            }
        }