diff options
| author | Patrick Lodder <[email protected]> | 2021-06-02 23:45:02 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-06-02 23:45:02 +0200 |
| commit | 8fcbf8cfe55638e8970c5c76608123797f5140e6 (patch) | |
| tree | e440a18b5bb2c86b3620ec295356255cb365dc38 /src | |
| parent | Merge pull request #2210 from rnicoll/1.21-block-subsidy (diff) | |
| parent | Remove default Signet (diff) | |
| download | discoin-8fcbf8cfe55638e8970c5c76608123797f5140e6.tar.xz discoin-8fcbf8cfe55638e8970c5c76608123797f5140e6.zip | |
Merge pull request #1828 from rnicoll/1.21-dev-scrypt-algo
Scrypt algorithm
Diffstat (limited to 'src')
32 files changed, 939 insertions, 121 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 8e8ce6646..16f7b5627 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -410,6 +410,9 @@ crypto_libbitcoin_crypto_base_a_SOURCES = \ crypto/poly1305.cpp \ crypto/ripemd160.cpp \ crypto/ripemd160.h \ + crypto/scrypt.cpp \ + crypto/scrypt-sse2.cpp \ + crypto/scrypt.h \ crypto/sha1.cpp \ crypto/sha1.h \ crypto/sha256.cpp \ @@ -672,7 +675,7 @@ if GLIBC_BACK_COMPAT endif libbitcoinconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) -libbitcoinconsensus_la_LIBADD = $(LIBSECP256K1) +libbitcoinconsensus_la_LIBADD = $(LIBSECP256K1) $(CRYPTO_LIBS) libbitcoinconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL libbitcoinconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 1bdfa9525..b8e0ec3a1 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -7,7 +7,7 @@ BENCH_SRCDIR = bench BENCH_BINARY = bench/bench_dogecoin$(EXEEXT) RAW_BENCH_FILES = \ - bench/data/block413567.raw + bench/data/block41385.raw GENERATED_BENCH_FILES = $(RAW_BENCH_FILES:.raw=.raw.h) bench_bench_dogecoin_SOURCES = \ @@ -81,7 +81,7 @@ CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES) CLEANFILES += $(CLEAN_BITCOIN_BENCH) -bench/data.cpp: bench/data/block413567.raw.h +bench/data.cpp: bench/data/block41385.raw.h dogecoin_bench: $(BENCH_BINARY) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 31738769f..461417987 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -266,6 +266,7 @@ BITCOIN_TESTS =\ test/script_tests.cpp \ test/script_standard_tests.cpp \ test/scriptnum_tests.cpp \ + test/scrypt_tests.cpp \ test/serialize_tests.cpp \ test/settings_tests.cpp \ test/sighash_tests.cpp \ diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp index a9f3f5f84..aa7e5865b 100644 --- a/src/bench/checkblock.cpp +++ b/src/bench/checkblock.cpp @@ -16,21 +16,21 @@ static void DeserializeBlockTest(benchmark::Bench& bench) { - CDataStream stream(benchmark::data::block413567, SER_NETWORK, PROTOCOL_VERSION); + CDataStream stream(benchmark::data::block41385, SER_NETWORK, PROTOCOL_VERSION); char a = '\0'; stream.write(&a, 1); // Prevent compaction bench.unit("block").run([&] { CBlock block; stream >> block; - bool rewound = stream.Rewind(benchmark::data::block413567.size()); + bool rewound = stream.Rewind(benchmark::data::block41385.size()); assert(rewound); }); } static void DeserializeAndCheckBlockTest(benchmark::Bench& bench) { - CDataStream stream(benchmark::data::block413567, SER_NETWORK, PROTOCOL_VERSION); + CDataStream stream(benchmark::data::block41385, SER_NETWORK, PROTOCOL_VERSION); char a = '\0'; stream.write(&a, 1); // Prevent compaction @@ -40,7 +40,7 @@ static void DeserializeAndCheckBlockTest(benchmark::Bench& bench) bench.unit("block").run([&] { CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here stream >> block; - bool rewound = stream.Rewind(benchmark::data::block413567.size()); + bool rewound = stream.Rewind(benchmark::data::block41385.size()); assert(rewound); BlockValidationState validationState; diff --git a/src/bench/data.cpp b/src/bench/data.cpp index 0ae4c7cad..2280b3914 100644 --- a/src/bench/data.cpp +++ b/src/bench/data.cpp @@ -7,8 +7,8 @@ namespace benchmark { namespace data { -#include <bench/data/block413567.raw.h> -const std::vector<uint8_t> block413567{block413567_raw, block413567_raw + sizeof(block413567_raw) / sizeof(block413567_raw[0])}; +#include <bench/data/block41385.raw.h> +const std::vector<uint8_t> block41385{block41385_raw, block41385_raw + sizeof(block41385_raw) / sizeof(block41385_raw[0])}; } // namespace data } // namespace benchmark diff --git a/src/bench/data.h b/src/bench/data.h index 5f13d766e..3f985e575 100644 --- a/src/bench/data.h +++ b/src/bench/data.h @@ -11,7 +11,7 @@ namespace benchmark { namespace data { -extern const std::vector<uint8_t> block413567; +extern const std::vector<uint8_t> block41385; } // namespace data } // namespace benchmark diff --git a/src/bench/data/block413567.raw b/src/bench/data/block413567.raw Binary files differdeleted file mode 100644 index 67d2d5d38..000000000 --- a/src/bench/data/block413567.raw +++ /dev/null diff --git a/src/bench/data/block41385.raw b/src/bench/data/block41385.raw Binary files differnew file mode 100644 index 000000000..328f7e9af --- /dev/null +++ b/src/bench/data/block41385.raw diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp index 4b45264a3..5b08c30ed 100644 --- a/src/bench/rpc_blockchain.cpp +++ b/src/bench/rpc_blockchain.cpp @@ -13,7 +13,7 @@ static void BlockToJsonVerbose(benchmark::Bench& bench) { - CDataStream stream(benchmark::data::block413567, SER_NETWORK, PROTOCOL_VERSION); + CDataStream stream(benchmark::data::block41385, SER_NETWORK, PROTOCOL_VERSION); char a = '\0'; stream.write(&a, 1); // Prevent compaction diff --git a/src/chain.h b/src/chain.h index 43e8a39f3..1f4eaae7e 100644 --- a/src/chain.h +++ b/src/chain.h @@ -243,6 +243,11 @@ public: * Does not imply the transactions are still stored on disk. (IsBlockPruned might return true) */ bool HaveTxsDownloaded() const { return nChainTx != 0; } + + uint256 GetBlockPoWHash() const + { + return GetBlockHeader().GetPoWHash(); + } int64_t GetBlockTime() const { diff --git a/src/chainparams.cpp b/src/chainparams.cpp index f6b8324a6..dd3e4a5a7 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -44,7 +44,7 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi * transaction cannot be spent since it did not originally exist in the * database. * - * CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1) + * CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1386325540, nBits=1e0ffff0, nNonce=99943, vtx=1) * CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0) * CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73) * CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B) @@ -52,8 +52,8 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi */ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { - const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; - const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; + const char* pszTimestamp = "Nintondo"; + const CScript genesisOutputScript = CScript() << ParseHex("040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9") << OP_CHECKSIG; return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward); } @@ -113,25 +113,18 @@ public: m_assumed_blockchain_size = 350; m_assumed_chain_state_size = 6; - genesis = CreateGenesisBlock(1386325540, 1930484355, 0x1d00ffff, 1, 88 * COIN); + genesis = CreateGenesisBlock(1386325540, 99943, 0x1e0ffff0, 1, 88 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x000000007610a818e726d4f943b5936e750de86c142a5f59606456c945350ec3")); - assert(genesis.hashMerkleRoot == uint256S("0x13abc7dbaf8e00e9e128cb4977e3a9d15ea5d4ff249dd625ee607f6023cdb3df")); + assert(consensus.hashGenesisBlock == uint256S("0x1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691")); + assert(genesis.hashMerkleRoot == uint256S("0x5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69")); // Note that of those which support the service bits prefix, most only support a subset of // possible options. // This is fine at runtime as we'll fall back to using them as an addrfetch if they don't support the // service bits we want, but we should get them updated to support all service bits wanted by any // release ASAP to avoid it where possible. - vSeeds.emplace_back("seed.bitcoin.sipa.be"); // Pieter Wuille, only supports x1, x5, x9, and xd - vSeeds.emplace_back("dnsseed.bluematt.me"); // Matt Corallo, only supports x9 - vSeeds.emplace_back("dnsseed.bitcoin.dashjr.org"); // Luke Dashjr - vSeeds.emplace_back("seed.bitcoinstats.com"); // Christian Decker, supports x1 - xf - vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch"); // Jonas Schnelli, only supports x1, x5, x9, and xd - vSeeds.emplace_back("seed.btc.petertodd.org"); // Peter Todd, only supports x1, x5, x9, and xd - vSeeds.emplace_back("seed.bitcoin.sprovoost.nl"); // Sjors Provoost - vSeeds.emplace_back("dnsseed.emzy.de"); // Stephan Oeste - vSeeds.emplace_back("seed.bitcoin.wiz.biz"); // Jason Maurice + vSeeds.emplace_back("seed.multidoge.org"); + vSeeds.emplace_back("seed2.multidoge.org"); base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,30); base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,22); @@ -232,19 +225,15 @@ public: m_assumed_blockchain_size = 40; m_assumed_chain_state_size = 2; - // Dogecoin: Note timestamp is tweaked for SHA256 interim mining, will need correcting for Scrypt - genesis = CreateGenesisBlock(1391503288, 1182687315, 0x1d00ffff, 1, 88 * COIN); + genesis = CreateGenesisBlock(1391503289, 997879, 0x1e0ffff0, 1, 88 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x00000000543fd974f37140a6192f890d744f220bd82ae428dbe684c7588347ad")); - assert(genesis.hashMerkleRoot == uint256S("0x13abc7dbaf8e00e9e128cb4977e3a9d15ea5d4ff249dd625ee607f6023cdb3df")); + assert(consensus.hashGenesisBlock == uint256S("0xbb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e")); + assert(genesis.hashMerkleRoot == uint256S("0x5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69")); vFixedSeeds.clear(); vSeeds.clear(); // nodes with support for servicebits filtering should be at the top - vSeeds.emplace_back("testnet-seed.bitcoin.jonasschnelli.ch"); - vSeeds.emplace_back("seed.tbtc.petertodd.org"); - vSeeds.emplace_back("seed.testnet.bitcoin.sprovoost.nl"); - vSeeds.emplace_back("testnet-seed.bluematt.me"); // Just a static list of stable node(s), only supports x9 + vSeeds.emplace_back("testseed.jrn.me.uk", true); base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,113); base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196); @@ -299,40 +288,27 @@ public: vSeeds.clear(); if (!args.IsArgSet("-signetchallenge")) { - bin = ParseHex("512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae"); - vSeeds.emplace_back("178.128.221.177"); - vSeeds.emplace_back("2a01:7c8:d005:390::5"); - vSeeds.emplace_back("v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333"); - - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000019fd16269a"); - consensus.defaultAssumeValid = uint256S("0x0000002a1de0f46379358c1fd09906f7ac59adf3712323ed90eb59e4c183c020"); // 9434 - m_assumed_blockchain_size = 1; - m_assumed_chain_state_size = 0; - chainTxData = ChainTxData{ - // Data from RPC: getchaintxstats 4096 0000002a1de0f46379358c1fd09906f7ac59adf3712323ed90eb59e4c183c020 - /* nTime */ 1603986000, - /* nTxCount */ 9582, - /* dTxRate */ 0.00159272030651341, - }; + // Dogecoin: Use OP_FALSE as challenge, as we have no default Signet + bin = ParseHex("50"); } else { const auto signet_challenge = args.GetArgs("-signetchallenge"); if (signet_challenge.size() != 1) { throw std::runtime_error(strprintf("%s: -signetchallenge cannot be multiple values.", __func__)); } bin = ParseHex(signet_challenge[0]); - - consensus.nMinimumChainWork = uint256{}; - consensus.defaultAssumeValid = uint256{}; - m_assumed_blockchain_size = 0; - m_assumed_chain_state_size = 0; - chainTxData = ChainTxData{ - 0, - 0, - 0, - }; LogPrintf("Signet with challenge %s\n", signet_challenge[0]); } + consensus.nMinimumChainWork = uint256{}; + consensus.defaultAssumeValid = uint256{}; + m_assumed_blockchain_size = 0; + m_assumed_chain_state_size = 0; + chainTxData = ChainTxData{ + 0, + 0, + 0, + }; + if (args.IsArgSet("-signetseednode")) { vSeeds = args.GetArgs("-signetseednode"); } @@ -356,7 +332,7 @@ public: consensus.nRuleChangeActivationThreshold = 1900; // 95% of 2000 consensus.nMinerConfirmationWindow = 2000; // nPowTargetTimespan / nPowTargetSpacing consensus.MinBIP9WarningHeight = 0; - consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.powLimit = uint256S("0x0000f77ae0000000000000000000000000000000000000000000000000000000"); consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 @@ -378,10 +354,10 @@ public: nDefaultPort = 55556; nPruneAfterHeight = 1000; - genesis = CreateGenesisBlock(1598918400, 52613770, 0x1e0377ae, 1, 50 * COIN); + genesis = CreateGenesisBlock(1622364566, 81621, 0x1f00f77a, 1, 50 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); + assert(consensus.hashGenesisBlock == uint256S("0xf21a2c00a3b58b3f1b245de5e30955c00784040a3e7042edb0d2eedd1fd085a5")); + assert(genesis.hashMerkleRoot == uint256S("0xb60e6a649c2c43248d6d8da2fb19daa337511fabfe3875f382adb686474fc021")); vFixedSeeds.clear(); @@ -426,7 +402,7 @@ public: consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = true; consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains - consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016) + consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 10080) consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; @@ -454,8 +430,8 @@ public: genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 88 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x4ebcb24a7efa4e2050e74d6c95f1ee318ed2b4df2b6f28b0d6b8318cb43762e8")); - assert(genesis.hashMerkleRoot == uint256S("0x13abc7dbaf8e00e9e128cb4977e3a9d15ea5d4ff249dd625ee607f6023cdb3df")); + assert(consensus.hashGenesisBlock == uint256S("0x3d2160a3b5dc4a9d62e7e66a295f70313ac808440ef7400d6c0772171ce973a5")); + assert(genesis.hashMerkleRoot == uint256S("0x5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69")); vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds. vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds. @@ -467,7 +443,7 @@ public: checkpointData = { { - {0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")}, + {0, uint256S("3d2160a3b5dc4a9d62e7e66a295f70313ac808440ef7400d6c0772171ce973a5")}, } }; diff --git a/src/crypto/scrypt-sse2.cpp b/src/crypto/scrypt-sse2.cpp new file mode 100644 index 000000000..c4f26aa30 --- /dev/null +++ b/src/crypto/scrypt-sse2.cpp @@ -0,0 +1,140 @@ +/* + * Copyright 2009 Colin Percival, 2011 ArtForz, 2012-2013 pooler + * 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. + */ + +#if defined(USE_SSE2) + +#include <crypto/scrypt.h> + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#include <emmintrin.h> + +static inline void xor_salsa8_sse2(__m128i B[4], const __m128i Bx[4]) +{ + __m128i X0, X1, X2, X3; + __m128i T; + int i; + + X0 = B[0] = _mm_xor_si128(B[0], Bx[0]); + X1 = B[1] = _mm_xor_si128(B[1], Bx[1]); + X2 = B[2] = _mm_xor_si128(B[2], Bx[2]); + X3 = B[3] = _mm_xor_si128(B[3], Bx[3]); + + for (i = 0; i < 8; i += 2) { + /* Operate on "columns". */ + T = _mm_add_epi32(X0, X3); + X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7)); + X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25)); + T = _mm_add_epi32(X1, X0); + X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9)); + X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23)); + T = _mm_add_epi32(X2, X1); + X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13)); + X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19)); + T = _mm_add_epi32(X3, X2); + X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18)); + X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14)); + + /* Rearrange data. */ + X1 = _mm_shuffle_epi32(X1, 0x93); + X2 = _mm_shuffle_epi32(X2, 0x4E); + X3 = _mm_shuffle_epi32(X3, 0x39); + + /* Operate on "rows". */ + T = _mm_add_epi32(X0, X1); + X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7)); + X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25)); + T = _mm_add_epi32(X3, X0); + X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9)); + X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23)); + T = _mm_add_epi32(X2, X3); + X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13)); + X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19)); + T = _mm_add_epi32(X1, X2); + X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18)); + X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14)); + + /* Rearrange data. */ + X1 = _mm_shuffle_epi32(X1, 0x39); + X2 = _mm_shuffle_epi32(X2, 0x4E); + X3 = _mm_shuffle_epi32(X3, 0x93); + } + + B[0] = _mm_add_epi32(B[0], X0); + B[1] = _mm_add_epi32(B[1], X1); + B[2] = _mm_add_epi32(B[2], X2); + B[3] = _mm_add_epi32(B[3], X3); +} + +void scrypt_1024_1_1_256_sp_sse2(const char *input, char *output, char *scratchpad) +{ + uint8_t B[128]; + union { + __m128i i128[8]; + uint32_t u32[32]; + } X; + __m128i *V; + uint32_t i, j, k; + + V = (__m128i *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63)); + + PBKDF2_SHA256((const uint8_t *)input, 80, (const uint8_t *)input, 80, 1, B, 128); + + for (k = 0; k < 2; k++) { + for (i = 0; i < 16; i++) { + X.u32[k * 16 + i] = le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]); + } + } + + for (i = 0; i < 1024; i++) { + for (k = 0; k < 8; k++) + V[i * 8 + k] = X.i128[k]; + xor_salsa8_sse2(&X.i128[0], &X.i128[4]); + xor_salsa8_sse2(&X.i128[4], &X.i128[0]); + } + for (i = 0; i < 1024; i++) { + j = 8 * (X.u32[16] & 1023); + for (k = 0; k < 8; k++) + X.i128[k] = _mm_xor_si128(X.i128[k], V[j + k]); + xor_salsa8_sse2(&X.i128[0], &X.i128[4]); + xor_salsa8_sse2(&X.i128[4], &X.i128[0]); + } + + for (k = 0; k < 2; k++) { + for (i = 0; i < 16; i++) { + le32enc(&B[(k * 16 + (i * 5 % 16)) * 4], X.u32[k * 16 + i]); + } + } + + PBKDF2_SHA256((const uint8_t *)input, 80, B, 128, 1, (uint8_t *)output, 32); +} + +#endif // USE_SSE2 diff --git a/src/crypto/scrypt.cpp b/src/crypto/scrypt.cpp new file mode 100644 index 000000000..3bdd9d6cb --- /dev/null +++ b/src/crypto/scrypt.cpp @@ -0,0 +1,576 @@ +/* + * Copyright 2009 Colin Percival, 2011 ArtForz, 2012-2013 pooler + * 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. + */ + +#include <crypto/scrypt.h> + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#if defined(USE_SSE2) && !defined(USE_SSE2_ALWAYS) +#ifdef _MSC_VER +// MSVC 64bit is unable to use inline asm +#include <intrin.h> +#else +// GCC Linux or i686-w64-mingw32 +#include <cpuid.h> +#endif +#endif +#ifndef __FreeBSD__ +static inline uint32_t be32dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + + ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); +} + +static inline void be32enc(void *pp, uint32_t x) +{ + uint8_t *p = (uint8_t *)pp; + p[3] = x & 0xff; + p[2] = (x >> 8) & 0xff; + p[1] = (x >> 16) & 0xff; + p[0] = (x >> 24) & 0xff; +} + +#endif + +typedef struct SHA256_CTXContext { + uint32_t total[2]; + uint32_t state[8]; + uint8_t buffer[64]; +} SHA256_CTX; + +#define GET_UINT32(n, b, i) \ + { \ + (n) = ((uint32_t)(b)[(i)] << 24) \ + | ((uint32_t)(b)[(i) + 1] << 16) \ + | ((uint32_t)(b)[(i) + 2] << 8) \ + | ((uint32_t)(b)[(i) + 3]); \ + } + +#define PUT_UINT32(n, b, i) \ + { \ + (b)[(i)] = (uint8_t)((n) >> 24); \ + (b)[(i) + 1] = (uint8_t)((n) >> 16); \ + (b)[(i) + 2] = (uint8_t)((n) >> 8); \ + (b)[(i) + 3] = (uint8_t)((n)); \ + } + +#define SHR(x, n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x, n) (SHR(x, n) | (x << (32 - n))) +#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) +#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define F0(x, y, z) ((x & y) | (z & (x | y))) +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define R(t) (W[t] = S1(W[t - 2]) + W[t - 7] + S0(W[t - 15]) + W[t - 16]) + +#define P(a, b, c, d, e, f, g, h, x, K) \ + { \ + temp1 = h + S3(e) + F1(e, f, g) + K + x; \ + temp2 = S2(a) + F0(a, b, c); \ + d += temp1; \ + h = temp1 + temp2; \ + } + +static void +SHA256_Init(SHA256_CTX* ctx) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; +} + +static void +SHA256_Process(SHA256_CTX* ctx, uint8_t data[64]) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A, B, C, D, E, F, G, H; + + GET_UINT32(W[0], data, 0); + GET_UINT32(W[1], data, 4); + GET_UINT32(W[2], data, 8); + GET_UINT32(W[3], data, 12); + GET_UINT32(W[4], data, 16); + GET_UINT32(W[5], data, 20); + GET_UINT32(W[6], data, 24); + GET_UINT32(W[7], data, 28); + GET_UINT32(W[8], data, 32); + GET_UINT32(W[9], data, 36); + GET_UINT32(W[10], data, 40); + GET_UINT32(W[11], data, 44); + GET_UINT32(W[12], data, 48); + GET_UINT32(W[13], data, 52); + GET_UINT32(W[14], data, 56); + GET_UINT32(W[15], data, 60); + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + + P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98); + P(H, A, B, C, D, E, F, G, W[1], 0x71374491); + P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF); + P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5); + P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B); + P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1); + P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4); + P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5); + P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98); + P(H, A, B, C, D, E, F, G, W[9], 0x12835B01); + P(G, H, A, B, C, D, E, F, W[10], 0x243185BE); + P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3); + P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74); + P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE); + P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7); + P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174); + P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1); + P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786); + P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6); + P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC); + P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F); + P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA); + P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC); + P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA); + P(A, B, C, D, E, F, G, H, R(24), 0x983E5152); + P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D); + P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8); + P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7); + P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3); + P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147); + P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351); + P(B, C, D, E, F, G, H, A, R(31), 0x14292967); + P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85); + P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138); + P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC); + P(F, G, H, A, B, C, D, E, R(35), 0x53380D13); + P(E, F, G, H, A, B, C, D, R(36), 0x650A7354); + P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB); + P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E); + P(B, C, D, E, F, G, H, A, R(39), 0x92722C85); + P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1); + P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B); + P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70); + P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3); + P(E, F, G, H, A, B, C, D, R(44), 0xD192E819); + P(D, E, F, G, H, A, B, C, R(45), 0xD6990624); + P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585); + P(B, C, D, E, F, G, H, A, R(47), 0x106AA070); + P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116); + P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08); + P(G, H, A, B, C, D, E, F, R(50), 0x2748774C); + P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5); + P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3); + P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A); + P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F); + P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3); + P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE); + P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F); + P(G, H, A, B, C, D, E, F, R(58), 0x84C87814); + P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208); + P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA); + P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB); + P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7); + P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +static void +SHA256_Update(SHA256_CTX* ctx, uint8_t* input, uint32_t length) +{ + uint32_t left, fill; + + if (!length) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += length; + ctx->total[0] &= 0xFFFFFFFF; + + if (ctx->total[0] < length) + ctx->total[1]++; + + if (left && length >= fill) { + memcpy((void*)(ctx->buffer + left), + (void*)input, fill); + SHA256_Process(ctx, ctx->buffer); + length -= fill; + input += fill; + left = 0; + } + + while (length >= 64) { + SHA256_Process(ctx, input); + length -= 64; + input += 64; + } + + if (length) { + memcpy((void*)(ctx->buffer + left), + (void*)input, length); + } +} + +static void +SHA256_Final(SHA256_CTX* ctx, uint8_t digest[32]) +{ + uint32_t last, padn; + uint32_t high, low; + uint8_t msglen[8]; + + high = (ctx->total[0] >> 29) + | (ctx->total[1] << 3); + low = (ctx->total[0] << 3); + + PUT_UINT32(high, msglen, 0); + PUT_UINT32(low, msglen, 4); + + last = ctx->total[0] & 0x3F; + padn = (last < 56) ? (56 - last) : (120 - last); + + uint8_t sha256_padding[64]; + memset(sha256_padding, 0, 64); + memset(sha256_padding, 0x80, 1); + + SHA256_Update(ctx, sha256_padding, padn); + SHA256_Update(ctx, msglen, 8); + + PUT_UINT32(ctx->state[0], digest, 0); + PUT_UINT32(ctx->state[1], digest, 4); + PUT_UINT32(ctx->state[2], digest, 8); + PUT_UINT32(ctx->state[3], digest, 12); + PUT_UINT32(ctx->state[4], digest, 16); + PUT_UINT32(ctx->state[5], digest, 20); + PUT_UINT32(ctx->state[6], digest, 24); + PUT_UINT32(ctx->state[7], digest, 28); +} + +typedef struct HMAC_SHA256Context { + SHA256_CTX ictx; + SHA256_CTX octx; +} HMAC_SHA256_CTX; + +/* Initialize an HMAC-SHA256 operation with the given key. */ +static void +HMAC_SHA256_Init(HMAC_SHA256_CTX *ctx, const void *_K, size_t Klen) +{ + unsigned char pad[64]; + unsigned char khash[32]; + const unsigned char *K = (const unsigned char *)_K; + size_t i; + + /* If Klen > 64, the key is really SHA256(K). */ + if (Klen > 64) { + SHA256_Init(&ctx->ictx); + SHA256_Update(&ctx->ictx, (uint8_t*)K, Klen); + SHA256_Final(&ctx->ictx, (uint8_t*)khash); + K = khash; + Klen = 32; + } + + /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ + SHA256_Init(&ctx->ictx); + memset(pad, 0x36, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + SHA256_Update(&ctx->ictx, pad, 64); + + /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ + SHA256_Init(&ctx->octx); + memset(pad, 0x5c, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + SHA256_Update(&ctx->octx, pad, 64); + + /* Clean the stack. */ + memset(khash, 0, 32); +} + +/* Add bytes to the HMAC-SHA256 operation. */ +static void +HMAC_SHA256_Update(HMAC_SHA256_CTX *ctx, const void *in, size_t len) +{ + /* Feed data to the inner SHA256 operation. */ + SHA256_Update(&ctx->ictx, (uint8_t*)in, len); +} + +/* Finish an HMAC-SHA256 operation. */ +static void +HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX *ctx) +{ + unsigned char ihash[32]; + + /* Finish the inner SHA256 operation. */ + SHA256_Final(&ctx->ictx, ihash); + + /* Feed the inner hash to the outer SHA256 operation. */ + SHA256_Update(&ctx->octx, ihash, 32); + + /* Finish the outer SHA256 operation. */ + SHA256_Final(&ctx->octx, digest); + + /* Clean the stack. */ + memset(ihash, 0, 32); +} + +/** + * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): + * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and + * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). + */ +void +PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen, const uint8_t *salt, + size_t saltlen, uint64_t c, uint8_t *buf, size_t dkLen) +{ + HMAC_SHA256_CTX PShctx, hctx; + size_t i; + uint8_t ivec[4]; + uint8_t U[32]; + uint8_t T[32]; + uint64_t j; + int k; + size_t clen; + + /* Compute HMAC state after processing P and S. */ + HMAC_SHA256_Init(&PShctx, passwd, passwdlen); + HMAC_SHA256_Update(&PShctx, salt, saltlen); + + /* Iterate through the blocks. */ + for (i = 0; i * 32 < dkLen; i++) { + /* Generate INT(i + 1). */ + be32enc(ivec, (uint32_t)(i + 1)); + + /* Compute U_1 = PRF(P, S || INT(i)). */ + memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); + HMAC_SHA256_Update(&hctx, ivec, 4); + HMAC_SHA256_Final(U, &hctx); + + /* T_i = U_1 ... */ + memcpy(T, U, 32); + + for (j = 2; j <= c; j++) { + /* Compute U_j. */ + HMAC_SHA256_Init(&hctx, passwd, passwdlen); + HMAC_SHA256_Update(&hctx, U, 32); + HMAC_SHA256_Final(U, &hctx); + + /* ... xor U_j ... */ + for (k = 0; k < 32; k++) + T[k] ^= U[k]; + } + + /* Copy as many bytes as necessary into buf. */ + clen = dkLen - i * 32; + if (clen > 32) + clen = 32; + memcpy(&buf[i * 32], T, clen); + } + + /* Clean PShctx, since we never called _Final on it. */ + memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); +} + +#define ROTL(a, b) (((a) << (b)) | ((a) >> (32 - (b)))) + +static inline void xor_salsa8(uint32_t B[16], const uint32_t Bx[16]) +{ + uint32_t x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15; + int i; + + x00 = (B[ 0] ^= Bx[ 0]); + x01 = (B[ 1] ^= Bx[ 1]); + x02 = (B[ 2] ^= Bx[ 2]); + x03 = (B[ 3] ^= Bx[ 3]); + x04 = (B[ 4] ^= Bx[ 4]); + x05 = (B[ 5] ^= Bx[ 5]); + x06 = (B[ 6] ^= Bx[ 6]); + x07 = (B[ 7] ^= Bx[ 7]); + x08 = (B[ 8] ^= Bx[ 8]); + x09 = (B[ 9] ^= Bx[ 9]); + x10 = (B[10] ^= Bx[10]); + x11 = (B[11] ^= Bx[11]); + x12 = (B[12] ^= Bx[12]); + x13 = (B[13] ^= Bx[13]); + x14 = (B[14] ^= Bx[14]); + x15 = (B[15] ^= Bx[15]); + for (i = 0; i < 8; i += 2) { + /* Operate on columns. */ + x04 ^= ROTL(x00 + x12, 7); x09 ^= ROTL(x05 + x01, 7); + x14 ^= ROTL(x10 + x06, 7); x03 ^= ROTL(x15 + x11, 7); + + x08 ^= ROTL(x04 + x00, 9); x13 ^= ROTL(x09 + x05, 9); + x02 ^= ROTL(x14 + x10, 9); x07 ^= ROTL(x03 + x15, 9); + + x12 ^= ROTL(x08 + x04, 13); x01 ^= ROTL(x13 + x09, 13); + x06 ^= ROTL(x02 + x14, 13); x11 ^= ROTL(x07 + x03, 13); + + x00 ^= ROTL(x12 + x08, 18); x05 ^= ROTL(x01 + x13, 18); + x10 ^= ROTL(x06 + x02, 18); x15 ^= ROTL(x11 + x07, 18); + + /* Operate on rows. */ + x01 ^= ROTL(x00 + x03, 7); x06 ^= ROTL(x05 + x04, 7); + x11 ^= ROTL(x10 + x09, 7); x12 ^= ROTL(x15 + x14, 7); + + x02 ^= ROTL(x01 + x00, 9); x07 ^= ROTL(x06 + x05, 9); + x08 ^= ROTL(x11 + x10, 9); x13 ^= ROTL(x12 + x15, 9); + + x03 ^= ROTL(x02 + x01, 13); x04 ^= ROTL(x07 + x06, 13); + x09 ^= ROTL(x08 + x11, 13); x14 ^= ROTL(x13 + x12, 13); + + x00 ^= ROTL(x03 + x02, 18); x05 ^= ROTL(x04 + x07, 18); + x10 ^= ROTL(x09 + x08, 18); x15 ^= ROTL(x14 + x13, 18); + } + B[ 0] += x00; + B[ 1] += x01; + B[ 2] += x02; + B[ 3] += x03; + B[ 4] += x04; + B[ 5] += x05; + B[ 6] += x06; + B[ 7] += x07; + B[ 8] += x08; + B[ 9] += x09; + B[10] += x10; + B[11] += x11; + B[12] += x12; + B[13] += x13; + B[14] += x14; + B[15] += x15; +} + +void scrypt_1024_1_1_256_sp_generic(const char *input, char *output, char *scratchpad) +{ + uint8_t B[128]; + uint32_t X[32]; + uint32_t *V; + uint32_t i, j, k; + + V = (uint32_t *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63)); + + PBKDF2_SHA256((const uint8_t *)input, 80, (const uint8_t *)input, 80, 1, B, 128); + + for (k = 0; k < 32; k++) + X[k] = le32dec(&B[4 * k]); + + for (i = 0; i < 1024; i++) { + memcpy(&V[i * 32], X, 128); + xor_salsa8(&X[0], &X[16]); + xor_salsa8(&X[16], &X[0]); + } + for (i = 0; i < 1024; i++) { + j = 32 * (X[16] & 1023); + for (k = 0; k < 32; k++) + X[k] ^= V[j + k]; + xor_salsa8(&X[0], &X[16]); + xor_salsa8(&X[16], &X[0]); + } + + for (k = 0; k < 32; k++) + le32enc(&B[4 * k], X[k]); + + PBKDF2_SHA256((const uint8_t *)input, 80, B, 128, 1, (uint8_t *)output, 32); +} + +#if defined(USE_SSE2) +// By default, set to generic scrypt function. This will prevent crash in case when scrypt_detect_sse2() wasn't called +void (*scrypt_1024_1_1_256_sp_detected)(const char *input, char *output, char *scratchpad) = &scrypt_1024_1_1_256_sp_generic; + +std::string scrypt_detect_sse2() +{ + std::string ret; +#if defined(USE_SSE2_ALWAYS) + ret = "scrypt: using scrypt-sse2 as built."; +#else // USE_SSE2_ALWAYS + // 32bit x86 Linux or Windows, detect cpuid features + unsigned int cpuid_edx=0; +#if defined(_MSC_VER) + // MSVC + int x86cpuid[4]; + __cpuid(x86cpuid, 1); + cpuid_edx = (unsigned int)buffer[3]; +#else // _MSC_VER + // Linux or i686-w64-mingw32 (gcc-4.6.3) + unsigned int eax, ebx, ecx; + __get_cpuid(1, &eax, &ebx, &ecx, &cpuid_edx); +#endif // _MSC_VER + + if (cpuid_edx & 1<<26) + { + scrypt_1024_1_1_256_sp_detected = &scrypt_1024_1_1_256_sp_sse2; + ret = "scrypt: using scrypt-sse2 as detected"; + } + else + { + scrypt_1024_1_1_256_sp_detected = &scrypt_1024_1_1_256_sp_generic; + ret = "scrypt: using scrypt-generic, SSE2 unavailable"; + } +#endif // USE_SSE2_ALWAYS + return ret; +} +#endif + +void scrypt_1024_1_1_256(const char *input, char *output) +{ + char scratchpad[SCRYPT_SCRATCHPAD_SIZE]; + scrypt_1024_1_1_256_sp(input, output, scratchpad); +} + +void SHA256(unsigned char* input, int len, unsigned char* output) +{ + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, (uint8_t*)input, len); + SHA256_Final(&ctx, (uint8_t*)output); +} + diff --git a/src/crypto/scrypt.h b/src/crypto/scrypt.h new file mode 100644 index 000000000..6ba31aee6 --- /dev/null +++ b/src/crypto/scrypt.h @@ -0,0 +1,49 @@ +#ifndef BITCOIN_CRYPTO_SCRYPT_H +#define BITCOIN_CRYPTO_SCRYPT_H + +#include <stdlib.h> +#include <stdint.h> + +static const int SCRYPT_SCRATCHPAD_SIZE = 131072 + 63; + +void scrypt_1024_1_1_256(const char *input, char *output); +void scrypt_1024_1_1_256_sp_generic(const char *input, char *output, char *scratchpad); + +#if defined(USE_SSE2) +#include <string> +#if defined(_M_X64) || defined(__x86_64__) || defined(_M_AMD64) || (defined(MAC_OSX) && defined(__i386__)) +#define USE_SSE2_ALWAYS 1 +#define scrypt_1024_1_1_256_sp(input, output, scratchpad) scrypt_1024_1_1_256_sp_sse2((input), (output), (scratchpad)) +#else +#define scrypt_1024_1_1_256_sp(input, output, scratchpad) scrypt_1024_1_1_256_sp_detected((input), (output), (scratchpad)) +#endif + +std::string scrypt_detect_sse2(); +void scrypt_1024_1_1_256_sp_sse2(const char *input, char *output, char *scratchpad); +extern void (*scrypt_1024_1_1_256_sp_detected)(const char *input, char *output, char *scratchpad); +#else +#define scrypt_1024_1_1_256_sp(input, output, scratchpad) scrypt_1024_1_1_256_sp_generic((input), (output), (scratchpad)) +#endif + +void +PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen, const uint8_t *salt, + size_t saltlen, uint64_t c, uint8_t *buf, size_t dkLen); + +#ifndef __FreeBSD__ +static inline uint32_t le32dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + + ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); +} + +static inline void le32enc(void *pp, uint32_t x) +{ + uint8_t *p = (uint8_t *)pp; + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; +} +#endif +#endif // BITCOIN_CRYPTO_SCRYPT_H diff --git a/src/init.cpp b/src/init.cpp index 097c645f1..36b82c243 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -85,7 +85,12 @@ #include <zmq/zmqrpc.h> #endif +#ifdef USE_SSE2 +#include <crypto/scrypt.h> +#endif + static bool fFeeEstimatesInitialized = false; + static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_REST_ENABLE = false; static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false; @@ -968,6 +973,10 @@ bool AppInitParameterInteraction(const ArgsManager& args) // on the command line or in this network's section of the config file. std::string network = args.GetChainName(); if (network == CBaseChainParams::SIGNET) { + // Dogecoin: Signet requires a challenge, but we can't halt when constructing the chainparams as they're constructed even if not used. + if (!args.IsArgSet("-signetchallenge")) { + return InitError(_("-signetchallenge must be specified when using -signet on Dogecoin as no default Signet is available.")); + } LogPrintf("Signet derived magic (message start): %s\n", HexStr(chainparams.MessageStart())); } bilingual_str errors; @@ -1370,6 +1379,11 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA if (!AppInitServers(context, node)) return InitError(_("Unable to start HTTP server. See debug log for details.")); } + +#if defined(USE_SSE2) + std::string sse2detect = scrypt_detect_sse2(); + LogPrintf("%s\n", sse2detect); +#endif // ********************************************************* Step 5: verify wallet database integrity for (const auto& client : node.chain_clients) { diff --git a/src/net_processing.cpp b/src/net_processing.cpp index cbb448649..d2a0e6d91 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2469,6 +2469,8 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat AddTimeData(pfrom.addr, nTimeOffset); // If the peer is old enough to have the old alert system, send it the final alert. + // TODO: Decide if we need to reintroduce alerts to Dogecoin + // https://github.com/dogecoin/dogecoin/issues/2231 if (greatest_common_version <= 70012) { CDataStream finalAlert(ParseHex("60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"), SER_NETWORK, PROTOCOL_VERSION); m_connman.PushMessage(&pfrom, CNetMsgMaker(greatest_common_version).Make("alert", finalAlert)); diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 50a30cb51..1aeabb3d5 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -7,12 +7,21 @@ #include <hash.h> #include <tinyformat.h> +#include <crypto/common.h> +#include <crypto/scrypt.h> uint256 CBlockHeader::GetHash() const { return SerializeHash(*this); } +uint256 CBlockHeader::GetPoWHash() const +{ + uint256 thash; + scrypt_1024_1_1_256((char*)&nVersion, (char*)&thash); + return thash; +} + std::string CBlock::ToString() const { std::stringstream s; diff --git a/src/primitives/block.h b/src/primitives/block.h index fd8fc8b86..20642d744 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -52,6 +52,8 @@ public: uint256 GetHash() const; + uint256 GetPoWHash() const; + int64_t GetBlockTime() const { return (int64_t)nTime; diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index a82adc251..b952d87e1 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -69,7 +69,7 @@ void RPCNestedTests::rpcNestedTests() QVERIFY(result == result2); RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())[tx][0]", &filtered); - QVERIFY(result == "13abc7dbaf8e00e9e128cb4977e3a9d15ea5d4ff249dd625ee607f6023cdb3df"); + QVERIFY(result == "5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69"); QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]"); RPCConsole::RPCParseCommandLine(nullptr, result, "importprivkey", false, &filtered); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 6522c0d73..74e1c469b 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -116,7 +116,7 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& CChainParams chainparams(Params()); - while (max_tries > 0 && block.nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus()) && !ShutdownRequested()) { + while (max_tries > 0 && block.nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(block.GetPoWHash(), block.nBits, chainparams.GetConsensus()) && !ShutdownRequested()) { ++block.nNonce; --max_tries; } diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp index f004ecc20..b6b5b55f5 100644 --- a/src/rpc/rawtransaction_util.cpp +++ b/src/rpc/rawtransaction_util.cpp @@ -115,7 +115,7 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal } else { CTxDestination destination = DecodeDestination(name_); if (!IsValidDestination(destination)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Bitcoin address: ") + name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dogecoin address: ") + name_); } if (!destinations.insert(destination).second) { diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 14cf1a4a7..fb3158b07 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -44,7 +44,7 @@ static CBlock BuildBlockTestCase() { bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); - while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; + while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; return block; } @@ -275,7 +275,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); - while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; + while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; // Test simple header round-trip with only coinbase { diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index 753c1bb5f..8b76d30ac 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -82,7 +82,7 @@ CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev, unsigned int extraNonce = 0; IncrementExtraNonce(&block, prev, extraNonce); - while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; + while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; return block; } diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 2a342fe70..3eefab9ef 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -51,34 +51,34 @@ constexpr static struct { unsigned char extranonce; unsigned int nonce; } blockinfo[] = { - {4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5}, - {2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84}, - {2, 0x83f30c2c}, {1, 0x48a73d5b}, {1, 0xef7dcd01}, {2, 0x6809c6c4}, - {2, 0x0883ab3c}, {1, 0x087bbbe2}, {2, 0x2104a814}, {2, 0xdffb6daa}, - {1, 0xee8a0a08}, {2, 0xba4237c1}, {1, 0xa70349dc}, {1, 0x344722bb}, - {3, 0xd6294733}, {2, 0xec9f5c94}, {2, 0xca2fbc28}, {1, 0x6ba4f406}, - {2, 0x015d4532}, {1, 0x6e119b7c}, {2, 0x43e8f314}, {2, 0x27962f38}, - {2, 0xb571b51b}, {2, 0xb36bee23}, {2, 0xd17924a8}, {2, 0x6bc212d9}, - {1, 0x630d4948}, {2, 0x9a4c4ebb}, {2, 0x554be537}, {1, 0xd63ddfc7}, - {2, 0xa10acc11}, {1, 0x759a8363}, {2, 0xfb73090d}, {1, 0xe82c6a34}, - {1, 0xe33e92d7}, {3, 0x658ef5cb}, {2, 0xba32ff22}, {5, 0x0227a10c}, - {1, 0xa9a70155}, {5, 0xd096d809}, {1, 0x37176174}, {1, 0x830b8d0f}, - {1, 0xc6e3910e}, {2, 0x823f3ca8}, {1, 0x99850849}, {1, 0x7521fb81}, - {1, 0xaacaabab}, {1, 0xd645a2eb}, {5, 0x7aea1781}, {5, 0x9d6e4b78}, - {1, 0x4ce90fd8}, {1, 0xabdc832d}, {6, 0x4a34f32a}, {2, 0xf2524c1c}, - {2, 0x1bbeb08a}, {1, 0xad47f480}, {1, 0x9f026aeb}, {1, 0x15a95049}, - {2, 0xd1cb95b2}, {2, 0xf84bbda5}, {1, 0x0fa62cd1}, {1, 0xe05f9169}, - {1, 0x78d194a9}, {5, 0x3e38147b}, {5, 0x737ba0d4}, {1, 0x63378e10}, - {1, 0x6d5f91cf}, {2, 0x88612eb8}, {2, 0xe9639484}, {1, 0xb7fabc9d}, - {2, 0x19b01592}, {1, 0x5a90dd31}, {2, 0x5bd7e028}, {2, 0x94d00323}, - {1, 0xa9b9c01a}, {1, 0x3a40de61}, {1, 0x56e7eec7}, {5, 0x859f7ef6}, - {1, 0xfd8e5630}, {1, 0x2b0c9f7f}, {1, 0xba700e26}, {1, 0x7170a408}, - {1, 0x70de86a8}, {1, 0x74d64cd5}, {1, 0x49e738a1}, {2, 0x6910b602}, - {0, 0x643c565f}, {1, 0x54264b3f}, {2, 0x97ea6396}, {2, 0x55174459}, - {2, 0x03e8779a}, {1, 0x98f34d8f}, {1, 0xc07b2b07}, {1, 0xdfe29668}, - {1, 0x3141c7c1}, {1, 0xb3b595f4}, {1, 0x735abf08}, {5, 0x623bfbce}, - {2, 0xd351e722}, {1, 0xf4ca48c9}, {1, 0x5b19c670}, {1, 0xa164bf0e}, - {2, 0xbbbeb305}, {2, 0xfe1c810a}, + {4, 0x127fad2d}, {2, 0x335d1b8f}, {1, 0x33d47094}, {2, 0x0b09ec28}, + {1, 0x06cf723b}, {2, 0x039202bc}, {1, 0x0a2c9d46}, {2, 0x6225cb92}, + {2, 0x6ea1513e}, {1, 0x4401bef3}, {1, 0x04d3a1d2}, {2, 0x1c512825}, + {2, 0x54a03b14}, {1, 0x6048e27d}, {1, 0x1b926afc}, {2, 0x68c4afbd}, + {2, 0x4439c313}, {1, 0x1263fceb}, {2, 0x834dee3e}, {2, 0xf21ed9dc}, + {1, 0xdcdac434}, {2, 0x4c1945be}, {1, 0x6d42a594}, {3, 0x20927a30}, + {3, 0xfd60f461}, {2, 0xd9ad2207}, {2, 0xe7f69d1a}, {1, 0x7fa9b932}, + {2, 0xb0511080}, {1, 0xe7d24cd5}, {2, 0x3c57e668}, {2, 0x83bfdc2e}, + {2, 0x6eeb4e10}, {2, 0x9cacbcfd}, {2, 0xb27ea98e}, {2, 0x6d57c5a7}, + {1, 0x6deb4fa8}, {2, 0xabf625c6}, {2, 0x27e7c569}, {1, 0x89c6e991}, + {2, 0xc359bc28}, {1, 0x6f25768d}, {2, 0x654a4c31}, {1, 0x5cd03bab}, + {1, 0xda405f69}, {3, 0xfea453e5}, {2, 0x137d2c3a}, {5, 0xdee2f36e}, + {1, 0xeccbcf26}, {5, 0x9237dbaa}, {1, 0xb7b9350b}, {1, 0xcd0c7eb2}, + {1, 0xf5ea5a32}, {2, 0x3486a7f3}, {1, 0xd0a0f2be}, {1, 0xe1238144}, + {1, 0x28b98a9b}, {1, 0xe79d02aa}, {5, 0xf4555d56}, {5, 0x74da0bb7}, + {1, 0x18728b91}, {1, 0x07ed3a93}, {6, 0xd7a5e106}, {2, 0xba50b06c}, + {2, 0x952c830d}, {1, 0xfbd1bb18}, {1, 0x36126967}, {1, 0xcce357d0}, + {2, 0xff1ec2d6}, {2, 0xbed5dfc9}, {1, 0x0d21fdd7}, {1, 0xd744edea}, + {1, 0xe09fc8f2}, {5, 0x2ad325c5}, {5, 0x466b6549}, {1, 0x10705d49}, + {1, 0xf88478ce}, {2, 0xbfda6c4a}, {2, 0x731fe414}, {1, 0x6f1b362e}, + {2, 0x6be709cf}, {1, 0x60553200}, {2, 0xf6a992f0}, {2, 0x1521f7f5}, + {1, 0x8b440273}, {1, 0xe9ade0c8}, {1, 0x4d414618}, {5, 0x7b48070d}, + {1, 0x1202ebae}, {1, 0xd23fe97e}, {1, 0x8d1d6505}, {1, 0xfafbaae3}, + {1, 0xf200353e}, {1, 0xe77bd65e}, {1, 0x9fa32102}, {2, 0x68dfa747}, + {0, 0x7c74d78e}, {1, 0x9b79cc6b}, {2, 0xad957cc2}, {2, 0x91acb818}, + {1, 0x00024b92}, {1, 0x0002a868}, {1, 0x0000767a}, {1, 0x0003f818}, + {1, 0x001e2f24}, {1, 0x001d43f5}, {1, 0x00074756}, {2, 0x0001cc72}, + {0, 0x0002bb2c}, {1, 0x001a9616}, }; static CBlockIndex CreateBlockIndex(int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_main) @@ -200,7 +200,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // Note that by default, these tests run with size accounting enabled. const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN); const CChainParams& chainparams = *chainParams; - CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; + // changed this to dogecoin genesis pubkey script + CScript scriptPubKey = CScript() << ParseHex("040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9") << OP_CHECKSIG; std::unique_ptr<CBlockTemplate> pblocktemplate; CMutableTransaction tx; CScript script; @@ -214,11 +215,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // Simple block creation, nothing special yet: BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); - // Dogecoin: Disable tests which spend rewards, until we have 240+ blocks in the mining tests - // TODO: Re-enable once we have Scrypt, Doge rewards and other early mining Dogecoin parameters in place, - // and can calculate 240 blocks to put into blockinfo[] above. - /* - // We can't make transactions until we have inputs // Therefore, load 110 blocks :) static_assert(sizeof(blockinfo) / sizeof(*blockinfo) == 110, "Should have 110 blocks to import"); @@ -230,7 +226,10 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { LOCK(cs_main); pblock->nVersion = 1; - pblock->nTime = ::ChainActive().Tip()->GetMedianTimePast()+1; + // Replaced ::ChainActive().Tip()->GetMedianTimePast()+1 with an actual 60 second block + // interval because median([1,2,2,3,3,3,4,4,4,4]) will eventually be problematic re: + // block timing. Tests should be more stable than that. + pblock->nTime = ::ChainActive().Tip()->GetBlockTime() + 60; CMutableTransaction txCoinbase(*pblock->vtx[0]); txCoinbase.nVersion = 1; txCoinbase.vin[0].scriptSig = CScript(); @@ -420,7 +419,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } // non-final txs in mempool - SetMockTime(::ChainActive().Tip()->GetMedianTimePast()+1); + // changed to 60 second block interval for consistency + SetMockTime(::ChainActive().Tip()->GetMedianTimePast()+60); int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST; // height map std::vector<int> prevheights; @@ -506,7 +506,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++) ::ChainActive().Tip()->GetAncestor(::ChainActive().Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast ::ChainActive().Tip()->nHeight++; - SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 1); + // changed to 60 second block interval for consistency + SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 60); BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U); @@ -517,7 +518,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) m_node.mempool->clear(); TestPackageSelection(chainparams, scriptPubKey, txFirst); - */ fCheckpointsEnabled = true; } diff --git a/src/test/scrypt_tests.cpp b/src/test/scrypt_tests.cpp new file mode 100644 index 000000000..d037c88d3 --- /dev/null +++ b/src/test/scrypt_tests.cpp @@ -0,0 +1,34 @@ +#include <boost/test/unit_test.hpp> + +#include <crypto/scrypt.h> +#include <uint256.h> +#include <util/strencodings.h> + +BOOST_AUTO_TEST_SUITE(scrypt_tests) + +BOOST_AUTO_TEST_CASE(scrypt_hashtest) +{ + // Test Scrypt hash with known inputs against expected outputs + #define HASHCOUNT 5 + const char* inputhex[HASHCOUNT] = { "020000004c1271c211717198227392b029a64a7971931d351b387bb80db027f270411e398a07046f7d4a08dd815412a8712f874a7ebf0507e3878bd24e20a3b73fd750a667d2f451eac7471b00de6659", "0200000011503ee6a855e900c00cfdd98f5f55fffeaee9b6bf55bea9b852d9de2ce35828e204eef76acfd36949ae56d1fbe81c1ac9c0209e6331ad56414f9072506a77f8c6faf551eac7471b00389d01", "02000000a72c8a177f523946f42f22c3e86b8023221b4105e8007e59e81f6beb013e29aaf635295cb9ac966213fb56e046dc71df5b3f7f67ceaeab24038e743f883aff1aaafaf551eac7471b0166249b", "010000007824bc3a8a1b4628485eee3024abd8626721f7f870f8ad4d2f33a27155167f6a4009d1285049603888fe85a84b6c803a53305a8d497965a5e896e1a00568359589faf551eac7471b0065434e", "0200000050bfd4e4a307a8cb6ef4aef69abc5c0f2d579648bd80d7733e1ccc3fbc90ed664a7f74006cb11bde87785f229ecd366c2d4e44432832580e0608c579e4cb76f383f7f551eac7471b00c36982" }; + const char* expected[HASHCOUNT] = { "00000000002bef4107f882f6115e0b01f348d21195dacd3582aa2dabd7985806" , "00000000003a0d11bdd5eb634e08b7feddcfbbf228ed35d250daf19f1c88fc94", "00000000000b40f895f288e13244728a6c2d9d59d8aff29c65f8dd5114a8ca81", "00000000003007005891cd4923031e99d8e8d72f6e8e7edc6a86181897e105fe", "000000000018f0b426a4afc7130ccb47fa02af730d345b4fe7c7724d3800ec8c" }; +#if defined(USE_SSE2) + (void) scrypt_detect_sse2(); +#endif + uint256 scrypthash; + std::vector<unsigned char> inputbytes; + char scratchpad[SCRYPT_SCRATCHPAD_SIZE]; + for (int i = 0; i < HASHCOUNT; i++) { + inputbytes = ParseHex(inputhex[i]); +#if defined(USE_SSE2) + // Test SSE2 scrypt + scrypt_1024_1_1_256_sp_sse2((const char*)&inputbytes[0], BEGIN(scrypthash), scratchpad); + BOOST_CHECK_EQUAL(scrypthash.ToString().c_str(), expected[i]); +#endif + // Test generic scrypt + scrypt_1024_1_1_256_sp_generic((const char*)&inputbytes[0], BEGIN(scrypthash), scratchpad); + BOOST_CHECK_EQUAL(scrypthash.ToString().c_str(), expected[i]); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp index 74536ae74..ca4fa9f33 100644 --- a/src/test/util/mining.cpp +++ b/src/test/util/mining.cpp @@ -27,7 +27,7 @@ CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) { auto block = PrepareBlock(node, coinbase_scriptPubKey); - while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { + while (!CheckProofOfWork(block->GetPoWHash(), block->nBits, Params().GetConsensus())) { ++block->nNonce; assert(block->nNonce); } diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index f3428b7f8..405a51c92 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -219,7 +219,7 @@ CBlock TestChain240Setup::CreateAndProcessBlock(const std::vector<CMutableTransa } RegenerateCommitments(block); - while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; + while (!CheckProofOfWork(block.GetPoWHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block); Assert(m_node.chainman)->ProcessNewBlock(chainparams, shared_pblock, true, nullptr); diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index a32b25899..920208900 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -103,7 +103,7 @@ std::shared_ptr<CBlock> MinerTestingSetup::FinalizeBlock(std::shared_ptr<CBlock> pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); - while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) { + while (!CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) { ++(pblock->nNonce); } diff --git a/src/txdb.cpp b/src/txdb.cpp index 72460e7c6..8f7820bc5 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -271,8 +271,14 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; - if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) - return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString()); + // Litecoin: Disable PoW Sanity check while loading block index from disk. + // We use the sha256 hash for the block index for performance reasons, which is recorded for later use. + // CheckProofOfWork() uses the scrypt hash which is discarded after a block is accepted. + // While it is technically feasible to verify the PoW, doing so takes several minutes as it + // requires recomputing every PoW hash during every Litecoin startup. + // We opt instead to simply trust the data that is on your local disk. + //if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) + // return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString()); pcursor->Next(); } else { diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 1a217dd12..c7e66d775 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -18,6 +18,7 @@ #include <vector> #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) +#define BEGIN(a) ((char*)&(a)) /** Used by SanitizeString() */ enum SafeChars diff --git a/src/validation.cpp b/src/validation.cpp index 7457ab50a..481eb0359 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1161,7 +1161,7 @@ bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::P } // Check the header - if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) + if (!CheckProofOfWork(block.GetPoWHash(), block.nBits, consensusParams)) return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); // Signet only: check block solution @@ -3342,7 +3342,7 @@ static bool FindUndoPos(BlockValidationState &state, int nFile, FlatFilePos &pos static bool CheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true) { // Check proof of work matches claimed amount - if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) + if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(), block.nBits, consensusParams)) return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, "high-hash", "proof of work failed"); return true; @@ -3526,8 +3526,8 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio // Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded: // check for version 2, 3 and 4 upgrades - if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) || - (block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) || + // Dogecoin: Version 2 enforcement was never used + if((block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) || (block.nVersion < 4 && nHeight >= consensusParams.BIP65Height)) return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, strprintf("bad-version(0x%08x)", block.nVersion), strprintf("rejected nVersion=0x%08x block", block.nVersion)); diff --git a/src/version.h b/src/version.h index 019c3a3ae..cdb18dcdf 100644 --- a/src/version.h +++ b/src/version.h @@ -15,7 +15,7 @@ static const int PROTOCOL_VERSION = 70016; static const int INIT_PROTO_VERSION = 209; //! disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION = 31800; +static const int MIN_PEER_PROTO_VERSION = 70003; //! BIP 0031, pong message, is enabled for all versions AFTER this one static const int BIP0031_VERSION = 60000; |