public void Should_Be_Converted_To_Real_Hash() { var headers = new HeaderHash(new Hash { { "foo", "bar" } }); Assert.NotNull(headers as Hash); }
public void Should_Return_Null_When_Delete_Is_Called_On_A_Non_Existent_Key() { var headers = new HeaderHash(new Hash { { "foo", "bar" } }); Assert.Null(headers.Delete("Hello")); }
public void Should_Return_The_Deleted_Value_When_Delete_Is_Called_On_An_Existing_Key() { var headers = new HeaderHash(new Hash { { "foo", "bar" } }); Assert.AreEqual("bar", headers.Delete("Foo")); }
public void Should_Check_Existence_of_Keys_Case_Insensitively() { var headers = new HeaderHash(new Hash { { "Content-MD5", "d5ff4e2a0 ..." } }); Assert.IsTrue(headers.ContainsKey("content-md5")); Assert.IsFalse(headers.ContainsKey("ETag")); }
public void Should_Convert_Array_Values_To_Strings_When_Converting_To_Hash() { var headers = new HeaderHash(new Hash { { "foo", new[] { "bar", "baz" } } }); Assert.AreEqual(new Hash { { "foo", "bar\nbaz" } }, headers.ToHash()); }
public void Should_Avoid_Unnecessary_Object_Creation_If_Possible() { var a = new HeaderHash(new Hash { { "foo", "bar" } }); var b = HeaderHash.Create(a); Assert.AreEqual(b.GetHashCode(), a.GetHashCode()); Assert.AreEqual(a, b); }
public void Should_Be_Able_To_Delete_The_Given_Key_Case_Insensitively() { var headers = new HeaderHash(new Hash { { "foo", "bar" } }); headers.Remove("FOO"); Assert.IsFalse(headers.ContainsKey("foo")); Assert.IsFalse(headers.ContainsKey("FOO")); }
public dynamic[] Call(IDictionary <string, dynamic> environment) { var response = _app.Call(environment); var headers = new HeaderHash(response[1]); if (!headers.ContainsKey("Content-Type") || headers["Content-Type"] == null) { headers["Content-Type"] = _contentType; } return(new[] { response[0], headers, response[2] }); }
public void Should_Retain_Header_Case() { var headers = new HeaderHash(new Hash { { "Content-MD5", "d5ff4e2a0 ..." } }); headers["ETag"] = "Boo!"; Assert.AreEqual(new Hash { { "Content-MD5", "d5ff4e2a0 ..." }, { "ETag", "Boo!" } }, headers); }
public void Should_Convert_Array_Values_To_Strings_When_Responding_To_Each() { var headers = new HeaderHash(new Hash { { "foo", new[] { "bar", "baz" } } }); headers.Each((key, value) => { Assert.AreEqual("foo", key); Assert.AreEqual("bar\nbaz", value); }); }
public void Should_Replace_Hashes_Correctly() { var headers = new HeaderHash(new Hash { { "Foo-Bar", "baz" } }); var hash = new Hash { { "foo", "bar" } }; headers.Replace(hash); Assert.AreEqual("bar", headers["foo"]); }
public dynamic[] Call(IDictionary <string, dynamic> environment) { var response = _app.Call(environment); var status = response[0]; var headers = response[1]; var body = response[2]; headers = new HeaderHash(headers); SetContentLength(status, headers, body); return(new[] { status, headers, body }); }
public void Should_Merge_Case_Insensitively() { var headers = new HeaderHash(new Hash { { "ETag", "HELLO" }, { "content-length", "123" } }); var otherHash = new Hash { { "Etag", "WORLD" }, { "Content-Length", "321" }, { "Foo", "BAR" } }; var merged = headers.Merge(otherHash); Assert.AreEqual(otherHash, merged); }
public void Should_Overwrite_Case_Insensitively_And_Assume_The_New_Keys_Case() { var headers = new HeaderHash(new Hash { { "Foo-Bar", "baz" } }); headers["foo-bar"] = "bizzle"; Assert.AreEqual("bizzle", headers["FOO-BAR"]); Assert.AreEqual(1, headers.Count); Assert.AreEqual(new Hash { { "foo-bar", "bizzle" } }, headers.ToHash()); }
public Response(dynamic body = null, int status = 200, Hash header = null, Action <dynamic> block = null) { if (body == null) { body = new List <dynamic>(); } if (header == null) { header = new Hash(); } Headers = new HeaderHash(new Hash { { "Content-Type", "text/html" } }).Merge(header); Status = status; Body = new List <dynamic>(); Writer = str => Body.Add(str); if (Headers.ContainsKey("Transfer-Encoding") && Headers["Transfer-Encoding"] == "chunked") { Chunked = true; } if (body is string) { Write(body); } else if (body is IEnumerable) { new IterableAdapter(body).Each(part => Write(part.ToString())); } else { throw new ArgumentException("Must be iterable.", "body"); } if (block != null) { block(this); } }
public Share(IStratumMiner miner, UInt64 jobId, IJob job, string extraNonce2, string nTimeString, string nonceString) { _logger.Debug("Entering share constructor: {0}", nonceString); Miner = miner; JobId = jobId; Job = job; Error = ShareError.None; var submitTime = TimeHelpers.NowInUnixTimestamp(); // time we recieved the share from miner. if (Job == null) { _logger.Error("Job is null"); Error = ShareError.JobNotFound; return; } if (extraNonce2 == null) { _logger.Error("extraNonce2 is NULL!"); } // check size of miner supplied extraNonce2 if (extraNonce2.Length / 2 != ExtraNonce.ExpectedExtraNonce2Size) { _logger.Error("Incorrect Extranonce2 size: {0} while expecting {1}", extraNonce2.Length, ExtraNonce.ExpectedExtraNonce2Size * 2); Error = ShareError.IncorrectExtraNonce2Size; return; } ExtraNonce2 = Convert.ToUInt32(extraNonce2, 16); // set extraNonce2 for the share. if (nTimeString == null) { _logger.Error("nTimeString is NULL!"); } // check size of miner supplied nTime. if (nTimeString.Length != 8) { _logger.Error("nTimeString length !=8: {0}", nTimeString.Length); Error = ShareError.IncorrectNTimeSize; return; } NTime = Convert.ToUInt32(nTimeString, 16); // read ntime for the share // make sure NTime is within range. if (NTime < job.BlockTemplate.CurTime || NTime > submitTime + 7200) { _logger.Error("NTime Out Of Range!"); Error = ShareError.NTimeOutOfRange; return; } if (nonceString == null) { _logger.Error("nonceString is NULL!"); } // check size of miner supplied nonce. if (nonceString.Length != 8) { _logger.Error("nonceString.Length != 8: {0}", nonceString.Length); Error = ShareError.IncorrectNonceSize; return; } Nonce = Convert.ToUInt32(nonceString, 16); // nonce supplied by the miner for the share. if (miner == null) { _logger.Error("miner is NULL!"); } // set job supplied parameters. Height = job.BlockTemplate.Height; // associated job's block height. ExtraNonce1 = miner.ExtraNonce; // extra nonce1 assigned to miner. // check for duplicate shares. if (!Job.RegisterShare(this)) // try to register share with the job and see if it's duplicated or not. { _logger.Error("Duplicate share: {0:l}", nonceString); Error = ShareError.DuplicateShare; return; } _logger.Debug("Serialize Share {0}", nonceString); // construct the coinbase. CoinbaseBuffer = Serializers.SerializeCoinbase(Job, ExtraNonce1, ExtraNonce2); CoinbaseHash = Coin.Coinbase.Utils.HashCoinbase(CoinbaseBuffer); // create the merkle root. MerkleRoot = Job.MerkleTree.WithFirst(CoinbaseHash).ReverseBuffer(); // create the block headers _logger.Debug("Getting Header buffer for Share {0}", nonceString); HeaderBuffer = Serializers.SerializeHeader(Job, MerkleRoot, NTime, Nonce); HeaderHash = Job.HashAlgorithm.Hash(HeaderBuffer); _logger.Debug("Got share {0} of length: {1}\nPOW: {2,64:l}\nTGT: {3,64:l}", nonceString, HeaderHash.Length, HeaderHash.ReverseBytes().ToHexString(), Job.Target.ToByteArray().ReverseBytes().ToHexString() ); HeaderValue = new BigInteger(HeaderHash); // calculate the share difficulty Difficulty = ((double)new BigRational(AlgorithmManager.Diff1, HeaderValue)) * Job.HashAlgorithm.Multiplier; // calculate the block difficulty BlockDiffAdjusted = Job.Difficulty * Job.HashAlgorithm.Multiplier; /* * Test false pozitive block candidates: negative bigints were the problem * byte[] testbytes = new byte[] { * 0xf7, 0xdf, 0xed, 0xbd, * 0x9a, 0x2b, 0xa5, 0x1f, * 0x7b, 0x0d, 0x68, 0x76, * 0xbe, 0x1f, 0x18, 0xd6, * 0x2d, 0x49, 0x94, 0x91, * 0x69, 0x11, 0x39, 0x41, * 0xdf, 0x1f, 0x25, 0xdb, * 0x9b, 0x4e, 0x97, 0xb7 * }; * string teststr = testbytes.ReverseBuffer().ToHexString(); * HeaderValue = new BigInteger(testbytes); */ // check if block candicate if (Job.Target >= HeaderValue) //if (true) //for Debug only { IsBlockCandidate = true; BlockHex = Serializers.SerializeBlock(Job, HeaderBuffer, CoinbaseBuffer, miner.Pool.Config.Coin.Options.IsProofOfStakeHybrid); BlockHash = HeaderBuffer.DoubleDigest().ReverseBuffer(); try { _logger.Debug("Job.Target is greater than or equal HeaderValue(POW-SCRYPT)!!!:\n{9}\n{10}\n\n" + "Big-Endian values for Block Header:\n" + "job.BlockTemplate.Version={0}\n" + "job.PreviousBlockHash={1}\n" + "MerkleRoot={2}\n" + "NTime={3}\n" + "job.EncodedDifficulty={4}\n" + "Nonce={5}\n" + "==============\n" + "result={6}\n\n" + "Big-Endian:\n" + "BlockHex={7}\n" + "BlockHash(2xSHA256)={8}\n", job.BlockTemplate.Version, BitConverter.ToString(job.PreviousBlockHash.HexToByteArray()).Replace("-", string.Empty), BitConverter.ToString(MerkleRoot).Replace("-", string.Empty), NTime, job.EncodedDifficulty, Nonce, BitConverter.ToString(HeaderBuffer).Replace("-", string.Empty), BlockHex, BitConverter.ToString(BlockHash).Replace("-", string.Empty), Job.Target.ToByteArray().ReverseBuffer().ToHexString(), HeaderValue.ToByteArray().ReverseBuffer().ToHexString() ); } catch (Exception e) { _logger.Error(e, "Something has happened while logging"); } } else { IsBlockCandidate = false; BlockHash = HeaderBuffer.DoubleDigest().ReverseBuffer(); // Check if share difficulty reaches miner difficulty. var lowDifficulty = Difficulty / miner.Difficulty < 0.99; // share difficulty should be equal or more then miner's target difficulty. if (!lowDifficulty) // if share difficulty is high enough to match miner's current difficulty. { return; // just accept the share. } if (Difficulty >= miner.PreviousDifficulty) // if the difficulty matches miner's previous difficulty before the last vardiff triggered difficulty change { return; // still accept the share. } // if the share difficulty can't match miner's current difficulty or previous difficulty Error = ShareError.LowDifficultyShare; // then just reject the share with low difficult share error. } }
public Share(IStratumMiner miner, UInt64 jobId, IJob job, string extraNonce2, string nTimeString, string nonceString) { Miner = miner; JobId = jobId; Job = job; Error = ShareError.None; UInt64 submitTime = TimeHelpers.NowInUnixTime64(); // time we recieved the share from miner. if (Job == null) { Error = ShareError.JobNotFound; return; } // check size of miner supplied extraNonce2 if (extraNonce2.Length / 2 != ExtraNonce.ExpectedExtraNonce2Size) { Error = ShareError.IncorrectExtraNonce2Size; return; } ExtraNonce2 = Convert.ToUInt32(extraNonce2, 16); // set extraNonce2 for the share. // check size of miner supplied nTime. if (nTimeString.Length != 16) { Error = ShareError.IncorrectNTimeSize; return; } NTime = Convert.ToUInt64(nTimeString, 16); // read ntime for the share // make sure NTime is within range. if (NTime < job.BlockTemplate.CurTime || NTime > submitTime + 7200) { Error = ShareError.NTimeOutOfRange; return; } // check size of miner supplied nonce. if (nonceString.Length != 16) { Error = ShareError.IncorrectNonceSize; return; } Nonce = Convert.ToUInt64(nonceString, 16); // nonce supplied by the miner for the share. // set job supplied parameters. Height = job.BlockTemplate.Height; // associated job's block height. ExtraNonce1 = miner.ExtraNonce; // extra nonce1 assigned to miner. // check for duplicate shares. if (!Job.RegisterShare(this)) // try to register share with the job and see if it's duplicated or not. { Error = ShareError.DuplicateShare; return; } // construct the coinbase. CoinbaseBuffer = Serializers.SerializeCoinbase(Job, ExtraNonce1, ExtraNonce2); CoinbaseHash = Coin.Coinbase.Utils.HashCoinbase(CoinbaseBuffer); var coinbaseNoSigBuffer = Serializers.SerializeCoinbaseForTxId(Job, ExtraNonce1, ExtraNonce2); CoinbaseTxId = Coin.Coinbase.Utils.HashCoinbase(coinbaseNoSigBuffer); // create the merkle root. MerkleRoot = Job.MerkleTree.WithFirst(CoinbaseHash).ReverseBuffer(); // create the block headers HeaderBuffer = Serializers.SerializeHeader(Job, MerkleRoot, NTime, Nonce); HeaderBufferForHash = Serializers.SerializeHeaderForHash(Job, MerkleRoot, NTime, Nonce); HeaderHash = Job.HashAlgorithm.Hash(HeaderBufferForHash, miner.Pool.Config.Coin.Options); HeaderHashValue = new BigInteger(HeaderHash); // calculate the share difficulty Difficulty = ((double)new BigRational(Algorithms.Diff1, HeaderHashValue)) * Job.HashAlgorithm.Multiplier; BigInteger minerTarget = (new BigRational(Algorithms.Diff1, new BigInteger((uint)miner.Difficulty)) * Job.HashAlgorithm.Multiplier).GetWholePart(); // calculate the block difficulty BlockDiffAdjusted = Job.Difficulty * Job.HashAlgorithm.Multiplier; // check if block candicate if (Job.Target >= HeaderHashValue) { IsBlockCandidate = true; BlockHex = Serializers.SerializeBlock(Job, HeaderBuffer, CoinbaseBuffer); BlockHash = HeaderHash.ReverseBuffer(); //HeaderBuffer.DoubleDigest().ReverseBuffer(); // TODO: make sure this is okay! } else { IsBlockCandidate = false; BlockHash = HeaderHash.ReverseBuffer();//HeaderBuffer.DoubleDigest().ReverseBuffer(); // Check if share difficulty reaches miner difficulty. var lowDifficulty = Difficulty / miner.Difficulty < 0.99; // share difficulty should be equal or more then miner's target difficulty. if (!lowDifficulty) // if share difficulty is high enough to match miner's current difficulty. { return; // just accept the share. } if (Difficulty >= miner.PreviousDifficulty) // if the difficulty matches miner's previous difficulty before the last vardiff triggered difficulty change { return; // still accept the share. } // if the share difficulty can't match miner's current difficulty or previous difficulty Error = ShareError.LowDifficultyShare; // then just reject the share with low difficult share error. } }