Skip to content

Commit 5d1bdca

Browse files
committed
Add Privora [VORA]
1 parent 7d89256 commit 5d1bdca

File tree

4 files changed

+215
-7
lines changed

4 files changed

+215
-7
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
using System.Globalization;
2+
using System.Text;
3+
using Miningcore.Blockchain.Bitcoin;
4+
using Miningcore.Blockchain.Bitcoin.DaemonResponses;
5+
using Miningcore.Crypto;
6+
using Miningcore.Crypto.Hashing.Progpow;
7+
using Miningcore.Extensions;
8+
using Miningcore.Stratum;
9+
using Miningcore.Time;
10+
using Miningcore.Util;
11+
using NBitcoin;
12+
using NBitcoin.DataEncoders;
13+
using Newtonsoft.Json.Linq;
14+
using NLog;
15+
using Transaction = NBitcoin.Transaction;
16+
17+
namespace Miningcore.Blockchain.Progpow.Custom.Privora;
18+
19+
public class PrivoraJob : ProgpowJob
20+
{
21+
public override (Share Share, string BlockHex) ProcessShareInternal(ILogger logger, StratumConnection worker, ulong nonce, string inputHeaderHash, string mixHash)
22+
{
23+
var context = worker.ContextAs<ProgpowWorkerContext>();
24+
var extraNonce1 = context.ExtraNonce1;
25+
26+
// build coinbase
27+
var coinbase = SerializeCoinbase(extraNonce1);
28+
Span<byte> coinbaseHash = stackalloc byte[32];
29+
coinbaseHasher.Digest(coinbase, coinbaseHash);
30+
31+
// hash block-header
32+
var headerBytes = SerializeHeader(coinbaseHash);
33+
Span<byte> headerHash = stackalloc byte[32];
34+
headerHasher.Digest(headerBytes, headerHash);
35+
headerHash.Reverse();
36+
37+
var headerHashHex = headerHash.ToHexString();
38+
39+
if(headerHashHex != inputHeaderHash)
40+
throw new StratumException(StratumError.MinusOne, $"bad header-hash");
41+
42+
if(!progpowHasher.Compute(logger, (int) BlockTemplate.Height, headerHash.ToArray(), nonce, out var mixHashOut, out var resultBytes))
43+
throw new StratumException(StratumError.MinusOne, "bad hash");
44+
45+
if(mixHash != mixHashOut.ToHexString())
46+
throw new StratumException(StratumError.MinusOne, $"bad mix-hash");
47+
48+
resultBytes.ReverseInPlace();
49+
mixHashOut.ReverseInPlace();
50+
51+
var resultValue = new uint256(resultBytes);
52+
var resultValueBig = resultBytes.AsSpan().ToBigInteger();
53+
54+
// calc share-diff
55+
var shareDiff = (double) new BigRational(FiroConstants.Diff1, resultValueBig) * shareMultiplier;
56+
var stratumDifficulty = context.Difficulty;
57+
var ratio = shareDiff / stratumDifficulty;
58+
59+
// check if the share meets the much harder block difficulty (block candidate)
60+
var isBlockCandidate = resultValue <= blockTargetValue;
61+
62+
// test if share meets at least workers current difficulty
63+
if(!isBlockCandidate && ratio < 0.99)
64+
{
65+
// check if share matched the previous difficulty from before a vardiff retarget
66+
if(context.VarDiff?.LastUpdate != null && context.PreviousDifficulty.HasValue)
67+
{
68+
ratio = shareDiff / context.PreviousDifficulty.Value;
69+
70+
if(ratio < 0.99)
71+
throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
72+
73+
// use previous difficulty
74+
stratumDifficulty = context.PreviousDifficulty.Value;
75+
}
76+
else
77+
{
78+
throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})");
79+
}
80+
}
81+
82+
var result = new Share
83+
{
84+
BlockHeight = BlockTemplate.Height,
85+
NetworkDifficulty = Difficulty,
86+
Difficulty = stratumDifficulty / shareMultiplier,
87+
};
88+
89+
if(!isBlockCandidate)
90+
{
91+
return (result, null);
92+
}
93+
94+
result.IsBlockCandidate = true;
95+
result.BlockHash = resultBytes.ReverseInPlace().ToHexString();
96+
97+
var blockBytes = SerializeBlock(headerBytes, coinbase, nonce, mixHashOut);
98+
var blockHex = blockBytes.ToHexString();
99+
100+
return (result, blockHex);
101+
}
102+
103+
#region Masternodes
104+
105+
protected override Money CreateMasternodeOutputs(Transaction tx, Money reward)
106+
{
107+
if(masterNodeParameters.Masternode != null)
108+
{
109+
Masternode[] masternodes;
110+
111+
// Dash v13 Multi-Master-Nodes
112+
if(masterNodeParameters.Masternode.Type == JTokenType.Array)
113+
masternodes = masterNodeParameters.Masternode.ToObject<Masternode[]>();
114+
else
115+
masternodes = new[] { masterNodeParameters.Masternode.ToObject<Masternode>() };
116+
117+
if(masternodes != null)
118+
{
119+
foreach(var masterNode in masternodes)
120+
{
121+
if(!string.IsNullOrEmpty(masterNode.Payee))
122+
{
123+
var payeeDestination = BitcoinUtils.AddressToDestination(masterNode.Payee, network);
124+
var payeeReward = masterNode.Amount;
125+
126+
tx.Outputs.Add(payeeReward, payeeDestination);
127+
//reward -= payeeReward; // VORA does not deduct payeeReward from coinbasevalue (reward) since it's the amount which goes to miners
128+
}
129+
}
130+
}
131+
}
132+
133+
return reward;
134+
}
135+
136+
#endregion // Masternodes
137+
138+
#region Founder
139+
140+
protected override Money CreateFounderOutputs(Transaction tx, Money reward)
141+
{
142+
if (coin.HasFounderFee)
143+
{
144+
Founder[] founders;
145+
146+
if(network.Name.ToLower() == "testnet")
147+
{
148+
founders = new[] { new Founder{ Payee = "TwnodAoZDovgCPq14Qif3EzeYj7FEF4vqf", Amount = 1000000000 } };
149+
}
150+
else
151+
{
152+
founders = new[] { new Founder{ Payee = "PfadcTvPhr8L9k6jaRbXT1mwgp8U8jXcp1", Amount = 1000000000 } };
153+
}
154+
155+
156+
foreach(var Founder in founders)
157+
{
158+
if(!string.IsNullOrEmpty(Founder.Payee))
159+
{
160+
var payeeAddress = BitcoinUtils.AddressToDestination(Founder.Payee, network);
161+
var payeeReward = Founder.Amount;
162+
tx.Outputs.Add(payeeReward, payeeAddress);
163+
//reward -= payeeReward; // VORA does not deduct payeeReward from coinbasevalue (reward) since it's the amount which goes to miners
164+
}
165+
}
166+
}
167+
168+
return reward;
169+
}
170+
171+
#endregion // Founder
172+
}

