Skip to content

Commit

Permalink
Fixed getblocktemplate() - invalid mode bug for peercoin and variants…
Browse files Browse the repository at this point in the history
…. Needs a coin.json configuration option though.

Added TimeConverter support for Block.cs:Time so peercoin variants is also supported - which can read utc time-strings.
Improved Transaction.cs:GetPoolOutput() so it can also support peercoin variants.
Updated TimeHelpers.cs.
Fixes #442.
Fixes #410.
  • Loading branch information
bonesoul committed Sep 23, 2014
1 parent e30afc0 commit 658ebbe
Show file tree
Hide file tree
Showing 19 changed files with 134 additions and 27 deletions.
4 changes: 2 additions & 2 deletions src/CoiniumServ/Banning/BanManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private void Ban(IMiner miner)
var ip = client.Connection.RemoteEndPoint.Address;

if(!_bannedIps.ContainsKey(ip))
_bannedIps.Add(ip, TimeHelpers.NowInUnixTime());
_bannedIps.Add(ip, TimeHelpers.NowInUnixTimestamp());

client.Connection.Disconnect();
}
Expand Down Expand Up @@ -148,7 +148,7 @@ private bool BanExpired(IPAddress ip)
{
var banTime = _bannedIps[ip];

var elapsedTime = TimeHelpers.NowInUnixTime() - banTime; // elapsed time since his ban.
var elapsedTime = TimeHelpers.NowInUnixTimestamp() - banTime; // elapsed time since his ban.
var timeLeft = Config.Duration - elapsedTime; // time left for his ban

if (timeLeft > 0) // if he has still remaining time
Expand Down
1 change: 1 addition & 0 deletions src/CoiniumServ/CoiniumServ.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
<Compile Include="Coin\Helpers\Hashrate.cs" />
<Compile Include="Configuration\IJsonConfigReader.cs" />
<Compile Include="Daemon\Converters\DifficultyConverter.cs" />
<Compile Include="Daemon\Converters\TimeConverter.cs" />
<Compile Include="Daemon\Errors\RpcError.cs" />
<Compile Include="Daemon\Errors\RpcErrorCode.cs" />
<Compile Include="Daemon\Exceptions\GenericRpcException.cs" />
Expand Down
66 changes: 66 additions & 0 deletions src/CoiniumServ/Daemon/Converters/TimeConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#region License
//
// CoiniumServ - Crypto Currency Mining Pool Server Software
// Copyright (C) 2013 - 2014, CoiniumServ Project - http://www.coinium.org
// http://www.coiniumserv.com - https://github.com/CoiniumServ/CoiniumServ
//
// This software is dual-licensed: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// For the terms of this license, see licenses/gpl_v3.txt.
//
// Alternatively, you can license this software under a commercial
// license or white-label it as set out in licenses/commercial.txt.
//
#endregion

using System;
using System.Globalization;
using CoiniumServ.Utils.Helpers.Time;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace CoiniumServ.Daemon.Converters
{
/// <summary>
/// Custom json converter for time fields which can parse int32 unix-time for bitcoin variants and utc time-string for peercoin variants.
/// </summary>
public class TimeConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
DateTime dateTime;
Int32 unixTime;

var token = JToken.Load(reader); // read the difficulty token.

// bitcoin variants use an Int32 for time.
if (int.TryParse(token.ToString(), out unixTime)) // try parsing as int32
return unixTime;

// peercoin variants use a date-time string.
if (DateTime.TryParseExact(token.ToString(), "yyyy-MM-dd HH:mm:ss UTC", CultureInfo.InvariantCulture,
DateTimeStyles.AdjustToUniversal, out dateTime)) // try parsing as utc string.
return dateTime.ToUnixTimestamp();

return existingValue; // return the default value.
}

public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
}
}
18 changes: 13 additions & 5 deletions src/CoiniumServ/Daemon/DaemonClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,14 +245,22 @@ public long GetBlockNumber()
/// https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki
/// https://en.bitcoin.it/wiki/Getblocktemplate
/// </summary>
public BlockTemplate GetBlockTemplate()
public BlockTemplate GetBlockTemplate(bool capabilitiesSupported = true)
{
var capabilities = new Dictionary<string, object>
var data = new Dictionary<string, object>();

if (capabilitiesSupported)
{
{"capabilities", new List<string> {"coinbasetxn", "workid", "coinbase/append"}}
};
// bitcoin variants can accept capabilities: https://github.com/bitcoin/bitcoin/blob/7388b74cd2c5e3b71e991d26953c89c059ba6f2f/src/rpcmining.cpp#L298
data.Add("capabilities", new List<string> {"coinbasetxn", "workid", "coinbase/append"});
}
else
{
// peercoin variants instead require mode: https://github.com/Peerunity/Peerunity/blob/master/src/bitcoinrpc.cpp#L2206
data.Add("mode", "template");
}

