/// <summary> /// Reads a single transaction off the blockchain in sequential order /// /// thanks /// https://en.bitcoin.it/wiki/Protocol_specification#block /// http://james.lab6.com/2012/01/12/bitcoin-285-bytes-that-changed-the-world/ /// https://code.google.com/p/blockchain/source/browse/trunk/BlockChain.h /// </summary> public Boolean Read() { var newBlock = new BitcoinBlock { MagicBytes = Dequeue(4) }; if (BitConverter.ToUInt32(newBlock.MagicBytes, 0) != 3652501241) { throw new Exception("Invalid magic number at the start of this block"); } newBlock.BlockSize = BitConverter.ToUInt32(Dequeue(4), 0); newBlock.BlockFormatVersion = BitConverter.ToUInt32(Dequeue(4), 0); newBlock.PreviousBlockHash = ReverseArray(Dequeue(32)); newBlock.MerkleRoot = ReverseArray(Dequeue(32)); newBlock.TimeStamp = Helper.UnixToDateTime(BitConverter.ToUInt32(Dequeue(4), 0)); newBlock.Bits = BitConverter.ToUInt32(Dequeue(4), 0); newBlock.Nonce = BitConverter.ToUInt32(Dequeue(4), 0); newBlock.TransactionCount = ReadVariableLengthInteger(Dequeue(1)); for (var t = 0; t < newBlock.TransactionCount; t++) { var newTransaction = new BitcoinTransaction(); newTransaction.TransactionVersionNumber = BitConverter.ToUInt32(Dequeue(4), 0); newTransaction.InputCount = ReadVariableLengthInteger(Dequeue(1)); for (var i = 0; i < newTransaction.InputCount; i++) { var newInput = new BitcoinInput(); newInput.InputTransactionHash = Dequeue(32); newInput.InputTransactionIndex = BitConverter.ToUInt32(Dequeue(4), 0); newInput.ResponseScriptLength = ReadVariableLengthInteger(Dequeue(1)); newInput.ResponseScript = Dequeue((int)newInput.ResponseScriptLength); newInput.SequenceNumber = BitConverter.ToUInt32(Dequeue(4), 0); newTransaction.Inputs.Add(newInput); } newTransaction.OutputCount = ReadVariableLengthInteger(Dequeue(1)); for (var o = 0; o < newTransaction.OutputCount; o++) { var newOutput = new BitcoinOutput(); newOutput.OutputValue = BitConverter.ToUInt64(Dequeue(8), 0); newOutput.ChallengeScriptLength = ReadVariableLengthInteger(Dequeue(1)); newOutput.ChallengeScript = Dequeue((int)newOutput.ChallengeScriptLength); newOutput.EcdsaPublickey = ExtractPublicKey(newOutput.ChallengeScript); newOutput.BitcoinAddress = ComputeBitcoinAddress(newOutput.EcdsaPublickey); // todo: expensive operation, should it be a feature flag? newTransaction.Outputs.Add(newOutput); } newTransaction.LockTime = BitConverter.ToUInt32(Dequeue(4), 0); newBlock.Transactions.Add(newTransaction); } CurrentBlock = newBlock; return(true); }
public static void Main(string[] args) { string hash = "0ade9b2864672074864c1d509ac427ffdcf16fe983ef6ebe8b0606afd3fb50a4"; BitcoinTransaction transaction = BlockchainAPI.GetTransaction(hash); Console.WriteLine("Block Number = {0}", transaction.BlockHeight); BitcoinBlock latestBlock = BlockchainAPI.GetLatestBlock(); Console.WriteLine("LatestBlock = {0}", latestBlock.BlockHeight); Console.WriteLine("Number of Confirmations = {0}", latestBlock.BlockHeight - transaction.BlockHeight); Console.ReadLine(); }
private async Task ReadNewBlocksAsync(Func <GetBlockRpcModel, Task> saveTransactions) { var hashToImport = await _lastImportendBlockHash.GetAsync(); if (string.IsNullOrEmpty(hashToImport)) { hashToImport = _firstBlock; } var block = await _bitcoinRpc.GetBlockAsync(hashToImport); while (true) { var newBlock = new BitcoinBlock { Hash = block.Hash, Time = block.GetTime(), Height = block.Height, Merkleroot = block.Merkleroot, Nonce = block.Nonce, Difficulty = block.Difficulty, Previousblockhash = block.Previousblockhash, Nextblockhash = block.Nextblockhash, TotalTransactions = block.Tx.Length }; //Console.WriteLine("\n block - " + newBlock.Hash + " room block " + newBlock.Height); await _bitcoinBlockRepository.SaveAsync(newBlock); await saveTransactions(block); await _lastImportendBlockHash.SetAsync(block.Hash, block.Height); if (block.IsLastBlock()) { //Console.WriteLine("block - " + newBlock.Hash + " room block " + newBlock.Height); //Console.WriteLine("It was the last block."); break; } block = await _bitcoinRpc.GetBlockAsync(block.Nextblockhash); } }