diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000..dc90e5a1 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security +# Label to use when marking an issue as stale +staleLabel: wontfix +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/README.md b/README.md index 53f91749..f867e5fa 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ $ sudo apt-get update -y $ sudo apt-get -y install dotnet-sdk-2.2 git cmake build-essential libssl-dev pkg-config libboost-all-dev libsodium-dev libzmq5 $ git clone https://github.com/coinfoundry/miningcore $ cd miningcore/src/Miningcore -$ dotnet publish -c Release --framework netcoreapp2.2 -o ../../build +$ dotnet publish -c Release --framework netcoreapp3.1 -o ../../build ``` #### Building on Windows @@ -145,7 +145,7 @@ Download and install the [.Net Core 2.2 SDK](https://www.microsoft.com/net/downl ```dosbatch > git clone https://github.com/coinfoundry/miningcore > cd miningcore/src/Miningcore -> dotnet publish -c Release --framework netcoreapp2.2 -o ..\..\build +> dotnet publish -c Release --framework netcoreapp3.1 -o ..\..\build ``` #### Building on Windows - Visual Studio diff --git a/appveyor.yml b/appveyor.yml index 4edf8831..e414a726 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ # Build worker image (VM template) image: -- Visual Studio 2017 +- Visual Studio 2019 - Ubuntu #---------------------------------# @@ -21,13 +21,13 @@ build_script: - sh: sudo apt-get update -y && sudo apt-get -y install cmake build-essential libssl-dev pkg-config libboost-all-dev libsodium-dev libzmq5 - # Publish - cd Miningcore - - dotnet publish -c Release --framework netcoreapp2.2 + - dotnet publish -c Release --framework netcoreapp3.1 - # Publish Artifacts - - sh: (cd bin/Release/netcoreapp2.2 && mkdir miningcore && cp -r publish/* miningcore && tar cf miningcore-linux-ubuntu-x64.tar.gz miningcore && appveyor PushArtifact miningcore-linux-ubuntu-x64.tar.gz) - - cmd: cd bin\Release\netcoreapp2.2 && mkdir miningcore && xcopy publish\* miningcore /S && 7z a miningcore-win-x64.zip miningcore && appveyor PushArtifact miningcore-win-x64.zip && cd ..\..\.. + - sh: (cd bin/Release/netcoreapp3.1 && mkdir miningcore && cp -r publish/* miningcore && tar cf miningcore-linux-ubuntu-x64.tar.gz miningcore && appveyor PushArtifact miningcore-linux-ubuntu-x64.tar.gz) + - cmd: cd bin\Release\netcoreapp3.1 && mkdir miningcore && xcopy publish\* miningcore /S && 7z a miningcore-win-x64.zip miningcore && appveyor PushArtifact miningcore-win-x64.zip && cd ..\..\.. - # Build Tests - cd ../Miningcore.Tests - - dotnet build -c Release --framework netcoreapp2.2 + - dotnet build -c Release --framework netcoreapp3.1 #---------------------------------# # tests configuration # diff --git a/src/Miningcore.Tests/Miningcore.Tests.csproj b/src/Miningcore.Tests/Miningcore.Tests.csproj index 2ea5169a..8977ebbd 100644 --- a/src/Miningcore.Tests/Miningcore.Tests.csproj +++ b/src/Miningcore.Tests/Miningcore.Tests.csproj @@ -10,7 +10,7 @@ - netcoreapp2.2 + netcoreapp3.1 false AnyCPU Miningcore.Tests @@ -35,7 +35,7 @@ - + all @@ -56,7 +56,7 @@ - + @@ -65,7 +65,7 @@ - + diff --git a/src/Miningcore/Api/Controllers/PoolApiController.cs b/src/Miningcore/Api/Controllers/PoolApiController.cs index 8dca3454..3d384b93 100644 --- a/src/Miningcore/Api/Controllers/PoolApiController.cs +++ b/src/Miningcore/Api/Controllers/PoolApiController.cs @@ -160,28 +160,37 @@ public async Task PagePoolMinersAsync( con, pool.Id, start, page, pageSize))) .Select(mapper.Map) .ToArray(); - + Response.Headers.Add("x-total-count",miners.Length.ToString()); return miners; } [HttpGet("{poolId}/blocks")] public async Task PagePoolBlocksPagedAsync( - string poolId, [FromQuery] int page, [FromQuery] int pageSize = 15, [FromQuery] BlockStatus[] state = null) + string poolId, [FromQuery] int page, [FromQuery] int _start ,[FromQuery] int _end ,[FromQuery] String _order ,[FromQuery] String _sort,[FromQuery] int perPage = 0,[FromQuery] int pageSize = 15, [FromQuery] BlockStatus[] state = null) { + //http://192.168.2.2:4000/api/pools/indexchain/blocks?_end=10&_order=ASC&_sort=id&_start=0 var pool = GetPool(poolId); + if(perPage != 0){ + pageSize = perPage; + } + bool shouldlimitbyid = _end > 0; var blockStates = state != null && state.Length > 0 ? state : new[] { BlockStatus.Confirmed, BlockStatus.Pending, BlockStatus.Orphaned }; - var blocks = (await cf.Run(con => blocksRepo.PageBlocksAsync(con, pool.Id, blockStates, page, pageSize))) + var blocks = shouldlimitbyid ? (await cf.Run(con => blocksRepo.PageBlocksAsyncPaged(con, pool.Id, blockStates, page, pageSize,_start,_end,_order,_sort))) + .Select(mapper.Map) + .ToArray():(await cf.Run(con => blocksRepo.PageBlocksAsync(con, pool.Id, blockStates, page, pageSize))) .Select(mapper.Map) .ToArray(); - + var totalcount = (await cf.Run(con => blocksRepo.PageBlocksAsync(con, pool.Id, blockStates, page, 100000000))) + .Select(mapper.Map) + .ToArray().Length; // enrich blocks var blockInfobaseDict = pool.Template.ExplorerBlockLinks; - - foreach(var block in blocks) + if (_start == 0 && _end < _start) + foreach(var block in blocks) { // compute infoLink if(blockInfobaseDict != null) @@ -197,6 +206,8 @@ public async Task PagePoolMinersAsync( } } } + + Response.Headers.Add("x-total-count",totalcount.ToString()); return blocks; } @@ -226,6 +237,7 @@ public async Task PagePoolMinersAsync( if(!string.IsNullOrEmpty(addressInfobaseUrl)) payment.AddressInfoLink = string.Format(addressInfobaseUrl, payment.Address); } + Response.Headers.Add("x-total-count",payments.Length.ToString()); return payments; } @@ -294,6 +306,7 @@ public async Task PagePoolMinersAsync( if(!string.IsNullOrEmpty(addressInfobaseUrl)) payment.AddressInfoLink = string.Format(addressInfobaseUrl, payment.Address); } + Response.Headers.Add("x-total-count",payments.Length.ToString()); return payments; } @@ -311,6 +324,7 @@ public async Task PagePoolMinersAsync( con, pool.Id, address, page, pageSize))) .Select(mapper.Map) .ToArray(); + Response.Headers.Add("x-total-count",balanceChanges.Length.ToString()); return balanceChanges; } @@ -327,6 +341,7 @@ public async Task PageMinerEarningsByDayAsync( var earnings = (await cf.Run(con => paymentsRepo.PageMinerPaymentsByDayAsync( con, pool.Id, address, page, pageSize))) .ToArray(); + Response.Headers.Add("x-total-count",earnings.Length.ToString()); return earnings; } @@ -341,6 +356,7 @@ public async Task PageMinerEarningsByDayAsync( throw new ApiException($"Invalid or missing miner address", HttpStatusCode.NotFound); var result = await GetMinerPerformanceInternal(mode, pool, address); + Response.Headers.Add("x-total-count",result.Length.ToString()); return result; } diff --git a/src/Miningcore/Api/Responses/GetBlocksResponse.cs b/src/Miningcore/Api/Responses/GetBlocksResponse.cs index aee3cd04..fbd00594 100644 --- a/src/Miningcore/Api/Responses/GetBlocksResponse.cs +++ b/src/Miningcore/Api/Responses/GetBlocksResponse.cs @@ -24,6 +24,7 @@ namespace Miningcore.Api.Responses { public class Block { + public long Id { get; set; } public string PoolId { get; set; } public ulong BlockHeight { get; set; } public double NetworkDifficulty { get; set; } diff --git a/src/Miningcore/Api/Responses/GetMinerStatsResponse.cs b/src/Miningcore/Api/Responses/GetMinerStatsResponse.cs index b459d311..2464145b 100644 --- a/src/Miningcore/Api/Responses/GetMinerStatsResponse.cs +++ b/src/Miningcore/Api/Responses/GetMinerStatsResponse.cs @@ -25,6 +25,7 @@ namespace Miningcore.Api.Responses { public class MinerPerformanceStats { + public long Id { get; set; } public string Miner { get; set; } public double Hashrate { get; set; } public double SharesPerSecond { get; set; } diff --git a/src/Miningcore/Api/Responses/GetPaymentsResponse.cs b/src/Miningcore/Api/Responses/GetPaymentsResponse.cs index 459c43f3..f18035bf 100644 --- a/src/Miningcore/Api/Responses/GetPaymentsResponse.cs +++ b/src/Miningcore/Api/Responses/GetPaymentsResponse.cs @@ -25,6 +25,7 @@ namespace Miningcore.Api.Responses { public class Payment { + public long Id { get; set; } public string Coin { get; set; } public string Address { get; set; } public string AddressInfoLink { get; set; } diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs index c7c55330..cf345e8f 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinConstants.cs @@ -35,6 +35,11 @@ public enum BitcoinAddressType /// Bech encoded, segwit /// BechSegwit, + /// + /// Bcash custom bech encoded + /// + CashAddr, + } public enum BitcoinTransactionCategory @@ -70,8 +75,9 @@ public class BitcoinConstants public const int ExtranoncePlaceHolderLength = 8; public const decimal SatoshisPerBitcoin = 100000000; public static double Pow2x32 = Math.Pow(2, 32); + public static double Pow2x42 = Math.Pow(2, 42); public static readonly BigInteger Diff1 = BigInteger.Parse("00ffff0000000000000000000000000000000000000000000000000000", NumberStyles.HexNumber); - public const int CoinbaseMinConfimations = 102; + public const int CoinbaseMinConfimations = 101; /// /// Pool-side mask for version-rolling (Overt ASIC-Boost) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs index 68651db4..e8871e3d 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJob.cs @@ -37,7 +37,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using Newtonsoft.Json.Linq; using Contract = Miningcore.Contracts.Contract; using Transaction = NBitcoin.Transaction; - +using Miningcore.Crypto.Hashing.Algorithms; namespace Miningcore.Blockchain.Bitcoin { public class BitcoinJob @@ -57,7 +57,7 @@ public class BitcoinJob protected PoolConfig poolConfig; protected BitcoinTemplate coin; private BitcoinTemplate.BitcoinNetworkParams networkParams; - protected readonly HashSet submissions = new HashSet(); + protected readonly HashSet submissions = new HashSet(StringComparer.OrdinalIgnoreCase); protected uint256 blockTargetValue; protected byte[] coinbaseFinal; protected string coinbaseFinalHex; @@ -112,10 +112,11 @@ protected virtual void BuildCoinbase() scriptSigFinalBytes.Length); // output transaction - txOut = coin.HasMasterNodes ? - CreateMasternodeOutputTransaction() : - (coin.HasPayee ? CreatePayeeOutputTransaction() : CreateOutputTransaction()); - + txOut = coin.HasMasterNodes ? CreateMasternodeOutputTransaction() : (coin.HasPayee ? CreatePayeeOutputTransaction() : CreateOutputTransaction()); + if(coin.HasCoinbasePayload){ + //Build txOut with superblock and cold reward payees for DVT + txOut = CreatePayloadOutputTransaction(); + } // build coinbase initial using(var stream = new MemoryStream()) { @@ -124,7 +125,7 @@ protected virtual void BuildCoinbase() // version bs.ReadWrite(ref txVersion); - // timestamp for POS coins + // // timestamp for POS coins if(isPoS) { var timestamp = BlockTemplate.CurTime; @@ -348,6 +349,7 @@ protected virtual (Share Share, string BlockHex) ProcessShareInternal( // hash block-header var headerBytes = SerializeHeader(coinbaseHash, nTime, nonce, context.VersionRollingMask, versionBits); Span headerHash = stackalloc byte[32]; + headerHasher.Digest(headerBytes, headerHash, (ulong) nTime, BlockTemplate, coin, networkParams); var headerValue = new uint256(headerHash); @@ -368,7 +370,7 @@ protected virtual (Share Share, string BlockHex) ProcessShareInternal( ratio = shareDiff / context.PreviousDifficulty.Value; if(ratio < 0.99) - throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share ({shareDiff})"); + throw new StratumException(StratumError.LowDifficultyShare, $"low difficulty share given ({shareDiff})"); // use previous difficulty stratumDifficulty = context.PreviousDifficulty.Value; @@ -432,7 +434,7 @@ protected virtual byte[] SerializeBlock(byte[] header, byte[] coinbase) bs.ReadWrite(ref coinbase); bs.ReadWrite(ref rawTransactionBuffer); - // POS coins require a zero byte appended to block which the daemon replaces with the signature + // // POS coins require a zero byte appended to block which the daemon replaces with the signature if(isPoS) bs.ReadWrite((byte) 0); @@ -492,10 +494,10 @@ protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) { var payeeAddress = BitcoinUtils.AddressToDestination(masterNode.Payee, network); var payeeReward = masterNode.Amount; - - reward -= payeeReward; - rewardToPool -= payeeReward; - + if(!(poolConfig.Template.Symbol == "IDX" ||poolConfig.Template.Symbol == "XZC")){ + reward -= payeeReward; + rewardToPool -= payeeReward; + } tx.Outputs.Add(payeeReward, payeeAddress); } } @@ -518,10 +520,11 @@ protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) if(!string.IsNullOrEmpty(masterNodeParameters.Payee)) { var payeeAddress = BitcoinUtils.AddressToDestination(masterNodeParameters.Payee, network); - var payeeReward = masterNodeParameters.PayeeAmount ?? (reward / 5); - + var payeeReward = masterNodeParameters.PayeeAmount; + if(!(poolConfig.Template.Symbol == "IDX" ||poolConfig.Template.Symbol == "XZC")){ reward -= payeeReward; rewardToPool -= payeeReward; + } tx.Outputs.Add(payeeReward, payeeAddress); } @@ -531,6 +534,56 @@ protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) #endregion // Masternodes + #region DevaultCoinbasePayload + + protected CoinbasePayloadBlockTemplateExtra coinbasepayloadParameters; + + protected virtual Transaction CreatePayloadOutputTransaction() + { + var blockReward = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); + rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); + + var tx = Transaction.Create(network); + + // outputs + rewardToPool = CreatePayloadOutputs(tx, blockReward); + + // Finally distribute remaining funds to pool + tx.Outputs.Insert(0, new TxOut(rewardToPool, poolAddressDestination)); + + return tx; + } + + protected virtual Money CreatePayloadOutputs(Transaction tx, Money reward) + { + if(coinbasepayloadParameters.CoinbasePayload != null) + { + CoinbasePayload[] coinbasepayloads; + if(coinbasepayloadParameters.CoinbasePayload.Type == JTokenType.Array) + coinbasepayloads = coinbasepayloadParameters.CoinbasePayload.ToObject(); + else + coinbasepayloads = new[] { coinbasepayloadParameters.CoinbasePayload.ToObject() }; + + foreach(var CoinbasePayee in coinbasepayloads) + { + if(!string.IsNullOrEmpty(CoinbasePayee.Payee)) + { + var payeeAddress = BitcoinUtils.CashAddrToDestination(CoinbasePayee.Payee, network); + var payeeReward = CoinbasePayee.Amount; + + reward -= payeeReward; + rewardToPool -= payeeReward; + + tx.Outputs.Add(payeeReward, payeeAddress); + } + } + } + + return reward; + } + + #endregion // DevaultCoinbasePayload + #region API-Surface public BlockTemplate BlockTemplate { get; protected set; } @@ -583,6 +636,12 @@ public void Init(BlockTemplate blockTemplate, string jobId, txVersion = txVersion + ((uint) (txType << 16)); } } + if(coin.HasCoinbasePayload){ + + coinbasepayloadParameters = BlockTemplate.Extra.SafeExtensionDataAs(); + + + } if(coin.HasPayee) payeeParameters = BlockTemplate.Extra.SafeExtensionDataAs(); diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManager.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManager.cs index 49825f69..4019b09d 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManager.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManager.cs @@ -120,9 +120,9 @@ await GetBlockTemplateAsync() : job = CreateJob(); job.Init(blockTemplate, NextJobId(), - poolConfig, extraPoolConfig, clusterConfig, clock, poolAddressDestination, network, isPoS, + poolConfig, extraPoolConfig, clusterConfig, clock, poolAddressDestination, network, false, ShareMultiplier, coin.CoinbaseHasherValue, coin.HeaderHasherValue, - !isPoS ? coin.BlockHasherValue : coin.PoSBlockHasherValue ?? coin.BlockHasherValue); + coin.BlockHasherValue); lock(jobLock) { diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs index b5d5ed46..50ba6585 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinJobManagerBase.cs @@ -500,11 +500,11 @@ protected override async Task PostStartInitAsync(CancellationToken ct) isPoS = difficultyResponse.Values().Any(x => x.Path == "proof-of-stake"); - // Create pool address script from response - if(!isPoS) - poolAddressDestination = AddressToDestination(poolConfig.Address, extraPoolConfig?.AddressType); - else - poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); + // // Create pool address script from response + //if(!isPoS) + poolAddressDestination = AddressToDestination(poolConfig.Address, (poolConfig.Template.Symbol == "DVT" || poolConfig.Template.Symbol == "BCHABC" || poolConfig.Template.Symbol == "BCH" ) ? BitcoinAddressType.CashAddr : extraPoolConfig?.AddressType); + // else + // poolAddressDestination = new PubKey(poolConfig.PubKey ?? validateAddressResponse.PubKey); // Payment-processing setup if(clusterConfig.PaymentProcessing?.Enabled == true && poolConfig.PaymentProcessing?.Enabled == true) @@ -518,7 +518,7 @@ protected override async Task PostStartInitAsync(CancellationToken ct) // update stats BlockchainStats.NetworkType = network.Name; - BlockchainStats.RewardType = isPoS ? "POS" : "POW"; + BlockchainStats.RewardType = "POW"; // block submission RPC method if(submitBlockResponse.Error?.Message?.ToLower() == "method not found") @@ -564,6 +564,9 @@ protected virtual IDestination AddressToDestination(string address, BitcoinAddre case BitcoinAddressType.BechSegwit: return BitcoinUtils.BechSegwitAddressToDestination(poolConfig.Address, network); + case BitcoinAddressType.CashAddr: + return BitcoinUtils.CashAddrToDestination(poolConfig.Address, network); + default: return BitcoinUtils.AddressToDestination(poolConfig.Address, network); } diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs index af61c880..1f1af0bc 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinPayoutHandler.cs @@ -163,7 +163,7 @@ public virtual async Task ClassifyBlocksAsync(Block[] blocks) // update progress var minConfirmations = extraPoolConfig?.MinimumConfirmations ?? BitcoinConstants.CoinbaseMinConfimations; block.ConfirmationProgress = Math.Min(1.0d, (double) transactionInfo.Confirmations / minConfirmations); - block.Reward = transactionInfo.Amount; // update actual block-reward from coinbase-tx + block.Reward = transactionInfo.Details[0].Amount; // update actual block-reward from coinbase-tx result.Add(block); messageBus.NotifyBlockConfirmationProgress(poolConfig.Id, block, coin); @@ -173,7 +173,7 @@ public virtual async Task ClassifyBlocksAsync(Block[] blocks) // matured and spendable coinbase transaction block.Status = BlockStatus.Confirmed; block.ConfirmationProgress = 1; - block.Reward = transactionInfo.Amount; // update actual block-reward from coinbase-tx + block.Reward = transactionInfo.Details[0].Amount; // update actual block-reward from coinbase-tx result.Add(block); logger.Info(() => $"[{LogCategory}] Unlocked block {block.BlockHeight} worth {FormatAmount(block.Reward)}"); @@ -208,11 +208,11 @@ public virtual Task CalculateBlockEffortAsync(Block block, double accumulatedBlo public virtual async Task PayoutAsync(Balance[] balances) { Contract.RequiresNonNull(balances, nameof(balances)); - + var roundnum = poolConfig.Template.Symbol == "DVT" ? 3:4; // build args var amounts = balances .Where(x => x.Amount > 0) - .ToDictionary(x => x.Address, x => Math.Round(x.Amount, 4)); + .ToDictionary(x => x.Address, x => Math.Round(x.Amount, roundnum)); if(amounts.Count == 0) return; @@ -242,14 +242,14 @@ public virtual async Task PayoutAsync(Balance[] balances) { args = new object[] { - string.Empty, // default account + "", // default account amounts, // addresses and associated amounts 1, // only spend funds covered by this many confirmations false, // Whether to add confirmations to transactions locked via InstantSend comment, // tx comment - subtractFeesFrom, // distribute transaction fee equally over all recipients - false, // use_is: Send this transaction as InstantSend - false, // Use anonymized funds only + subtractFeesFrom // distribute transaction fee equally over all recipients + // false, // use_is: Send this transaction as InstantSend + // false, // Use anonymized funds only }; } } diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs index f5636ea6..93fc5929 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinPool.cs @@ -42,7 +42,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using Newtonsoft.Json; using Newtonsoft.Json.Linq; using NLog; - namespace Miningcore.Blockchain.Bitcoin { [CoinFamily(CoinFamily.Bitcoin)] @@ -62,7 +61,7 @@ public BitcoinPool(IComponentContext ctx, protected object currentJobParams; protected BitcoinJobManager manager; private BitcoinTemplate coin; - + public int submitcount = 0; protected virtual async Task OnSubscribeAsync(StratumClient client, Timestamped tsRequest) { var request = tsRequest.Value; @@ -196,8 +195,8 @@ protected virtual async Task OnSubmitAsync(StratumClient client, Timestamped $"[{client.ConnectionId}] Share accepted: D={Math.Round(share.Difficulty * coin.ShareMultiplier, 3)}"); + submitcount+=1; + logger.Info(() => $"[{client.ConnectionId}] Total Shares:{submitcount} Share accepted: D={Math.Round(share.Difficulty * coin.ShareMultiplier, 3)}"); // update pool stats if(share.IsBlockCandidate) diff --git a/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs b/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs index 1119f262..444b89de 100644 --- a/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs +++ b/src/Miningcore/Blockchain/Bitcoin/BitcoinUtils.cs @@ -23,6 +23,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System.Linq; using NBitcoin; using NBitcoin.DataEncoders; +using static Miningcore.Blockchain.Bitcoin.CashAddr; +using static Miningcore.Blockchain.Bitcoin.BchAddr; namespace Miningcore.Blockchain.Bitcoin { @@ -56,5 +58,11 @@ public static IDestination BechSegwitAddressToDestination(string address, Networ Debug.Assert(result.GetAddress(expectedNetwork).ToString() == address); return result; } + public static IDestination CashAddrToDestination(string address, Network expectedNetwork) + { + BchAddr.BchAddrData bchAddr = BchAddr.DecodeCashAddressWithPrefix(address); + var result = new KeyId(bchAddr.Hash); + return result; + } } } diff --git a/src/Miningcore/Blockchain/Bitcoin/CashAddr.cs b/src/Miningcore/Blockchain/Bitcoin/CashAddr.cs new file mode 100644 index 00000000..6727db58 --- /dev/null +++ b/src/Miningcore/Blockchain/Bitcoin/CashAddr.cs @@ -0,0 +1,674 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NBitcoin.DataEncoders; +namespace Miningcore.Blockchain.Bitcoin{ + + // https://github.com/bitcoincashjs/bchaddrjs + public static class BchAddr + { + public enum CashFormat + { + Legacy, + Bitpay, + Cashaddr + } + + public enum CashNetwork + { + Mainnet, + Testnet, + RegTest, + DevaultMainnet + } + + public enum CashType + { + P2PKH, + P2SH + } + + public class BchAddrData + { + public CashFormat Format { get; set; } + public CashNetwork Network { get; set; } + public CashType Type { get; set; } + public byte[] Hash { get; set; } + + public string GetHash() + { + if (Hash == null) return null; + return Encoders.Hex.EncodeData(Hash); + } + + public string AsLegacyAddress => EncodeAsLegacy(this); + public string AsBitpayAddress => EncodeAsBitpay(this); + public string AsCashaddrAddress => EncodeAsCashaddr(this); + public string AsCashaddrAddressNoPrefix => EncodeAsCashaddrNoPrefix(this); + + public static BchAddrData Create(CashFormat format, CashNetwork network, CashType type, byte[] hash) + { + return new BchAddrData + { + Format = format, + Network = network, + Type = type, + Hash = hash, + }; + } + } + + /// + /// Encodes the given decoded address into legacy format + /// + /// + /// + public static string EncodeAsLegacy(BchAddrData decoded) + { + var versionByte = GetVersionByte(CashFormat.Legacy, decoded.Network, decoded.Type); + var buffer = new byte[1] { versionByte }; + buffer = buffer.Concat(decoded.Hash).ToArray(); + return Encoders.Base58Check.EncodeData(buffer); + } + + /// + /// Encodes the given decoded address into bitpay format + /// + /// + /// + public static string EncodeAsBitpay(BchAddrData decoded) + { + var versionByte = GetVersionByte(CashFormat.Bitpay, decoded.Network, decoded.Type); + var buffer = new byte[1] { versionByte }; + buffer = buffer.Concat(decoded.Hash).ToArray(); + return Encoders.Base58Check.EncodeData(buffer); + } + + /// + /// Encodes the given decoded address into cashaddr format + /// + /// + /// + public static string EncodeAsCashaddr(BchAddrData decoded) + { + var prefix = GetCashaddrkPrefix(decoded); + var type = decoded.Type == CashType.P2PKH ? "P2PKH" : "P2SH"; + var hash = decoded.Hash; + return CashAddr.Encode(prefix, type, hash); + } + + /// + /// Encodes the given decoded address into cashaddr format without a prefix + /// + /// + /// + public static string EncodeAsCashaddrNoPrefix(BchAddrData decoded) + { + var address = EncodeAsCashaddr(decoded); + if (address.IndexOf(":") != -1) + { + return address.Split(':')[1]; + } + throw new Validation.ValidationError($"Invalid BchAddrData"); + } + + public static string GetCashaddrkPrefix(BchAddrData data) + { + switch (data.Network) + { + case CashNetwork.Mainnet: + return "bitcoincash"; + case CashNetwork.DevaultMainnet: + return "devault"; + case CashNetwork.Testnet: + return "bchtest"; + case CashNetwork.RegTest: + return "bchreg"; + } + throw new Validation.ValidationError($"Invalid BchAddrData"); + } + + /// + /// Detects what is the given address' format + /// + /// + /// + public static BchAddrData DecodeAddress(string address) + { + try + { + return DecodeBase58Address(address); + } + catch { } + try + { + return DecodeCashAddress(address); + } + catch { } + throw new Validation.ValidationError($"Invalid address {address}"); + } + + /// + /// returns the Version byte for base58 formats + /// + /// + /// + /// + /// + private static byte GetVersionByte(CashFormat format, CashNetwork network, CashType type) + { + switch (format) + { + case CashFormat.Legacy: + if (network == CashNetwork.Mainnet && type == CashType.P2PKH) return 0; + else if (network == CashNetwork.Mainnet && type == CashType.P2SH) return 5; + break; + case CashFormat.Bitpay: + if (network == CashNetwork.Mainnet && type == CashType.P2PKH) return 28; + else if (network == CashNetwork.Mainnet && type == CashType.P2SH) return 40; + break; + } + if (network == CashNetwork.Testnet && type == CashType.P2PKH) return 111; + else if (network == CashNetwork.Testnet && type == CashType.P2SH) return 196; + else if (network == CashNetwork.RegTest && type == CashType.P2PKH) return 111; + else if (network == CashNetwork.RegTest && type == CashType.P2SH) return 196; + throw new Validation.ValidationError("Invalid parameters"); + } + + /// + /// Decodes the given address into its constituting hash, format, network and type + /// + /// A valid Bitcoin Cash address in any format + /// + private static BchAddrData DecodeBase58Address(string address) + { + var payload = Encoders.Base58Check.DecodeData(address); + var versionByte = payload[0]; + var hash = payload.Skip(1).ToArray(); + switch (versionByte) + { + case 0: + return BchAddrData.Create(CashFormat.Legacy, CashNetwork.Mainnet, CashType.P2PKH, hash); + case 5: + return BchAddrData.Create(CashFormat.Legacy, CashNetwork.Mainnet, CashType.P2SH, hash); + case 111: + return BchAddrData.Create(CashFormat.Legacy, CashNetwork.Testnet, CashType.P2PKH, hash); + case 196: + return BchAddrData.Create(CashFormat.Legacy, CashNetwork.Testnet, CashType.P2SH, hash); + case 28: + return BchAddrData.Create(CashFormat.Bitpay, CashNetwork.Mainnet, CashType.P2PKH, hash); + case 40: + return BchAddrData.Create(CashFormat.Bitpay, CashNetwork.Mainnet, CashType.P2SH, hash); + default: + throw new Validation.ValidationError($"Invalid address type in version byte: {versionByte}"); + } + } + + /// + /// Attempts to decode the given address assuming it is a cashaddr address + /// + /// A valid Bitcoin Cash address in any format + /// + private static BchAddrData DecodeCashAddress(string address) + { + if (address.IndexOf(":") != -1) + { + return DecodeCashAddressWithPrefix(address); + } + else + { + var prefixes = new string[] { "bitcoincash", "bchtest", "bchreg" }; + foreach (var prefix in prefixes) + { + try + { + var result = DecodeCashAddressWithPrefix(prefix + ":" + address); + return result; + } + catch { } + } + } + throw new Validation.ValidationError($"Invalid address {address}"); + } + + /// + /// Attempts to decode the given address assuming it is a cashaddr address with explicit prefix + /// + /// A valid Bitcoin Cash address in any format + /// + public static BchAddrData DecodeCashAddressWithPrefix(string address) + { + var decoded = CashAddr.Decode(address); + var type = decoded.Type == "P2PKH" ? CashType.P2PKH : CashType.P2SH; + switch (decoded.Prefix) + { + case "bitcoincash": + return BchAddrData.Create(CashFormat.Cashaddr, CashNetwork.Mainnet, type, decoded.Hash); + case "devault": + return BchAddrData.Create(CashFormat.Cashaddr, CashNetwork.DevaultMainnet, type, decoded.Hash); + case "bchtest": + return BchAddrData.Create(CashFormat.Cashaddr, CashNetwork.Testnet, type, decoded.Hash); + case "regtest": + return BchAddrData.Create(CashFormat.Cashaddr, CashNetwork.RegTest, type, decoded.Hash); + } + throw new Validation.ValidationError($"Invalid address {address}"); + } + } + + // https://github.com/bitcoincashjs/cashaddrjs + public static class CashAddr + { + public class CashAddrData + { + public string Prefix { get; set; } + public string Type { get; set; } + public byte[] Hash { get; set; } + } + + static string[] VALID_PREFIXES = new string[] { "devault","bitcoincash", "bchtest", "bchreg" }; + + /// + /// Encodes a hash from a given type into a Bitcoin Cash address with the given prefix + /// + /// prefix Network prefix. E.g.: 'bitcoincash' + /// type Type of address to generate. Either 'P2PKH' or 'P2SH' + /// hash Hash to encode represented as an array of 8-bit integers + /// + public static string Encode(string prefix, string type, byte[] hash) + { + Validation.Validate(IsValidPrefix(prefix), $"Invalid prefix: {prefix}"); + var prefixData = Concat(PrefixToByte5Array(prefix), new byte[1]); + var versionByte = GetTypeBits(type) + GetHashSizeBits(hash); + var payloadData = ToByte5Array(Concat(new byte[1] { (byte)versionByte }, hash)); + var checksumData = Concat(Concat(prefixData, payloadData), new byte[8]); + var payload = Concat(payloadData, ChecksumToByte5Array(Polymod(checksumData))); + return prefix + ':' + Base32.Encode(payload); + } + + /// + /// Decodes the given address into its constituting prefix, type and hash + /// + /// Address to decode. E.g.: 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a' + /// DecodeData + public static CashAddrData Decode(string address) + { + var pieces = address.ToLower().Split(':'); + Validation.Validate(pieces.Length == 2, $"Missing prefix: {address}"); + var prefix = pieces[0]; + var payload = Base32.Decode(pieces[1]); + Validation.Validate(ValidChecksum(prefix, payload), $"Invalid checksum: {address}"); + var data = payload.Take(payload.Length - 8).ToArray(); + var payloadData = FromByte5Array(data); + var versionByte = payloadData[0]; + var hash = payloadData.Skip(1).ToArray(); + Validation.Validate(GetHashSize((byte)versionByte) == hash.Length * 8, $"Invalid hash size: {address}"); + var type = GetType((byte)versionByte); + return new CashAddrData + { + Prefix = prefix, + Type = type, + Hash = hash + }; + } + + /// + /// Retrieves the address type from its bit representation within the version byte + /// + /// + /// + public static string GetType(byte versionByte) + { + switch (versionByte & 120) + { + case 0: + return "P2PKH"; + case 8: + return "P2SH"; + default: + throw new Validation.ValidationError($"Invalid address type in version byte: {versionByte}"); + } + } + + /// + /// Verify that the payload has not been corrupted by checking that the checksum is valid + /// + /// + /// + /// + public static bool ValidChecksum(string prefix, byte[] payload) + { + var prefixData = Concat(PrefixToByte5Array(prefix), new byte[1]); + var checksumData = Concat(prefixData, payload); + return Polymod(checksumData).Equals(0); + } + + + /// + /// Returns the concatenation a and b + /// + public static byte[] Concat(byte[] a, byte[] b) + { + return a.Concat(b).ToArray(); + } + + /// + /// Returns an array representation of the given checksum to be encoded within the address' payload + /// + /// + /// + public static byte[] ChecksumToByte5Array(long checksum) + { + var result = new byte[8]; + for (var i = 0; i < 8; ++i) + { + result[7 - i] = (byte)(checksum & 31); + checksum = checksum >> 5; + } + return result; + } + + /// + /// Computes a checksum from the given input data as specified for the CashAddr + /// + /// + /// + public static long Polymod(byte[] data) + { + var GENERATOR = new long[] { 0x98f2bc8e61, 0x79b76d99e2, 0xf33e5fb3c4, 0xae2eabe2a8, 0x1e4f43e470 }; + long checksum = 1; + for (var i = 0; i < data.Length; ++i) + { + var value = data[i]; + var topBits = checksum >> 35; + checksum = ((checksum & 0x07ffffffff) << 5) ^ value; + for (var j = 0; j < GENERATOR.Length; ++j) + { + if (((topBits >> j) & 1).Equals(1)) + { + checksum = checksum ^ GENERATOR[j]; + } + } + } + return checksum ^ 1; + } + + /// + /// Checks whether a string is a valid prefix; ie., it has a single letter case + /// and is one of 'bitcoincash', 'bchtest', or 'bchreg'. + /// + /// + /// + public static bool IsValidPrefix(string prefix) + { + return HasSingleCase(prefix) && VALID_PREFIXES.Contains(prefix.ToLower()); + } + + /// + /// Derives an array from the given prefix to be used in the computation of the address checksum + /// + /// Network prefix. E.g.: 'bitcoincash' + /// + public static byte[] PrefixToByte5Array(string prefix) + { + var result = new byte[prefix.Length]; + int i = 0; + foreach (char c in prefix.ToCharArray()) + { + result[i++] = (byte)(c & 31); + } + return result; + } + + /// + /// Returns true if, and only if, the given string contains either uppercase or lowercase letters, but not both + /// + /// + /// + public static bool HasSingleCase(string str) + { + return str == str.ToLower() || str == str.ToUpper(); + } + + /// + /// Returns the bit representation of the length in bits of the given hash within the version byte + /// + /// Hash to encode represented as an array of 8-bit integers + /// + public static byte GetHashSizeBits(byte[] hash) + { + switch (hash.Length * 8) + { + case 160: + return 0; + case 192: + return 1; + case 224: + return 2; + case 256: + return 3; + case 320: + return 4; + case 384: + return 5; + case 448: + return 6; + case 512: + return 7; + default: + throw new Validation.ValidationError($"Invalid hash size: {hash.Length}"); + } + } + + /// + /// Retrieves the the length in bits of the encoded hash from its bit representation within the version byte + /// + /// + /// + public static int GetHashSize(byte versionByte) + { + switch (versionByte & 7) + { + case 0: + return 160; + case 1: + return 192; + case 2: + return 224; + case 3: + return 256; + case 4: + return 320; + case 5: + return 384; + case 6: + return 448; + case 7: + return 512; + default: + throw new Validation.ValidationError($"Invalid versionByte: {versionByte}"); + } + } + + /// + /// Returns the bit representation of the given type within the version byte + /// + /// Address type. Either 'P2PKH' or 'P2SH' + /// + public static byte GetTypeBits(string type) + { + switch (type) + { + case "P2PKH": + return 0; + case "P2SH": + return 8; + default: + throw new Validation.ValidationError($"Invalid type: {type}"); + } + } + + /// + /// Converts an array of 8-bit integers into an array of 5-bit integers, right-padding with zeroes if necessary + /// + /// + /// + public static byte[] ToByte5Array(byte[] data) + { + return ConvertBits.Convert(data, 8, 5); + } + + /// + /// Converts an array of 5-bit integers back into an array of 8-bit integers + /// removing extra zeroes left from padding if necessary. + /// Throws a ValidationError if input is not a zero-padded array of 8-bit integers + /// + /// + /// + public static byte[] FromByte5Array(byte[] data) + { + return ConvertBits.Convert(data, 5, 8, true); + } + + } + + internal static class ConvertBits + { + /// + /// Converts an array of integers made up of 'from' bits into an + /// array of integers made up of 'to' bits.The output array is + /// zero-padded if necessary, unless strict mode is true. + /// + /// data Array of integers made up of 'from' bits + /// from Length in bits of elements in the input array + /// to Length in bits of elements in the output array + /// strictMode Require the conversion to be completed without padding + /// + public static byte[] Convert(byte[] data, int from, int to, bool strictMode = false) + { + Validation.Validate(from > 0, "Invald 'from' parameter"); + Validation.Validate(to > 0, "Invald 'to' parameter"); + Validation.Validate(data.Length > 0, "Invald data"); + var d = data.Length * from / (double)to; + var length = strictMode ? (int)Math.Floor(d) : (int)Math.Ceiling(d); + var mask = (1 << to) - 1; + var result = new byte[length]; + var index = 0; + var accumulator = 0; + var bits = 0; + for (var i = 0; i < data.Length; ++i) + { + var value = data[i]; + Validation.Validate(0 <= value && (value >> from) == 0, $"Invalid value: {value}"); + accumulator = (accumulator << from) | value; + bits += from; + while (bits >= to) + { + bits -= to; + result[index] = (byte)((accumulator >> bits) & mask); + ++index; + } + } + if (!strictMode) + { + if (bits > 0) + { + result[index] = (byte)((accumulator << (to - bits)) & mask); + ++index; + } + } + else + { + Validation.Validate( + bits < from && ((accumulator << (to - bits)) & mask) == 0, + $"Input cannot be converted to {to} bits without padding, but strict mode was used" + ); + } + return result; + } + } + + internal static class Base32 + { + private static readonly char[] DIGITS; + private static Dictionary CHAR_MAP = new Dictionary(); + + static Base32() + { + DIGITS = "qpzry9x8gf2tvdw0s3jn54khce6mua7l".ToCharArray(); + for (int i = 0; i < DIGITS.Length; i++) CHAR_MAP[DIGITS[i]] = i; + } + + /// + /// Decodes the given base32-encoded string into an array of 5-bit integers + /// + /// + /// + public static byte[] Decode(string encoded) + { + if (encoded.Length == 0) + { + throw new CashaddrBase32EncoderException("Invalid encoded string"); + } + var result = new byte[encoded.Length]; + int next = 0; + foreach (char c in encoded.ToCharArray()) + { + if (!CHAR_MAP.ContainsKey(c)) + { + throw new CashaddrBase32EncoderException($"Invalid character: {c}"); + } + result[next++] = (byte)CHAR_MAP[c]; + } + return result; + } + + /// + /// Encodes the given array of 5-bit integers as a base32-encoded string + /// + /// data Array of integers between 0 and 31 inclusive + /// + public static string Encode(byte[] data) + { + if (data.Length == 0) + { + throw new CashaddrBase32EncoderException("Invalid data"); + } + string base32 = String.Empty; + for (var i = 0; i < data.Length; ++i) + { + var value = data[i]; + if (0 <= value && value < 32) + base32 += DIGITS[value]; + else + throw new CashaddrBase32EncoderException($"Invalid value: {value}"); + } + return base32; + } + + private class CashaddrBase32EncoderException : Exception + { + public CashaddrBase32EncoderException(string message) : base(message) + { + } + } + } + + internal static class Validation + { + public static void Validate(bool condition, string message) + { + if (!condition) + { + throw new ValidationError(message); + } + } + + internal class ValidationError : Exception + { + public ValidationError(string message) : base(message) + { + } + } + } + +} \ No newline at end of file diff --git a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/DevaultCoinbasePayload.cs b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/DevaultCoinbasePayload.cs new file mode 100644 index 00000000..63f01047 --- /dev/null +++ b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/DevaultCoinbasePayload.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Miningcore.Blockchain.Bitcoin.DaemonResponses +{ + public class CoinbasePayload + { + public string Payee { get; set; } + public string Script { get; set; } + public long Amount { get; set; } + } + + public class CoinbasePayloadBlockTemplateExtra : PayeeBlockTemplateExtra + { + [JsonProperty("coinbase_payload")] + public JToken CoinbasePayload { get; set; } + } + +} diff --git a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs new file mode 100644 index 00000000..f13d19ca --- /dev/null +++ b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Founder.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Miningcore.Blockchain.Bitcoin.DaemonResponses +{ + public class Founder + { + public string Payee { get; set; } + public string Script { get; set; } + public long Amount { get; set; } + } + + public class FounderBlockTemplateExtra : PayeeBlockTemplateExtra + { + + [JsonProperty("founder")] + public Founder Founder { get; set; } + } +} diff --git a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Masternode.cs b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Masternode.cs index 31f7e018..24dd7dd1 100644 --- a/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Masternode.cs +++ b/src/Miningcore/Blockchain/Bitcoin/DaemonResponses/Masternode.cs @@ -23,6 +23,9 @@ public class MasterNodeBlockTemplateExtra : PayeeBlockTemplateExtra { public JToken Masternode { get; set; } + [JsonProperty("indexnode")] + private JToken Indexnode { set { Masternode = value; } } + [JsonProperty("masternode_payments_started")] public bool MasternodePaymentsStarted { get; set; } diff --git a/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs b/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs new file mode 100644 index 00000000..32b0fd77 --- /dev/null +++ b/src/Miningcore/Blockchain/Bitcoin/IndexBlockHeader.cs @@ -0,0 +1,330 @@ +using NBitcoin.BouncyCastle.Math; +using NBitcoin.Crypto; +using NBitcoin.DataEncoders; +using NBitcoin.RPC; +#if !NOJSONNET +using Newtonsoft.Json.Linq; +#endif +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace NBitcoin +{ + /// + /// Nodes collect new transactions into a block, hash them into a hash tree, + /// and scan through nonce values to make the block's hash satisfy proof-of-work + /// requirements. When they solve the proof-of-work, they broadcast the block + /// to everyone and the block is added to the block chain. The first transaction + /// in the block is a special one that creates a new coin owned by the creator + /// of the block. + /// + public class IndexBlockHeader : IBitcoinSerializable + { + internal const int Size = 81; + + + public static IndexBlockHeader Parse(string hex, Network network) + { + if (network == null) + throw new ArgumentNullException(nameof(network)); + return Parse(hex, network.Consensus.ConsensusFactory); + } + + public static IndexBlockHeader Parse(string hex, Consensus consensus) + { + if (consensus == null) + throw new ArgumentNullException(nameof(consensus)); + return Parse(hex, consensus.ConsensusFactory); + } + + public static IndexBlockHeader Parse(string hex, ConsensusFactory consensusFactory) + { + if (consensusFactory == null) + throw new ArgumentNullException(nameof(consensusFactory)); + return new IndexBlockHeader(Encoders.Hex.DecodeData(hex), consensusFactory); + } + + + [Obsolete("Use Parse(string hex, Network|Consensus|ConsensusFactory) instead")] + public static IndexBlockHeader Parse(string hex) + { + return Parse(hex, Consensus.Main.ConsensusFactory); + } + + [Obsolete("You should instantiate IndexBlockHeader from ConsensusFactory.CreateIndexBlockHeader")] + public IndexBlockHeader() + { + SetNull(); + } + + public IndexBlockHeader(string hex, Network network) + : this(hex, network?.Consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(network))) + { + + } + + public IndexBlockHeader(string hex, Consensus consensus) + : this(hex, consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(consensus))) + { + + } + + public IndexBlockHeader(string hex, ConsensusFactory consensusFactory) + { + if (hex == null) + throw new ArgumentNullException(nameof(hex)); + if (consensusFactory == null) + throw new ArgumentNullException(nameof(consensusFactory)); + BitcoinStream bs = new BitcoinStream(Encoders.Hex.DecodeData(hex)) + { + ConsensusFactory = consensusFactory + }; + this.ReadWrite(bs); + } + + [Obsolete("Use new IndexBlockHeader(string hex, Network|Consensus|ConsensusFactory) instead")] + public IndexBlockHeader(string hex) + : this(Encoders.Hex.DecodeData(hex)) + { + + } + + + public IndexBlockHeader(byte[] data, Network network) + : this(data, network?.Consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(network))) + { + + } + + public IndexBlockHeader(byte[] data, Consensus consensus) + : this(data, consensus?.ConsensusFactory ?? throw new ArgumentNullException(nameof(consensus))) + { + + } + + public IndexBlockHeader(byte[] data, ConsensusFactory consensusFactory) + { + if (data == null) + throw new ArgumentNullException(nameof(data)); + if (consensusFactory == null) + throw new ArgumentNullException(nameof(consensusFactory)); + BitcoinStream bs = new BitcoinStream(data) + { + ConsensusFactory = consensusFactory + }; + this.ReadWrite(bs); + } + + + [Obsolete("Use new IndexBlockHeader(byte[] hex, Network|Consensus|ConsensusFactory) instead")] + public IndexBlockHeader(byte[] bytes) + { + this.ReadWrite(bytes); + } + + + // header + const int CURRENT_VERSION = 3; + + protected uint256 hashPrevBlock; + + public uint256 HashPrevBlock + { + get + { + return hashPrevBlock; + } + set + { + hashPrevBlock = value; + } + } + protected uint256 hashMerkleRoot; + + protected uint nTime; + protected uint nBits; + + public Target Bits + { + get + { + return nBits; + } + set + { + nBits = value; + } + } + + protected int nVersion; + + public int Version + { + get + { + return nVersion; + } + set + { + nVersion = value; + } + } + + protected uint nNonce; + + public uint Nonce + { + get + { + return nNonce; + } + set + { + nNonce = value; + } + } + public uint256 HashMerkleRoot + { + get + { + return hashMerkleRoot; + } + set + { + hashMerkleRoot = value; + } + } + protected bool fProofOfStake; + public bool ProofOfStake + { + get + { + return fProofOfStake; + } + set + { + fProofOfStake = value; + } + } + + protected internal virtual void SetNull() + { + nVersion = CURRENT_VERSION; + hashPrevBlock = 0; + hashMerkleRoot = 0; + nTime = 0; + nBits = 0; + nNonce = 0; + fProofOfStake = false; + } + + public virtual bool IsNull + { + get + { + return (nBits == 0); + } + } + #region IBitcoinSerializable Members + + public virtual void ReadWrite(BitcoinStream stream) + { + stream.ReadWrite(ref nVersion); + stream.ReadWrite(ref hashPrevBlock); + stream.ReadWrite(ref hashMerkleRoot); + stream.ReadWrite(ref nTime); + stream.ReadWrite(ref nBits); + stream.ReadWrite(ref nNonce); + stream.ReadWrite(ref fProofOfStake); + + } + + + #endregion + + + public virtual uint256 GetPoWHash() + { + return GetHash(); + } + + public uint256 GetHash() + { + uint256 h = null; + var hashes = _Hashes; + if (hashes != null) + { + h = hashes[0]; + } + if (h != null) + return h; + + using (var hs = CreateHashStream()) + { + var stream = new BitcoinStream(hs, true); + stream.SerializationTypeScope(SerializationType.Hash); + this.ReadWrite(stream); + h = hs.GetHash(); + } + + hashes = _Hashes; + if (hashes != null) + { + hashes[0] = h; + } + return h; + } + + protected virtual HashStreamBase CreateHashStream() + { + return new HashStream(); + } + + [Obsolete("Call PrecomputeHash(true, true) instead")] + public void CacheHashes() + { + PrecomputeHash(true, true); + } + + /// + /// Precompute the block header hash so that later calls to GetHash() will returns the precomputed hash + /// + /// If true, the previous precomputed hash is thrown away, else it is reused + /// If true, the hash will be calculated and cached at the first call to GetHash(), else it will be immediately + public void PrecomputeHash(bool invalidateExisting, bool lazily) + { + _Hashes = invalidateExisting ? new uint256[1] : _Hashes ?? new uint256[1]; + if (!lazily && _Hashes[0] == null) + _Hashes[0] = GetHash(); + } + + + uint256[] _Hashes; + + public DateTimeOffset BlockTime + { + get + { + return Utils.UnixTimeToDateTime(nTime); + } + set + { + this.nTime = Utils.DateTimeToUnixTime(value); + } + } + + static BigInteger Pow256 = BigInteger.ValueOf(2).Pow(256); + public bool CheckProofOfWork() + { + var bits = Bits.ToBigInteger(); + if (bits.CompareTo(BigInteger.Zero) <= 0 || bits.CompareTo(Pow256) >= 0) + return false; + // Check proof of work matches claimed amount + return GetPoWHash() <= Bits.ToUInt256(); + } + + + } +} \ No newline at end of file diff --git a/src/Miningcore/Blockchain/Cryptonote/CryptonoteWorkerJob.cs b/src/Miningcore/Blockchain/Cryptonote/CryptonoteWorkerJob.cs index 83d8a3ae..85d2d24d 100644 --- a/src/Miningcore/Blockchain/Cryptonote/CryptonoteWorkerJob.cs +++ b/src/Miningcore/Blockchain/Cryptonote/CryptonoteWorkerJob.cs @@ -18,6 +18,7 @@ portions of the Software. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +using System; using System.Collections.Generic; namespace Miningcore.Blockchain.Cryptonote @@ -35,6 +36,6 @@ public CryptonoteWorkerJob(string jobId, double difficulty) public uint ExtraNonce { get; set; } public double Difficulty { get; set; } - public HashSet Submissions { get; } = new HashSet(); + public HashSet Submissions { get; } = new HashSet(StringComparer.OrdinalIgnoreCase); } } diff --git a/src/Miningcore/Blockchain/Equihash/EquihashJob.cs b/src/Miningcore/Blockchain/Equihash/EquihashJob.cs index dba80155..411eebec 100644 --- a/src/Miningcore/Blockchain/Equihash/EquihashJob.cs +++ b/src/Miningcore/Blockchain/Equihash/EquihashJob.cs @@ -50,7 +50,7 @@ public class EquihashJob protected Network network; protected IDestination poolAddressDestination; - protected readonly HashSet submissions = new HashSet(); + protected readonly HashSet submissions = new HashSet(StringComparer.OrdinalIgnoreCase); protected uint256 blockTargetValue; protected byte[] coinbaseInitial; diff --git a/src/Miningcore/Configuration/ClusterConfig.cs b/src/Miningcore/Configuration/ClusterConfig.cs index 2ee4d099..67d064aa 100644 --- a/src/Miningcore/Configuration/ClusterConfig.cs +++ b/src/Miningcore/Configuration/ClusterConfig.cs @@ -164,6 +164,9 @@ public partial class BitcoinNetworkParams [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public bool HasMasterNodes { get; set; } + [JsonProperty("hasCoinbasePayload")] + public bool HasCoinbasePayload { get; set; } + [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] [DefaultValue(1.0d)] public double ShareMultiplier { get; set; } = 1.0d; diff --git a/src/Miningcore/Crypto/Hashing/Algorithms/Quark.cs b/src/Miningcore/Crypto/Hashing/Algorithms/Quark.cs new file mode 100644 index 00000000..18667762 --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Algorithms/Quark.cs @@ -0,0 +1,42 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +using System; +using Miningcore.Contracts; +using Miningcore.Native; + +namespace Miningcore.Crypto.Hashing.Algorithms +{ + public unsafe class Quark : IHashAlgorithm + { + public void Digest(ReadOnlySpan data, Span result, params object[] extra) + { + Contract.Requires(result.Length >= 32, $"{nameof(result)} must be greater or equal 32 bytes"); + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + LibMultihash.quark(input, output, (uint) data.Length); + } + } + } + } +} diff --git a/src/Miningcore/Crypto/Hashing/Algorithms/X16RV2.cs b/src/Miningcore/Crypto/Hashing/Algorithms/X16RV2.cs new file mode 100644 index 00000000..e2c9fe8a --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Algorithms/X16RV2.cs @@ -0,0 +1,42 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +using System; +using Miningcore.Contracts; +using Miningcore.Native; + +namespace Miningcore.Crypto.Hashing.Algorithms +{ + public unsafe class X16RV2 : IHashAlgorithm + { + public void Digest(ReadOnlySpan data, Span result, params object[] extra) + { + Contract.Requires(result.Length >= 32, $"{nameof(result)} must be greater or equal 32 bytes"); + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + LibMultihash.x16rv2(input, output, (uint) data.Length); + } + } + } + } +} diff --git a/src/Miningcore/Crypto/Hashing/Algorithms/YesPower_SugarChain.cs b/src/Miningcore/Crypto/Hashing/Algorithms/YesPower_SugarChain.cs new file mode 100644 index 00000000..bdee801d --- /dev/null +++ b/src/Miningcore/Crypto/Hashing/Algorithms/YesPower_SugarChain.cs @@ -0,0 +1,42 @@ +/* +Copyright 2017 Coin Foundry (coinfoundry.org) +Authors: Oliver Weichhold (oliver@weichhold.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +using System; +using Miningcore.Contracts; +using Miningcore.Native; + +namespace Miningcore.Crypto.Hashing.Algorithms +{ + public unsafe class YesPower_Sugarchain : IHashAlgorithm + { + public void Digest(ReadOnlySpan data, Span result, params object[] extra) + { + Contract.Requires(result.Length >= 32, $"{nameof(result)} must be greater or equal 32 bytes"); + + fixed (byte* input = data) + { + fixed (byte* output = result) + { + LibMultihash.yespower_sugarchain(input, output, (uint) data.Length); + } + } + } + } +} diff --git a/src/Miningcore/Mining/StatsRecorder.cs b/src/Miningcore/Mining/StatsRecorder.cs index 35a9e88d..0ac67b7e 100644 --- a/src/Miningcore/Mining/StatsRecorder.cs +++ b/src/Miningcore/Mining/StatsRecorder.cs @@ -5,13 +5,13 @@ using System.Linq; using System.Net.Sockets; using System.Threading; -using System.Threading.Tasks; +using System.Threading.Tasks; using Autofac; using AutoMapper; using Miningcore.Configuration; using Miningcore.Contracts; using Miningcore.Extensions; -using Miningcore.Messaging; +using Miningcore.Messaging; using Miningcore.Persistence; using Miningcore.Persistence.Model; using Miningcore.Persistence.Repositories; @@ -33,8 +33,8 @@ public StatsRecorder(IComponentContext ctx, { Contract.RequiresNonNull(ctx, nameof(ctx)); Contract.RequiresNonNull(clock, nameof(clock)); - Contract.RequiresNonNull(cf, nameof(cf)); - Contract.RequiresNonNull(messageBus, nameof(messageBus)); + Contract.RequiresNonNull(cf, nameof(cf)); + Contract.RequiresNonNull(messageBus, nameof(messageBus)); Contract.RequiresNonNull(mapper, nameof(mapper)); Contract.RequiresNonNull(shareRepo, nameof(shareRepo)); Contract.RequiresNonNull(statsRepo, nameof(statsRepo)); @@ -58,8 +58,8 @@ public StatsRecorder(IComponentContext ctx, private readonly IComponentContext ctx; private readonly IShareRepository shareRepo; private readonly CancellationTokenSource cts = new CancellationTokenSource(); - private readonly ConcurrentDictionary pools = new ConcurrentDictionary(); - private readonly TimeSpan interval = TimeSpan.FromMinutes(5); + private readonly ConcurrentDictionary pools = new ConcurrentDictionary(); + private readonly TimeSpan interval = TimeSpan.FromMinutes(1); private const int HashrateCalculationWindow = 1200; // seconds private const int MinHashrateCalculationWindow = 300; // seconds private const double HashrateBoostFactor = 1.1d; @@ -84,7 +84,7 @@ public void AttachPool(IMiningPool pool) public void Start() { Task.Run(async () => - { + { logger.Info(() => "Online"); // warm-up delay @@ -153,7 +153,9 @@ private async Task UpdatePoolHashratesAsync() var poolHashesAccumulated = result.Sum(x => x.Sum); var poolHashesCountAccumulated = result.Sum(x => x.Count); var poolHashrate = pool.HashrateFromShares(poolHashesAccumulated, windowActual) * HashrateBoostFactor; - + if(poolId == "indexchain"){ + poolHashrate *= 11.2; + } // update pool.PoolStats.ConnectedMiners = byMiner.Length; pool.PoolStats.PoolHashrate = (ulong) Math.Ceiling(poolHashrate); @@ -211,7 +213,7 @@ string buildKey(string miner, string worker = null) // calculate & update miner, worker hashrates foreach(var minerHashes in byMiner) - { + { double minerTotalHashrate = 0; await cf.RunTx(async (con, tx) => @@ -229,13 +231,16 @@ await cf.RunTx(async (con, tx) => if(windowActual >= MinHashrateCalculationWindow) { var hashrate = pool.HashrateFromShares(item.Sum, windowActual) * HashrateBoostFactor; + if(poolId == "indexchain"){ + hashrate *= 11.2; + } minerTotalHashrate += hashrate; // update stats.Hashrate = hashrate; stats.Worker = item.Worker; - stats.SharesPerSecond = (double) item.Count / windowActual; - + stats.SharesPerSecond = (double) item.Count / windowActual; + // persist await statsRepo.InsertMinerWorkerPerformanceStatsAsync(con, tx, stats); @@ -245,9 +250,9 @@ await cf.RunTx(async (con, tx) => // book keeping currentNonZeroMinerWorkers.Add(buildKey(stats.Miner, stats.Worker)); } - } - }); - + } + }); + messageBus.NotifyHashrateUpdated(pool.Config.Id, minerTotalHashrate, stats.Miner, null); } diff --git a/src/Miningcore/Miningcore.csproj b/src/Miningcore/Miningcore.csproj index 7f46795d..141bc85e 100644 --- a/src/Miningcore/Miningcore.csproj +++ b/src/Miningcore/Miningcore.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.2 + netcoreapp3.1 Miningcore Miningcore AnyCPU @@ -58,7 +58,8 @@ - + + diff --git a/src/Miningcore/Native/LibMultihash.cs b/src/Miningcore/Native/LibMultihash.cs index cc452b8c..c92ce919 100644 --- a/src/Miningcore/Native/LibMultihash.cs +++ b/src/Miningcore/Native/LibMultihash.cs @@ -112,9 +112,15 @@ public static unsafe class LibMultihash [DllImport("libmultihash", EntryPoint = "c11_export", CallingConvention = CallingConvention.Cdecl)] public static extern int c11(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "yespower_sugarchain_export", CallingConvention = CallingConvention.Cdecl)] + public static extern int yespower_sugarchain(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "x16r_export", CallingConvention = CallingConvention.Cdecl)] public static extern int x16r(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "x16rv2_export", CallingConvention = CallingConvention.Cdecl)] + public static extern int x16rv2(byte* input, void* output, uint inputLength); + [DllImport("libmultihash", EntryPoint = "x16s_export", CallingConvention = CallingConvention.Cdecl)] public static extern int x16s(byte* input, void* output, uint inputLength); diff --git a/src/Miningcore/Persistence/Model/MinerWorkerPerformanceStats.cs b/src/Miningcore/Persistence/Model/MinerWorkerPerformanceStats.cs index 7b48efcd..bc394e8a 100644 --- a/src/Miningcore/Persistence/Model/MinerWorkerPerformanceStats.cs +++ b/src/Miningcore/Persistence/Model/MinerWorkerPerformanceStats.cs @@ -4,6 +4,7 @@ namespace Miningcore.Persistence.Model { public class MinerWorkerPerformanceStats { + public long Id { get; set; } public string PoolId { get; set; } public string Miner { get; set; } public string Worker { get; set; } diff --git a/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs b/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs index eb855c79..a086527c 100644 --- a/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs +++ b/src/Miningcore/Persistence/Postgres/Repositories/BlockRepository.cs @@ -21,7 +21,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Data; using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; using AutoMapper; using Dapper; using Miningcore.Extensions; @@ -89,18 +89,33 @@ public async Task PageBlocksAsync(IDbConnection con, string poolId, Blo })) .Select(mapper.Map) .ToArray(); - } - + } + public async Task PageBlocksAsyncPaged(IDbConnection con, string poolId, BlockStatus[] status, int page, int pageSize,int _start,int _end,string _order,string _sort) + { + logger.LogInvoke(new[] { poolId }); + string query = "SELECT * FROM blocks WHERE poolid = @poolid AND status = ANY(@status) AND id <= " + _end + + " ORDER BY " + _sort + " " + _order + " OFFSET @offset FETCH NEXT (@pageSize) ROWS ONLY"; + + return (await con.QueryAsync(query, new + { + poolId, + status = status.Select(x => x.ToString().ToLower()).ToArray(), + offset = page * pageSize, + pageSize + })) + .Select(mapper.Map) + .ToArray(); + } public async Task PageBlocksAsync(IDbConnection con, BlockStatus[] status, int page, int pageSize) { const string query = "SELECT * FROM blocks WHERE status = ANY(@status) " + "ORDER BY created DESC OFFSET @offset FETCH NEXT (@pageSize) ROWS ONLY"; - return (await con.QueryAsync(query, new - { - status = status.Select(x => x.ToString().ToLower()).ToArray(), - offset = page * pageSize, - pageSize + return (await con.QueryAsync(query, new + { + status = status.Select(x => x.ToString().ToLower()).ToArray(), + offset = page * pageSize, + pageSize })) .Select(mapper.Map) .ToArray(); diff --git a/src/Miningcore/Persistence/Postgres/Repositories/StatsRepository.cs b/src/Miningcore/Persistence/Postgres/Repositories/StatsRepository.cs index 50f13484..ca9656ac 100644 --- a/src/Miningcore/Persistence/Postgres/Repositories/StatsRepository.cs +++ b/src/Miningcore/Persistence/Postgres/Repositories/StatsRepository.cs @@ -21,7 +21,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Data; using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; using AutoMapper; using Dapper; using Miningcore.Extensions; @@ -104,15 +104,15 @@ public async Task GetPoolPerformanceBetweenAsync(IDbConnection con, string trunc = null; - switch(interval) - { - case SampleInterval.Hour: - trunc = "hour"; - break; - - case SampleInterval.Day: - trunc = "day"; - break; + switch(interval) + { + case SampleInterval.Hour: + trunc = "hour"; + break; + + case SampleInterval.Day: + trunc = "day"; + break; } var query = $"SELECT date_trunc('{trunc}', created) AS created, " + @@ -200,20 +200,20 @@ public async Task GetPoolMinerWorkerHashratesAsync(IDbCon logger.LogInvoke(); const string query = - "SELECT s.miner, s.worker, s.hashrate FROM " + - "(" + - " WITH cte AS" + - " (" + - " SELECT" + - " ROW_NUMBER() OVER (partition BY miner, worker ORDER BY created DESC) as rk," + - " miner, worker, hashrate" + - " FROM minerstats" + - " WHERE poolid = @poolId" + - " )" + - " SELECT miner, worker, hashrate" + - " FROM cte" + - " WHERE rk = 1" + - ") s " + + "SELECT s.miner, s.worker, s.hashrate FROM " + + "(" + + " WITH cte AS" + + " (" + + " SELECT" + + " ROW_NUMBER() OVER (partition BY miner, worker ORDER BY created DESC) as rk," + + " miner, worker, hashrate" + + " FROM minerstats" + + " WHERE poolid = @poolId" + + " )" + + " SELECT miner, worker, hashrate" + + " FROM cte" + + " WHERE rk = 1" + + ") s " + "WHERE s.hashrate > 0;"; return (await con.QueryAsync(query, new { poolId })) @@ -320,20 +320,20 @@ public async Task PagePoolMinersByHashrateAsync(I const string query = "WITH tmp AS " + "( " + " SELECT " + - " ms.miner, " + + " ms.miner, " + + " ms.id, " + " ms.hashrate, " + " ms.sharespersecond, " + " ROW_NUMBER() OVER(PARTITION BY ms.miner ORDER BY ms.hashrate DESC) AS rk " + - " FROM (SELECT miner, SUM(hashrate) AS hashrate, SUM(sharespersecond) AS sharespersecond " + + " FROM (SELECT miner, id , SUM(hashrate) AS hashrate, SUM(sharespersecond) AS sharespersecond " + " FROM minerstats " + - " WHERE poolid = @poolid AND created >= @from GROUP BY miner, created) ms " + + " WHERE poolid = @poolid AND created >= @from GROUP BY id, created) ms " + ") " + - "SELECT t.miner, t.hashrate, t.sharespersecond " + + "SELECT t.id, t.miner, t.hashrate, t.sharespersecond " + "FROM tmp t " + "WHERE t.rk = 1 " + "ORDER by t.hashrate DESC " + "OFFSET @offset FETCH NEXT (@pageSize) ROWS ONLY"; - return (await con.QueryAsync(query, new { poolId, from, offset = page * pageSize, pageSize })) .Select(mapper.Map) .ToArray(); diff --git a/src/Miningcore/Persistence/Repositories/IBlockRepository.cs b/src/Miningcore/Persistence/Repositories/IBlockRepository.cs index 3dda0018..210b0005 100644 --- a/src/Miningcore/Persistence/Repositories/IBlockRepository.cs +++ b/src/Miningcore/Persistence/Repositories/IBlockRepository.cs @@ -20,7 +20,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Data; -using System.Threading.Tasks; +using System.Threading.Tasks; using Miningcore.Persistence.Model; namespace Miningcore.Persistence.Repositories @@ -32,6 +32,8 @@ public interface IBlockRepository Task UpdateBlockAsync(IDbConnection con, IDbTransaction tx, Block block); Task PageBlocksAsync(IDbConnection con, string poolId, BlockStatus[] status, int page, int pageSize); + Task PageBlocksAsyncPaged(IDbConnection con, string poolId, BlockStatus[] status, int page, int pageSize,int _start,int _end,string _order,string _sort); + Task PageBlocksAsync(IDbConnection con, BlockStatus[] status, int page, int pageSize); Task GetPendingBlocksForPoolAsync(IDbConnection con, string poolId); Task GetBlockBeforeAsync(IDbConnection con, string poolId, BlockStatus[] status, DateTime before); diff --git a/src/Miningcore/Program.cs b/src/Miningcore/Program.cs index 97f460a7..5d3bc037 100644 --- a/src/Miningcore/Program.cs +++ b/src/Miningcore/Program.cs @@ -730,10 +730,11 @@ private static void StartApi() services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddControllersAsServices() - .AddJsonOptions(options => + .AddNewtonsoftJson(options => { options.SerializerSettings.Formatting = Formatting.Indented; }); + services.AddMvc(option => option.EnableEndpointRouting = false); // Gzip Compression services.AddResponseCompression(); @@ -755,10 +756,11 @@ private static void StartApi() UseIpWhiteList(app, true, new[] { "/metrics" }, clusterConfig.Api?.MetricsIpWhitelist); app.UseResponseCompression(); - app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials()); + app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("x-total-count")); app.UseWebSockets(); app.MapWebSocketManager("/notifications", app.ApplicationServices.GetService()); app.UseMetricServer(); + app.UseMvc(); }) .UseKestrel(options => diff --git a/src/Miningcore/coins.json b/src/Miningcore/coins.json index 6701fb11..865246e3 100644 --- a/src/Miningcore/coins.json +++ b/src/Miningcore/coins.json @@ -35,6 +35,25 @@ "explorerTxLink": "https://www.blocktrail.com/BCC/tx/{0}", "explorerAccountLink": "https://www.blocktrail.com/BCC/address/{0}" }, + "devault": { + "name": "DeVault", + "symbol": "DVT", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "sha256d" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "sha256d" } ] + }, + "hasCoinbasePayload" : true, + "explorerBlockLink": "https://devault.llama.network/block/$height$", + "explorerTxLink": "https://devault.llama.network/tx/{0}", + "explorerAccountLink": "https://www.blocktrail.com/address/devault:{0}" + }, "namecoin": { "name": "Namecoin", "symbol": "NMC", @@ -286,6 +305,35 @@ "explorerTxLink": "https://bchain.info/GLT/tx/{0}", "explorerAccountLink": "https://bchain.info/GLT/addr/{0}" }, + "indexchain": { + "name": "IndexChain", + "symbol": "IDX", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "x16rv2" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "x16rv2" } ] + }, + "posBlockHasher": { + "hash": "reverse", + "args": [ + { + "hash": "x16rv2" + } + ] + }, + "hasPayees":true, + "hasMasterNodes": true, + "shareMultiplier": 4096, + "explorerBlockLink": "http://202.182.107.84/block/$hash$", + "explorerTxLink": "http://202.182.107.84/tx/{0}", + "explorerAccountLink": "http://202.182.107.84/address/{0}" + }, "mooncoin": { "name": "MoonCoin", "symbol": "MOON", @@ -389,12 +437,32 @@ "hash": "sha256d" }, "headerHasher": { - "hash": "x16s" + "hash": "x21s" + }, + "blockHasher": { + "hash": "reverse", + "args": [ { "hash": "x21s" } ] + }, + "shareMultiplier": 256, + "explorerBlockLink": "http://explorer.pigeoncoin.org/block/$hash$", + "explorerTxLink": "http://explorer.pigeoncoin.org/tx/{0}", + "explorerAccountLink": "http://explorer.pigeoncoin.org/address/{0}" + }, + "pigeoncoin-testnet": { + "name": "Pigeoncoin", + "symbol": "PGN", + "family": "bitcoin", + "coinbaseHasher": { + "hash": "sha256d" + }, + "headerHasher": { + "hash": "x21s" }, "blockHasher": { "hash": "reverse", - "args": [ { "hash": "x16s" } ] + "args": [ { "hash": "x21s" } ] }, + "hasMasterNodes":true, "shareMultiplier": 256, "explorerBlockLink": "http://explorer.pigeoncoin.org/block/$hash$", "explorerTxLink": "http://explorer.pigeoncoin.org/tx/{0}", diff --git a/src/Miningcore/linux-build.sh b/src/Miningcore/linux-build.sh index a3889448..782ae4ec 100755 --- a/src/Miningcore/linux-build.sh +++ b/src/Miningcore/linux-build.sh @@ -5,4 +5,4 @@ BUILDIR=${1:-../../build} echo "Building into $BUILDIR" -dotnet publish -c Release --framework netcoreapp2.2 -o $BUILDIR +dotnet publish -c Release --framework netcoreapp3.1 -o $BUILDIR diff --git a/src/Native/libmultihash/Makefile b/src/Native/libmultihash/Makefile index 0c1a2e26..f67c6d3a 100644 --- a/src/Native/libmultihash/Makefile +++ b/src/Native/libmultihash/Makefile @@ -12,7 +12,7 @@ OBJECTS = bcrypt.o blake.o blake2s.o c11.o dcrypt.o fresh.o lane.o \ sha3/sph_luffa.o sha3/sph_shabal.o sha3/sph_shavite.o sha3/sph_simd.o sha3/sph_skein.o sha3/sph_whirlpool.o \ sha3/sph_haval.o sha3/sph_sha2.o sha3/sph_sha2big.o sha3/sph_blake2s.o sha3/sm3.o sha3/panama.o \ sha3/extra.o sha3/gost_streebog.o sha3/sph_tiger.o sha3/SWIFFTX.o KeccakP-800-reference.o \ - shavite3.o skein.o x11.o x13.o x15.o x17.o x16r.o x16s.o x21s.o odocrypt.o x25x.o \ + shavite3.o skein.o yespower_sugarchain.o x11.o x13.o x15.o x17.o x16r.o x16rv2.o x16s.o x21s.o odocrypt.o x25x.o \ Lyra2.o Lyra2RE.o Sponge.o geek.o \ equi/util.o equi/support/cleanse.o equi/random.o \ equi/uint256.o equi/arith_uint256.o equi/crypto/hmac_sha512.o \ diff --git a/src/Native/libmultihash/exports.cpp b/src/Native/libmultihash/exports.cpp index 02194b73..efdeed46 100644 --- a/src/Native/libmultihash/exports.cpp +++ b/src/Native/libmultihash/exports.cpp @@ -43,7 +43,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "c11.h" #include "Lyra2RE.h" #include "Lyra2.h" +#include "yespower_sugarchain.h" #include "x16r.h" +#include "x16rv2.h" #include "x16s.h" #include "x21s.h" #include "x25x.h" @@ -213,11 +215,21 @@ extern "C" MODULE_API void lyra2rev3_export(const char* input, char* output) lyra2re3_hash(input, output); } +extern "C" MODULE_API void yespower_sugarchain_export(const char* input, char* output, uint32_t input_len) +{ + yespower_hash(input, output); +} + extern "C" MODULE_API void x16r_export(const char* input, char* output, uint32_t input_len) { x16r_hash(input, output, input_len); } +extern "C" MODULE_API void x16rv2_export(const char* input, char* output, uint32_t input_len) +{ + x16rv2_hash(input, output,input_len); +} + extern "C" MODULE_API void x21s_export(const char* input, char* output, uint32_t input_len) { x21s_hash(input, output, input_len); diff --git a/src/Native/libmultihash/libmultihash.vcxproj b/src/Native/libmultihash/libmultihash.vcxproj index 7522da19..9a227db1 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj +++ b/src/Native/libmultihash/libmultihash.vcxproj @@ -256,11 +256,13 @@ + + @@ -343,11 +345,14 @@ + + + diff --git a/src/Native/libmultihash/libmultihash.vcxproj.filters b/src/Native/libmultihash/libmultihash.vcxproj.filters index 0ec24faa..dd59d9c1 100644 --- a/src/Native/libmultihash/libmultihash.vcxproj.filters +++ b/src/Native/libmultihash/libmultihash.vcxproj.filters @@ -205,6 +205,9 @@ Header Files + + + Header Files Header Files @@ -481,6 +484,9 @@ Source Files + + Source Files + Source Files diff --git a/src/Native/libmultihash/sha3/sph_tiger.h b/src/Native/libmultihash/sha3/sph_tiger.h index 10191f3d..1a586853 100644 --- a/src/Native/libmultihash/sha3/sph_tiger.h +++ b/src/Native/libmultihash/sha3/sph_tiger.h @@ -188,4 +188,4 @@ void sph_tiger2_comp(const sph_u64 msg[8], sph_u64 val[3]); #endif -#endif +#endif \ No newline at end of file diff --git a/src/Native/libmultihash/tiger.c b/src/Native/libmultihash/tiger.c new file mode 100644 index 00000000..f22fcb97 --- /dev/null +++ b/src/Native/libmultihash/tiger.c @@ -0,0 +1,697 @@ +/* $Id: tiger.c 216 2010-06-08 09:46:57Z tp $ */ +/* + * Tiger / Tiger2 implementation. + * + * ==========================(LICENSE BEGIN)============================ + * + * Copyright (c) 2007-2010 Projet RNRT SAPHIR + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * ===========================(LICENSE END)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_tiger.h" + +#if SPH_64 + +static const sph_u64 T1[256] = { + SPH_C64(0x02AAB17CF7E90C5E), SPH_C64(0xAC424B03E243A8EC), + SPH_C64(0x72CD5BE30DD5FCD3), SPH_C64(0x6D019B93F6F97F3A), + SPH_C64(0xCD9978FFD21F9193), SPH_C64(0x7573A1C9708029E2), + SPH_C64(0xB164326B922A83C3), SPH_C64(0x46883EEE04915870), + SPH_C64(0xEAACE3057103ECE6), SPH_C64(0xC54169B808A3535C), + SPH_C64(0x4CE754918DDEC47C), SPH_C64(0x0AA2F4DFDC0DF40C), + SPH_C64(0x10B76F18A74DBEFA), SPH_C64(0xC6CCB6235AD1AB6A), + SPH_C64(0x13726121572FE2FF), SPH_C64(0x1A488C6F199D921E), + SPH_C64(0x4BC9F9F4DA0007CA), SPH_C64(0x26F5E6F6E85241C7), + SPH_C64(0x859079DBEA5947B6), SPH_C64(0x4F1885C5C99E8C92), + SPH_C64(0xD78E761EA96F864B), SPH_C64(0x8E36428C52B5C17D), + SPH_C64(0x69CF6827373063C1), SPH_C64(0xB607C93D9BB4C56E), + SPH_C64(0x7D820E760E76B5EA), SPH_C64(0x645C9CC6F07FDC42), + SPH_C64(0xBF38A078243342E0), SPH_C64(0x5F6B343C9D2E7D04), + SPH_C64(0xF2C28AEB600B0EC6), SPH_C64(0x6C0ED85F7254BCAC), + SPH_C64(0x71592281A4DB4FE5), SPH_C64(0x1967FA69CE0FED9F), + SPH_C64(0xFD5293F8B96545DB), SPH_C64(0xC879E9D7F2A7600B), + SPH_C64(0x860248920193194E), SPH_C64(0xA4F9533B2D9CC0B3), + SPH_C64(0x9053836C15957613), SPH_C64(0xDB6DCF8AFC357BF1), + SPH_C64(0x18BEEA7A7A370F57), SPH_C64(0x037117CA50B99066), + SPH_C64(0x6AB30A9774424A35), SPH_C64(0xF4E92F02E325249B), + SPH_C64(0x7739DB07061CCAE1), SPH_C64(0xD8F3B49CECA42A05), + SPH_C64(0xBD56BE3F51382F73), SPH_C64(0x45FAED5843B0BB28), + SPH_C64(0x1C813D5C11BF1F83), SPH_C64(0x8AF0E4B6D75FA169), + SPH_C64(0x33EE18A487AD9999), SPH_C64(0x3C26E8EAB1C94410), + SPH_C64(0xB510102BC0A822F9), SPH_C64(0x141EEF310CE6123B), + SPH_C64(0xFC65B90059DDB154), SPH_C64(0xE0158640C5E0E607), + SPH_C64(0x884E079826C3A3CF), SPH_C64(0x930D0D9523C535FD), + SPH_C64(0x35638D754E9A2B00), SPH_C64(0x4085FCCF40469DD5), + SPH_C64(0xC4B17AD28BE23A4C), SPH_C64(0xCAB2F0FC6A3E6A2E), + SPH_C64(0x2860971A6B943FCD), SPH_C64(0x3DDE6EE212E30446), + SPH_C64(0x6222F32AE01765AE), SPH_C64(0x5D550BB5478308FE), + SPH_C64(0xA9EFA98DA0EDA22A), SPH_C64(0xC351A71686C40DA7), + SPH_C64(0x1105586D9C867C84), SPH_C64(0xDCFFEE85FDA22853), + SPH_C64(0xCCFBD0262C5EEF76), SPH_C64(0xBAF294CB8990D201), + SPH_C64(0xE69464F52AFAD975), SPH_C64(0x94B013AFDF133E14), + SPH_C64(0x06A7D1A32823C958), SPH_C64(0x6F95FE5130F61119), + SPH_C64(0xD92AB34E462C06C0), SPH_C64(0xED7BDE33887C71D2), + SPH_C64(0x79746D6E6518393E), SPH_C64(0x5BA419385D713329), + SPH_C64(0x7C1BA6B948A97564), SPH_C64(0x31987C197BFDAC67), + SPH_C64(0xDE6C23C44B053D02), SPH_C64(0x581C49FED002D64D), + SPH_C64(0xDD474D6338261571), SPH_C64(0xAA4546C3E473D062), + SPH_C64(0x928FCE349455F860), SPH_C64(0x48161BBACAAB94D9), + SPH_C64(0x63912430770E6F68), SPH_C64(0x6EC8A5E602C6641C), + SPH_C64(0x87282515337DDD2B), SPH_C64(0x2CDA6B42034B701B), + SPH_C64(0xB03D37C181CB096D), SPH_C64(0xE108438266C71C6F), + SPH_C64(0x2B3180C7EB51B255), SPH_C64(0xDF92B82F96C08BBC), + SPH_C64(0x5C68C8C0A632F3BA), SPH_C64(0x5504CC861C3D0556), + SPH_C64(0xABBFA4E55FB26B8F), SPH_C64(0x41848B0AB3BACEB4), + SPH_C64(0xB334A273AA445D32), SPH_C64(0xBCA696F0A85AD881), + SPH_C64(0x24F6EC65B528D56C), SPH_C64(0x0CE1512E90F4524A), + SPH_C64(0x4E9DD79D5506D35A), SPH_C64(0x258905FAC6CE9779), + SPH_C64(0x2019295B3E109B33), SPH_C64(0xF8A9478B73A054CC), + SPH_C64(0x2924F2F934417EB0), SPH_C64(0x3993357D536D1BC4), + SPH_C64(0x38A81AC21DB6FF8B), SPH_C64(0x47C4FBF17D6016BF), + SPH_C64(0x1E0FAADD7667E3F5), SPH_C64(0x7ABCFF62938BEB96), + SPH_C64(0xA78DAD948FC179C9), SPH_C64(0x8F1F98B72911E50D), + SPH_C64(0x61E48EAE27121A91), SPH_C64(0x4D62F7AD31859808), + SPH_C64(0xECEBA345EF5CEAEB), SPH_C64(0xF5CEB25EBC9684CE), + SPH_C64(0xF633E20CB7F76221), SPH_C64(0xA32CDF06AB8293E4), + SPH_C64(0x985A202CA5EE2CA4), SPH_C64(0xCF0B8447CC8A8FB1), + SPH_C64(0x9F765244979859A3), SPH_C64(0xA8D516B1A1240017), + SPH_C64(0x0BD7BA3EBB5DC726), SPH_C64(0xE54BCA55B86ADB39), + SPH_C64(0x1D7A3AFD6C478063), SPH_C64(0x519EC608E7669EDD), + SPH_C64(0x0E5715A2D149AA23), SPH_C64(0x177D4571848FF194), + SPH_C64(0xEEB55F3241014C22), SPH_C64(0x0F5E5CA13A6E2EC2), + SPH_C64(0x8029927B75F5C361), SPH_C64(0xAD139FABC3D6E436), + SPH_C64(0x0D5DF1A94CCF402F), SPH_C64(0x3E8BD948BEA5DFC8), + SPH_C64(0xA5A0D357BD3FF77E), SPH_C64(0xA2D12E251F74F645), + SPH_C64(0x66FD9E525E81A082), SPH_C64(0x2E0C90CE7F687A49), + SPH_C64(0xC2E8BCBEBA973BC5), SPH_C64(0x000001BCE509745F), + SPH_C64(0x423777BBE6DAB3D6), SPH_C64(0xD1661C7EAEF06EB5), + SPH_C64(0xA1781F354DAACFD8), SPH_C64(0x2D11284A2B16AFFC), + SPH_C64(0xF1FC4F67FA891D1F), SPH_C64(0x73ECC25DCB920ADA), + SPH_C64(0xAE610C22C2A12651), SPH_C64(0x96E0A810D356B78A), + SPH_C64(0x5A9A381F2FE7870F), SPH_C64(0xD5AD62EDE94E5530), + SPH_C64(0xD225E5E8368D1427), SPH_C64(0x65977B70C7AF4631), + SPH_C64(0x99F889B2DE39D74F), SPH_C64(0x233F30BF54E1D143), + SPH_C64(0x9A9675D3D9A63C97), SPH_C64(0x5470554FF334F9A8), + SPH_C64(0x166ACB744A4F5688), SPH_C64(0x70C74CAAB2E4AEAD), + SPH_C64(0xF0D091646F294D12), SPH_C64(0x57B82A89684031D1), + SPH_C64(0xEFD95A5A61BE0B6B), SPH_C64(0x2FBD12E969F2F29A), + SPH_C64(0x9BD37013FEFF9FE8), SPH_C64(0x3F9B0404D6085A06), + SPH_C64(0x4940C1F3166CFE15), SPH_C64(0x09542C4DCDF3DEFB), + SPH_C64(0xB4C5218385CD5CE3), SPH_C64(0xC935B7DC4462A641), + SPH_C64(0x3417F8A68ED3B63F), SPH_C64(0xB80959295B215B40), + SPH_C64(0xF99CDAEF3B8C8572), SPH_C64(0x018C0614F8FCB95D), + SPH_C64(0x1B14ACCD1A3ACDF3), SPH_C64(0x84D471F200BB732D), + SPH_C64(0xC1A3110E95E8DA16), SPH_C64(0x430A7220BF1A82B8), + SPH_C64(0xB77E090D39DF210E), SPH_C64(0x5EF4BD9F3CD05E9D), + SPH_C64(0x9D4FF6DA7E57A444), SPH_C64(0xDA1D60E183D4A5F8), + SPH_C64(0xB287C38417998E47), SPH_C64(0xFE3EDC121BB31886), + SPH_C64(0xC7FE3CCC980CCBEF), SPH_C64(0xE46FB590189BFD03), + SPH_C64(0x3732FD469A4C57DC), SPH_C64(0x7EF700A07CF1AD65), + SPH_C64(0x59C64468A31D8859), SPH_C64(0x762FB0B4D45B61F6), + SPH_C64(0x155BAED099047718), SPH_C64(0x68755E4C3D50BAA6), + SPH_C64(0xE9214E7F22D8B4DF), SPH_C64(0x2ADDBF532EAC95F4), + SPH_C64(0x32AE3909B4BD0109), SPH_C64(0x834DF537B08E3450), + SPH_C64(0xFA209DA84220728D), SPH_C64(0x9E691D9B9EFE23F7), + SPH_C64(0x0446D288C4AE8D7F), SPH_C64(0x7B4CC524E169785B), + SPH_C64(0x21D87F0135CA1385), SPH_C64(0xCEBB400F137B8AA5), + SPH_C64(0x272E2B66580796BE), SPH_C64(0x3612264125C2B0DE), + SPH_C64(0x057702BDAD1EFBB2), SPH_C64(0xD4BABB8EACF84BE9), + SPH_C64(0x91583139641BC67B), SPH_C64(0x8BDC2DE08036E024), + SPH_C64(0x603C8156F49F68ED), SPH_C64(0xF7D236F7DBEF5111), + SPH_C64(0x9727C4598AD21E80), SPH_C64(0xA08A0896670A5FD7), + SPH_C64(0xCB4A8F4309EBA9CB), SPH_C64(0x81AF564B0F7036A1), + SPH_C64(0xC0B99AA778199ABD), SPH_C64(0x959F1EC83FC8E952), + SPH_C64(0x8C505077794A81B9), SPH_C64(0x3ACAAF8F056338F0), + SPH_C64(0x07B43F50627A6778), SPH_C64(0x4A44AB49F5ECCC77), + SPH_C64(0x3BC3D6E4B679EE98), SPH_C64(0x9CC0D4D1CF14108C), + SPH_C64(0x4406C00B206BC8A0), SPH_C64(0x82A18854C8D72D89), + SPH_C64(0x67E366B35C3C432C), SPH_C64(0xB923DD61102B37F2), + SPH_C64(0x56AB2779D884271D), SPH_C64(0xBE83E1B0FF1525AF), + SPH_C64(0xFB7C65D4217E49A9), SPH_C64(0x6BDBE0E76D48E7D4), + SPH_C64(0x08DF828745D9179E), SPH_C64(0x22EA6A9ADD53BD34), + SPH_C64(0xE36E141C5622200A), SPH_C64(0x7F805D1B8CB750EE), + SPH_C64(0xAFE5C7A59F58E837), SPH_C64(0xE27F996A4FB1C23C), + SPH_C64(0xD3867DFB0775F0D0), SPH_C64(0xD0E673DE6E88891A), + SPH_C64(0x123AEB9EAFB86C25), SPH_C64(0x30F1D5D5C145B895), + SPH_C64(0xBB434A2DEE7269E7), SPH_C64(0x78CB67ECF931FA38), + SPH_C64(0xF33B0372323BBF9C), SPH_C64(0x52D66336FB279C74), + SPH_C64(0x505F33AC0AFB4EAA), SPH_C64(0xE8A5CD99A2CCE187), + SPH_C64(0x534974801E2D30BB), SPH_C64(0x8D2D5711D5876D90), + SPH_C64(0x1F1A412891BC038E), SPH_C64(0xD6E2E71D82E56648), + SPH_C64(0x74036C3A497732B7), SPH_C64(0x89B67ED96361F5AB), + SPH_C64(0xFFED95D8F1EA02A2), SPH_C64(0xE72B3BD61464D43D), + SPH_C64(0xA6300F170BDC4820), SPH_C64(0xEBC18760ED78A77A), +}; + +static const sph_u64 T2[256] = { + SPH_C64(0xE6A6BE5A05A12138), SPH_C64(0xB5A122A5B4F87C98), + SPH_C64(0x563C6089140B6990), SPH_C64(0x4C46CB2E391F5DD5), + SPH_C64(0xD932ADDBC9B79434), SPH_C64(0x08EA70E42015AFF5), + SPH_C64(0xD765A6673E478CF1), SPH_C64(0xC4FB757EAB278D99), + SPH_C64(0xDF11C6862D6E0692), SPH_C64(0xDDEB84F10D7F3B16), + SPH_C64(0x6F2EF604A665EA04), SPH_C64(0x4A8E0F0FF0E0DFB3), + SPH_C64(0xA5EDEEF83DBCBA51), SPH_C64(0xFC4F0A2A0EA4371E), + SPH_C64(0xE83E1DA85CB38429), SPH_C64(0xDC8FF882BA1B1CE2), + SPH_C64(0xCD45505E8353E80D), SPH_C64(0x18D19A00D4DB0717), + SPH_C64(0x34A0CFEDA5F38101), SPH_C64(0x0BE77E518887CAF2), + SPH_C64(0x1E341438B3C45136), SPH_C64(0xE05797F49089CCF9), + SPH_C64(0xFFD23F9DF2591D14), SPH_C64(0x543DDA228595C5CD), + SPH_C64(0x661F81FD99052A33), SPH_C64(0x8736E641DB0F7B76), + SPH_C64(0x15227725418E5307), SPH_C64(0xE25F7F46162EB2FA), + SPH_C64(0x48A8B2126C13D9FE), SPH_C64(0xAFDC541792E76EEA), + SPH_C64(0x03D912BFC6D1898F), SPH_C64(0x31B1AAFA1B83F51B), + SPH_C64(0xF1AC2796E42AB7D9), SPH_C64(0x40A3A7D7FCD2EBAC), + SPH_C64(0x1056136D0AFBBCC5), SPH_C64(0x7889E1DD9A6D0C85), + SPH_C64(0xD33525782A7974AA), SPH_C64(0xA7E25D09078AC09B), + SPH_C64(0xBD4138B3EAC6EDD0), SPH_C64(0x920ABFBE71EB9E70), + SPH_C64(0xA2A5D0F54FC2625C), SPH_C64(0xC054E36B0B1290A3), + SPH_C64(0xF6DD59FF62FE932B), SPH_C64(0x3537354511A8AC7D), + SPH_C64(0xCA845E9172FADCD4), SPH_C64(0x84F82B60329D20DC), + SPH_C64(0x79C62CE1CD672F18), SPH_C64(0x8B09A2ADD124642C), + SPH_C64(0xD0C1E96A19D9E726), SPH_C64(0x5A786A9B4BA9500C), + SPH_C64(0x0E020336634C43F3), SPH_C64(0xC17B474AEB66D822), + SPH_C64(0x6A731AE3EC9BAAC2), SPH_C64(0x8226667AE0840258), + SPH_C64(0x67D4567691CAECA5), SPH_C64(0x1D94155C4875ADB5), + SPH_C64(0x6D00FD985B813FDF), SPH_C64(0x51286EFCB774CD06), + SPH_C64(0x5E8834471FA744AF), SPH_C64(0xF72CA0AEE761AE2E), + SPH_C64(0xBE40E4CDAEE8E09A), SPH_C64(0xE9970BBB5118F665), + SPH_C64(0x726E4BEB33DF1964), SPH_C64(0x703B000729199762), + SPH_C64(0x4631D816F5EF30A7), SPH_C64(0xB880B5B51504A6BE), + SPH_C64(0x641793C37ED84B6C), SPH_C64(0x7B21ED77F6E97D96), + SPH_C64(0x776306312EF96B73), SPH_C64(0xAE528948E86FF3F4), + SPH_C64(0x53DBD7F286A3F8F8), SPH_C64(0x16CADCE74CFC1063), + SPH_C64(0x005C19BDFA52C6DD), SPH_C64(0x68868F5D64D46AD3), + SPH_C64(0x3A9D512CCF1E186A), SPH_C64(0x367E62C2385660AE), + SPH_C64(0xE359E7EA77DCB1D7), SPH_C64(0x526C0773749ABE6E), + SPH_C64(0x735AE5F9D09F734B), SPH_C64(0x493FC7CC8A558BA8), + SPH_C64(0xB0B9C1533041AB45), SPH_C64(0x321958BA470A59BD), + SPH_C64(0x852DB00B5F46C393), SPH_C64(0x91209B2BD336B0E5), + SPH_C64(0x6E604F7D659EF19F), SPH_C64(0xB99A8AE2782CCB24), + SPH_C64(0xCCF52AB6C814C4C7), SPH_C64(0x4727D9AFBE11727B), + SPH_C64(0x7E950D0C0121B34D), SPH_C64(0x756F435670AD471F), + SPH_C64(0xF5ADD442615A6849), SPH_C64(0x4E87E09980B9957A), + SPH_C64(0x2ACFA1DF50AEE355), SPH_C64(0xD898263AFD2FD556), + SPH_C64(0xC8F4924DD80C8FD6), SPH_C64(0xCF99CA3D754A173A), + SPH_C64(0xFE477BACAF91BF3C), SPH_C64(0xED5371F6D690C12D), + SPH_C64(0x831A5C285E687094), SPH_C64(0xC5D3C90A3708A0A4), + SPH_C64(0x0F7F903717D06580), SPH_C64(0x19F9BB13B8FDF27F), + SPH_C64(0xB1BD6F1B4D502843), SPH_C64(0x1C761BA38FFF4012), + SPH_C64(0x0D1530C4E2E21F3B), SPH_C64(0x8943CE69A7372C8A), + SPH_C64(0xE5184E11FEB5CE66), SPH_C64(0x618BDB80BD736621), + SPH_C64(0x7D29BAD68B574D0B), SPH_C64(0x81BB613E25E6FE5B), + SPH_C64(0x071C9C10BC07913F), SPH_C64(0xC7BEEB7909AC2D97), + SPH_C64(0xC3E58D353BC5D757), SPH_C64(0xEB017892F38F61E8), + SPH_C64(0xD4EFFB9C9B1CC21A), SPH_C64(0x99727D26F494F7AB), + SPH_C64(0xA3E063A2956B3E03), SPH_C64(0x9D4A8B9A4AA09C30), + SPH_C64(0x3F6AB7D500090FB4), SPH_C64(0x9CC0F2A057268AC0), + SPH_C64(0x3DEE9D2DEDBF42D1), SPH_C64(0x330F49C87960A972), + SPH_C64(0xC6B2720287421B41), SPH_C64(0x0AC59EC07C00369C), + SPH_C64(0xEF4EAC49CB353425), SPH_C64(0xF450244EEF0129D8), + SPH_C64(0x8ACC46E5CAF4DEB6), SPH_C64(0x2FFEAB63989263F7), + SPH_C64(0x8F7CB9FE5D7A4578), SPH_C64(0x5BD8F7644E634635), + SPH_C64(0x427A7315BF2DC900), SPH_C64(0x17D0C4AA2125261C), + SPH_C64(0x3992486C93518E50), SPH_C64(0xB4CBFEE0A2D7D4C3), + SPH_C64(0x7C75D6202C5DDD8D), SPH_C64(0xDBC295D8E35B6C61), + SPH_C64(0x60B369D302032B19), SPH_C64(0xCE42685FDCE44132), + SPH_C64(0x06F3DDB9DDF65610), SPH_C64(0x8EA4D21DB5E148F0), + SPH_C64(0x20B0FCE62FCD496F), SPH_C64(0x2C1B912358B0EE31), + SPH_C64(0xB28317B818F5A308), SPH_C64(0xA89C1E189CA6D2CF), + SPH_C64(0x0C6B18576AAADBC8), SPH_C64(0xB65DEAA91299FAE3), + SPH_C64(0xFB2B794B7F1027E7), SPH_C64(0x04E4317F443B5BEB), + SPH_C64(0x4B852D325939D0A6), SPH_C64(0xD5AE6BEEFB207FFC), + SPH_C64(0x309682B281C7D374), SPH_C64(0xBAE309A194C3B475), + SPH_C64(0x8CC3F97B13B49F05), SPH_C64(0x98A9422FF8293967), + SPH_C64(0x244B16B01076FF7C), SPH_C64(0xF8BF571C663D67EE), + SPH_C64(0x1F0D6758EEE30DA1), SPH_C64(0xC9B611D97ADEB9B7), + SPH_C64(0xB7AFD5887B6C57A2), SPH_C64(0x6290AE846B984FE1), + SPH_C64(0x94DF4CDEACC1A5FD), SPH_C64(0x058A5BD1C5483AFF), + SPH_C64(0x63166CC142BA3C37), SPH_C64(0x8DB8526EB2F76F40), + SPH_C64(0xE10880036F0D6D4E), SPH_C64(0x9E0523C9971D311D), + SPH_C64(0x45EC2824CC7CD691), SPH_C64(0x575B8359E62382C9), + SPH_C64(0xFA9E400DC4889995), SPH_C64(0xD1823ECB45721568), + SPH_C64(0xDAFD983B8206082F), SPH_C64(0xAA7D29082386A8CB), + SPH_C64(0x269FCD4403B87588), SPH_C64(0x1B91F5F728BDD1E0), + SPH_C64(0xE4669F39040201F6), SPH_C64(0x7A1D7C218CF04ADE), + SPH_C64(0x65623C29D79CE5CE), SPH_C64(0x2368449096C00BB1), + SPH_C64(0xAB9BF1879DA503BA), SPH_C64(0xBC23ECB1A458058E), + SPH_C64(0x9A58DF01BB401ECC), SPH_C64(0xA070E868A85F143D), + SPH_C64(0x4FF188307DF2239E), SPH_C64(0x14D565B41A641183), + SPH_C64(0xEE13337452701602), SPH_C64(0x950E3DCF3F285E09), + SPH_C64(0x59930254B9C80953), SPH_C64(0x3BF299408930DA6D), + SPH_C64(0xA955943F53691387), SPH_C64(0xA15EDECAA9CB8784), + SPH_C64(0x29142127352BE9A0), SPH_C64(0x76F0371FFF4E7AFB), + SPH_C64(0x0239F450274F2228), SPH_C64(0xBB073AF01D5E868B), + SPH_C64(0xBFC80571C10E96C1), SPH_C64(0xD267088568222E23), + SPH_C64(0x9671A3D48E80B5B0), SPH_C64(0x55B5D38AE193BB81), + SPH_C64(0x693AE2D0A18B04B8), SPH_C64(0x5C48B4ECADD5335F), + SPH_C64(0xFD743B194916A1CA), SPH_C64(0x2577018134BE98C4), + SPH_C64(0xE77987E83C54A4AD), SPH_C64(0x28E11014DA33E1B9), + SPH_C64(0x270CC59E226AA213), SPH_C64(0x71495F756D1A5F60), + SPH_C64(0x9BE853FB60AFEF77), SPH_C64(0xADC786A7F7443DBF), + SPH_C64(0x0904456173B29A82), SPH_C64(0x58BC7A66C232BD5E), + SPH_C64(0xF306558C673AC8B2), SPH_C64(0x41F639C6B6C9772A), + SPH_C64(0x216DEFE99FDA35DA), SPH_C64(0x11640CC71C7BE615), + SPH_C64(0x93C43694565C5527), SPH_C64(0xEA038E6246777839), + SPH_C64(0xF9ABF3CE5A3E2469), SPH_C64(0x741E768D0FD312D2), + SPH_C64(0x0144B883CED652C6), SPH_C64(0xC20B5A5BA33F8552), + SPH_C64(0x1AE69633C3435A9D), SPH_C64(0x97A28CA4088CFDEC), + SPH_C64(0x8824A43C1E96F420), SPH_C64(0x37612FA66EEEA746), + SPH_C64(0x6B4CB165F9CF0E5A), SPH_C64(0x43AA1C06A0ABFB4A), + SPH_C64(0x7F4DC26FF162796B), SPH_C64(0x6CBACC8E54ED9B0F), + SPH_C64(0xA6B7FFEFD2BB253E), SPH_C64(0x2E25BC95B0A29D4F), + SPH_C64(0x86D6A58BDEF1388C), SPH_C64(0xDED74AC576B6F054), + SPH_C64(0x8030BDBC2B45805D), SPH_C64(0x3C81AF70E94D9289), + SPH_C64(0x3EFF6DDA9E3100DB), SPH_C64(0xB38DC39FDFCC8847), + SPH_C64(0x123885528D17B87E), SPH_C64(0xF2DA0ED240B1B642), + SPH_C64(0x44CEFADCD54BF9A9), SPH_C64(0x1312200E433C7EE6), + SPH_C64(0x9FFCC84F3A78C748), SPH_C64(0xF0CD1F72248576BB), + SPH_C64(0xEC6974053638CFE4), SPH_C64(0x2BA7B67C0CEC4E4C), + SPH_C64(0xAC2F4DF3E5CE32ED), SPH_C64(0xCB33D14326EA4C11), + SPH_C64(0xA4E9044CC77E58BC), SPH_C64(0x5F513293D934FCEF), + SPH_C64(0x5DC9645506E55444), SPH_C64(0x50DE418F317DE40A), + SPH_C64(0x388CB31A69DDE259), SPH_C64(0x2DB4A83455820A86), + SPH_C64(0x9010A91E84711AE9), SPH_C64(0x4DF7F0B7B1498371), + SPH_C64(0xD62A2EABC0977179), SPH_C64(0x22FAC097AA8D5C0E), +}; + +static const sph_u64 T3[256] = { + SPH_C64(0xF49FCC2FF1DAF39B), SPH_C64(0x487FD5C66FF29281), + SPH_C64(0xE8A30667FCDCA83F), SPH_C64(0x2C9B4BE3D2FCCE63), + SPH_C64(0xDA3FF74B93FBBBC2), SPH_C64(0x2FA165D2FE70BA66), + SPH_C64(0xA103E279970E93D4), SPH_C64(0xBECDEC77B0E45E71), + SPH_C64(0xCFB41E723985E497), SPH_C64(0xB70AAA025EF75017), + SPH_C64(0xD42309F03840B8E0), SPH_C64(0x8EFC1AD035898579), + SPH_C64(0x96C6920BE2B2ABC5), SPH_C64(0x66AF4163375A9172), + SPH_C64(0x2174ABDCCA7127FB), SPH_C64(0xB33CCEA64A72FF41), + SPH_C64(0xF04A4933083066A5), SPH_C64(0x8D970ACDD7289AF5), + SPH_C64(0x8F96E8E031C8C25E), SPH_C64(0xF3FEC02276875D47), + SPH_C64(0xEC7BF310056190DD), SPH_C64(0xF5ADB0AEBB0F1491), + SPH_C64(0x9B50F8850FD58892), SPH_C64(0x4975488358B74DE8), + SPH_C64(0xA3354FF691531C61), SPH_C64(0x0702BBE481D2C6EE), + SPH_C64(0x89FB24057DEDED98), SPH_C64(0xAC3075138596E902), + SPH_C64(0x1D2D3580172772ED), SPH_C64(0xEB738FC28E6BC30D), + SPH_C64(0x5854EF8F63044326), SPH_C64(0x9E5C52325ADD3BBE), + SPH_C64(0x90AA53CF325C4623), SPH_C64(0xC1D24D51349DD067), + SPH_C64(0x2051CFEEA69EA624), SPH_C64(0x13220F0A862E7E4F), + SPH_C64(0xCE39399404E04864), SPH_C64(0xD9C42CA47086FCB7), + SPH_C64(0x685AD2238A03E7CC), SPH_C64(0x066484B2AB2FF1DB), + SPH_C64(0xFE9D5D70EFBF79EC), SPH_C64(0x5B13B9DD9C481854), + SPH_C64(0x15F0D475ED1509AD), SPH_C64(0x0BEBCD060EC79851), + SPH_C64(0xD58C6791183AB7F8), SPH_C64(0xD1187C5052F3EEE4), + SPH_C64(0xC95D1192E54E82FF), SPH_C64(0x86EEA14CB9AC6CA2), + SPH_C64(0x3485BEB153677D5D), SPH_C64(0xDD191D781F8C492A), + SPH_C64(0xF60866BAA784EBF9), SPH_C64(0x518F643BA2D08C74), + SPH_C64(0x8852E956E1087C22), SPH_C64(0xA768CB8DC410AE8D), + SPH_C64(0x38047726BFEC8E1A), SPH_C64(0xA67738B4CD3B45AA), + SPH_C64(0xAD16691CEC0DDE19), SPH_C64(0xC6D4319380462E07), + SPH_C64(0xC5A5876D0BA61938), SPH_C64(0x16B9FA1FA58FD840), + SPH_C64(0x188AB1173CA74F18), SPH_C64(0xABDA2F98C99C021F), + SPH_C64(0x3E0580AB134AE816), SPH_C64(0x5F3B05B773645ABB), + SPH_C64(0x2501A2BE5575F2F6), SPH_C64(0x1B2F74004E7E8BA9), + SPH_C64(0x1CD7580371E8D953), SPH_C64(0x7F6ED89562764E30), + SPH_C64(0xB15926FF596F003D), SPH_C64(0x9F65293DA8C5D6B9), + SPH_C64(0x6ECEF04DD690F84C), SPH_C64(0x4782275FFF33AF88), + SPH_C64(0xE41433083F820801), SPH_C64(0xFD0DFE409A1AF9B5), + SPH_C64(0x4325A3342CDB396B), SPH_C64(0x8AE77E62B301B252), + SPH_C64(0xC36F9E9F6655615A), SPH_C64(0x85455A2D92D32C09), + SPH_C64(0xF2C7DEA949477485), SPH_C64(0x63CFB4C133A39EBA), + SPH_C64(0x83B040CC6EBC5462), SPH_C64(0x3B9454C8FDB326B0), + SPH_C64(0x56F56A9E87FFD78C), SPH_C64(0x2DC2940D99F42BC6), + SPH_C64(0x98F7DF096B096E2D), SPH_C64(0x19A6E01E3AD852BF), + SPH_C64(0x42A99CCBDBD4B40B), SPH_C64(0xA59998AF45E9C559), + SPH_C64(0x366295E807D93186), SPH_C64(0x6B48181BFAA1F773), + SPH_C64(0x1FEC57E2157A0A1D), SPH_C64(0x4667446AF6201AD5), + SPH_C64(0xE615EBCACFB0F075), SPH_C64(0xB8F31F4F68290778), + SPH_C64(0x22713ED6CE22D11E), SPH_C64(0x3057C1A72EC3C93B), + SPH_C64(0xCB46ACC37C3F1F2F), SPH_C64(0xDBB893FD02AAF50E), + SPH_C64(0x331FD92E600B9FCF), SPH_C64(0xA498F96148EA3AD6), + SPH_C64(0xA8D8426E8B6A83EA), SPH_C64(0xA089B274B7735CDC), + SPH_C64(0x87F6B3731E524A11), SPH_C64(0x118808E5CBC96749), + SPH_C64(0x9906E4C7B19BD394), SPH_C64(0xAFED7F7E9B24A20C), + SPH_C64(0x6509EADEEB3644A7), SPH_C64(0x6C1EF1D3E8EF0EDE), + SPH_C64(0xB9C97D43E9798FB4), SPH_C64(0xA2F2D784740C28A3), + SPH_C64(0x7B8496476197566F), SPH_C64(0x7A5BE3E6B65F069D), + SPH_C64(0xF96330ED78BE6F10), SPH_C64(0xEEE60DE77A076A15), + SPH_C64(0x2B4BEE4AA08B9BD0), SPH_C64(0x6A56A63EC7B8894E), + SPH_C64(0x02121359BA34FEF4), SPH_C64(0x4CBF99F8283703FC), + SPH_C64(0x398071350CAF30C8), SPH_C64(0xD0A77A89F017687A), + SPH_C64(0xF1C1A9EB9E423569), SPH_C64(0x8C7976282DEE8199), + SPH_C64(0x5D1737A5DD1F7ABD), SPH_C64(0x4F53433C09A9FA80), + SPH_C64(0xFA8B0C53DF7CA1D9), SPH_C64(0x3FD9DCBC886CCB77), + SPH_C64(0xC040917CA91B4720), SPH_C64(0x7DD00142F9D1DCDF), + SPH_C64(0x8476FC1D4F387B58), SPH_C64(0x23F8E7C5F3316503), + SPH_C64(0x032A2244E7E37339), SPH_C64(0x5C87A5D750F5A74B), + SPH_C64(0x082B4CC43698992E), SPH_C64(0xDF917BECB858F63C), + SPH_C64(0x3270B8FC5BF86DDA), SPH_C64(0x10AE72BB29B5DD76), + SPH_C64(0x576AC94E7700362B), SPH_C64(0x1AD112DAC61EFB8F), + SPH_C64(0x691BC30EC5FAA427), SPH_C64(0xFF246311CC327143), + SPH_C64(0x3142368E30E53206), SPH_C64(0x71380E31E02CA396), + SPH_C64(0x958D5C960AAD76F1), SPH_C64(0xF8D6F430C16DA536), + SPH_C64(0xC8FFD13F1BE7E1D2), SPH_C64(0x7578AE66004DDBE1), + SPH_C64(0x05833F01067BE646), SPH_C64(0xBB34B5AD3BFE586D), + SPH_C64(0x095F34C9A12B97F0), SPH_C64(0x247AB64525D60CA8), + SPH_C64(0xDCDBC6F3017477D1), SPH_C64(0x4A2E14D4DECAD24D), + SPH_C64(0xBDB5E6D9BE0A1EEB), SPH_C64(0x2A7E70F7794301AB), + SPH_C64(0xDEF42D8A270540FD), SPH_C64(0x01078EC0A34C22C1), + SPH_C64(0xE5DE511AF4C16387), SPH_C64(0x7EBB3A52BD9A330A), + SPH_C64(0x77697857AA7D6435), SPH_C64(0x004E831603AE4C32), + SPH_C64(0xE7A21020AD78E312), SPH_C64(0x9D41A70C6AB420F2), + SPH_C64(0x28E06C18EA1141E6), SPH_C64(0xD2B28CBD984F6B28), + SPH_C64(0x26B75F6C446E9D83), SPH_C64(0xBA47568C4D418D7F), + SPH_C64(0xD80BADBFE6183D8E), SPH_C64(0x0E206D7F5F166044), + SPH_C64(0xE258A43911CBCA3E), SPH_C64(0x723A1746B21DC0BC), + SPH_C64(0xC7CAA854F5D7CDD3), SPH_C64(0x7CAC32883D261D9C), + SPH_C64(0x7690C26423BA942C), SPH_C64(0x17E55524478042B8), + SPH_C64(0xE0BE477656A2389F), SPH_C64(0x4D289B5E67AB2DA0), + SPH_C64(0x44862B9C8FBBFD31), SPH_C64(0xB47CC8049D141365), + SPH_C64(0x822C1B362B91C793), SPH_C64(0x4EB14655FB13DFD8), + SPH_C64(0x1ECBBA0714E2A97B), SPH_C64(0x6143459D5CDE5F14), + SPH_C64(0x53A8FBF1D5F0AC89), SPH_C64(0x97EA04D81C5E5B00), + SPH_C64(0x622181A8D4FDB3F3), SPH_C64(0xE9BCD341572A1208), + SPH_C64(0x1411258643CCE58A), SPH_C64(0x9144C5FEA4C6E0A4), + SPH_C64(0x0D33D06565CF620F), SPH_C64(0x54A48D489F219CA1), + SPH_C64(0xC43E5EAC6D63C821), SPH_C64(0xA9728B3A72770DAF), + SPH_C64(0xD7934E7B20DF87EF), SPH_C64(0xE35503B61A3E86E5), + SPH_C64(0xCAE321FBC819D504), SPH_C64(0x129A50B3AC60BFA6), + SPH_C64(0xCD5E68EA7E9FB6C3), SPH_C64(0xB01C90199483B1C7), + SPH_C64(0x3DE93CD5C295376C), SPH_C64(0xAED52EDF2AB9AD13), + SPH_C64(0x2E60F512C0A07884), SPH_C64(0xBC3D86A3E36210C9), + SPH_C64(0x35269D9B163951CE), SPH_C64(0x0C7D6E2AD0CDB5FA), + SPH_C64(0x59E86297D87F5733), SPH_C64(0x298EF221898DB0E7), + SPH_C64(0x55000029D1A5AA7E), SPH_C64(0x8BC08AE1B5061B45), + SPH_C64(0xC2C31C2B6C92703A), SPH_C64(0x94CC596BAF25EF42), + SPH_C64(0x0A1D73DB22540456), SPH_C64(0x04B6A0F9D9C4179A), + SPH_C64(0xEFFDAFA2AE3D3C60), SPH_C64(0xF7C8075BB49496C4), + SPH_C64(0x9CC5C7141D1CD4E3), SPH_C64(0x78BD1638218E5534), + SPH_C64(0xB2F11568F850246A), SPH_C64(0xEDFABCFA9502BC29), + SPH_C64(0x796CE5F2DA23051B), SPH_C64(0xAAE128B0DC93537C), + SPH_C64(0x3A493DA0EE4B29AE), SPH_C64(0xB5DF6B2C416895D7), + SPH_C64(0xFCABBD25122D7F37), SPH_C64(0x70810B58105DC4B1), + SPH_C64(0xE10FDD37F7882A90), SPH_C64(0x524DCAB5518A3F5C), + SPH_C64(0x3C9E85878451255B), SPH_C64(0x4029828119BD34E2), + SPH_C64(0x74A05B6F5D3CECCB), SPH_C64(0xB610021542E13ECA), + SPH_C64(0x0FF979D12F59E2AC), SPH_C64(0x6037DA27E4F9CC50), + SPH_C64(0x5E92975A0DF1847D), SPH_C64(0xD66DE190D3E623FE), + SPH_C64(0x5032D6B87B568048), SPH_C64(0x9A36B7CE8235216E), + SPH_C64(0x80272A7A24F64B4A), SPH_C64(0x93EFED8B8C6916F7), + SPH_C64(0x37DDBFF44CCE1555), SPH_C64(0x4B95DB5D4B99BD25), + SPH_C64(0x92D3FDA169812FC0), SPH_C64(0xFB1A4A9A90660BB6), + SPH_C64(0x730C196946A4B9B2), SPH_C64(0x81E289AA7F49DA68), + SPH_C64(0x64669A0F83B1A05F), SPH_C64(0x27B3FF7D9644F48B), + SPH_C64(0xCC6B615C8DB675B3), SPH_C64(0x674F20B9BCEBBE95), + SPH_C64(0x6F31238275655982), SPH_C64(0x5AE488713E45CF05), + SPH_C64(0xBF619F9954C21157), SPH_C64(0xEABAC46040A8EAE9), + SPH_C64(0x454C6FE9F2C0C1CD), SPH_C64(0x419CF6496412691C), + SPH_C64(0xD3DC3BEF265B0F70), SPH_C64(0x6D0E60F5C3578A9E), +}; + +static const sph_u64 T4[256] = { + SPH_C64(0x5B0E608526323C55), SPH_C64(0x1A46C1A9FA1B59F5), + SPH_C64(0xA9E245A17C4C8FFA), SPH_C64(0x65CA5159DB2955D7), + SPH_C64(0x05DB0A76CE35AFC2), SPH_C64(0x81EAC77EA9113D45), + SPH_C64(0x528EF88AB6AC0A0D), SPH_C64(0xA09EA253597BE3FF), + SPH_C64(0x430DDFB3AC48CD56), SPH_C64(0xC4B3A67AF45CE46F), + SPH_C64(0x4ECECFD8FBE2D05E), SPH_C64(0x3EF56F10B39935F0), + SPH_C64(0x0B22D6829CD619C6), SPH_C64(0x17FD460A74DF2069), + SPH_C64(0x6CF8CC8E8510ED40), SPH_C64(0xD6C824BF3A6ECAA7), + SPH_C64(0x61243D581A817049), SPH_C64(0x048BACB6BBC163A2), + SPH_C64(0xD9A38AC27D44CC32), SPH_C64(0x7FDDFF5BAAF410AB), + SPH_C64(0xAD6D495AA804824B), SPH_C64(0xE1A6A74F2D8C9F94), + SPH_C64(0xD4F7851235DEE8E3), SPH_C64(0xFD4B7F886540D893), + SPH_C64(0x247C20042AA4BFDA), SPH_C64(0x096EA1C517D1327C), + SPH_C64(0xD56966B4361A6685), SPH_C64(0x277DA5C31221057D), + SPH_C64(0x94D59893A43ACFF7), SPH_C64(0x64F0C51CCDC02281), + SPH_C64(0x3D33BCC4FF6189DB), SPH_C64(0xE005CB184CE66AF1), + SPH_C64(0xFF5CCD1D1DB99BEA), SPH_C64(0xB0B854A7FE42980F), + SPH_C64(0x7BD46A6A718D4B9F), SPH_C64(0xD10FA8CC22A5FD8C), + SPH_C64(0xD31484952BE4BD31), SPH_C64(0xC7FA975FCB243847), + SPH_C64(0x4886ED1E5846C407), SPH_C64(0x28CDDB791EB70B04), + SPH_C64(0xC2B00BE2F573417F), SPH_C64(0x5C9590452180F877), + SPH_C64(0x7A6BDDFFF370EB00), SPH_C64(0xCE509E38D6D9D6A4), + SPH_C64(0xEBEB0F00647FA702), SPH_C64(0x1DCC06CF76606F06), + SPH_C64(0xE4D9F28BA286FF0A), SPH_C64(0xD85A305DC918C262), + SPH_C64(0x475B1D8732225F54), SPH_C64(0x2D4FB51668CCB5FE), + SPH_C64(0xA679B9D9D72BBA20), SPH_C64(0x53841C0D912D43A5), + SPH_C64(0x3B7EAA48BF12A4E8), SPH_C64(0x781E0E47F22F1DDF), + SPH_C64(0xEFF20CE60AB50973), SPH_C64(0x20D261D19DFFB742), + SPH_C64(0x16A12B03062A2E39), SPH_C64(0x1960EB2239650495), + SPH_C64(0x251C16FED50EB8B8), SPH_C64(0x9AC0C330F826016E), + SPH_C64(0xED152665953E7671), SPH_C64(0x02D63194A6369570), + SPH_C64(0x5074F08394B1C987), SPH_C64(0x70BA598C90B25CE1), + SPH_C64(0x794A15810B9742F6), SPH_C64(0x0D5925E9FCAF8C6C), + SPH_C64(0x3067716CD868744E), SPH_C64(0x910AB077E8D7731B), + SPH_C64(0x6A61BBDB5AC42F61), SPH_C64(0x93513EFBF0851567), + SPH_C64(0xF494724B9E83E9D5), SPH_C64(0xE887E1985C09648D), + SPH_C64(0x34B1D3C675370CFD), SPH_C64(0xDC35E433BC0D255D), + SPH_C64(0xD0AAB84234131BE0), SPH_C64(0x08042A50B48B7EAF), + SPH_C64(0x9997C4EE44A3AB35), SPH_C64(0x829A7B49201799D0), + SPH_C64(0x263B8307B7C54441), SPH_C64(0x752F95F4FD6A6CA6), + SPH_C64(0x927217402C08C6E5), SPH_C64(0x2A8AB754A795D9EE), + SPH_C64(0xA442F7552F72943D), SPH_C64(0x2C31334E19781208), + SPH_C64(0x4FA98D7CEAEE6291), SPH_C64(0x55C3862F665DB309), + SPH_C64(0xBD0610175D53B1F3), SPH_C64(0x46FE6CB840413F27), + SPH_C64(0x3FE03792DF0CFA59), SPH_C64(0xCFE700372EB85E8F), + SPH_C64(0xA7BE29E7ADBCE118), SPH_C64(0xE544EE5CDE8431DD), + SPH_C64(0x8A781B1B41F1873E), SPH_C64(0xA5C94C78A0D2F0E7), + SPH_C64(0x39412E2877B60728), SPH_C64(0xA1265EF3AFC9A62C), + SPH_C64(0xBCC2770C6A2506C5), SPH_C64(0x3AB66DD5DCE1CE12), + SPH_C64(0xE65499D04A675B37), SPH_C64(0x7D8F523481BFD216), + SPH_C64(0x0F6F64FCEC15F389), SPH_C64(0x74EFBE618B5B13C8), + SPH_C64(0xACDC82B714273E1D), SPH_C64(0xDD40BFE003199D17), + SPH_C64(0x37E99257E7E061F8), SPH_C64(0xFA52626904775AAA), + SPH_C64(0x8BBBF63A463D56F9), SPH_C64(0xF0013F1543A26E64), + SPH_C64(0xA8307E9F879EC898), SPH_C64(0xCC4C27A4150177CC), + SPH_C64(0x1B432F2CCA1D3348), SPH_C64(0xDE1D1F8F9F6FA013), + SPH_C64(0x606602A047A7DDD6), SPH_C64(0xD237AB64CC1CB2C7), + SPH_C64(0x9B938E7225FCD1D3), SPH_C64(0xEC4E03708E0FF476), + SPH_C64(0xFEB2FBDA3D03C12D), SPH_C64(0xAE0BCED2EE43889A), + SPH_C64(0x22CB8923EBFB4F43), SPH_C64(0x69360D013CF7396D), + SPH_C64(0x855E3602D2D4E022), SPH_C64(0x073805BAD01F784C), + SPH_C64(0x33E17A133852F546), SPH_C64(0xDF4874058AC7B638), + SPH_C64(0xBA92B29C678AA14A), SPH_C64(0x0CE89FC76CFAADCD), + SPH_C64(0x5F9D4E0908339E34), SPH_C64(0xF1AFE9291F5923B9), + SPH_C64(0x6E3480F60F4A265F), SPH_C64(0xEEBF3A2AB29B841C), + SPH_C64(0xE21938A88F91B4AD), SPH_C64(0x57DFEFF845C6D3C3), + SPH_C64(0x2F006B0BF62CAAF2), SPH_C64(0x62F479EF6F75EE78), + SPH_C64(0x11A55AD41C8916A9), SPH_C64(0xF229D29084FED453), + SPH_C64(0x42F1C27B16B000E6), SPH_C64(0x2B1F76749823C074), + SPH_C64(0x4B76ECA3C2745360), SPH_C64(0x8C98F463B91691BD), + SPH_C64(0x14BCC93CF1ADE66A), SPH_C64(0x8885213E6D458397), + SPH_C64(0x8E177DF0274D4711), SPH_C64(0xB49B73B5503F2951), + SPH_C64(0x10168168C3F96B6B), SPH_C64(0x0E3D963B63CAB0AE), + SPH_C64(0x8DFC4B5655A1DB14), SPH_C64(0xF789F1356E14DE5C), + SPH_C64(0x683E68AF4E51DAC1), SPH_C64(0xC9A84F9D8D4B0FD9), + SPH_C64(0x3691E03F52A0F9D1), SPH_C64(0x5ED86E46E1878E80), + SPH_C64(0x3C711A0E99D07150), SPH_C64(0x5A0865B20C4E9310), + SPH_C64(0x56FBFC1FE4F0682E), SPH_C64(0xEA8D5DE3105EDF9B), + SPH_C64(0x71ABFDB12379187A), SPH_C64(0x2EB99DE1BEE77B9C), + SPH_C64(0x21ECC0EA33CF4523), SPH_C64(0x59A4D7521805C7A1), + SPH_C64(0x3896F5EB56AE7C72), SPH_C64(0xAA638F3DB18F75DC), + SPH_C64(0x9F39358DABE9808E), SPH_C64(0xB7DEFA91C00B72AC), + SPH_C64(0x6B5541FD62492D92), SPH_C64(0x6DC6DEE8F92E4D5B), + SPH_C64(0x353F57ABC4BEEA7E), SPH_C64(0x735769D6DA5690CE), + SPH_C64(0x0A234AA642391484), SPH_C64(0xF6F9508028F80D9D), + SPH_C64(0xB8E319A27AB3F215), SPH_C64(0x31AD9C1151341A4D), + SPH_C64(0x773C22A57BEF5805), SPH_C64(0x45C7561A07968633), + SPH_C64(0xF913DA9E249DBE36), SPH_C64(0xDA652D9B78A64C68), + SPH_C64(0x4C27A97F3BC334EF), SPH_C64(0x76621220E66B17F4), + SPH_C64(0x967743899ACD7D0B), SPH_C64(0xF3EE5BCAE0ED6782), + SPH_C64(0x409F753600C879FC), SPH_C64(0x06D09A39B5926DB6), + SPH_C64(0x6F83AEB0317AC588), SPH_C64(0x01E6CA4A86381F21), + SPH_C64(0x66FF3462D19F3025), SPH_C64(0x72207C24DDFD3BFB), + SPH_C64(0x4AF6B6D3E2ECE2EB), SPH_C64(0x9C994DBEC7EA08DE), + SPH_C64(0x49ACE597B09A8BC4), SPH_C64(0xB38C4766CF0797BA), + SPH_C64(0x131B9373C57C2A75), SPH_C64(0xB1822CCE61931E58), + SPH_C64(0x9D7555B909BA1C0C), SPH_C64(0x127FAFDD937D11D2), + SPH_C64(0x29DA3BADC66D92E4), SPH_C64(0xA2C1D57154C2ECBC), + SPH_C64(0x58C5134D82F6FE24), SPH_C64(0x1C3AE3515B62274F), + SPH_C64(0xE907C82E01CB8126), SPH_C64(0xF8ED091913E37FCB), + SPH_C64(0x3249D8F9C80046C9), SPH_C64(0x80CF9BEDE388FB63), + SPH_C64(0x1881539A116CF19E), SPH_C64(0x5103F3F76BD52457), + SPH_C64(0x15B7E6F5AE47F7A8), SPH_C64(0xDBD7C6DED47E9CCF), + SPH_C64(0x44E55C410228BB1A), SPH_C64(0xB647D4255EDB4E99), + SPH_C64(0x5D11882BB8AAFC30), SPH_C64(0xF5098BBB29D3212A), + SPH_C64(0x8FB5EA14E90296B3), SPH_C64(0x677B942157DD025A), + SPH_C64(0xFB58E7C0A390ACB5), SPH_C64(0x89D3674C83BD4A01), + SPH_C64(0x9E2DA4DF4BF3B93B), SPH_C64(0xFCC41E328CAB4829), + SPH_C64(0x03F38C96BA582C52), SPH_C64(0xCAD1BDBD7FD85DB2), + SPH_C64(0xBBB442C16082AE83), SPH_C64(0xB95FE86BA5DA9AB0), + SPH_C64(0xB22E04673771A93F), SPH_C64(0x845358C9493152D8), + SPH_C64(0xBE2A488697B4541E), SPH_C64(0x95A2DC2DD38E6966), + SPH_C64(0xC02C11AC923C852B), SPH_C64(0x2388B1990DF2A87B), + SPH_C64(0x7C8008FA1B4F37BE), SPH_C64(0x1F70D0C84D54E503), + SPH_C64(0x5490ADEC7ECE57D4), SPH_C64(0x002B3C27D9063A3A), + SPH_C64(0x7EAEA3848030A2BF), SPH_C64(0xC602326DED2003C0), + SPH_C64(0x83A7287D69A94086), SPH_C64(0xC57A5FCB30F57A8A), + SPH_C64(0xB56844E479EBE779), SPH_C64(0xA373B40F05DCBCE9), + SPH_C64(0xD71A786E88570EE2), SPH_C64(0x879CBACDBDE8F6A0), + SPH_C64(0x976AD1BCC164A32F), SPH_C64(0xAB21E25E9666D78B), + SPH_C64(0x901063AAE5E5C33C), SPH_C64(0x9818B34448698D90), + SPH_C64(0xE36487AE3E1E8ABB), SPH_C64(0xAFBDF931893BDCB4), + SPH_C64(0x6345A0DC5FBBD519), SPH_C64(0x8628FE269B9465CA), + SPH_C64(0x1E5D01603F9C51EC), SPH_C64(0x4DE44006A15049B7), + SPH_C64(0xBF6C70E5F776CBB1), SPH_C64(0x411218F2EF552BED), + SPH_C64(0xCB0C0708705A36A3), SPH_C64(0xE74D14754F986044), + SPH_C64(0xCD56D9430EA8280E), SPH_C64(0xC12591D7535F5065), + SPH_C64(0xC83223F1720AEF96), SPH_C64(0xC3A0396F7363A51F), +}; + +#define PASS(a, b, c, mul) do { \ + ROUND(a, b, c, X0, mul); \ + ROUND(b, c, a, X1, mul); \ + ROUND(c, a, b, X2, mul); \ + ROUND(a, b, c, X3, mul); \ + ROUND(b, c, a, X4, mul); \ + ROUND(c, a, b, X5, mul); \ + ROUND(a, b, c, X6, mul); \ + ROUND(b, c, a, X7, mul); \ + } while (0) + +#define ROUND(a, b, c, x, mul) do { \ + c ^= x; \ + a = SPH_T64(a - (T1[c & 0xFF] ^ T2[(c >> 16) & 0xFF] \ + ^ T3[(c >> 32) & 0xFF] ^ T4[(c >> 48) & 0xFF])); \ + b = SPH_T64(b + (T4[(c >> 8) & 0xFF] ^ T3[(c >> 24) & 0xFF] \ + ^ T2[(c >> 40) & 0xFF] ^ T1[(c >> 56) & 0xFF])); \ + b = mul(b); \ + } while (0) + +#define MUL5(x) SPH_T64((x) * SPH_C64(5)) +#define MUL7(x) SPH_T64((x) * SPH_C64(7)) +#define MUL9(x) SPH_T64((x) * SPH_C64(9)) + +#define KSCHED do { \ + X0 = SPH_T64(X0 - (X7 ^ SPH_C64(0xA5A5A5A5A5A5A5A5))); \ + X1 ^= X0; \ + X2 = SPH_T64(X2 + X1); \ + X3 = SPH_T64(X3 - (X2 ^ (~X1 << 19))); \ + X4 ^= X3; \ + X5 = SPH_T64(X5 + X4); \ + X6 = SPH_T64(X6 - (X5 ^ (~X4 >> 23))); \ + X7 ^= X6; \ + X0 = SPH_T64(X0 + X7); \ + X1 = SPH_T64(X1 - (X0 ^ (~X7 << 19))); \ + X2 ^= X1; \ + X3 = SPH_T64(X3 + X2); \ + X4 = SPH_T64(X4 - (X3 ^ (~X2 >> 23))); \ + X5 ^= X4; \ + X6 = SPH_T64(X6 + X5); \ + X7 = SPH_T64(X7 - (X6 ^ SPH_C64(0x0123456789ABCDEF))); \ + } while (0) + +#define TIGER_ROUND_BODY(in, r) do { \ + sph_u64 A, B, C; \ + sph_u64 X0, X1, X2, X3, X4, X5, X6, X7; \ + \ + A = (r)[0]; \ + B = (r)[1]; \ + C = (r)[2]; \ + \ + X0 = (in(0)); \ + X1 = (in(1)); \ + X2 = (in(2)); \ + X3 = (in(3)); \ + X4 = (in(4)); \ + X5 = (in(5)); \ + X6 = (in(6)); \ + X7 = (in(7)); \ + PASS(A, B, C, MUL5); \ + KSCHED; \ + PASS(C, A, B, MUL7); \ + KSCHED; \ + PASS(B, C, A, MUL9); \ + \ + (r)[0] ^= A; \ + (r)[1] = SPH_T64(B - (r)[1]); \ + (r)[2] = SPH_T64(C + (r)[2]); \ + } while (0) + +/* + * One round of Tiger. The data must be aligned for 64-bit access. + */ +static void +tiger_round(const unsigned char *data, sph_u64 r[3]) +{ +#define TIGER_IN(i) sph_dec64le_aligned(data + 8 * (i)) + TIGER_ROUND_BODY(TIGER_IN, r); +#undef TIGER_IN +} + +/* see sph_tiger.h */ +void +sph_tiger_init(void *cc) +{ + sph_tiger_context *sc; + + sc = (sph_tiger_context*)cc; + sc->val[0] = SPH_C64(0x0123456789ABCDEF); + sc->val[1] = SPH_C64(0xFEDCBA9876543210); + sc->val[2] = SPH_C64(0xF096A5B4C3B2E187); + sc->count = 0; +} + +#define RFUN tiger_round +#define HASH tiger +#define LE64 1 +#define BLEN 64U +#define PW01 1 +#define PLW1 1 +#include "md_helper.c" + +/* see sph_tiger.h */ +void +sph_tiger_close(void *cc, void *dst) +{ + tiger_close(cc, dst, 3); + sph_tiger_init(cc); +} + +/* see sph_tiger.h */ +void +sph_tiger_comp(const sph_u64 msg[8], sph_u64 val[3]) +{ +#define TIGER_IN(i) msg[i] + TIGER_ROUND_BODY(TIGER_IN, val); +#undef TIGER_IN +} + +#undef HASH +#define HASH tiger2 +#undef PW01 +#define CLOSE_ONLY 1 +#include "md_helper.c" + +/* see sph_tiger.h */ +void +sph_tiger2_close(void *cc, void *dst) +{ + tiger2_close(cc, dst, 3); + sph_tiger2_init(cc); +} + +#endif \ No newline at end of file diff --git a/src/Native/libmultihash/x16r.c b/src/Native/libmultihash/x16r.c index 4d116b83..b271798a 100644 --- a/src/Native/libmultihash/x16r.c +++ b/src/Native/libmultihash/x16r.c @@ -174,4 +174,4 @@ void x16r_hash(const char* input, char* output, uint32_t len) size = 64; } memcpy(output, hash, 32); -} +} \ No newline at end of file diff --git a/src/Native/libmultihash/x16r.h b/src/Native/libmultihash/x16r.h index 4a41ec85..dddc7cec 100644 --- a/src/Native/libmultihash/x16r.h +++ b/src/Native/libmultihash/x16r.h @@ -13,4 +13,4 @@ void x16r_hash(const char* input, char* output, uint32_t len); } #endif -#endif +#endif \ No newline at end of file diff --git a/src/Native/libmultihash/x16rv2.c b/src/Native/libmultihash/x16rv2.c new file mode 100644 index 00000000..539dbcc9 --- /dev/null +++ b/src/Native/libmultihash/x16rv2.c @@ -0,0 +1,194 @@ +#include +#include +#include +#include + +#include "sha3/sph_blake.h" +#include "sha3/sph_bmw.h" +#include "sha3/sph_groestl.h" +#include "sha3/sph_jh.h" +#include "sha3/sph_keccak.h" +#include "sha3/sph_skein.h" +#include "sha3/sph_luffa.h" +#include "sha3/sph_cubehash.h" +#include "sha3/sph_shavite.h" +#include "sha3/sph_simd.h" +#include "sha3/sph_echo.h" +#include "sha3/sph_hamsi.h" +#include "sha3/sph_fugue.h" +#include "sha3/sph_shabal.h" +#include "sha3/sph_whirlpool.h" +#include "sha3/sph_sha2.h" +#include "sha3/sph_tiger.h" + +enum Algo { + BLAKE = 0, + BMW, + GROESTL, + JH, + KECCAK, + SKEIN, + LUFFA, + CUBEHASH, + SHAVITE, + SIMD, + ECHO, + HAMSI, + FUGUE, + SHABAL, + WHIRLPOOL, + SHA512, + HASH_FUNC_COUNT +}; + +static void getAlgoString(const uint8_t* prevblock, char *output) +{ + char *sptr = output; + int j; + + for (j = 0; j < HASH_FUNC_COUNT; j++) { + char b = (15 - j) >> 1; // 16 ascii hex chars, reversed + uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; + if (algoDigit >= 10) + sprintf(sptr, "%c", 'A' + (algoDigit - 10)); + else + sprintf(sptr, "%u", (uint32_t) algoDigit); + sptr++; + } + *sptr = '\0'; +} +void x16rv2_hash(const char* input, char* output, uint32_t len) +{ + uint32_t hash[64/4]; + char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + sph_tiger_context ctx_tiger; + + void *in = (void*) input; + int size = len; + + getAlgoString(&input[4], hashOrder); + + for (int i = 0; i < 16; i++) + { + const char elem = hashOrder[i]; + const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; + + switch (algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (int j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, hash, 64); + sph_keccak512_close(&ctx_keccak, hash); + break; + case LUFFA: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (int j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, hash, 64); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_tiger_init(&ctx_tiger); + sph_tiger(&ctx_tiger, (const void*) in, size); + sph_tiger_close(&ctx_tiger, (void*) hash); + for (int j = 24; j < 64; ++j) ((uint8_t*)hash)[j] = 0; // Pad the 24 bytes to bring it to 64 bytes + + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) hash, 64); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + } + in = (void*) hash; + size = 64; + } + memcpy(output, hash, 32); +} \ No newline at end of file diff --git a/src/Native/libmultihash/x16rv2.h b/src/Native/libmultihash/x16rv2.h new file mode 100644 index 00000000..9ff2bf4a --- /dev/null +++ b/src/Native/libmultihash/x16rv2.h @@ -0,0 +1,16 @@ +#ifndef X16RV2_H +#define X16RV2_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void x16rv2_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/Native/libmultihash/yespower_ref.c b/src/Native/libmultihash/yespower_ref.c new file mode 100644 index 00000000..6e61e5f0 --- /dev/null +++ b/src/Native/libmultihash/yespower_ref.c @@ -0,0 +1,580 @@ +/*- + * Copyright 2009 Colin Percival + * Copyright 2013-2018 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + * + * This is a proof-of-work focused fork of yescrypt, including reference and + * cut-down implementation of the obsolete yescrypt 0.5 (based off its first + * submission to PHC back in 2014) and a new proof-of-work specific variation + * known as yespower 1.0. The former is intended as an upgrade for + * cryptocurrencies that already use yescrypt 0.5 and the latter may be used + * as a further upgrade (hard fork) by those and other cryptocurrencies. The + * version of algorithm to use is requested through parameters, allowing for + * both algorithms to co-exist in client and miner implementations (such as in + * preparation for a hard-fork). + * + * This is the reference implementation. Its purpose is to provide a simple + * human- and machine-readable specification that implementations intended + * for actual use should be tested against. It is deliberately mostly not + * optimized, and it is not meant to be used in production. Instead, use + * yespower-opt.c. + */ + +#warning "This reference implementation is deliberately mostly not optimized. Use yespower-opt.c instead unless you're testing (against) the reference implementation on purpose." + +#include +#include +#include +#include + +#include "sha256.h" +#include "sysendian.h" + +#include "yespower.h" + +static void blkcpy(uint32_t *dst, const uint32_t *src, size_t count) +{ + do { + *dst++ = *src++; + } while (--count); +} + +static void blkxor(uint32_t *dst, const uint32_t *src, size_t count) +{ + do { + *dst++ ^= *src++; + } while (--count); +} + +/** + * salsa20(B): + * Apply the Salsa20 core to the provided block. + */ +static void salsa20(uint32_t B[16], uint32_t rounds) +{ + uint32_t x[16]; + size_t i; + + /* SIMD unshuffle */ + for (i = 0; i < 16; i++) + x[i * 5 % 16] = B[i]; + + for (i = 0; i < rounds; i += 2) { +#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) + /* Operate on columns */ + x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); + x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); + + x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); + x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); + + x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); + x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); + + x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); + x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); + + /* Operate on rows */ + x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); + x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); + + x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); + x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); + + x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); + x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); + + x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); + x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); +#undef R + } + + /* SIMD shuffle */ + for (i = 0; i < 16; i++) + B[i] += x[i * 5 % 16]; +} + +/** + * blockmix_salsa(B): + * Compute B = BlockMix_{salsa20, 1}(B). The input B must be 128 bytes in + * length. + */ +static void blockmix_salsa(uint32_t *B, uint32_t rounds) +{ + uint32_t X[16]; + size_t i; + + /* 1: X <-- B_{2r - 1} */ + blkcpy(X, &B[16], 16); + + /* 2: for i = 0 to 2r - 1 do */ + for (i = 0; i < 2; i++) { + /* 3: X <-- H(X xor B_i) */ + blkxor(X, &B[i * 16], 16); + salsa20(X, rounds); + + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + blkcpy(&B[i * 16], X, 16); + } +} + +/* + * These are tunable, but they must meet certain constraints and are part of + * what defines a yespower version. + */ +#define PWXsimple 2 +#define PWXgather 4 +/* Version 0.5 */ +#define PWXrounds_0_5 6 +#define Swidth_0_5 8 +/* Version 1.0 */ +#define PWXrounds_1_0 3 +#define Swidth_1_0 11 + +/* Derived values. Not tunable on their own. */ +#define PWXbytes (PWXgather * PWXsimple * 8) +#define PWXwords (PWXbytes / sizeof(uint32_t)) +#define rmin ((PWXbytes + 127) / 128) + +/* Runtime derived values. Not tunable on their own. */ +#define Swidth_to_Sbytes1(Swidth) ((1 << Swidth) * PWXsimple * 8) +#define Swidth_to_Smask(Swidth) (((1 << Swidth) - 1) * PWXsimple * 8) + +typedef struct { + yespower_version_t version; + uint32_t salsa20_rounds; + uint32_t PWXrounds, Swidth, Sbytes, Smask; + uint32_t *S; + uint32_t (*S0)[2], (*S1)[2], (*S2)[2]; + size_t w; +} pwxform_ctx_t; + +/** + * pwxform(B): + * Transform the provided block using the provided S-boxes. + */ +static void pwxform(uint32_t *B, pwxform_ctx_t *ctx) +{ + uint32_t (*X)[PWXsimple][2] = (uint32_t (*)[PWXsimple][2])B; + uint32_t (*S0)[2] = ctx->S0, (*S1)[2] = ctx->S1, (*S2)[2] = ctx->S2; + uint32_t Smask = ctx->Smask; + size_t w = ctx->w; + size_t i, j, k; + + /* 1: for i = 0 to PWXrounds - 1 do */ + for (i = 0; i < ctx->PWXrounds; i++) { + /* 2: for j = 0 to PWXgather - 1 do */ + for (j = 0; j < PWXgather; j++) { + uint32_t xl = X[j][0][0]; + uint32_t xh = X[j][0][1]; + uint32_t (*p0)[2], (*p1)[2]; + + /* 3: p0 <-- (lo(B_{j,0}) & Smask) / (PWXsimple * 8) */ + p0 = S0 + (xl & Smask) / sizeof(*S0); + /* 4: p1 <-- (hi(B_{j,0}) & Smask) / (PWXsimple * 8) */ + p1 = S1 + (xh & Smask) / sizeof(*S1); + + /* 5: for k = 0 to PWXsimple - 1 do */ + for (k = 0; k < PWXsimple; k++) { + uint64_t x, s0, s1; + + /* 6: B_{j,k} <-- (hi(B_{j,k}) * lo(B_{j,k}) + S0_{p0,k}) xor S1_{p1,k} */ + s0 = ((uint64_t)p0[k][1] << 32) + p0[k][0]; + s1 = ((uint64_t)p1[k][1] << 32) + p1[k][0]; + + xl = X[j][k][0]; + xh = X[j][k][1]; + + x = (uint64_t)xh * xl; + x += s0; + x ^= s1; + + X[j][k][0] = x; + X[j][k][1] = x >> 32; + } + + if (ctx->version != YESPOWER_0_5 && + (i == 0 || j < PWXgather / 2)) { + if (j & 1) { + for (k = 0; k < PWXsimple; k++) { + S1[w][0] = X[j][k][0]; + S1[w][1] = X[j][k][1]; + w++; + } + } else { + for (k = 0; k < PWXsimple; k++) { + S0[w + k][0] = X[j][k][0]; + S0[w + k][1] = X[j][k][1]; + } + } + } + } + } + + if (ctx->version != YESPOWER_0_5) { + /* 14: (S0, S1, S2) <-- (S2, S0, S1) */ + ctx->S0 = S2; + ctx->S1 = S0; + ctx->S2 = S1; + /* 15: w <-- w mod 2^Swidth */ + ctx->w = w & ((1 << ctx->Swidth) * PWXsimple - 1); + } +} + +/** + * blockmix_pwxform(B, ctx, r): + * Compute B = BlockMix_pwxform{salsa20, ctx, r}(B). The input B must be + * 128r bytes in length. + */ +static void blockmix_pwxform(uint32_t *B, pwxform_ctx_t *ctx, size_t r) +{ + uint32_t X[PWXwords]; + size_t r1, i; + + /* Convert 128-byte blocks to PWXbytes blocks */ + /* 1: r_1 <-- 128r / PWXbytes */ + r1 = 128 * r / PWXbytes; + + /* 2: X <-- B'_{r_1 - 1} */ + blkcpy(X, &B[(r1 - 1) * PWXwords], PWXwords); + + /* 3: for i = 0 to r_1 - 1 do */ + for (i = 0; i < r1; i++) { + /* 4: if r_1 > 1 */ + if (r1 > 1) { + /* 5: X <-- X xor B'_i */ + blkxor(X, &B[i * PWXwords], PWXwords); + } + + /* 7: X <-- pwxform(X) */ + pwxform(X, ctx); + + /* 8: B'_i <-- X */ + blkcpy(&B[i * PWXwords], X, PWXwords); + } + + /* 10: i <-- floor((r_1 - 1) * PWXbytes / 64) */ + i = (r1 - 1) * PWXbytes / 64; + + /* 11: B_i <-- H(B_i) */ + salsa20(&B[i * 16], ctx->salsa20_rounds); + +#if 1 /* No-op with our current pwxform settings, but do it to make sure */ + /* 12: for i = i + 1 to 2r - 1 do */ + for (i++; i < 2 * r; i++) { + /* 13: B_i <-- H(B_i xor B_{i-1}) */ + blkxor(&B[i * 16], &B[(i - 1) * 16], 16); + salsa20(&B[i * 16], ctx->salsa20_rounds); + } +#endif +} + +/** + * integerify(B, r): + * Return the result of parsing B_{2r-1} as a little-endian integer. + */ +static uint32_t integerify(const uint32_t *B, size_t r) +{ +/* + * Our 32-bit words are in host byte order. Also, they are SIMD-shuffled, but + * we only care about the least significant 32 bits anyway. + */ + const uint32_t *X = &B[(2 * r - 1) * 16]; + return X[0]; +} + +/** + * p2floor(x): + * Largest power of 2 not greater than argument. + */ +static uint32_t p2floor(uint32_t x) +{ + uint32_t y; + while ((y = x & (x - 1))) + x = y; + return x; +} + +/** + * wrap(x, i): + * Wrap x to the range 0 to i-1. + */ +static uint32_t wrap(uint32_t x, uint32_t i) +{ + uint32_t n = p2floor(i); + return (x & (n - 1)) + (i - n); +} + +/** + * smix1(B, r, N, V, X, ctx): + * Compute first loop of B = SMix_r(B, N). The input B must be 128r bytes in + * length; the temporary storage V must be 128rN bytes in length; the temporary + * storage X must be 128r bytes in length. + */ +static void smix1(uint32_t *B, size_t r, uint32_t N, + uint32_t *V, uint32_t *X, pwxform_ctx_t *ctx) +{ + size_t s = 32 * r; + uint32_t i, j; + size_t k; + + /* 1: X <-- B */ + for (k = 0; k < 2 * r; k++) + for (i = 0; i < 16; i++) + X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]); + + if (ctx->version != YESPOWER_0_5) { + for (k = 1; k < r; k++) { + blkcpy(&X[k * 32], &X[(k - 1) * 32], 32); + blockmix_pwxform(&X[k * 32], ctx, 1); + } + } + + /* 2: for i = 0 to N - 1 do */ + for (i = 0; i < N; i++) { + /* 3: V_i <-- X */ + blkcpy(&V[i * s], X, s); + + if (i > 1) { + /* j <-- Wrap(Integerify(X), i) */ + j = wrap(integerify(X, r), i); + + /* X <-- X xor V_j */ + blkxor(X, &V[j * s], s); + } + + /* 4: X <-- H(X) */ + if (V != ctx->S) + blockmix_pwxform(X, ctx, r); + else + blockmix_salsa(X, ctx->salsa20_rounds); + } + + /* B' <-- X */ + for (k = 0; k < 2 * r; k++) + for (i = 0; i < 16; i++) + le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]); +} + +/** + * smix2(B, r, N, Nloop, V, X, ctx): + * Compute second loop of B = SMix_r(B, N). The input B must be 128r bytes in + * length; the temporary storage V must be 128rN bytes in length; the temporary + * storage X must be 128r bytes in length. The value N must be a power of 2 + * greater than 1. + */ +static void smix2(uint32_t *B, size_t r, uint32_t N, uint32_t Nloop, + uint32_t *V, uint32_t *X, pwxform_ctx_t *ctx) +{ + size_t s = 32 * r; + uint32_t i, j; + size_t k; + + /* X <-- B */ + for (k = 0; k < 2 * r; k++) + for (i = 0; i < 16; i++) + X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]); + + /* 6: for i = 0 to N - 1 do */ + for (i = 0; i < Nloop; i++) { + /* 7: j <-- Integerify(X) mod N */ + j = integerify(X, r) & (N - 1); + + /* 8.1: X <-- X xor V_j */ + blkxor(X, &V[j * s], s); + /* V_j <-- X */ + if (Nloop != 2) + blkcpy(&V[j * s], X, s); + + /* 8.2: X <-- H(X) */ + blockmix_pwxform(X, ctx, r); + } + + /* 10: B' <-- X */ + for (k = 0; k < 2 * r; k++) + for (i = 0; i < 16; i++) + le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]); +} + +/** + * smix(B, r, N, p, t, V, X, ctx): + * Compute B = SMix_r(B, N). The input B must be 128rp bytes in length; the + * temporary storage V must be 128rN bytes in length; the temporary storage + * X must be 128r bytes in length. The value N must be a power of 2 and at + * least 16. + */ +static void smix(uint32_t *B, size_t r, uint32_t N, + uint32_t *V, uint32_t *X, pwxform_ctx_t *ctx) +{ + uint32_t Nloop_all = (N + 2) / 3; /* 1/3, round up */ + uint32_t Nloop_rw = Nloop_all; + + Nloop_all++; Nloop_all &= ~(uint32_t)1; /* round up to even */ + if (ctx->version == YESPOWER_0_5) { + Nloop_rw &= ~(uint32_t)1; /* round down to even */ + } else { + Nloop_rw++; Nloop_rw &= ~(uint32_t)1; /* round up to even */ + } + + smix1(B, 1, ctx->Sbytes / 128, ctx->S, X, ctx); + smix1(B, r, N, V, X, ctx); + smix2(B, r, N, Nloop_rw /* must be > 2 */, V, X, ctx); + smix2(B, r, N, Nloop_all - Nloop_rw /* 0 or 2 */, V, X, ctx); +} + +/** + * yespower(local, src, srclen, params, dst): + * Compute yespower(src[0 .. srclen - 1], N, r), to be checked for "< target". + * + * Return 0 on success; or -1 on error. + */ +int yespower(yespower_local_t *local, + const uint8_t *src, size_t srclen, + const yespower_params_t *params, yespower_binary_t *dst) +{ + yespower_version_t version = params->version; + uint32_t N = params->N; + uint32_t r = params->r; + const uint8_t *pers = params->pers; + size_t perslen = params->perslen; + int retval = -1; + size_t B_size, V_size; + uint32_t *B, *V, *X, *S; + pwxform_ctx_t ctx; + uint32_t sha256[8]; + + /* Sanity-check parameters */ + if ((version != YESPOWER_0_5 && version != YESPOWER_1_0) || + N < 1024 || N > 512 * 1024 || r < 8 || r > 32 || + (N & (N - 1)) != 0 || r < rmin || + (!pers && perslen)) { + errno = EINVAL; + return -1; + } + + /* Allocate memory */ + B_size = (size_t)128 * r; + V_size = B_size * N; + if ((V = malloc(V_size)) == NULL) + return -1; + if ((B = malloc(B_size)) == NULL) + goto free_V; + if ((X = malloc(B_size)) == NULL) + goto free_B; + ctx.version = version; + if (version == YESPOWER_0_5) { + ctx.salsa20_rounds = 8; + ctx.PWXrounds = PWXrounds_0_5; + ctx.Swidth = Swidth_0_5; + ctx.Sbytes = 2 * Swidth_to_Sbytes1(ctx.Swidth); + } else { + ctx.salsa20_rounds = 2; + ctx.PWXrounds = PWXrounds_1_0; + ctx.Swidth = Swidth_1_0; + ctx.Sbytes = 3 * Swidth_to_Sbytes1(ctx.Swidth); + } + if ((S = malloc(ctx.Sbytes)) == NULL) + goto free_X; + ctx.S = S; + ctx.S0 = (uint32_t (*)[2])S; + ctx.S1 = ctx.S0 + (1 << ctx.Swidth) * PWXsimple; + ctx.S2 = ctx.S1 + (1 << ctx.Swidth) * PWXsimple; + ctx.Smask = Swidth_to_Smask(ctx.Swidth); + ctx.w = 0; + + SHA256_Buf(src, srclen, (uint8_t *)sha256); + + if (version != YESPOWER_0_5) { + if (pers) { + src = pers; + srclen = perslen; + } else { + srclen = 0; + } + } + + /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ + PBKDF2_SHA256((uint8_t *)sha256, sizeof(sha256), + src, srclen, 1, (uint8_t *)B, B_size); + + blkcpy(sha256, B, sizeof(sha256) / sizeof(sha256[0])); + + /* 3: B_i <-- MF(B_i, N) */ + smix(B, r, N, V, X, &ctx); + + if (version == YESPOWER_0_5) { + /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ + PBKDF2_SHA256((uint8_t *)sha256, sizeof(sha256), + (uint8_t *)B, B_size, 1, (uint8_t *)dst, sizeof(*dst)); + + if (pers) { + HMAC_SHA256_Buf(dst, sizeof(*dst), pers, perslen, + (uint8_t *)sha256); + SHA256_Buf(sha256, sizeof(sha256), (uint8_t *)dst); + } + } else { + HMAC_SHA256_Buf((uint8_t *)B + B_size - 64, 64, + sha256, sizeof(sha256), (uint8_t *)dst); + } + + /* Success! */ + retval = 0; + + /* Free memory */ + free(S); +free_X: + free(X); +free_B: + free(B); +free_V: + free(V); + + return retval; +} + +int yespower_tls(const uint8_t *src, size_t srclen, + const yespower_params_t *params, yespower_binary_t *dst) +{ +/* The reference implementation doesn't use thread-local storage */ + return yespower(NULL, src, srclen, params, dst); +} + +int yespower_init_local(yespower_local_t *local) +{ +/* The reference implementation doesn't use the local structure */ + local->base = local->aligned = NULL; + local->base_size = local->aligned_size = 0; + return 0; +} + +int yespower_free_local(yespower_local_t *local) +{ +/* The reference implementation frees its memory in yespower() */ + (void)local; /* unused */ + return 0; +} \ No newline at end of file diff --git a/src/Native/libmultihash/yespower_sugarchain.c b/src/Native/libmultihash/yespower_sugarchain.c new file mode 100644 index 00000000..fc87fdbe --- /dev/null +++ b/src/Native/libmultihash/yespower_sugarchain.c @@ -0,0 +1,15 @@ +#include "yespower_sugarchain.h" +/* + * yespower for sugarchain + */ +int yespower_hash(const char *input, char *output) +{ + yespower_params_t params = { + .version = YESPOWER_1_0, + .N = 2048, + .r = 32, + .pers = "Satoshi Nakamoto 31/Oct/2008 Proof-of-work is essentially one-CPU-one-vote", + .perslen = 74 + }; + return yespower_tls(input, 80, ¶ms, (yespower_binary_t *) output); +} \ No newline at end of file diff --git a/src/Native/libmultihash/yespower_sugarchain.h b/src/Native/libmultihash/yespower_sugarchain.h new file mode 100644 index 00000000..3d29d152 --- /dev/null +++ b/src/Native/libmultihash/yespower_sugarchain.h @@ -0,0 +1,130 @@ +/*- + * Copyright 2009 Colin Percival + * Copyright 2013-2018 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + */ +#ifndef _YESPOWER_H_ +#define _YESPOWER_H_ + +#include +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif +int yespower_hash(const char *input, char *output); +/** + * Internal type used by the memory allocator. Please do not use it directly. + * Use yespower_local_t instead. + */ +typedef struct { + void *base, *aligned; + size_t base_size, aligned_size; +} yespower_region_t; + +/** + * Type for thread-local (RAM) data structure. + */ +typedef yespower_region_t yespower_local_t; + +/* + * Type for yespower algorithm version numbers. + */ +typedef enum { YESPOWER_0_5 = 5, YESPOWER_1_0 = 10 } yespower_version_t; + +/** + * yespower parameters combined into one struct. + */ +typedef struct { + yespower_version_t version; + uint32_t N, r; + const uint8_t *pers; + size_t perslen; +} yespower_params_t; + +/** + * A 256-bit yespower hash. + */ +typedef struct { + unsigned char uc[32]; +} yespower_binary_t; + +/** + * yespower_init_local(local): + * Initialize the thread-local (RAM) data structure. Actual memory allocation + * is currently fully postponed until a call to yespower(). + * + * Return 0 on success; or -1 on error. + * + * MT-safe as long as local is local to the thread. + */ +extern int yespower_init_local(yespower_local_t *local); + +/** + * yespower_free_local(local): + * Free memory that may have been allocated for an initialized thread-local + * (RAM) data structure. + * + * Return 0 on success; or -1 on error. + * + * MT-safe as long as local is local to the thread. + */ +extern int yespower_free_local(yespower_local_t *local); + +/** + * yespower(local, src, srclen, params, dst): + * Compute yespower(src[0 .. srclen - 1], N, r), to be checked for "< target". + * local is the thread-local data structure, allowing to preserve and reuse a + * memory allocation across calls, thereby reducing processing overhead. + * + * Return 0 on success; or -1 on error. + * + * local must be initialized with yespower_init_local(). + * + * MT-safe as long as local and dst are local to the thread. + */ +extern int yespower(yespower_local_t *local, + const uint8_t *src, size_t srclen, + const yespower_params_t *params, yespower_binary_t *dst); + +/** + * yespower_tls(src, srclen, params, dst): + * Compute yespower(src[0 .. srclen - 1], N, r), to be checked for "< target". + * The memory allocation is maintained internally using thread-local storage. + * + * Return 0 on success; or -1 on error. + * + * MT-safe as long as dst is local to the thread. + */ +extern int yespower_tls(const uint8_t *src, size_t srclen, + const yespower_params_t *params, yespower_binary_t *dst); + +#ifdef __cplusplus +} +#endif + +#endif /* !_YESPOWER_H_ */ \ No newline at end of file