public Blockchain ReadBlockchain(BlockchainKey chainedBlock) { throw new NotImplementedException(); }
public Data.Blockchain ReadBlockchain(BlockchainKey blockchainKey) { CheckDatabaseFolder(); var blockListBuilder = ImmutableList.CreateBuilder<ChainedBlock>(); var utxoBuilder = ImmutableDictionary.CreateBuilder<UInt256, UnspentTx>(); var connString = @"Server=localhost; Database=BitSharp_Blockchains; Trusted_Connection=true;"; using (var conn = new SqlConnection(connString)) { conn.Open(); using (var cmd = conn.CreateCommand()) { cmd.CommandText = @" SELECT BlockHash, PreviousBlockHash, Height, TotalWork FROM ChainedBlocks WHERE Guid = @guid AND RootBlockHash = @rootBlockHash ORDER BY Height ASC"; cmd.Parameters.SetValue("@guid", SqlDbType.Binary, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", SqlDbType.Binary, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var blockHash = reader.GetUInt256(0); var previousBlockHash = reader.GetUInt256(1); var height = reader.GetInt32(2); var totalWork = reader.GetBigInteger(3); blockListBuilder.Add(new ChainedBlock(blockHash, previousBlockHash, height, totalWork)); } } } using (var cmd = conn.CreateCommand()) { cmd.CommandText = @" SELECT UtxoChunkBytes FROM UtxoData WHERE Guid = @guid AND RootBlockHash = @rootBlockHash"; cmd.Parameters.SetValue("@guid", SqlDbType.Binary, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", SqlDbType.Binary, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var chunkBytes = reader.GetBytes(0); var chunkStream = new MemoryStream(chunkBytes); using (var chunkReader = new BinaryReader(chunkStream)) { var chunkLength = chunkReader.Read4Bytes().ToIntChecked(); var outputs = new TxOutputKey[chunkLength]; for (var i = 0; i < chunkLength; i++) { var prevTxHash = chunkReader.Read32Bytes(); var prevTxOutputIndex = chunkReader.Read4Bytes(); outputs[i] = new TxOutputKey(prevTxHash, prevTxOutputIndex); } //TODO utxoBuilder.UnionWith(outputs); } } } } } return new Data.Blockchain(blockListBuilder.ToImmutable(), blockListBuilder.Select(x => x.BlockHash).ToImmutableHashSet(), utxoBuilder.ToImmutable()); }
public BlockchainKey WriteBlockchain(Data.Blockchain blockchain) { var guid = Guid.NewGuid(); var blockchainKey = new BlockchainKey(guid, blockchain.RootBlockHash); var connString = @"Server=localhost; Database=BitSharp_Blockchains; Trusted_Connection=true;"; using (var conn = new SqlConnection(connString)) { conn.Open(); using (var trans = conn.BeginTransaction()) { // write out the metadata for the blockchain using (var cmd = conn.CreateCommand()) { cmd.Transaction = trans; cmd.CommandText = @" INSERT INTO BlockchainMetadata (Guid, RootBlockHash, TotalWork, IsComplete) VALUES (@guid, @rootBlockHash, @totalWork, 0);"; cmd.Parameters.SetValue("@guid", SqlDbType.Binary, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", SqlDbType.Binary, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); cmd.Parameters.SetValue("@totalWork", SqlDbType.Binary, 64).Value = blockchain.TotalWork.ToDbByteArray(); cmd.ExecuteNonQuery(); } // write out the block metadata comprising the blockchain using (var cmd = conn.CreateCommand()) { cmd.Transaction = trans; cmd.CommandText = @" INSERT INTO ChainedBlocks (Guid, RootBlockHash, BlockHash, PreviousBlockHash, Height, TotalWork) VALUES (@guid, @rootBlockHash, @blockHash, @previousBlockHash, @height, @totalWork)"; cmd.Parameters.SetValue("@guid", SqlDbType.Binary, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", SqlDbType.Binary, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); cmd.Parameters.Add(new SqlParameter { ParameterName = "@blockHash", SqlDbType = SqlDbType.Binary, Size = 32 }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@previousBlockHash", SqlDbType = SqlDbType.Binary, Size = 32 }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@height", SqlDbType = SqlDbType.Int }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@totalWork", SqlDbType = SqlDbType.Binary, Size = 64 }); foreach (var chainedBlock in blockchain.BlockList) { cmd.Parameters["@blockHash"].Value = chainedBlock.BlockHash.ToDbByteArray(); cmd.Parameters["@previousBlockHash"].Value = chainedBlock.PreviousBlockHash.ToDbByteArray(); cmd.Parameters["@height"].Value = chainedBlock.Height; cmd.Parameters["@totalWork"].Value = chainedBlock.TotalWork.ToDbByteArray(); cmd.ExecuteNonQuery(); } } // write out the utxo using (var cmd = conn.CreateCommand()) { cmd.Transaction = trans; cmd.CommandText = @" INSERT INTO UtxoData (Guid, RootBlockhash, UtxoChunkBytes) VALUES (@guid, @rootBlockHash, @utxoChunkBytes)"; cmd.Parameters.SetValue("@guid", SqlDbType.Binary, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", SqlDbType.Binary, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); cmd.Parameters.Add(new SqlParameter { ParameterName = "@utxoChunkBytes", SqlDbType = SqlDbType.VarBinary }); var chunkSize = 100000; var currentOffset = 0; var chunkBytes = new byte[4 + (36 * chunkSize)]; using (var utxoEnumerator = blockchain.Utxo.GetEnumerator()) { // chunk outer loop while (currentOffset < blockchain.Utxo.Count) { var chunkLength = Math.Min(chunkSize, blockchain.Utxo.Count - currentOffset); var chunkStream = new MemoryStream(chunkBytes); using (var chunkWriter = new BinaryWriter(chunkStream)) { chunkWriter.Write4Bytes((UInt32)chunkLength); // chunk inner loop for (var i = 0; i < chunkLength; i++) { // get the next output from the utxo if (!utxoEnumerator.MoveNext()) throw new Exception(); var output = utxoEnumerator.Current; //TODO chunkWriter.Write32Bytes(output.TxHash); //TODO chunkWriter.Write4Bytes((UInt32)output.TxOutputIndex); } cmd.Parameters["@utxoChunkBytes"].Size = chunkBytes.Length; cmd.Parameters["@utxoChunkBytes"].Value = chunkBytes; } // write the chunk cmd.ExecuteNonQuery(); currentOffset += chunkLength; } // there should be no items left in utxo at this point if (utxoEnumerator.MoveNext()) throw new Exception(); } } // mark write as complete using (var cmd = conn.CreateCommand()) { cmd.Transaction = trans; cmd.CommandText = @" UPDATE BlockchainMetadata SET IsComplete = 1 WHERE Guid = @guid AND RootBlockHash = @rootBlockHash;"; cmd.Parameters.SetValue("@guid", SqlDbType.Binary, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", SqlDbType.Binary, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); cmd.ExecuteNonQuery(); } trans.Commit(); } } return blockchainKey; }
public Data.Blockchain ReadBlockchain(BlockchainKey blockchainKey) { CheckDatabaseFolder(); var blockListBuilder = ImmutableList.CreateBuilder<ChainedBlock>(); var utxoBuilder = ImmutableHashSet.CreateBuilder<TxOutputKey>(); var dbPath = GetDatabasePath(blockchainKey.Guid); var connString = @"ServerType=1; DataSource=localhost; Database={0}; Pooling=false; User=SYSDBA; Password=NA;".Format2(dbPath); using (var conn = new FbConnection(connString)) { conn.Open(); using (var cmd = conn.CreateCommand()) { cmd.CommandText = @" SELECT BlockHash, PreviousBlockHash, Height, TotalWork FROM ChainedBlocks WHERE Guid = @guid AND RootBlockHash = @rootBlockHash ORDER BY Height ASC"; cmd.Parameters.SetValue("@guid", FbDbType.Char, FbCharset.Octets, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", FbDbType.Char, FbCharset.Octets, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var blockHash = reader.GetUInt256(0); var previousBlockHash = reader.GetUInt256(1); var height = reader.GetInt32(2); var totalWork = reader.GetBigInteger(3); blockListBuilder.Add(new ChainedBlock(blockHash, previousBlockHash, height, totalWork)); } } } using (var cmd = conn.CreateCommand()) { cmd.CommandText = @" SELECT UtxoChunkBytes FROM UtxoData WHERE Guid = @guid AND RootBlockHash = @rootBlockHash"; cmd.Parameters.SetValue("@guid", FbDbType.Char, FbCharset.Octets, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", FbDbType.Char, FbCharset.Octets, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var chunkBytes = reader.GetBytes(0); var chunkStream = new MemoryStream(chunkBytes); using (var chunkReader = new BinaryReader(chunkStream)) { var chunkLength = chunkReader.Read4Bytes().ToIntChecked(); var outputs = new TxOutputKey[chunkLength]; for (var i = 0; i < chunkLength; i++) { var prevTxHash = chunkReader.Read32Bytes(); var prevTxOutputIndex = chunkReader.Read4Bytes(); outputs[i] = new TxOutputKey(prevTxHash, prevTxOutputIndex); } utxoBuilder.UnionWith(outputs); } } } } } return new Data.Blockchain(blockListBuilder.ToImmutable(), blockListBuilder.Select(x => x.BlockHash).ToImmutableHashSet(), utxoBuilder.ToImmutable()); }