diff --git a/Changelog.md b/Changelog.md
index 72a9c2743..219f49c62 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,9 @@
+##### [v0.1.2 alpha - Piri Reis](https://github.com/CoiniumServ/CoiniumServ/releases/tag/v0.1.2-alpha) - 14.08.2014
+
+**Payments**
+* Fixed a major bug in payment processor which was preventing payments to miners.
+* Fixed a bug in statistics manager.
+
##### [v0.1.1 alpha - Piri Reis](https://github.com/CoiniumServ/CoiniumServ/releases/tag/v0.1.1-alpha) - 10.08.2014
**Mining**
* Improved SocketServiceContext and removed unnecessary overhead.
diff --git a/README.md b/README.md
index 1294543ad..4b12762db 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ You can send tips and furher support the project or get tips for contributing by
### Status
-Expect a functioning alpha soon.
+[v0.1.2 alpha](https://github.com/CoiniumServ/CoiniumServ/releases/tag/v0.1.2-alpha) released
### Features
diff --git a/src/CoiniumServ/Blocks/BlockProcessor.cs b/src/CoiniumServ/Blocks/BlockProcessor.cs
index 05254b0ee..9967f233d 100644
--- a/src/CoiniumServ/Blocks/BlockProcessor.cs
+++ b/src/CoiniumServ/Blocks/BlockProcessor.cs
@@ -75,19 +75,11 @@ public Block GetBlock(string blockHash)
}
}
- public TransactionDetail GetPoolOutput(Block block)
+ public Transaction GetGenerationTransaction(Block block)
{
try
{
- var genTx = _daemonClient.GetTransaction(block.Tx.First()); // query the transaction
-
- if (genTx == null) // make sure the generation transaction exists
- return null;
-
- // check if coin includes output address data in transaction details.
- return genTx.Details.Any(x => x.Address == null)
- ? genTx.Details.FirstOrDefault(x => x.Account == _poolAccount) // some coins doesn't include address field in outputs, so try to determine using the associated account name.
- : genTx.Details.FirstOrDefault(x => x.Address == _poolConfig.Wallet.Adress); // if coin includes address field in outputs, just use it.
+ return _daemonClient.GetTransaction(block.Tx.First()); // query the transaction
}
catch (RpcException e)
{
@@ -95,5 +87,10 @@ public TransactionDetail GetPoolOutput(Block block)
return null;
}
}
+
+ public TransactionDetail GetPoolOutput(Transaction transaction)
+ {
+ return transaction.GetPoolOutput(_poolConfig.Wallet.Adress, _poolAccount);
+ }
}
}
diff --git a/src/CoiniumServ/Blocks/IBlockProcessor.cs b/src/CoiniumServ/Blocks/IBlockProcessor.cs
index 0620a6642..fdd8a308d 100644
--- a/src/CoiniumServ/Blocks/IBlockProcessor.cs
+++ b/src/CoiniumServ/Blocks/IBlockProcessor.cs
@@ -29,6 +29,8 @@ public interface IBlockProcessor
{
Block GetBlock(string blockHash);
- TransactionDetail GetPoolOutput(Block block);
+ Transaction GetGenerationTransaction(Block block);
+
+ TransactionDetail GetPoolOutput(Transaction transaction);
}
}
diff --git a/src/CoiniumServ/Daemon/Responses/Transaction.cs b/src/CoiniumServ/Daemon/Responses/Transaction.cs
index b69d200d7..3ad8705b5 100644
--- a/src/CoiniumServ/Daemon/Responses/Transaction.cs
+++ b/src/CoiniumServ/Daemon/Responses/Transaction.cs
@@ -22,12 +22,19 @@
#endregion
using System.Collections.Generic;
+using System.Linq;
namespace CoiniumServ.Daemon.Responses
{
public class Transaction
{
- public double Amount { get; set; }
+ public double Amount { get; set; } // seems it's set to 0 for immature transactions or generation transactions.
+
+ ///
+ /// As Amount may not always return the total transaction amount, TotalAmount calculates and return the value using transaction details
+ ///
+ public double TotalAmount { get { return Details.Sum(item => item.Amount); } }
+
public int Confirmations { get; set; }
public bool Generated { get; set; }
@@ -46,7 +53,22 @@ public class Transaction
public int TimeReceived { get; set; }
public List Details { get; set; }
-
+
+
+ ///
+ /// Returns the transaction detail that contains the output for pool.
+ ///
+ ///
+ ///
+ ///
+ public TransactionDetail GetPoolOutput(string poolAddress, string poolAccount)
+ {
+ // 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.
+ }
+
// not sure if fields below even exists / used
//public double Fee { get; set; }
//public string Comment { get; set; }
diff --git a/src/CoiniumServ/Payments/PaymentProcessor.cs b/src/CoiniumServ/Payments/PaymentProcessor.cs
index c39109772..a6692ca73 100644
--- a/src/CoiniumServ/Payments/PaymentProcessor.cs
+++ b/src/CoiniumServ/Payments/PaymentProcessor.cs
@@ -143,6 +143,9 @@ private IList CalculateRewards(IEnumerable rounds
// set previous balances
foreach(var pair in previousBalances)
{
+ if (pair.Value == 0) // skip zero balances
+ continue;
+
if (!workerBalances.ContainsKey(pair.Key))
workerBalances.Add(pair.Key, new WorkerBalance(pair.Key, _magnitude));
@@ -284,8 +287,10 @@ private void QueryBlock(ref IPersistedBlock block)
return;
}
+ var genTx = _blockProcessor.GetGenerationTransaction(blockInfo); // get the generation transaction.
+
// get the output transaction that targets pools central wallet.
- var poolOutput = _blockProcessor.GetPoolOutput(blockInfo);
+ var poolOutput = _blockProcessor.GetPoolOutput(genTx);
// make sure we have a valid reference to poolOutput
if (poolOutput == null)
@@ -294,6 +299,8 @@ private void QueryBlock(ref IPersistedBlock block)
return;
}
+ block.SetReward((decimal)poolOutput.Amount); // set the reward of the block to miners.
+
switch (poolOutput.Category)
{
case "immature":
@@ -307,6 +314,7 @@ private void QueryBlock(ref IPersistedBlock block)
break;
}
+
// TODO: add back these.
// total amount of coins contained in the block.
// candidate.Amount = transaction.Details.Sum(output => (decimal)output.Amount);
diff --git a/src/CoiniumServ/Persistance/Blocks/IPersistedBlock.cs b/src/CoiniumServ/Persistance/Blocks/IPersistedBlock.cs
index 7baf2c469..994357d76 100644
--- a/src/CoiniumServ/Persistance/Blocks/IPersistedBlock.cs
+++ b/src/CoiniumServ/Persistance/Blocks/IPersistedBlock.cs
@@ -31,9 +31,10 @@ public interface IPersistedBlock
BlockStatus Status { get; set; }
string BlockHash { get; }
string TransactionHash { get; }
- decimal Reward { get; }
decimal Amount { get; }
-
+ decimal Reward { get; }
bool IsPending { get; }
+
+ void SetReward(decimal reward);
}
}
diff --git a/src/CoiniumServ/Persistance/Blocks/PersistedBlock.cs b/src/CoiniumServ/Persistance/Blocks/PersistedBlock.cs
index 076616d7c..26ff34b1c 100644
--- a/src/CoiniumServ/Persistance/Blocks/PersistedBlock.cs
+++ b/src/CoiniumServ/Persistance/Blocks/PersistedBlock.cs
@@ -36,19 +36,23 @@ public class PersistedBlock:IPersistedBlock
public string TransactionHash { get; private set; }
- public decimal Reward { get; private set; }
-
public decimal Amount { get; private set; }
+ public decimal Reward { get; private set; }
+
public bool IsPending { get { return Status != BlockStatus.Orphaned && Status != BlockStatus.Confirmed; } }
- public PersistedBlock(BlockStatus status, uint height, string blockHash, string transactionHash, decimal amount, decimal reward)
+ public PersistedBlock(BlockStatus status, uint height, string blockHash, string transactionHash, decimal amount)
{
Status = status;
Height = height;
BlockHash = blockHash;
TransactionHash = transactionHash;
Amount = amount;
+ }
+
+ public void SetReward(decimal reward)
+ {
Reward = reward;
}
}
diff --git a/src/CoiniumServ/Persistance/Redis/Redis.cs b/src/CoiniumServ/Persistance/Redis/Redis.cs
index 44d875766..cefa4beac 100644
--- a/src/CoiniumServ/Persistance/Redis/Redis.cs
+++ b/src/CoiniumServ/Persistance/Redis/Redis.cs
@@ -119,7 +119,8 @@ public void AddBlock(IShare share)
// add block to pending.
var pendingKey = string.Format("{0}:blocks:pending", _coin);
- var entry = string.Format("{0}:{1}", share.BlockHash.ToHexString(), share.Block.Tx.First());
+ // entry format: blockHash:txHash:Amount
+ var entry = string.Format("{0}:{1}:{2}", share.BlockHash.ToHexString(), share.Block.Tx.First(), share.GenerationTransaction.TotalAmount);
_client.ZAdd(pendingKey, Tuple.Create(share.Block.Height, entry));
}
@@ -364,8 +365,9 @@ public IEnumerable GetBlocks(BlockStatus status)
var data = item.Split(':');
var blockHash = data[0];
var transactionHash = data[1];
+ var amount = decimal.Parse(data[2]);
- blocks.Add((UInt32) score, new PersistedBlock(status, (UInt32) score, blockHash, transactionHash, 0, 0));
+ blocks.Add((UInt32)score, new PersistedBlock(status, (UInt32)score, blockHash, transactionHash, amount));
}
}
catch (Exception e)
diff --git a/src/CoiniumServ/Shares/IShare.cs b/src/CoiniumServ/Shares/IShare.cs
index aa1da2066..e61dca2b8 100644
--- a/src/CoiniumServ/Shares/IShare.cs
+++ b/src/CoiniumServ/Shares/IShare.cs
@@ -43,6 +43,8 @@ public interface IShare
Block Block { get; }
+ Transaction GenerationTransaction { get; }
+
///
/// Is the block data accepted by the coin daemon?
///
@@ -89,6 +91,6 @@ public interface IShare
byte[] BlockHash { get; }
- void SetFoundBlock(Block block);
+ void SetFoundBlock(Block block, Transaction genTx);
}
}
diff --git a/src/CoiniumServ/Shares/Share.cs b/src/CoiniumServ/Shares/Share.cs
index 07484b7e1..a2472a1a4 100644
--- a/src/CoiniumServ/Shares/Share.cs
+++ b/src/CoiniumServ/Shares/Share.cs
@@ -41,6 +41,7 @@ public class Share : IShare
public bool IsValid { get { return Error == ShareError.None; } }
public bool IsBlockCandidate { get; private set; }
public Block Block { get; private set; }
+ public Transaction GenerationTransaction { get; private set; }
public bool IsBlockAccepted { get { return Block != null; } }
public IMiner Miner { get; private set; }
public ShareError Error { get; private set; }
@@ -163,9 +164,10 @@ public Share(IStratumMiner miner, UInt64 jobId, IJob job, string extraNonce2, st
}
}
- public void SetFoundBlock(Block block)
+ public void SetFoundBlock(Block block, Transaction genTx)
{
Block = block;
+ GenerationTransaction = genTx;
}
}
}
diff --git a/src/CoiniumServ/Shares/ShareManager.cs b/src/CoiniumServ/Shares/ShareManager.cs
index b8d231e21..89194f952 100644
--- a/src/CoiniumServ/Shares/ShareManager.cs
+++ b/src/CoiniumServ/Shares/ShareManager.cs
@@ -201,7 +201,9 @@ private bool SubmitBlock(IShare share)
return false;
}
- var poolOutput = _blockProcessor.GetPoolOutput(block); // get the output that targets pool's central address.
+ var genTx = _blockProcessor.GetGenerationTransaction(block); // get the generation transaction.
+
+ var poolOutput = _blockProcessor.GetPoolOutput(genTx); // get the output that targets pool's central address.
// make sure the blocks generation transaction contains our central pool wallet address
if (poolOutput == null)
@@ -211,7 +213,7 @@ private bool SubmitBlock(IShare share)
}
// if the code flows here, then it means the block was succesfully submitted and belongs to us.
- share.SetFoundBlock(block); // assign the block to share.
+ share.SetFoundBlock(block, genTx); // assign the block to share.
return true;
}
diff --git a/src/CoiniumServ/Statistics/PerPool.cs b/src/CoiniumServ/Statistics/PerPool.cs
index 4cb15359a..b696a816f 100644
--- a/src/CoiniumServ/Statistics/PerPool.cs
+++ b/src/CoiniumServ/Statistics/PerPool.cs
@@ -129,6 +129,9 @@ private void RecacheWorkers()
foreach (var miner in _minerManager.Miners)
{
+ if (!miner.Authenticated)
+ continue;
+
Workers.Add(miner.Username, shares.ContainsKey(miner.Username) ? shares[miner.Username] : 0);
}
diff --git a/src/CoiniumServ/Utils/Versions/VersionInfo.cs b/src/CoiniumServ/Utils/Versions/VersionInfo.cs
index 7f89ec287..ca927ae4f 100644
--- a/src/CoiniumServ/Utils/Versions/VersionInfo.cs
+++ b/src/CoiniumServ/Utils/Versions/VersionInfo.cs
@@ -41,7 +41,7 @@ public static class Assembly
///
/// Main assemby version.
///
- public const string Version = "0.1.1.*";
+ public const string Version = "0.1.2.*";
}
}
}
diff --git a/src/CoiniumServ/web/default/pool.cshtml b/src/CoiniumServ/web/default/pool.cshtml
index 14076fa0d..cd259f45b 100644
--- a/src/CoiniumServ/web/default/pool.cshtml
+++ b/src/CoiniumServ/web/default/pool.cshtml
@@ -98,13 +98,13 @@
@switch (block.Status)
{
case BlockStatus.Pending:
- @block.Status
+ @block.Status
break;
case BlockStatus.Orphaned:
- @block.Status
+ @block.Status
break;
case BlockStatus.Confirmed:
- @block.Status
+ @block.Status
break;
}