public static CheckStakeResult CheckStakeKernelHash(MintTemplate template, uint txTime, ulong stakeModifier, uint stakeMinAge) { var retobj = new CheckStakeResult { Id = template.Id, OfAddress = template.OfAddress, StakeModifier = stakeModifier, BlockFromTime = template.BlockFromTime, PrevTxOffset = template.PrevTxOffset, PrevTxTime = template.PrevTxTime, PrevTxOutIndex = template.PrevTxOutIndex, FutureTimestamp = txTime, }; if (txTime < template.PrevTxTime) { // Transaction timestamp violation return(retobj); } if (template.BlockFromTime + stakeMinAge > txTime) { // Min age requirement return(retobj); } var bnTargetPerCoinDay = Mint.CompactToBig(template.Bits !.Value); long nTimeWeight = txTime - template.PrevTxTime; if (nTimeWeight > PeercoinConstants.StakeMaxAge) { nTimeWeight = PeercoinConstants.StakeMaxAge; } long timeReduction = stakeMinAge; nTimeWeight -= timeReduction; var t1 = new BigInteger(24 * 60 * 60); var t2 = new BigInteger(PeercoinConstants.Coin); var t3 = new BigInteger(template.PrevTxOutValue); var t4 = new BigInteger(nTimeWeight); BigInteger bnCoinDayWeight = (((t3 * t4) / t2)) / t1; BigInteger targetInt = bnCoinDayWeight * (bnTargetPerCoinDay); //byte[] array = new byte[28]; var buffer = new byte[28]; var bufferindex = 0; byte[] arrStakemodifier = BitConverter.GetBytes(stakeModifier); //put stakemodifier in buffer for (var i = 0; i < 8; i++) { buffer[bufferindex] = arrStakemodifier[i]; bufferindex++; } new List <uint> { (uint)template.BlockFromTime, (uint)template.PrevTxOffset, (uint)template.PrevTxTime, (uint)template.PrevTxOutIndex, (uint)txTime } .ForEach(num => { var dn = num; for (var i = 0; i < 4; i++) { buffer[bufferindex] = (byte)(dn & 0xff); dn >>= 8; bufferindex++; } }); //no reverse so keep it in little endian var hashProofOfStake = Mint.DoubleSha256(buffer.ToList()).ToArray(); //keep it in little-endian .Reverse().ToArray(); //add zero to last in array to make it unsigned: // https://docs.microsoft.com/en-us/dotnet/api/system.numerics.biginteger.-ctor?view=netframework-4.5.2#System_Numerics_BigInteger__ctor_System_Byte___ var lastindex = hashProofOfStake.Length - 1; if ((hashProofOfStake[lastindex] & 0x80) > 0) { byte[] temp = new byte[hashProofOfStake.Length]; Array.Copy(hashProofOfStake, temp, hashProofOfStake.Length); hashProofOfStake = new byte[temp.Length + 1]; Array.Copy(temp, hashProofOfStake, temp.Length); } var hashProofOfStakeInt = new BigInteger(hashProofOfStake); if (hashProofOfStakeInt > targetInt) { return(retobj); } //yeah, below target! retobj.minTarget = (hashProofOfStakeInt / bnCoinDayWeight) - new BigInteger(1); retobj.success = true; retobj.hash = hashProofOfStake; retobj.Id = template.Id; var comp = Mint.IncCompact( Mint.BigToCompact(retobj.minTarget) ); retobj.minimumDifficulty = Mint.CompactToDiff(comp); return(retobj); }
public static async Task FindStakes(BlockChainParser parser, List <UnspentTransactionData> unspents) { foreach (var unspent in unspents) { unspent.blockhash = await parser.GetBlockHash(unspent.txid); unspent.blockheight = await parser.Parse(unspent.blockhash); await parser.Parse(unspent.blockhash); var block = _blockRepository !.GetBlockState(unspent.blockheight); unspent.blocktime = block !.bt; var output = _transactionRepository !.GetOutput(unspent.txid, unspent.vout); unspent.units = output !.units; } // set negative if expecting a slight increase in POS diff in future: var minMarginDifficulty = -0.35f; var templates = new List <MintTemplate>(); var addresses = unspents.Select(un => un.address) .Distinct() .ToList(); foreach (var address in addresses) { var unspentsbyaddress = _transactionRepository !.GetUnspents(address) .Where(unspent => unspents.Any(u => u.txid == unspent.Id !.Substring(2, 64) && u.vout.ToString() == unspent.Id.Substring(67))) .ToList(); unspentsbyaddress.ForEach(unspent => { var mintTemplate = new MintTemplate( unspent.Id, address, unspent.BlockFromTime, unspent.PrevTxOffset, unspent.PrevTxTime, unspent.PrevTxOutIndex, unspent.PrevTxOutValue); mintTemplate.SetBitsWithDifficulty(((Convert.ToSingle(PosDifficulty) - minMarginDifficulty))); if (templates.All(t => t.Id != mintTemplate.Id)) { templates.Add(mintTemplate); } }); } //load modifiers: // start with a block way back assuming there are 6 blocks in an hour: // see also: consensus.nStakeTargetSpacing = 10 * 60; // 10-minute block spacing var start = BlockHeight - (6 * 24 * 31) - 10; var end = BlockHeight; for (var i = start; i < end; i++) { await parser.Parse(i); } var futurestakes = await StartSearch(templates); ExitWithJson(null, futurestakes); }