return MakeRequest<BlockTemplate>("getblocktemplate", capabilities);
return MakeRequest<BlockTemplate>("getblocktemplate", data);
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/CoiniumServ/Daemon/IDaemonClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace CoiniumServ.Daemon
{
public interface IDaemonClient
{
BlockTemplate GetBlockTemplate();
BlockTemplate GetBlockTemplate(bool capabilitiesSupported = true);

BlockTemplate GetBlockTemplate(string blockHex);

Expand Down
12 changes: 12 additions & 0 deletions src/CoiniumServ/Daemon/Responses/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,21 @@
#endregion
using System;
using System.Collections.Generic;
using CoiniumServ.Daemon.Converters;
using Newtonsoft.Json;

namespace CoiniumServ.Daemon.Responses
{
public class Block
{
public string Hash { get; set; }

public Int32 Confirmations { get; set; }

public Int32 Size { get; set; }

public Int32 Height { get; set; }

public Int32 Version { get; set; }

/// <summary>
Expand All @@ -39,10 +45,16 @@ public class Block
public string MerkleRoot { get; set; }

public List<string> Tx { get; set; }

[JsonConverter(typeof(TimeConverter))]
public Int32 Time { get; set; }

public UInt32 Nonce { get; set; }

public string Bits { get; set; }

public double Difficulty { get; set; }

public string NextBlockHash { get; set; }
}
}
16 changes: 12 additions & 4 deletions src/CoiniumServ/Daemon/Responses/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,18 @@ public TransactionDetail GetPoolOutput(string poolAddress, string poolAccount)
if (Details == null) // make sure we have valid outputs.
return null;

// check if coin includes output address data in transaction details.
return Details.Any(x => x.Address == null)
? Details.FirstOrDefault(x => x.Account == poolAccount) // some coins doesn't include address field in outputs, so try to determine using the associated account name.
: Details.FirstOrDefault(x => x.Address == poolAddress); // if coin includes address field in outputs, just use it.
// kinda weird stuff goin here;
// bitcoin variants;
// case 1) some of bitcoin variants can include the "address" in the transaction detail and we can basically find the output comparing against it.
// case 2) some other bitcoin variants can include "address account" name in transaction detail and we again find the output comparing against it.
// case 3) peercoin variants is where things get complicated, even if you set an account name to an address, they peercoin variants will refuse use the name in details.

if (Details.Any(x => x.Address == poolAddress)) // check for case 1.
return Details.First(x => x.Address == poolAddress); // return the output that matches pool address.
else if (Details.Any(x => x.Account == poolAccount)) // check for case 2.
return Details.First(x => x.Account == poolAccount);
else // case 3 - if we can't match pool address or pool account, just return the very first output.
return Details.FirstOrDefault();
}

// not sure if fields below even exists / used
Expand Down
2 changes: 1 addition & 1 deletion src/CoiniumServ/Jobs/Job.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public Job(UInt64 id, IHashAlgorithm algorithm, IBlockTemplate blockTemplate, IG
PreviousBlockHashReversed = blockTemplate.PreviousBlockHash.HexToByteArray().ReverseByteOrder().ToHexString();
CoinbaseInitial = generationTransaction.Initial.ToHexString();
CoinbaseFinal = generationTransaction.Final.ToHexString();
CreationTime = TimeHelpers.NowInUnixTime();
CreationTime = TimeHelpers.NowInUnixTimestamp();

_shares = new List<UInt64>();

Expand Down
4 changes: 2 additions & 2 deletions src/CoiniumServ/Jobs/Manager/JobManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ private void BlockPoller(object stats)

try
{
var blockTemplate = _daemonClient.GetBlockTemplate();
var blockTemplate = _daemonClient.GetBlockTemplate(false);

if (blockTemplate.Height == _jobTracker.Current.Height) // if network reports the same block-height with our current job.
return; // just return.
Expand Down Expand Up @@ -146,7 +146,7 @@ private IJob GetNewJob()
{
try
{
var blockTemplate = _daemonClient.GetBlockTemplate();
var blockTemplate = _daemonClient.GetBlockTemplate(false);

// TODO: convert generation transaction to ioc & DI based.
var generationTransaction = new GenerationTransaction(ExtraNonce, _daemonClient, blockTemplate, _poolConfig);
Expand Down
2 changes: 1 addition & 1 deletion src/CoiniumServ/Jobs/Tracker/JobTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private void CleanUp(object state)
var startingCount = _jobs.Count;

// calculate the cleanup delta time - jobs created before this will be cleaned up.
var delta = TimeHelpers.NowInUnixTime() - _cleanupFrequency;
var delta = TimeHelpers.NowInUnixTimestamp() - _cleanupFrequency;

// find expired jobs that were created before our calcualted delta time.
_jobs = _jobs.Where(j => j.Value.CreationTime >= delta || j.Value == Current)
Expand Down
2 changes: 1 addition & 1 deletion src/CoiniumServ/Persistance/Blocks/PersistedBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public PersistedBlock(UInt32 height, String blockhash, Double amount, Int32 conf
Height = height;
BlockHash = blockhash;
Amount = (decimal)amount;
CreatedAt = time.UnixTimeToDateTime();
CreatedAt = time.UnixTimestampToDateTime();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void AddBlock(IShare share)
blockHash = share.BlockHash.ToHexString(),
txHash = share.Block.Tx.First(),
amount = (decimal)share.GenerationTransaction.TotalAmount,
createdAt = share.Block.Time.UnixTimeToDateTime()
createdAt = share.Block.Time.UnixTimestampToDateTime()
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void AddShare(IShare share)
{
var hashrateKey = string.Format("{0}:hashrate", _coin);
var entry = string.Format("{0}:{1}", share.Difficulty, share.Miner.Username);
_redisProvider.Client.ZAdd(hashrateKey, Tuple.Create(TimeHelpers.NowInUnixTime(), entry));
_redisProvider.Client.ZAdd(hashrateKey, Tuple.Create(TimeHelpers.NowInUnixTimestamp(), entry));
}

//_client.EndPipe(); // execute the batch commands.
Expand Down
2 changes: 1 addition & 1 deletion src/CoiniumServ/Pools/Pool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public void Recache()
private void CalculateHashrate()
{
// read hashrate stats.
var windowTime = TimeHelpers.NowInUnixTime() - _configManager.StatisticsConfig.HashrateWindow;
var windowTime = TimeHelpers.NowInUnixTimestamp() - _configManager.StatisticsConfig.HashrateWindow;
_storageLayer.DeleteExpiredHashrateData(windowTime);
var hashrates = _storageLayer.GetHashrateData(windowTime);

Expand Down
2 changes: 1 addition & 1 deletion src/CoiniumServ/Shares/Share.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public Share(IStratumMiner miner, UInt64 jobId, IJob job, string extraNonce2, st
Job = job;
Error = ShareError.None;

var submitTime = TimeHelpers.NowInUnixTime(); // time we recieved the share from miner.
var submitTime = TimeHelpers.NowInUnixTimestamp(); // time we recieved the share from miner.

if (Job == null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/CoiniumServ/Transactions/GenerationTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public GenerationTransaction(IExtraNonce extraNonce, IDaemonClient daemonClient,
new SignatureScript(
blockTemplate.Height,
blockTemplate.CoinBaseAux.Flags,
TimeHelpers.NowInUnixTime(),
TimeHelpers.NowInUnixTimestamp(),
(byte) extraNonce.ExtraNoncePlaceholder.Length,
"/CoiniumServ/")
}
Expand Down
17 changes: 14 additions & 3 deletions src/CoiniumServ/Utils/Helpers/Time/TimeHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,27 @@ namespace CoiniumServ.Utils.Helpers.Time
{
public static class TimeHelpers
{
public static Int32 NowInUnixTime()
public static Int32 NowInUnixTimestamp()
{
return (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
}

public static DateTime UnixTimeToDateTime(this int unixTimeStamp)
public static int ToUnixTimestamp(this DateTime value)
{
return (int)Math.Truncate((value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}


public static int UnixTimestamp(this DateTime value)
{
return (int)Math.Truncate((value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}

public static DateTime UnixTimestampToDateTime(this int unixTimeStamp)
{
// Unix timestamp is seconds past epoch
var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToUniversalTime();
return dtDateTime;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/CoiniumServ/Vardiff/VardiffManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private void OnShare(object sender, EventArgs e)
if (miner == null)
return;

var now = TimeHelpers.NowInUnixTime();
var now = TimeHelpers.NowInUnixTimestamp();

if (miner.VardiffBuffer == null)
{
Expand Down
3 changes: 2 additions & 1 deletion src/CoiniumServ/config/coins/peercoin.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "Peercoin",
"symbol": "PPC",
"algorithm": "sha256"
"algorithm": "sha256",
"reward": "pos"
}

0 comments on commit 658ebbe

Please sign in to comment.