public static byte[] EncodeBlockHeader(UInt32 Version, UInt256 PreviousBlock, UInt256 MerkleRoot, UInt32 Time, UInt32 Bits, UInt32 Nonce) { var stream = new MemoryStream(); using (var writer = new BinaryWriter(stream)) { writer.Write4Bytes(Version); writer.Write32Bytes(PreviousBlock); writer.Write32Bytes(MerkleRoot); writer.Write4Bytes(Time); writer.Write4Bytes(Bits); writer.Write4Bytes(Nonce); return stream.ToArray(); } }
public static byte[] EncodeTransaction(UInt32 Version, ImmutableArray<TxInput> Inputs, ImmutableArray<TxOutput> Outputs, UInt32 LockTime) { var stream = new MemoryStream(); using (var writer = new BinaryWriter(stream)) { writer.Write4Bytes(Version); writer.WriteVarInt((UInt64)Inputs.Length); foreach (var input in Inputs) { writer.Write32Bytes(input.PreviousTxOutputKey.TxHash); writer.Write4Bytes(input.PreviousTxOutputKey.TxOutputIndex); writer.WriteVarBytes(input.ScriptSignature.ToArray()); writer.Write4Bytes(input.Sequence); } writer.WriteVarInt((UInt64)Outputs.Length); foreach (var output in Outputs) { writer.Write8Bytes(output.Value); writer.WriteVarBytes(output.ScriptPublicKey.ToArray()); } writer.Write4Bytes(LockTime); return stream.ToArray(); } }
public static void EncodeTxInput(Stream stream, TxInput txInput) { using (var writer = new BinaryWriter(stream, Encoding.ASCII, leaveOpen: true)) { writer.Write32Bytes(txInput.PreviousTxOutputKey.TxHash); writer.Write4Bytes(txInput.PreviousTxOutputKey.TxOutputIndex); writer.WriteVarBytes(txInput.ScriptSignature.ToArray()); writer.Write4Bytes(txInput.Sequence); } }
public static void EncodeInventoryVector(Stream stream, InventoryVector invVector) { using (var writer = new BinaryWriter(stream, Encoding.ASCII, leaveOpen: true)) { writer.Write4Bytes(invVector.Type); writer.Write32Bytes(invVector.Hash); } }
public static void EncodeGetBlocksPayload(Stream stream, GetBlocksPayload getBlocksPayload) { using (var writer = new BinaryWriter(stream, Encoding.ASCII, leaveOpen: true)) { writer.Write4Bytes(getBlocksPayload.Version); writer.EncodeList(getBlocksPayload.BlockLocatorHashes, locatorHash => writer.Write32Bytes(locatorHash)); writer.Write32Bytes(getBlocksPayload.HashStop); } }
public static void EncodeBlockHeader(Stream stream, BlockHeader blockHeader) { using (var writer = new BinaryWriter(stream, Encoding.ASCII, leaveOpen: true)) { writer.Write4Bytes(blockHeader.Version); writer.Write32Bytes(blockHeader.PreviousBlock); writer.Write32Bytes(blockHeader.MerkleRoot); writer.Write4Bytes(blockHeader.Time); writer.Write4Bytes(blockHeader.Bits); writer.Write4Bytes(blockHeader.Nonce); } }
public BlockchainKey WriteBlockchain(Data.Blockchain blockchain) { var guid = Guid.NewGuid(); CreateDatabase(guid); var blockchainKey = new BlockchainKey(guid, blockchain.RootBlockHash); var dbPath = GetDatabasePath(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 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", FbDbType.Char, FbCharset.Octets, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", FbDbType.Char, FbCharset.Octets, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); cmd.Parameters.SetValue("@totalWork", FbDbType.Char, FbCharset.Octets, 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", FbDbType.Char, FbCharset.Octets, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", FbDbType.Char, FbCharset.Octets, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); cmd.Parameters.Add(new FbParameter { ParameterName = "@blockHash", FbDbType = FbDbType.Char, Charset = FbCharset.Octets, Size = 32 }); cmd.Parameters.Add(new FbParameter { ParameterName = "@previousBlockHash", FbDbType = FbDbType.Char, Charset = FbCharset.Octets, Size = 32 }); cmd.Parameters.Add(new FbParameter { ParameterName = "@height", FbDbType = FbDbType.Integer }); cmd.Parameters.Add(new FbParameter { ParameterName = "@totalWork", FbDbType = FbDbType.Char, Charset = FbCharset.Octets, 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", FbDbType.Char, FbCharset.Octets, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", FbDbType.Char, FbCharset.Octets, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); cmd.Parameters.Add(new FbParameter { ParameterName = "@utxoChunkBytes", FbDbType = FbDbType.Binary }); 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; chunkWriter.Write32Bytes(output.TxHash); 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", FbDbType.Char, FbCharset.Octets, 16).Value = blockchainKey.Guid.ToByteArray(); cmd.Parameters.SetValue("@rootBlockHash", FbDbType.Char, FbCharset.Octets, 32).Value = blockchainKey.RootBlockHash.ToDbByteArray(); cmd.ExecuteNonQuery(); } trans.Commit(); } } return blockchainKey; }