From 1dcac5faa2b1477034f82466ffb16170fa2e9bb6 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Wed, 2 Sep 2015 17:01:29 +0300 Subject: [PATCH] Remove Hash, Hash256, Hash160 and ScryptHash256 classes. --- Novacoin/AddressTools.cs | 4 +- Novacoin/CBlock.cs | 10 +- Novacoin/CBlockHeader.cs | 24 +++--- Novacoin/CBlockStore.cs | 32 +++--- Novacoin/CKey.cs | 6 +- Novacoin/CKeyID.cs | 4 +- Novacoin/CKeyPair.cs | 4 +- Novacoin/COutPoint.cs | 13 ++- Novacoin/CScript.cs | 2 +- Novacoin/CScriptID.cs | 4 +- Novacoin/CTransaction.cs | 4 +- Novacoin/CryptoUtils.cs | 139 +++++++++++++++++++++++++++- Novacoin/Hash.cs | 227 --------------------------------------------- Novacoin/Hash160.cs | 63 ------------- Novacoin/Hash256.cs | 97 ------------------- Novacoin/Novacoin.csproj | 4 - Novacoin/ScriptCode.cs | 4 +- Novacoin/ScryptHash256.cs | 145 ----------------------------- Novacoin/base_uint.cs | 51 +++++++--- Novacoin/uint160.cs | 115 +++++++++++++++-------- Novacoin/uint256.cs | 123 +++++++++++++++--------- NovacoinTest/Program.cs | 21 ++-- 22 files changed, 395 insertions(+), 701 deletions(-) delete mode 100644 Novacoin/Hash.cs delete mode 100644 Novacoin/Hash160.cs delete mode 100644 Novacoin/Hash256.cs delete mode 100644 Novacoin/ScryptHash256.cs diff --git a/Novacoin/AddressTools.cs b/Novacoin/AddressTools.cs index 9ca95b4..b740987 100644 --- a/Novacoin/AddressTools.cs +++ b/Novacoin/AddressTools.cs @@ -67,7 +67,7 @@ namespace Novacoin { var dataBytes = new byte[bytes.Length + 4]; bytes.CopyTo(dataBytes, 0); - var checkSum = Hash256.ComputeRaw256(bytes).Take(4).ToArray(); + var checkSum = CryptoUtils.ComputeHash256(bytes).Take(4).ToArray(); checkSum.CopyTo(dataBytes, dataBytes.Length - 4); // add 4-byte hash check to the end return Base58Encode(dataBytes); @@ -128,7 +128,7 @@ namespace Novacoin Array.Copy(rawData, result, result.Length); Array.Copy(rawData, result.Length, resultCheckSum, 0, 4); - var checkSum = Hash256.ComputeRaw256(result).Take(4).ToArray(); + var checkSum = CryptoUtils.ComputeHash256(result).Take(4).ToArray(); if (!checkSum.SequenceEqual(resultCheckSum)) { diff --git a/Novacoin/CBlock.cs b/Novacoin/CBlock.cs index a620d26..d80e68e 100644 --- a/Novacoin/CBlock.cs +++ b/Novacoin/CBlock.cs @@ -128,7 +128,7 @@ namespace Novacoin public bool CheckBlock(bool fCheckPOW = true, bool fCheckMerkleRoot = true, bool fCheckSig = true) { - var uniqueTX = new List(); // tx hashes + var uniqueTX = new List(); // tx hashes uint nSigOps = 0; // total sigops // Basic sanity checkings @@ -269,7 +269,7 @@ namespace Novacoin return true; } - private bool CheckProofOfWork(ScryptHash256 hash, uint nBits) + private bool CheckProofOfWork(uint256 hash, uint nBits) { // TODO: stub! @@ -405,7 +405,7 @@ namespace Novacoin /// /// Merkle root /// - public Hash256 hashMerkleRoot + public uint256 hashMerkleRoot { get { @@ -413,7 +413,7 @@ namespace Novacoin foreach (var tx in vtx) { - merkleTree.AddRange(Hash256.ComputeRaw256(tx)); + merkleTree.AddRange(CryptoUtils.ComputeHash256(tx)); } int levelOffset = 0; @@ -431,7 +431,7 @@ namespace Novacoin levelOffset += nLevelSize; } - return (merkleTree.Count == 0) ? new Hash256() : new Hash256(merkleTree.GetRange(merkleTree.Count-32, 32).ToArray()); + return (merkleTree.Count == 0) ? 0 : (uint256)merkleTree.GetRange(merkleTree.Count-32, 32).ToArray(); } } diff --git a/Novacoin/CBlockHeader.cs b/Novacoin/CBlockHeader.cs index e5557c3..09cbd1b 100644 --- a/Novacoin/CBlockHeader.cs +++ b/Novacoin/CBlockHeader.cs @@ -37,12 +37,12 @@ namespace Novacoin /// /// Previous block hash. /// - public ScryptHash256 prevHash; + public uint256 prevHash; /// /// Merkle root hash. /// - public Hash256 merkleRoot; + public uint256 merkleRoot; /// /// Block timestamp. @@ -65,8 +65,8 @@ namespace Novacoin public CBlockHeader () { nVersion = 6; - prevHash = new ScryptHash256(); - merkleRoot = new Hash256(); + prevHash = new uint256(); + merkleRoot = new uint256(); nTime = Interop.GetTime(); nBits = 0; nNonce = 0; @@ -75,8 +75,8 @@ namespace Novacoin public CBlockHeader(CBlockHeader header) { nVersion = header.nVersion; - prevHash = new ScryptHash256(header.prevHash); - merkleRoot = new Hash256(header.merkleRoot); + prevHash = header.prevHash; + merkleRoot = header.merkleRoot; nTime = header.nTime; nBits = header.nBits; nNonce = header.nNonce; @@ -85,8 +85,8 @@ namespace Novacoin internal CBlockHeader(ref BinaryReader reader) { nVersion = reader.ReadUInt32(); - prevHash = new ScryptHash256(reader.ReadBytes(32)); - merkleRoot = new Hash256(reader.ReadBytes(32)); + prevHash = reader.ReadBytes(32); + merkleRoot = reader.ReadBytes(32); nTime = reader.ReadUInt32(); nBits = reader.ReadUInt32(); nNonce = reader.ReadUInt32(); @@ -104,8 +104,8 @@ namespace Novacoin var reader = new BinaryReader(stream); nVersion = reader.ReadUInt32(); - prevHash = new ScryptHash256(reader.ReadBytes(32)); - merkleRoot = new Hash256(reader.ReadBytes(32)); + prevHash = reader.ReadBytes(32); + merkleRoot = reader.ReadBytes(32); nTime = reader.ReadUInt32(); nBits = reader.ReadUInt32(); nNonce = reader.ReadUInt32(); @@ -136,10 +136,10 @@ namespace Novacoin return resultBytes; } - public ScryptHash256 Hash + public uint256 Hash { get { - return ScryptHash256.Compute256(this); + return CryptoUtils.ComputeScryptHash256(this); } } diff --git a/Novacoin/CBlockStore.cs b/Novacoin/CBlockStore.cs index cf6c515..6753bfe 100644 --- a/Novacoin/CBlockStore.cs +++ b/Novacoin/CBlockStore.cs @@ -100,9 +100,9 @@ namespace Novacoin /// /// Block header /// Header hash - public ScryptHash256 FillHeader(CBlockHeader header) + public uint256 FillHeader(CBlockHeader header) { - ScryptHash256 _hash; + uint256 _hash; Hash = _hash = header.Hash; nVersion = header.nVersion; @@ -125,8 +125,8 @@ namespace Novacoin CBlockHeader header = new CBlockHeader(); header.nVersion = nVersion; - header.prevHash = new ScryptHash256(prevHash); - header.merkleRoot = new Hash256(merkleRoot); + header.prevHash = prevHash; + header.merkleRoot = merkleRoot; header.nTime = nTime; header.nBits = nBits; header.nNonce = nNonce; @@ -327,18 +327,18 @@ namespace Novacoin /// /// Map of block tree nodes. /// - private ConcurrentDictionary blockMap = new ConcurrentDictionary(); + private ConcurrentDictionary blockMap = new ConcurrentDictionary(); /// /// Orphaned blocks map. /// - private ConcurrentDictionary orphanMap = new ConcurrentDictionary(); - private ConcurrentDictionary orphanMapByPrev = new ConcurrentDictionary(); + private ConcurrentDictionary orphanMap = new ConcurrentDictionary(); + private ConcurrentDictionary orphanMapByPrev = new ConcurrentDictionary(); /// /// Map of unspent items. /// - private ConcurrentDictionary txMap = new ConcurrentDictionary(); + private ConcurrentDictionary txMap = new ConcurrentDictionary(); public static CBlockStore Instance; @@ -415,14 +415,14 @@ namespace Novacoin // Init list of block items foreach (var item in blockTreeItems) { - blockMap.TryAdd(new ScryptHash256(item.Hash), item); + blockMap.TryAdd(item.Hash, item); } } Instance = this; } - public bool GetTransaction(Hash256 TxID, ref CTransaction tx) + public bool GetTransaction(uint256 TxID, ref CTransaction tx) { var reader = new BinaryReader(fStreamReadWrite).BaseStream; var QueryTx = dbConn.Query("select * from [TransactionStorage] where [TransactionHash] = ?", (byte[])TxID); @@ -440,7 +440,7 @@ namespace Novacoin private bool AddItemToIndex(ref CBlockStoreItem itemTemplate, ref CBlock block) { var writer = new BinaryWriter(fStreamReadWrite).BaseStream; - var blockHash = new ScryptHash256(itemTemplate.Hash); + uint256 blockHash = itemTemplate.Hash; if (blockMap.ContainsKey(blockHash)) { @@ -501,7 +501,7 @@ namespace Novacoin public bool AcceptBlock(ref CBlock block) { - ScryptHash256 hash = block.header.Hash; + uint256 hash = block.header.Hash; if (blockMap.ContainsKey(hash)) { @@ -555,7 +555,7 @@ namespace Novacoin return true; } - public bool GetBlock(ScryptHash256 blockHash, ref CBlock block) + public bool GetBlock(uint256 blockHash, ref CBlock block) { var reader = new BinaryReader(fStreamReadWrite).BaseStream; @@ -573,7 +573,7 @@ namespace Novacoin public bool ProcessBlock(ref CBlock block) { - ScryptHash256 blockHash = block.header.Hash; + var blockHash = block.header.Hash; if (blockMap.ContainsKey(blockHash)) { @@ -631,12 +631,12 @@ namespace Novacoin } // Recursively process any orphan blocks that depended on this one - var orphansQueue = new List(); + var orphansQueue = new List(); orphansQueue.Add(blockHash); for (int i = 0; i < orphansQueue.Count; i++) { - ScryptHash256 hashPrev = orphansQueue[i]; + var hashPrev = orphansQueue[i]; foreach (var pair in orphanMap) { diff --git a/Novacoin/CKey.cs b/Novacoin/CKey.cs index 355c66e..672f0be 100644 --- a/Novacoin/CKey.cs +++ b/Novacoin/CKey.cs @@ -82,11 +82,11 @@ namespace Novacoin /// Data hash /// Signature bytes /// Checking result - public bool VerifySignature(Hash sigHash, byte[] signature) + public bool VerifySignature(uint256 sigHash, byte[] signature) { var signer = SignerUtilities.GetSigner("NONEwithECDSA"); signer.Init(false, _Public); - signer.BlockUpdate(sigHash, 0, sigHash.hashSize); + signer.BlockUpdate(sigHash, 0, sigHash.Size); return signer.VerifySignature(signature); } @@ -97,7 +97,7 @@ namespace Novacoin /// New key ID public CKeyID KeyID { - get { return new CKeyID(Hash160.Compute160(_Public.Q.GetEncoded())); } + get { return new CKeyID(CryptoUtils.ComputeHash160(_Public.Q.GetEncoded())); } } /// diff --git a/Novacoin/CKeyID.cs b/Novacoin/CKeyID.cs index 62639a1..be51bf1 100644 --- a/Novacoin/CKeyID.cs +++ b/Novacoin/CKeyID.cs @@ -23,11 +23,12 @@ namespace Novacoin /// public class CKeyID : uint160 { + #region Constructors public CKeyID() : base() { } - public CKeyID(CKeyID KeyID) : base(KeyID) + public CKeyID(CKeyID KeyID) : base(KeyID as uint160) { } @@ -38,6 +39,7 @@ namespace Novacoin public CKeyID(byte[] hashBytes) : base(hashBytes) { } + #endregion /// /// Generate Pay-to-PubkeyHash address diff --git a/Novacoin/CKeyPair.cs b/Novacoin/CKeyPair.cs index a1d50a8..5dcedbb 100644 --- a/Novacoin/CKeyPair.cs +++ b/Novacoin/CKeyPair.cs @@ -142,11 +142,11 @@ namespace Novacoin /// /// Hash to sigh /// Signature bytes sequence - public byte[] Sign(Hash sigHash) + public byte[] Sign(uint256 sigHash) { var signer = SignerUtilities.GetSigner("NONEwithECDSA"); signer.Init(true, _Private); - signer.BlockUpdate(sigHash, 0, sigHash.hashSize); + signer.BlockUpdate(sigHash, 0, sigHash.Size); return signer.GenerateSignature(); } diff --git a/Novacoin/COutPoint.cs b/Novacoin/COutPoint.cs index 9e628e9..09d0690 100644 --- a/Novacoin/COutPoint.cs +++ b/Novacoin/COutPoint.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.IO; +using System.Linq; using System.Text; namespace Novacoin @@ -29,7 +30,7 @@ namespace Novacoin /// /// Hash of parent transaction. /// - public Hash256 hash; + public uint256 hash; /// /// Parent input number. @@ -43,11 +44,11 @@ namespace Novacoin public COutPoint() { - hash = new Hash256(); + hash = new uint256(); n = uint.MaxValue; } - public COutPoint(Hash256 hashIn, uint nIn) + public COutPoint(uint256 hashIn, uint nIn) { hash = hashIn; n = nIn; @@ -55,7 +56,7 @@ namespace Novacoin public COutPoint(COutPoint o) { - hash = new Hash256(o.hash); + hash = o.hash; n = o.n; } @@ -63,13 +64,13 @@ namespace Novacoin { Contract.Requires(bytes.Length == 36, "Any valid outpoint reference data item is exactly 36 bytes long."); - hash = new Hash256(bytes); + hash = bytes.Take(32).ToArray(); n = BitConverter.ToUInt32(bytes, 32); } public bool IsNull { - get { return hash.IsZero && n == uint.MaxValue; } + get { return !hash && n == uint.MaxValue; } } public static implicit operator byte[] (COutPoint o) diff --git a/Novacoin/CScript.cs b/Novacoin/CScript.cs index 95ca17a..817d2fa 100644 --- a/Novacoin/CScript.cs +++ b/Novacoin/CScript.cs @@ -510,7 +510,7 @@ namespace Novacoin public CScriptID ScriptID { - get { return new CScriptID(Hash160.Compute160(codeBytes.ToArray())); } + get { return new CScriptID(CryptoUtils.ComputeHash160(codeBytes.ToArray())); } } /// diff --git a/Novacoin/CScriptID.cs b/Novacoin/CScriptID.cs index b9ead5a..9035de5 100644 --- a/Novacoin/CScriptID.cs +++ b/Novacoin/CScriptID.cs @@ -23,11 +23,12 @@ namespace Novacoin /// public class CScriptID : uint160 { + #region Constructors public CScriptID() : base() { } - public CScriptID(CScriptID KeyID) : base(KeyID) + public CScriptID(CScriptID KeyID) : base(KeyID as uint160) { } @@ -38,6 +39,7 @@ namespace Novacoin public CScriptID(byte[] hashBytes) : base(hashBytes) { } + #endregion /// /// Generate Pay-to-ScriptHash address diff --git a/Novacoin/CTransaction.cs b/Novacoin/CTransaction.cs index 1070703..fb865a4 100644 --- a/Novacoin/CTransaction.cs +++ b/Novacoin/CTransaction.cs @@ -398,9 +398,9 @@ namespace Novacoin /// /// Transaction hash /// - public Hash256 Hash + public uint256 Hash { - get { return Hash256.Compute256(this); } + get { return CryptoUtils.ComputeHash256(this); } } /// diff --git a/Novacoin/CryptoUtils.cs b/Novacoin/CryptoUtils.cs index 12e4bfd..72cc210 100644 --- a/Novacoin/CryptoUtils.cs +++ b/Novacoin/CryptoUtils.cs @@ -17,16 +17,33 @@ */ using System; +using System.Diagnostics.Contracts; using System.IO; using System.Security.Cryptography; namespace Novacoin { + /// + /// Hashing functionality. + /// public class CryptoUtils { + #region Private instances for various hashing algorithm implementations. + /// + /// Computes the SHA1 hash for the input data using the managed library. + /// private static SHA1Managed _sha1 = new SHA1Managed(); + + /// + /// Computes the SHA256 hash for the input data using the managed library. + /// private static SHA256Managed _sha256 = new SHA256Managed(); + + /// + /// Computes the SHA1 hash for the input data using the managed library. + /// private static RIPEMD160Managed _ripe160 = new RIPEMD160Managed(); + #endregion /// /// Sha1 calculation @@ -88,8 +105,9 @@ namespace Novacoin /// Hashing result public static byte[] ComputeHash256(ref byte[] input1, ref byte[] input2) { - var buffer = new byte[64]; + var buffer = new byte[input1.Length + input2.Length]; + // Fill the buffer input1.CopyTo(buffer, 0); input2.CopyTo(buffer, input1.Length); @@ -97,6 +115,51 @@ namespace Novacoin return _sha256.ComputeHash(digest1, 0, digest1.Length); } + /// + /// Calculate PBKDF2-SHA256(SALSA20/8(PBKDF2-SHA256(X))) + /// + /// Bytes to hash + /// Hashing result + public static byte[] ComputeScryptHash256(byte[] inputBytes) + { + var V = new uint[(131072 + 63) / sizeof(uint)]; + + var keyBytes1 = PBKDF2_Sha256(128, inputBytes, inputBytes, 1); + var X = Interop.ToUInt32Array(keyBytes1); + + for (var i = 0; i < 1024; i++) + { + Array.Copy(X, 0, V, i * 32, 32); + + xor_salsa8(ref X, 0, ref X, 16); + xor_salsa8(ref X, 16, ref X, 0); + } + for (var i = 0; i < 1024; i++) + { + var j = 32 * (X[16] & 1023); + for (var k = 0; k < 32; k++) + { + X[k] ^= V[j + k]; + } + xor_salsa8(ref X, 0, ref X, 16); + xor_salsa8(ref X, 16, ref X, 0); + } + + var xBytes = Interop.LEBytes(X); + + return PBKDF2_Sha256(32, inputBytes, xBytes, 1); + } + + + #region PBKDF2-SHA256 + /// + /// Managed implementation of PBKDF2-SHA256. + /// + /// Key length + /// Password + /// Salt + /// Amount of derive iterations. + /// Derived key public static byte[] PBKDF2_Sha256(int dklen, byte[] password, byte[] salt, int iterationCount) { /* Init HMAC state. */ @@ -169,5 +232,79 @@ namespace Novacoin } } } + #endregion + + #region SALSA20/8 + private static void xor_salsa8(ref uint[] B, int indexB, ref uint[] Bx, int indexBx) + { + uint x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15; + byte i; + + x00 = (B[indexB + 0] ^= Bx[indexBx + 0]); + x01 = (B[indexB + 1] ^= Bx[indexBx + 1]); + x02 = (B[indexB + 2] ^= Bx[indexBx + 2]); + x03 = (B[indexB + 3] ^= Bx[indexBx + 3]); + x04 = (B[indexB + 4] ^= Bx[indexBx + 4]); + x05 = (B[indexB + 5] ^= Bx[indexBx + 5]); + x06 = (B[indexB + 6] ^= Bx[indexBx + 6]); + x07 = (B[indexB + 7] ^= Bx[indexBx + 7]); + x08 = (B[indexB + 8] ^= Bx[indexBx + 8]); + x09 = (B[indexB + 9] ^= Bx[indexBx + 9]); + x10 = (B[indexB + 10] ^= Bx[indexBx + 10]); + x11 = (B[indexB + 11] ^= Bx[indexBx + 11]); + x12 = (B[indexB + 12] ^= Bx[indexBx + 12]); + x13 = (B[indexB + 13] ^= Bx[indexBx + 13]); + x14 = (B[indexB + 14] ^= Bx[indexBx + 14]); + x15 = (B[indexB + 15] ^= Bx[indexBx + 15]); + + Func R = (a, b) => (((a) << (b)) | ((a) >> (32 - (b)))); + + for (i = 0; i < 8; i += 2) + { + /* Operate on columns. */ + x04 ^= R(x00 + x12, 7); x09 ^= R(x05 + x01, 7); + x14 ^= R(x10 + x06, 7); x03 ^= R(x15 + x11, 7); + + x08 ^= R(x04 + x00, 9); x13 ^= R(x09 + x05, 9); + x02 ^= R(x14 + x10, 9); x07 ^= R(x03 + x15, 9); + + x12 ^= R(x08 + x04, 13); x01 ^= R(x13 + x09, 13); + x06 ^= R(x02 + x14, 13); x11 ^= R(x07 + x03, 13); + + x00 ^= R(x12 + x08, 18); x05 ^= R(x01 + x13, 18); + x10 ^= R(x06 + x02, 18); x15 ^= R(x11 + x07, 18); + + /* Operate on rows. */ + x01 ^= R(x00 + x03, 7); x06 ^= R(x05 + x04, 7); + x11 ^= R(x10 + x09, 7); x12 ^= R(x15 + x14, 7); + + x02 ^= R(x01 + x00, 9); x07 ^= R(x06 + x05, 9); + x08 ^= R(x11 + x10, 9); x13 ^= R(x12 + x15, 9); + + x03 ^= R(x02 + x01, 13); x04 ^= R(x07 + x06, 13); + x09 ^= R(x08 + x11, 13); x14 ^= R(x13 + x12, 13); + + x00 ^= R(x03 + x02, 18); x05 ^= R(x04 + x07, 18); + x10 ^= R(x09 + x08, 18); x15 ^= R(x14 + x13, 18); + } + + B[indexB + 0] += x00; + B[indexB + 1] += x01; + B[indexB + 2] += x02; + B[indexB + 3] += x03; + B[indexB + 4] += x04; + B[indexB + 5] += x05; + B[indexB + 6] += x06; + B[indexB + 7] += x07; + B[indexB + 8] += x08; + B[indexB + 9] += x09; + B[indexB + 10] += x10; + B[indexB + 11] += x11; + B[indexB + 12] += x12; + B[indexB + 13] += x13; + B[indexB + 14] += x14; + B[indexB + 15] += x15; + } + #endregion } } diff --git a/Novacoin/Hash.cs b/Novacoin/Hash.cs deleted file mode 100644 index 5b1d3b7..0000000 --- a/Novacoin/Hash.cs +++ /dev/null @@ -1,227 +0,0 @@ -/** - * Novacoin classes library - * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) - - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -using System; -using System.Diagnostics.Contracts; -using System.Linq; - -namespace Novacoin -{ - public abstract class Hash : IEquatable, IComparable - { - /// - /// Array of digest bytes. - /// - protected byte[] _hashBytes; - - /// - /// Hash size, must be overriden - /// - public abstract int hashSize - { - get; - } - - /// - /// Initializes an empty instance of the Hash class. - /// - public Hash() - { - _hashBytes = new byte[hashSize]; - } - - /// - /// Initializes a new instance of Hash class - /// - /// Array of bytes - public Hash(byte[] bytes, int offset = 0) - { - if (bytes.Length - offset < hashSize) - { - throw new ArgumentException("You need to provide a sufficient amount of data to initialize new instance of hash object."); - } - - _hashBytes = new byte[hashSize]; - Array.Copy(bytes, offset, _hashBytes, 0, hashSize); - } - - /// - /// Initializes a new instance of Hash class as a copy of another one - /// - /// Instance of hash class - public Hash(Hash h) - { - _hashBytes = new byte[h.hashSize]; - h._hashBytes.CopyTo(_hashBytes, 0); - } - - public bool IsZero - { - get { return !_hashBytes.Any(b => b != 0); } - } - - public static implicit operator byte[](Hash h) - { - return h._hashBytes; - } - - public bool Equals(Hash item) - { - if ((object)item == null) - { - return false; - } - return _hashBytes.SequenceEqual((byte[])item); - } - - public override bool Equals(object o) - { - if (o == null) - { - return false; - } - - return _hashBytes.SequenceEqual(((Hash)o)._hashBytes); - } - - public override int GetHashCode() - { - int hash = 17; - unchecked - { - foreach (var element in _hashBytes) - { - hash = hash * 31 + element.GetHashCode(); - } - } - return hash; - } - - public int CompareTo(Hash item) - { - if (this > item) - { - return 1; - } - else if (this < item) - { - return -1; - } - - return 0; - } - - public static bool operator <(Hash a, Hash b) - { - Contract.Requires((object)a != null && (object)b != null, "Null references are not allowed."); - Contract.Requires(a.hashSize == b.hashSize, "Hashes must have the same size."); - - for (int i = a.hashSize - 1; i >= 0; i--) - { - if (a._hashBytes[i] < b._hashBytes[i]) - { - return true; - } - else if (a._hashBytes[i] > b._hashBytes[i]) - { - return false; - } - } - - return false; - } - - public static bool operator <=(Hash a, Hash b) - { - Contract.Requires((object)a != null && (object)b != null, "Null references are not allowed."); - Contract.Requires(a.hashSize == b.hashSize, "Hashes must have the same size."); - - for (int i = a.hashSize - 1; i >= 0; i--) - { - if (a._hashBytes[i] < b._hashBytes[i]) - { - return true; - } - else if (a._hashBytes[i] > b._hashBytes[i]) - { - return false; - } - } - - return false; - } - - public static bool operator >(Hash a, Hash b) - { - Contract.Requires((object)a != null && (object)b != null, "Null references are not allowed."); - Contract.Requires(a.hashSize == b.hashSize, "Hashes must have the same size."); - - for (int i = a.hashSize - 1; i >= 0; i--) - { - if (a._hashBytes[i] > b._hashBytes[i]) - { - return true; - } - else if (a._hashBytes[i] < b._hashBytes[i]) - { - return false; - } - } - - return false; - } - - public static bool operator >=(Hash a, Hash b) - { - Contract.Requires((object)a != null && (object)b != null, "Null references are not allowed."); - Contract.Requires(a.hashSize == b.hashSize, "Hashes must have the same size."); - - for (int i = a.hashSize - 1; i >= 0; i--) - { - if (a._hashBytes[i] > b._hashBytes[i]) - { - return true; - } - else if (a._hashBytes[i] < b._hashBytes[i]) - { - return false; - } - } - - return true; - } - - public static bool operator ==(Hash a, Hash b) - { - Contract.Requires((object)a != null && (object)b != null, "Null references are not allowed."); - Contract.Requires(a.hashSize == b.hashSize, "Hashes must have the same size."); - - return a._hashBytes.SequenceEqual(b._hashBytes); - } - - public static bool operator !=(Hash a, Hash b) - { - return !(a == b); - } - - public override string ToString() - { - return Interop.ToHex(Interop.ReverseBytes(_hashBytes)); - } - } -} diff --git a/Novacoin/Hash160.cs b/Novacoin/Hash160.cs deleted file mode 100644 index f95165b..0000000 --- a/Novacoin/Hash160.cs +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Novacoin classes library - * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) - - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -using System.Linq; -using Org.BouncyCastle.Crypto.Digests; - -namespace Novacoin -{ - /// - /// Representation of pubkey/script hash. - /// - public class Hash160 : Hash - { - /// - /// Computes RIPEMD160 hash using managed library - /// - //private static readonly RIPEMD160Managed _hasher160 = new RIPEMD160Managed(); - - private static RipeMD160Digest _hasher160 = new RipeMD160Digest(); - private static Sha256Digest _hasher256 = new Sha256Digest(); - - // 20 bytes - public override int hashSize - { - get { return _hasher160.GetDigestSize(); } - } - - public Hash160() : base() { } - public Hash160(byte[] bytes, int offset = 0) : base(bytes, offset) { } - public Hash160(Hash160 h) : base(h) { } - - public static Hash160 Compute160(byte[] inputBytes) - { - var dataBytes = inputBytes.ToArray(); - - var digest1 = new byte[_hasher256.GetDigestSize()]; - var digest2 = new byte[_hasher160.GetDigestSize()]; - - _hasher256.BlockUpdate(dataBytes, 0, dataBytes.Length); - _hasher256.DoFinal(digest1, 0); - _hasher160.BlockUpdate(digest1, 0, digest1.Length); - _hasher160.DoFinal(digest2, 0); - - return new Hash160(digest2); - } - } -} - diff --git a/Novacoin/Hash256.cs b/Novacoin/Hash256.cs deleted file mode 100644 index 3d3a360..0000000 --- a/Novacoin/Hash256.cs +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Novacoin classes library - * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) - - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - - -using Org.BouncyCastle.Crypto.Digests; - -namespace Novacoin -{ - /// - /// Representation of Double SHA-256 hash - /// - public class Hash256 : Hash - { - private static Sha256Digest _hasher256 = new Sha256Digest(); - - // 32 bytes - public override int hashSize - { - get { return _hasher256.GetDigestSize(); } - } - - public Hash256() : base() { } - public Hash256(byte[] bytes, int offset=0) : base(bytes, offset) { } - public Hash256(Hash256 h) : base(h) { } - - public static Hash256 Compute256(byte[] dataBytes) - { - var digest1 = new byte[32]; - var digest2 = new byte[32]; - - _hasher256.BlockUpdate(dataBytes, 0, dataBytes.Length); - _hasher256.DoFinal(digest1, 0); - _hasher256.BlockUpdate(digest1, 0, digest1.Length); - _hasher256.DoFinal(digest2, 0); - - return new Hash256(digest2); - } - - public static Hash256 Compute256(ref byte[] input1, ref byte[] input2) - { - var digest1 = new byte[_hasher256.GetDigestSize()]; - var digest2 = new byte[_hasher256.GetDigestSize()]; - - _hasher256.BlockUpdate(input1, 0, input1.Length); - _hasher256.BlockUpdate(input2, 0, input2.Length); - _hasher256.DoFinal(digest1, 0); - - _hasher256.BlockUpdate(digest1, 0, digest1.Length); - _hasher256.DoFinal(digest2, 0); - - return new Hash256(digest2); - } - - public static byte[] ComputeRaw256(byte[] dataBytes) - { - var digest1 = new byte[32]; - var digest2 = new byte[32]; - - _hasher256.BlockUpdate(dataBytes, 0, dataBytes.Length); - _hasher256.DoFinal(digest1, 0); - _hasher256.BlockUpdate(digest1, 0, digest1.Length); - _hasher256.DoFinal(digest2, 0); - - return digest2; - } - - public static byte[] ComputeRaw256(ref byte[] input1, ref byte[] input2) - { - var digest1 = new byte[_hasher256.GetDigestSize()]; - var digest2 = new byte[_hasher256.GetDigestSize()]; - - _hasher256.BlockUpdate(input1, 0, input1.Length); - _hasher256.BlockUpdate(input2, 0, input2.Length); - _hasher256.DoFinal(digest1, 0); - - _hasher256.BlockUpdate(digest1, 0, digest1.Length); - _hasher256.DoFinal(digest2, 0); - - return digest2; - } - } -} diff --git a/Novacoin/Novacoin.csproj b/Novacoin/Novacoin.csproj index b7b6318..dfd1b81 100644 --- a/Novacoin/Novacoin.csproj +++ b/Novacoin/Novacoin.csproj @@ -119,10 +119,8 @@ - - @@ -130,8 +128,6 @@ - - diff --git a/Novacoin/ScriptCode.cs b/Novacoin/ScriptCode.cs index 14bc2e5..ab0db3f 100644 --- a/Novacoin/ScriptCode.cs +++ b/Novacoin/ScriptCode.cs @@ -656,7 +656,7 @@ namespace Novacoin /// Input number /// Hash type flag /// - public static Hash256 SignatureHash(CScript script, CTransaction txTo, int nIn, int nHashType) + public static uint256 SignatureHash(CScript script, CTransaction txTo, int nIn, int nHashType) { Contract.Requires(nIn < txTo.vin.Length, "nIn out of range."); @@ -727,7 +727,7 @@ namespace Novacoin var txBytes = (byte[])txTmp; var nHashTypeBytes = BitConverter.GetBytes(nHashType); - return Hash256.Compute256(ref txBytes, ref nHashTypeBytes); + return CryptoUtils.ComputeHash256(ref txBytes, ref nHashTypeBytes); } // diff --git a/Novacoin/ScryptHash256.cs b/Novacoin/ScryptHash256.cs deleted file mode 100644 index 4f95926..0000000 --- a/Novacoin/ScryptHash256.cs +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Novacoin classes library - * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) - - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -using System; - -namespace Novacoin -{ - /// - /// Representation of scrypt hash - /// - public class ScryptHash256 : Hash - { - // 32 bytes - public override int hashSize - { - get { return 32; } - } - - public ScryptHash256() : base() { } - public ScryptHash256(byte[] bytes, int offset = 0) : base(bytes, offset) { } - public ScryptHash256(ScryptHash256 h) : base(h) { } - - /// - /// Calculate scrypt hash and return new instance of ScryptHash256 class - /// - /// Byte sequence to hash - /// Hashing result instance - public static ScryptHash256 Compute256(byte[] inputBytes) - { - var V = new uint[(131072 + 63) / sizeof(uint)]; - - var keyBytes1 = CryptoUtils.PBKDF2_Sha256(128, (byte[])inputBytes, (byte[])inputBytes, 1); - var X = Interop.ToUInt32Array(keyBytes1); - - for (var i = 0; i < 1024; i++) - { - Array.Copy(X, 0, V, i * 32, 32); - - xor_salsa8(ref X, 0, ref X, 16); - xor_salsa8(ref X, 16, ref X, 0); - } - for (var i = 0; i < 1024; i++) - { - var j = 32 * (X[16] & 1023); - for (var k = 0; k < 32; k++) - { - X[k] ^= V[j + k]; - } - xor_salsa8(ref X, 0, ref X, 16); - xor_salsa8(ref X, 16, ref X, 0); - } - - var xBytes = Interop.LEBytes(X); - var keyBytes2 = CryptoUtils.PBKDF2_Sha256(32, (byte[])inputBytes, xBytes, 1); - - return new ScryptHash256(keyBytes2); - } - - private static void xor_salsa8(ref uint[] B, int indexB, ref uint[] Bx, int indexBx) - { - uint x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15; - byte i; - - x00 = (B[indexB + 0] ^= Bx[indexBx + 0]); - x01 = (B[indexB + 1] ^= Bx[indexBx + 1]); - x02 = (B[indexB + 2] ^= Bx[indexBx + 2]); - x03 = (B[indexB + 3] ^= Bx[indexBx + 3]); - x04 = (B[indexB + 4] ^= Bx[indexBx + 4]); - x05 = (B[indexB + 5] ^= Bx[indexBx + 5]); - x06 = (B[indexB + 6] ^= Bx[indexBx + 6]); - x07 = (B[indexB + 7] ^= Bx[indexBx + 7]); - x08 = (B[indexB + 8] ^= Bx[indexBx + 8]); - x09 = (B[indexB + 9] ^= Bx[indexBx + 9]); - x10 = (B[indexB + 10] ^= Bx[indexBx + 10]); - x11 = (B[indexB + 11] ^= Bx[indexBx + 11]); - x12 = (B[indexB + 12] ^= Bx[indexBx + 12]); - x13 = (B[indexB + 13] ^= Bx[indexBx + 13]); - x14 = (B[indexB + 14] ^= Bx[indexBx + 14]); - x15 = (B[indexB + 15] ^= Bx[indexBx + 15]); - - Func R = (a, b) => (((a) << (b)) | ((a) >> (32 - (b)))); - - for (i = 0; i < 8; i += 2) - { - /* Operate on columns. */ - x04 ^= R(x00 + x12, 7); x09 ^= R(x05 + x01, 7); - x14 ^= R(x10 + x06, 7); x03 ^= R(x15 + x11, 7); - - x08 ^= R(x04 + x00, 9); x13 ^= R(x09 + x05, 9); - x02 ^= R(x14 + x10, 9); x07 ^= R(x03 + x15, 9); - - x12 ^= R(x08 + x04, 13); x01 ^= R(x13 + x09, 13); - x06 ^= R(x02 + x14, 13); x11 ^= R(x07 + x03, 13); - - x00 ^= R(x12 + x08, 18); x05 ^= R(x01 + x13, 18); - x10 ^= R(x06 + x02, 18); x15 ^= R(x11 + x07, 18); - - /* Operate on rows. */ - x01 ^= R(x00 + x03, 7); x06 ^= R(x05 + x04, 7); - x11 ^= R(x10 + x09, 7); x12 ^= R(x15 + x14, 7); - - x02 ^= R(x01 + x00, 9); x07 ^= R(x06 + x05, 9); - x08 ^= R(x11 + x10, 9); x13 ^= R(x12 + x15, 9); - - x03 ^= R(x02 + x01, 13); x04 ^= R(x07 + x06, 13); - x09 ^= R(x08 + x11, 13); x14 ^= R(x13 + x12, 13); - - x00 ^= R(x03 + x02, 18); x05 ^= R(x04 + x07, 18); - x10 ^= R(x09 + x08, 18); x15 ^= R(x14 + x13, 18); - } - - B[indexB + 0] += x00; - B[indexB + 1] += x01; - B[indexB + 2] += x02; - B[indexB + 3] += x03; - B[indexB + 4] += x04; - B[indexB + 5] += x05; - B[indexB + 6] += x06; - B[indexB + 7] += x07; - B[indexB + 8] += x08; - B[indexB + 9] += x09; - B[indexB + 10] += x10; - B[indexB + 11] += x11; - B[indexB + 12] += x12; - B[indexB + 13] += x13; - B[indexB + 14] += x14; - B[indexB + 15] += x15; - } - } -} diff --git a/Novacoin/base_uint.cs b/Novacoin/base_uint.cs index 502d871..adfa75f 100644 --- a/Novacoin/base_uint.cs +++ b/Novacoin/base_uint.cs @@ -28,31 +28,43 @@ namespace Novacoin /// public class base_uint : IComparable, IEquatable, IEqualityComparer { + #region Internal representation + /// + /// Length of internal representation + /// protected int nWidth; + /// + /// Big numbers are stored as array of unsigned 32-bit integers. + /// protected uint[] pn; + #endregion - public double getDouble() + #region Helper properties + public double Double { - double ret = 0.0; - double fact = 1.0; - - for (int i = 0; i < nWidth; i++) + get { - ret += fact * pn[i]; - fact *= 4294967296.0; - } + double ret = 0.0; + double fact = 1.0; - return ret; + for (int i = 0; i < nWidth; i++) + { + ret += fact * pn[i]; + fact *= 4294967296.0; + } + + return ret; + } } - public ulong GetLow64() + public ulong Low64 { - return pn[0] | (ulong)pn[1] << 32; + get { return pn[0] | (ulong)pn[1] << 32; } } - public uint GetLow32() + public uint Low32 { - return pn[0]; + get { return pn[0]; } } /// @@ -75,11 +87,11 @@ namespace Novacoin { for (int pos = nWidth - 1; pos >= 0; pos--) { - if (pn[pos]!=0) + if (pn[pos] != 0) { for (int bits = 31; bits > 0; bits--) { - if ((pn[pos] & 1 << bits)!=0) + if ((pn[pos] & 1 << bits) != 0) return 32 * pos + bits + 1; } return 32 * pos + 1; @@ -88,7 +100,14 @@ namespace Novacoin return 0; } } + #endregion + + /// + /// Negation operator + /// + /// Value + /// True if value is zero, false otherwise. public static bool operator !(base_uint a) { for (int i = 0; i < a.nWidth; i++) @@ -308,7 +327,7 @@ namespace Novacoin #region IEquatable public bool Equals(base_uint a) { - if (a == null) + if (object.ReferenceEquals(a, null)) { return false; } diff --git a/Novacoin/uint160.cs b/Novacoin/uint160.cs index 595aa1a..4da1929 100644 --- a/Novacoin/uint160.cs +++ b/Novacoin/uint160.cs @@ -1,14 +1,29 @@ -using System; -using System.Collections.Generic; +/** + * Novacoin classes library + * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +using System; using System.Diagnostics.Contracts; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Novacoin { public class uint160 : base_uint { + #region Access to internal representation new protected int nWidth { get { return base.nWidth; } @@ -19,7 +34,9 @@ namespace Novacoin get { return base.pn; } private set { base.pn = value; } } + #endregion + #region Constructors public uint160() { nWidth = 5; @@ -57,60 +74,66 @@ namespace Novacoin var bytes = Interop.ReverseBytes(Interop.HexToArray(hex)); pn = Interop.ToUInt32Array(bytes); } + #endregion - public static uint160 operator ~(uint160 a) + #region Cast operators + public static implicit operator uint160(byte[] bytes) { - var ret = new uint160(); - for (int i = 0; i < a.nWidth; i++) - { - ret.pn[i] = ~a.pn[i]; - } - return ret; + return new uint160(bytes); } - public static uint160 operator -(uint160 a) + public static implicit operator uint160(ulong n) + { + return new uint160(n); + } + #endregion + + #region Bitwise operations + public static uint160 operator ~(uint160 a) { var ret = new uint160(); for (int i = 0; i < a.nWidth; i++) { ret.pn[i] = ~a.pn[i]; } - ret++; return ret; } - - public static uint160 operator ++(uint160 a) + public static uint160 operator ^(uint160 a, uint160 b) { - int i = 0; - while (++a.pn[i] == 0 && i < a.nWidth - 1) + var result = new uint160(); + result.pn = new uint[a.nWidth]; + for (int i = 0; i < result.nWidth; i++) { - i++; + result.pn[i] = a.pn[i] ^ b.pn[i]; } - return a; + return result; } - public static uint160 operator --(uint160 a) + public static uint160 operator &(uint160 a, uint160 b) { - int i = 0; - while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1) + var result = new uint160(); + result.pn = new uint[a.nWidth]; + for (int i = 0; i < result.nWidth; i++) { - i++; + result.pn[i] = a.pn[i] & b.pn[i]; } - return a; + return result; } - public static uint160 operator ^(uint160 a, uint160 b) + public static uint160 operator |(uint160 a, uint160 b) { var result = new uint160(); result.pn = new uint[a.nWidth]; for (int i = 0; i < result.nWidth; i++) { - result.pn[i] = a.pn[i] ^ b.pn[i]; + result.pn[i] = a.pn[i] | b.pn[i]; } return result; } + #endregion + #region Basic arithmetics public static uint160 operator +(uint160 a, uint160 b) { var result = new uint160(); @@ -139,28 +162,41 @@ namespace Novacoin return a - new uint160(b); } - public static uint160 operator &(uint160 a, uint160 b) + public static uint160 operator -(uint160 a) { - var result = new uint160(); - result.pn = new uint[a.nWidth]; - for (int i = 0; i < result.nWidth; i++) + var ret = new uint160(); + for (int i = 0; i < a.nWidth; i++) { - result.pn[i] = a.pn[i] & b.pn[i]; + ret.pn[i] = ~a.pn[i]; } - return result; + ret++; + return ret; } - public static uint160 operator |(uint160 a, uint160 b) + + public static uint160 operator ++(uint160 a) { - var result = new uint160(); - result.pn = new uint[a.nWidth]; - for (int i = 0; i < result.nWidth; i++) + int i = 0; + while (++a.pn[i] == 0 && i < a.nWidth - 1) { - result.pn[i] = a.pn[i] | b.pn[i]; + i++; } - return result; + return a; } + public static uint160 operator --(uint160 a) + { + int i = 0; + while (--a.pn[i] == uint.MaxValue && i < a.nWidth - 1) + { + i++; + } + return a; + } + + #endregion + + #region Shift public static uint160 operator <<(uint160 a, int shift) { var result = new uint160(); @@ -204,5 +240,6 @@ namespace Novacoin return result; } + #endregion } } diff --git a/Novacoin/uint256.cs b/Novacoin/uint256.cs index 0c451ef..317b8d6 100644 --- a/Novacoin/uint256.cs +++ b/Novacoin/uint256.cs @@ -1,15 +1,29 @@ -using System; -using System.Collections.Generic; +/** + * Novacoin classes library + * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +using System; using System.Diagnostics.Contracts; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Numerics; namespace Novacoin { public class uint256 : base_uint { + #region Access to internal representation new protected int nWidth { get { return base.nWidth; } private set { base.nWidth = value; } @@ -18,7 +32,9 @@ namespace Novacoin get { return base.pn; } private set { base.pn = value; } } + #endregion + #region Constructors public uint256() { nWidth = 8; @@ -57,7 +73,21 @@ namespace Novacoin var bytes = Interop.ReverseBytes(Interop.HexToArray(hex)); pn = Interop.ToUInt32Array(bytes); } + #endregion + + #region Cast operators + public static implicit operator uint256(byte[] bytes) + { + return new uint256(bytes); + } + + public static implicit operator uint256(ulong n) + { + return new uint256(n); + } + #endregion + #region Compact representation /// /// Compact representation of unsigned 256bit numbers. /// @@ -72,11 +102,11 @@ namespace Novacoin int nSize = (bits + 7) / 8; uint nCompact = 0; if (nSize <= 3) - nCompact = ((uint)GetLow64()) << 8 * (3 - nSize); + nCompact = ((uint)Low64) << 8 * (3 - nSize); else { uint256 bn = this >> 8 * (nSize - 3); - nCompact = (uint)bn.GetLow64(); + nCompact = (uint)bn.Low64; } if ((nCompact & 0x00800000) != 0) @@ -113,12 +143,9 @@ namespace Novacoin pn = i.pn; } } + #endregion - private void SetBytes(byte[] bytes) - { - pn = Interop.ToUInt32Array(Interop.ReverseBytes(bytes)); - } - + #region Bitwise operations public static uint256 operator ~(uint256 a) { var ret = new uint256(); @@ -129,6 +156,41 @@ namespace Novacoin return ret; } + public static uint256 operator ^(uint256 a, uint256 b) + { + var result = new uint256(); + result.pn = new uint[a.nWidth]; + for (int i = 0; i < result.nWidth; i++) + { + result.pn[i] = a.pn[i] ^ b.pn[i]; + } + return result; + } + + public static uint256 operator &(uint256 a, uint256 b) + { + var result = new uint256(); + result.pn = new uint[a.nWidth]; + for (int i = 0; i < result.nWidth; i++) + { + result.pn[i] = a.pn[i] & b.pn[i]; + } + return result; + } + + public static uint256 operator |(uint256 a, uint256 b) + { + var result = new uint256(); + result.pn = new uint[a.nWidth]; + for (int i = 0; i < result.nWidth; i++) + { + result.pn[i] = a.pn[i] | b.pn[i]; + } + return result; + } + #endregion + + #region Basic arithmetics public static uint256 operator -(uint256 a) { var ret = new uint256(); @@ -161,16 +223,6 @@ namespace Novacoin return a; } - public static uint256 operator ^(uint256 a, uint256 b) - { - var result = new uint256(); - result.pn = new uint[a.nWidth]; - for (int i = 0; i < result.nWidth; i++) - { - result.pn[i] = a.pn[i] ^ b.pn[i]; - } - return result; - } public static uint256 operator +(uint256 a, uint256 b) { @@ -199,29 +251,9 @@ namespace Novacoin { return a - new uint256(b); } + #endregion - public static uint256 operator &(uint256 a, uint256 b) - { - var result = new uint256(); - result.pn = new uint[a.nWidth]; - for (int i = 0; i < result.nWidth; i++) - { - result.pn[i] = a.pn[i] & b.pn[i]; - } - return result; - } - - public static uint256 operator |(uint256 a, uint256 b) - { - var result = new uint256(); - result.pn = new uint[a.nWidth]; - for (int i = 0; i < result.nWidth; i++) - { - result.pn[i] = a.pn[i] | b.pn[i]; - } - return result; - } - + #region Shift public static uint256 operator <<(uint256 a, int shift) { var result = new uint256(); @@ -265,5 +297,6 @@ namespace Novacoin return result; } + #endregion } } diff --git a/NovacoinTest/Program.cs b/NovacoinTest/Program.cs index 4b9c63d..c8295c2 100644 --- a/NovacoinTest/Program.cs +++ b/NovacoinTest/Program.cs @@ -79,7 +79,7 @@ namespace NovacoinTest /// ECDSA keypair signing test var data = "Превед!"; - var sigHash = Hash256.Compute256(Encoding.UTF8.GetBytes(data)); + uint256 sigHash = CryptoUtils.ComputeHash256(Encoding.UTF8.GetBytes(data)); var signature = keyPair1.Sign(sigHash); Console.WriteLine("Signature: {0}", Interop.ToHex(signature)); @@ -102,7 +102,7 @@ namespace NovacoinTest /// Block header hashing test byte[] dataBytesForScrypt = b1.header; - var scryptHash = ScryptHash256.Compute256(dataBytesForScrypt); + uint256 scryptHash = CryptoUtils.ComputeScryptHash256(dataBytesForScrypt); Console.WriteLine("\nblock1 header hash: {0}", scryptHash); @@ -117,7 +117,7 @@ namespace NovacoinTest Console.WriteLine("scriptPubKey address: {0}\n", new CPubKey(solutions.First()).KeyID.ToString()); Console.WriteLine("scriptPubKeyHash solved: {0}", ScriptCode.Solver(scriptPubKeyHash, out typeRet, out solutions)); - Console.WriteLine("scriptPubKeyHash address: {0}\n", new CKeyID(new Hash160(solutions.First())).ToString()); + Console.WriteLine("scriptPubKeyHash address: {0}\n", new CKeyID(solutions.First()).ToString()); /// Some SetDestination tests var scriptDestinationTest = new CScript(); @@ -137,7 +137,7 @@ namespace NovacoinTest scriptDestinationTest.SetDestination(keyPair1.PubKey.KeyID); Console.WriteLine("\tscriptDestinationTest solved: {0}", ScriptCode.Solver(scriptDestinationTest, out typeRet, out solutions)); - Console.WriteLine("\tscriptDestinationTest address: {0}\n", new CKeyID(new Hash160(solutions.First()))); + Console.WriteLine("\tscriptDestinationTest address: {0}\n", new CKeyID(solutions.First())); Console.WriteLine("Multisig with three random keys:"); @@ -166,15 +166,15 @@ namespace NovacoinTest scriptP2SHTest.SetDestination(scriptDestinationTest.ScriptID); Console.WriteLine("\tscriptP2SHTest solved: {0}", ScriptCode.Solver(scriptP2SHTest, out typeRet, out solutions)); - Console.WriteLine("\tscriptP2SHTest address: {0}\n", new CScriptID(new Hash160(solutions.First()))); + Console.WriteLine("\tscriptP2SHTest address: {0}\n", new CScriptID(solutions.First())); // SignatureHash tests var txS = new CTransaction(Interop.HexToArray("01000000ccfe9e550d083902781746c80954e3af56e930235befb798f987667021a2f32dc0099499cd010000006b483045022100b5f6783af4f7f60866c889fd668c93ee110ecc3751208fe0b49cc7ace47e52e8022075652e1e960a50b27436ab04f2728b3bba09d07a858691559d99c1ac5dd74f16012103fe065856d7fa8cd41d0047600af2ec1ebe8c6198c1a889e90d8ce6b2f1f8afd7ffffffff2c6009a7494f38f7797bb9ef2aeafb093ae433208171a504367373df4164399d010000004847304402205f1b74bbc37219918f3de13ff645ecc7093512fecda4fcbcac2174c44144361102202149f1adcfcd473ec8a662b5b166b600208d92596e30b33fb402b4720bac3da101ffffffffbf1dd11394d2c0d3cbd4e0b56c74e7463ed5a19f22fe219ee700c61f834b3948010000006a473044022004824a9e071c40707e5309e510fd2cc105fd430504ceefce48aeed1c8fcf3bd7022023f4a43c58e4012284d8df25b55940199d19d4ca664053e2d5c1cc93ef441c3c012103fe065856d7fa8cd41d0047600af2ec1ebe8c6198c1a889e90d8ce6b2f1f8afd7ffffffffea06d18d8034a3645a8d5da75ed5c5f68a9dd09a798a876bef5d2cc9db8819390100000048473044022018e016973d87a53d6f14ae9929aa3c426d3d3a76eb81b3f1e996f0ec24ebacb302203668f165e6e9d5818eb3d108d23e2390213a6921ddfd51dbfca4ffebad73029601ffffffff5bda9a2a98debbda4ddad400a340190fcba4f4b3268f0a9d88eb5541bd7dadfc0100000049483045022100c4d210a6cd3edc6bc9cbfee1a8506ff239ef60baf7ebd46ffefb43e20a575d6c022019ea10cf480dadbb6332a03a404a3991437ffc9fef044c07112e2d15f3de74de01ffffffff5bda9a2a98debbda4ddad400a340190fcba4f4b3268f0a9d88eb5541bd7dadfc020000004948304502210084f5781ff88c201caca29b724f89fad5d72320a578239a3a2834ba669ea92b7e02207651ef9f7c60c2cc4fe187c98587252f3196fb1c31ed8f6c1f1f41e9a90d75ff01ffffffff61a9d75745092786bcbd48cc5860845beea607b8994790e9734f9fa68951bb66010000006b483045022100d2d3f925472970b9a0d365a120a9a6c9b7b0b3b3aacedaa40532397c6252da2f02206939d3cade4bada339799a4d651a7a33cb381640f6acef5fbecbe55ae1fa2364012103fe065856d7fa8cd41d0047600af2ec1ebe8c6198c1a889e90d8ce6b2f1f8afd7ffffffff635c711ba32bd587d349521475d2bd133a402c178543183c027cc1414a7837500100000049483045022100aece1ca9d902eaece08ec9704005196046f3a0b6f561cd17e9b09c01fed1447602207e68e21be4fcb895f045337741b42f43d218bb5c681f8e2eac5f9f3ffc8caf8301ffffffff7ddd7385fd7b81f19ccaa6ccd629bd2ab2a0af7ca69831c6dbb3b02c31de95db0100000049483045022100b260f2065dea407006e424d3cbb20009c807f422cee4ac8fb3553e4a81d62a7702204c67c99e792542cfe19a6956b101b4fd754a01fb1538b54e5f2141210729f09b01ffffffff8faebe377bc4211e41bd7e4a551e1de530040f8a55797f82e12d4d3c6a0b9fff010000004847304402204637911286c073fa0a8211e8427a6c63201bdac73e7b2760d3d9c7d748c9267c02205df709fdd06e3fb600ab81a17a1becc829769f1cb117b1520755d4f2a38429f001fffffffff1be969005bfcab4bcdaf835470680e2a309290b97d79fe63f7cbe904560b2d601000000484730440220352ad1a1ea5d92ddc13b7507a05180574c7309822f684ecf7321b7e925e5104302201e6a06e2f2d05a3d665cc6180fafacb658514a2f1bb632de99e88e4c26149e2501fffffffffa2019204a766fb4614be3d12bfb1ab35ad756e144193249e83660ca78898b3b0200000048473044022024f21eaf955291a9aec2cd45f42add62d8a30626aa9246664226fb3b56bf632f02205a3b46ec2857fec2fcb73663a57f99e4fcda328e8f1283198e8e9c5b4a2a3e0f01ffffffffd25e023fbdcd571ae346bf7aa142f5e32ca1aec23adae314ee209af22572cf1f000000006a4730440220551627592cbb7d970222a4d57a32aed50f1e93e81ae69958f26e56ca3b561715022019b12e560ff31013d0941ca2100ecdf9a3c3602b5c76b83d3b3c87d723d32ce3012103fe065856d7fa8cd41d0047600af2ec1ebe8c6198c1a889e90d8ce6b2f1f8afd7ffffffff02402d0000000000001976a91479f1d300be0da277e7ae217e99c6cc8a4f8717fe88ac00943577000000001976a914cbc5a055ae068d34b4a93e4c9adb9cb10262ae4f88ac00000000")); - Hash256 sigHashAll = ScriptCode.SignatureHash(txS.vout[0].scriptPubKey, txS, 1, (int)sigflag.SIGHASH_ALL); - Hash256 sigHashNone = ScriptCode.SignatureHash(txS.vout[0].scriptPubKey, txS, 1, (int)sigflag.SIGHASH_NONE); - Hash256 sigHashSingle = ScriptCode.SignatureHash(txS.vout[0].scriptPubKey, txS, 1, (int)sigflag.SIGHASH_SINGLE); - Hash256 sigHashAnyone = ScriptCode.SignatureHash(txS.vout[0].scriptPubKey, txS, 1, (int)sigflag.SIGHASH_ANYONECANPAY); + uint256 sigHashAll = ScriptCode.SignatureHash(txS.vout[0].scriptPubKey, txS, 1, (int)sigflag.SIGHASH_ALL); + uint256 sigHashNone = ScriptCode.SignatureHash(txS.vout[0].scriptPubKey, txS, 1, (int)sigflag.SIGHASH_NONE); + uint256 sigHashSingle = ScriptCode.SignatureHash(txS.vout[0].scriptPubKey, txS, 1, (int)sigflag.SIGHASH_SINGLE); + uint256 sigHashAnyone = ScriptCode.SignatureHash(txS.vout[0].scriptPubKey, txS, 1, (int)sigflag.SIGHASH_ANYONECANPAY); Console.WriteLine("sigHashAll={0}", sigHashAll); Console.WriteLine("sigHashNone={0}", sigHashNone); @@ -228,8 +228,7 @@ namespace NovacoinTest elapsedMs = watch.ElapsedMilliseconds; Console.WriteLine("Unserialization time: {0} ms\n", elapsedMs); - - Hash256 merkleroot = null; + uint256 merkleroot = null; Console.WriteLine("\nRinning 100 iterations of merkle tree computation for very big block..."); -- 1.7.1