src/Miningcore/Blockchain/Progpow/ProgpowJob.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,12 @@ public virtual void Init(BlockTemplate blockTemplate, string jobId,
206206

207207
this.extraNoncePlaceHolderLength = RavencoinConstants.ExtranoncePlaceHolderLength;
208208
this.shareMultiplier = shareMultiplier;
209-
209+
210210
if(coin.HasMasterNodes)
211211
{
212212
masterNodeParameters = BlockTemplate.Extra.SafeExtensionDataAs<MasterNodeBlockTemplateExtra>();
213213

214-
if(coin.Symbol == "FIRO")
214+
if(coin.Symbol == "FIRO" || coin.Symbol == "VORA")
215215
{
216216
if(masterNodeParameters.Extra?.ContainsKey("znode") == true)
217217
{
@@ -226,7 +226,7 @@ public virtual void Init(BlockTemplate blockTemplate, string jobId,
226226
txVersion += txType << 16;
227227
}
228228
}
229-
229+
230230
if(coin.HasPayee)
231231
payeeParameters = BlockTemplate.Extra.SafeExtensionDataAs<PayeeBlockTemplateExtra>();
232232

@@ -249,7 +249,7 @@ public virtual void Init(BlockTemplate blockTemplate, string jobId,
249249
this.headerHasher = headerHasher;
250250
this.blockHasher = blockHasher;
251251
this.progpowHasher = progpowHasher;
252-
252+
253253
if(!string.IsNullOrEmpty(BlockTemplate.Target))
254254
this.blockTargetValue = new uint256(BlockTemplate.Target);
255255
else
@@ -303,4 +303,4 @@ private string CreateHeaderHash(ProgpowWorkerJob workerJob)
303303

304304

305305
#endregion // API-Surface
306-
}
306+
}

src/Miningcore/Blockchain/Progpow/ProgpowJobManager.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Miningcore.Blockchain.Bitcoin.DaemonResponses;
55
using Miningcore.Blockchain.Progpow.Custom.Firo;
66
using Miningcore.Blockchain.Progpow.Custom.Kiiro;
7+
using Miningcore.Blockchain.Progpow.Custom.Privora;
78
using Miningcore.Blockchain.Progpow.Custom.Realichain;
89
using Miningcore.Blockchain.Progpow.Custom.Telestai;
910
using Miningcore.Configuration;
@@ -60,8 +61,11 @@ private ProgpowJob CreateJob()
6061
return new RealichainJob();
6162
case "TLS":
6263
return new TelestaiJob();
64+
case "VORA":
65+
return new PrivoraJob();
66+
6367
}
64-
68+
6569
return new ProgpowJob();
6670
}
6771

@@ -332,4 +336,4 @@ public async ValueTask<Share> SubmitShareAsync(StratumConnection worker, object
332336
}
333337

334338
#endregion // API-Surface
335-
}
339+
}

src/Miningcore/coins.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3050,6 +3050,38 @@
30503050
"explorerTxLink": "https://explorer.phicoin.net/tx/{0}",
30513051
"explorerAccountLink": "https://explorer.phicoin.net/address/{0}"
30523052
},
3053+
"privora": {
3054+
"name": "Privora",
3055+
"symbol": "VORA",
3056+
"family": "progpow",
3057+
"progpower": "firopow",
3058+
"website": "https://privora.org/",
3059+
"github": "https://github.com/PrivoraCore/Privora",
3060+
"market": "",
3061+
"twitter": "",
3062+
"telegram": "https://t.me/PrivoraTM",
3063+
"discord": "https://discord.gg/4AM5SUVzgs",
3064+
"coinbaseHasher": {
3065+
"hash": "sha256d"
3066+
},
3067+
"headerHasher": {
3068+
"hash": "sha256d"
3069+
},
3070+
"blockHasher": {
3071+
"hash": "reverse",
3072+
"args": [
3073+
{
3074+
"hash": "sha256d"
3075+
}
3076+
]
3077+
},
3078+
"hasFounderFee": true,
3079+
"hasMasterNodes": true,
3080+
"shareMultiplier": 1,
3081+
"explorerBlockLink": "https://explorer.privora.org/block/$hash$",
3082+
"explorerTxLink": "https://explorer.privora.org/tx/{0}",
3083+
"explorerAccountLink": "https://explorer.privora.org/address/{0}"
3084+
},
30533085
"telestai": {
30543086
"name": "Telestai",
30553087
"symbol": "TLS",

0 commit comments

Comments
 (0)