using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
+using System.IO;
namespace Novacoin
{
///
/// TODO: rewrite using MemoryStream
/// </summary>
- public class ByteQueue
+ public class ByteQueue : IDisposable
{
- private int _Index;
- private List<byte> _Elements;
+ private bool disposed = false;
- public ByteQueue(byte[] List, int Start)
+ private MemoryStream _Stream;
+ private BinaryReader _Reader;
+
+ public ByteQueue(ref byte[] buffer, int Start)
{
- _Elements = new List<byte>(List);
- _Index = Start;
+ _Stream = new MemoryStream(buffer);
+ _Stream.Seek(Start, SeekOrigin.Begin);
+ _Reader = new BinaryReader(_Stream);
}
- public ByteQueue(byte[] List)
+ public ByteQueue(ref byte[] buffer)
{
- _Elements = new List<byte>(List);
- _Index = 0;
+ _Stream = new MemoryStream(buffer);
+ _Reader = new BinaryReader(_Stream);
}
- public ByteQueue(List<byte> List, int Start)
+ public ByteQueue(ref List<byte> List, int Start)
{
- _Elements = new List<byte>(List);
- _Index = Start;
+ _Stream = new MemoryStream(List.ToArray());
+ _Stream.Seek(Start, SeekOrigin.Begin);
+ _Reader = new BinaryReader(_Stream);
}
- public ByteQueue(List<byte> List)
+ public ByteQueue(ref List<byte> List)
{
- _Elements = new List<byte>(List);
- _Index = 0;
+ _Stream = new MemoryStream(List.ToArray());
+ _Reader = new BinaryReader(_Stream);
}
- public byte Get()
+ ~ByteQueue()
{
- if (_Elements.Count <= _Index)
- {
- throw new ByteQueueException("No elements left.");
- }
-
- return _Elements[_Index++];
+ Dispose(false);
}
- public bool TryGet(ref byte Element)
+ public void Dispose()
{
- if (_Elements.Count <= _Index)
- {
- return false;
- }
-
- Element = _Elements[_Index++];
-
- return true;
+ Dispose(true);
+ GC.SuppressFinalize(this);
}
- public byte GetCurrent()
+ protected virtual void Dispose(bool disposing)
{
- return _Elements[_Index];
+ if (!disposed)
+ {
+ if (disposing)
+ {
+ _Reader.Dispose();
+ _Stream.Dispose();
+ }
+
+ disposed = true;
+ }
}
- public byte[] Get(int nCount)
+ public byte Get()
{
- Contract.Requires<ArgumentException>(Count - Index >= nCount, "nCount is greater than amount of elements.");
-
- var result = _Elements.GetRange(_Index, nCount).ToArray();
- _Index += nCount;
+ if (_Stream.Position == _Stream.Length)
+ {
+ throw new ByteQueueException("No elements left.");
+ }
- return result;
+ return _Reader.ReadByte();
}
- public bool TryGet(int nCount, ref byte[] Elements)
+ public bool TryGet(ref byte Element)
{
- if (Count - Index < nCount)
+ if (_Stream.Position == _Stream.Length)
{
return false;
}
- Elements = _Elements.GetRange(_Index, nCount).ToArray();
- _Index += nCount;
+ Element = _Reader.ReadByte();
return true;
}
- public byte[] GetCurrent(int nCount)
+ public byte[] Get(int nCount)
{
Contract.Requires<ArgumentException>(Count - Index >= nCount, "nCount is greater than amount of elements.");
- var result = _Elements.GetRange(_Index, nCount).ToArray();
-
- return result;
+ return _Reader.ReadBytes(nCount);
}
- public bool TryGetCurrent(int nCount, ref byte[] Elements)
+ public bool TryGet(int nCount, ref byte[] Elements)
{
- if (Count - Index < nCount)
- {
- return false;
- }
-
- Elements = _Elements.GetRange(_Index, nCount).ToArray();
-
- return true;
+ Elements = _Reader.ReadBytes(nCount);
+ return (Elements.Length == nCount);
}
/// <summary>
/// </summary>
public int Index
{
- get { return _Index; }
+ get { return (int)_Stream.Position; }
}
public int Count
{
- get { return _Elements.Count; }
+ get { return (int)_Stream.Length; }
}
public ulong GetVarInt()
{
- byte prefix = Get();
-
- switch (prefix)
+ try
{
- case 0xfd: // ushort
- return BitConverter.ToUInt16(Get(2), 0);
- case 0xfe: // uint
- return BitConverter.ToUInt32(Get(4), 0);
- case 0xff: // ulong
- return BitConverter.ToUInt64(Get(8), 0);
- default:
- return prefix;
+ byte prefix = _Reader.ReadByte();
+
+ switch (prefix)
+ {
+ case 0xfd: // ushort
+ return _Reader.ReadUInt16();
+ case 0xfe: // uint
+ return _Reader.ReadUInt32();
+ case 0xff: // ulong
+ return _Reader.ReadUInt64();
+ default:
+ return prefix;
+ }
+ }
+ catch (EndOfStreamException e)
+ {
+ throw new ByteQueueException("No elements left.", e);
}
}
}
}
+
+
{
try
{
- ByteQueue wBytes = new ByteQueue(blockBytes);
+ ByteQueue wBytes = new ByteQueue(ref blockBytes);
// Fill the block header fields
header = new CBlockHeader(wBytes.Get(80));
}
// Check timestamp
- if (header.nTime > NetInfo.FutureDrift(NetInfo.GetAdjustedTime()))
+ if (header.nTime > NetUtils.FutureDrift(NetUtils.GetAdjustedTime()))
{
return false;
}
// Check coinbase timestamp
- if (header.nTime < NetInfo.PastDrift(vtx[0].nTime))
+ if (header.nTime < NetUtils.PastDrift(vtx[0].nTime))
{
return false;
}
// Seek to the end and then append magic bytes there.
writer.Seek(0, SeekOrigin.End);
writer.Write(magicBytes, 0, magicBytes.Length);
- writer.Write(blkLenBytes, 0, blkLenBytes.Length);
// Save block size and current position in the block cursor fields.
nBlockPos = writer.Position;
nBlockSize = blockBytes.Length;
// Write block and flush the stream.
+ writer.Write(blkLenBytes, 0, blkLenBytes.Length);
writer.Write(blockBytes, 0, blockBytes.Length);
writer.Flush();
/// <summary>
/// Block file stream with read access
/// </summary>
- private Stream reader;
-
- /// <summary>
- /// Block file stream with write access
- /// </summary>
- private Stream writer;
+ private Stream fStreamReadWrite;
/// <summary>
/// Init the block storage manager.
bool firstInit = !File.Exists(strDbFile);
dbConn = new SQLiteConnection(new SQLitePlatformGeneric(), strDbFile);
- var fStreamReadWrite = File.Open(strBlockFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
- reader = new BinaryReader(fStreamReadWrite).BaseStream;
- writer = new BinaryWriter(fStreamReadWrite).BaseStream;
+ fStreamReadWrite = File.Open(strBlockFile, FileMode.OpenOrCreate, FileAccess.ReadWrite);
if (firstInit)
{
public bool GetTransaction(Hash256 TxID, ref CTransaction tx)
{
+ var reader = new BinaryReader(fStreamReadWrite).BaseStream;
var QueryTx = dbConn.Query<CTransactionStoreItem>("select * from [TransactionStorage] where [TransactionHash] = ?", (byte[])TxID);
if (QueryTx.Count == 1)
private bool AddItemToIndex(ref CBlockStoreItem itemTemplate, ref CBlock block)
{
+ var writer = new BinaryWriter(fStreamReadWrite).BaseStream;
var blockHash = new ScryptHash256(itemTemplate.Hash);
if (blockMap.ContainsKey(blockHash))
uint nHeight = prevBlockCursor.nHeight + 1;
// Check timestamp against prev
- if (NetInfo.FutureDrift(block.header.nTime) < prevBlockHeader.nTime)
+ if (NetUtils.FutureDrift(block.header.nTime) < prevBlockHeader.nTime)
{
// block's timestamp is too early
return false;
public bool GetBlock(ScryptHash256 blockHash, ref CBlock block)
{
+ var reader = new BinaryReader(fStreamReadWrite).BaseStream;
+
var QueryBlock = dbConn.Query<CBlockStoreItem>("select * from [BlockStorage] where [Hash] = ?", (byte[])blockHash);
if (QueryBlock.Count == 1)
{
// Free other state (managed objects).
- reader.Dispose();
- writer.Dispose();
+ fStreamReadWrite.Dispose();
}
if (dbConn != null)
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
+using System.IO;
using System.Text;
namespace Novacoin
public static implicit operator byte[] (COutPoint o)
{
- var r = new List<byte>();
- r.AddRange((byte[])o.hash);
- r.AddRange(BitConverter.GetBytes(o.n));
+ var stream = new MemoryStream();
+ var writer = new BinaryWriter(stream);
- return r.ToArray();
+ writer.Write(o.hash);
+ writer.Write(o.n);
+
+ var outBytes = stream.ToArray();
+
+ writer.Close();
+
+ return outBytes;
}
public override string ToString()
public string ToHex()
{
- return Interop.ToHex((byte[])this);
+ return Interop.ToHex(this);
}
/// <summary>
/// <returns></returns>
public ByteQueue GetByteQueue()
{
- return new ByteQueue(codeBytes);
+ return new ByteQueue(ref codeBytes);
}
/// <summary>
}
var count = 0;
- var bq1 = new ByteQueue(codeBytes);
+ var bq1 = new ByteQueue(ref codeBytes);
byte[] pushData;
instruction opcode;
var count = 0;
var newScript = new CScript();
- var bq1 = new ByteQueue(codeBytes);
+ var bq1 = new ByteQueue(ref codeBytes);
while (ScriptCode.GetOp(ref bq1, out opcode, out pushData))
{
{
get
{
- var wCodeBytes = new ByteQueue(codeBytes);
+ var wCodeBytes = new ByteQueue(ref codeBytes);
instruction opcode; // Current instruction
byte[] pushArgs; // OP_PUSHDATAn argument
{
get
{
- var wCodeBytes = new ByteQueue(codeBytes);
+ var wCodeBytes = new ByteQueue(ref codeBytes);
byte[] pushArgs; // OP_PUSHDATAn argument
instruction opcode; // Current instruction
/// <returns>Amount of sigops</returns>
public uint GetSigOpCount(bool fAccurate)
{
- var wCodeBytes = new ByteQueue(codeBytes);
+ var wCodeBytes = new ByteQueue(ref codeBytes);
instruction opcode; // Current instruction
byte[] pushArgs; // OP_PUSHDATAn argument
public override string ToString()
{
var sb = new StringBuilder();
- var wCodeBytes = new ByteQueue(codeBytes);
+ var wCodeBytes = new ByteQueue(ref codeBytes);
instruction opcode; // Current instruction
byte[] pushArgs; // OP_PUSHDATAn argument
using System;
using System.Text;
using System.Collections.Generic;
+using System.IO;
namespace Novacoin
{
}
if (nBlockTime == 0)
{
- nBlockTime = NetInfo.GetAdjustedTime();
+ nBlockTime = NetUtils.GetAdjustedTime();
}
- if (nLockTime < (nLockTime < NetInfo.nLockTimeThreshold ? nBlockHeight : nBlockTime))
+ if (nLockTime < (nLockTime < NetUtils.nLockTimeThreshold ? nBlockHeight : nBlockTime))
{
return true;
}
{
try
{
- var wBytes = new ByteQueue(txBytes);
+ var wBytes = new ByteQueue(ref txBytes);
nVersion = BitConverter.ToUInt32(wBytes.Get(4), 0);
nTime = BitConverter.ToUInt32(wBytes.Get(4), 0);
/// </summary>
public static implicit operator byte[] (CTransaction tx)
{
- var resultBytes = new List<byte>();
+ var stream = new MemoryStream();
+ var writer = new BinaryWriter(stream);
- resultBytes.AddRange(BitConverter.GetBytes(tx.nVersion));
- resultBytes.AddRange(BitConverter.GetBytes(tx.nTime));
- resultBytes.AddRange(VarInt.EncodeVarInt(tx.vin.LongLength));
+ writer.Write(tx.nVersion);
+ writer.Write(tx.nTime);
+ writer.Write(VarInt.EncodeVarInt(tx.vin.LongLength));
foreach (var input in tx.vin)
{
- resultBytes.AddRange((byte[])input);
+ writer.Write(input);
}
- resultBytes.AddRange(VarInt.EncodeVarInt(tx.vout.LongLength));
+ writer.Write(VarInt.EncodeVarInt(tx.vout.LongLength));
foreach (var output in tx.vout)
{
- resultBytes.AddRange((byte[])output);
+ writer.Write(output);
}
- resultBytes.AddRange(BitConverter.GetBytes(tx.nLockTime));
+ writer.Write(tx.nLockTime);
- return resultBytes.ToArray();
+ var resultBytes = stream.ToArray();
+
+ writer.Close();
+
+ return resultBytes;
}
+
+
public override string ToString()
{
var sb = new StringBuilder();
using System;
using System.Text;
using System.Collections.Generic;
+using System.IO;
namespace Novacoin
{
/// <returns>Byte sequence.</returns>
public static implicit operator byte[] (CTxIn input)
{
- var inputBytes = new List<byte>();
+ var stream = new MemoryStream();
+ var writer = new BinaryWriter(stream);
- inputBytes.AddRange((byte[])input.prevout); // prevout
+ writer.Write(input.prevout); // prevout
+ writer.Write(VarInt.EncodeVarInt(input.scriptSig.Size)); // scriptSig length
+ writer.Write(input.scriptSig); // scriptSig
+ writer.Write(input.nSequence); // nSequence
- var s = (byte[])input.scriptSig;
- inputBytes.AddRange(VarInt.EncodeVarInt(s.Length)); // scriptSig length
- inputBytes.AddRange(s); // scriptSig
- inputBytes.AddRange(BitConverter.GetBytes(input.nSequence)); // Sequence
-
- return inputBytes.ToArray();
+ var inputBytes = stream.ToArray();
+ writer.Close();
+ return inputBytes;
}
-
+
public bool IsFinal
{
get { return (nSequence == uint.MaxValue); }
using System;
using System.Text;
using System.Collections.Generic;
+using System.IO;
namespace Novacoin
{
/// <returns>Byte sequence.</returns>
public static implicit operator byte[] (CTxOut output)
{
- var resultBytes = new List<byte>();
+ var stream = new MemoryStream();
+ var writer = new BinaryWriter(stream);
- resultBytes.AddRange(BitConverter.GetBytes(output.nValue)); // txout value
+ writer.Write(output.nValue); // txout value
+ writer.Write(VarInt.EncodeVarInt(output.scriptPubKey.Size)); // scriptPubKey length
+ writer.Write(output.scriptPubKey); // scriptPubKey
- byte[] s = output.scriptPubKey;
- resultBytes.AddRange(VarInt.EncodeVarInt(s.Length)); // scriptPubKey length
- resultBytes.AddRange(s); // scriptPubKey
+ var resultBytes = stream.ToArray();
- return resultBytes.ToArray();
+ writer.Close();
+
+ return resultBytes;
}
/// <summary>
--- /dev/null
+\feffusing System;
+
+namespace Novacoin
+{
+ internal class NetUtils
+ {
+ public static readonly uint nLockTimeThreshold = 500000000;
+ private static readonly uint nDrift = 7200;
+
+ public static uint GetAdjustedTime()
+ {
+ return Interop.GetTime();
+ }
+
+ public static uint FutureDrift(uint nTime)
+ {
+ return nTime + nDrift; // up to 2 hours from the future
+ }
+
+ public static uint PastDrift(uint nTime)
+ {
+ return nTime - nDrift; // up to 2 hours from the past
+ }
+ }
+}
\ No newline at end of file
</ItemGroup>
<ItemGroup>
<Compile Include="AddressTools.cs" />
+ <Compile Include="ByteQueue.cs" />
<Compile Include="CBlockStore.cs" />
<Compile Include="CKey.cs" />
<Compile Include="CKeyID.cs" />
<Compile Include="SHA1.cs" />
<Compile Include="SHA256.cs" />
<Compile Include="VarInt.cs" />
- <Compile Include="ByteQueue.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="CTxIn.cs" />
<Compile Include="CTransaction.cs" />
using System;
using System.Collections.Generic;
+using System.IO;
namespace Novacoin
{
return prefix;
}
}
+
+ public static ulong ReadVarInt(ref BinaryReader reader)
+ {
+ byte prefix = reader.ReadByte();
+
+ switch (prefix)
+ {
+ case 0xfd: // ushort
+ return reader.ReadUInt16();
+ case 0xfe: // uint
+ return reader.ReadUInt32();
+ case 0xff: // ulong
+ return reader.ReadUInt64();
+ default:
+ return prefix;
+ }
+ }
+
}
}
Console.WriteLine("{0} != {1} : {2}", hash1.ToString(), hash2.ToString(), hash1 != hash2);
Console.WriteLine("{0} == {1} : {2}\n", hash2.ToString(), hash3.ToString(), hash2 == hash3);
+
/*
/// Pre-09854c5 revisions were affected by integer overflow bug, this issue was caused by incorrect deserialization of input value. Below you can see an example, broken transaction and its normal version.
Console.WriteLine(txNoBug);
*/
- /*
+
Console.WriteLine("Reading the block file...");
var bs = new CBlockStore();
bs.ParseBlockFile();
- */
+
Console.ReadLine();
}