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();
- reader.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;
+ }
+ }
+
}
}