aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatrick Lodder <[email protected]>2021-06-02 23:45:02 +0200
committerGitHub <[email protected]>2021-06-02 23:45:02 +0200
commit8fcbf8cfe55638e8970c5c76608123797f5140e6 (patch)
treee440a18b5bb2c86b3620ec295356255cb365dc38 /src
parentMerge pull request #2210 from rnicoll/1.21-block-subsidy (diff)
parentRemove default Signet (diff)
downloaddiscoin-8fcbf8cfe55638e8970c5c76608123797f5140e6.tar.xz
discoin-8fcbf8cfe55638e8970c5c76608123797f5140e6.zip
Merge pull request #1828 from rnicoll/1.21-dev-scrypt-algo
Scrypt algorithm
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/Makefile.bench.include4
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/bench/checkblock.cpp8
-rw-r--r--src/bench/data.cpp4
-rw-r--r--src/bench/data.h2
-rw-r--r--src/bench/data/block413567.rawbin999887 -> 0 bytes
-rw-r--r--src/bench/data/block41385.rawbin0 -> 102806 bytes
-rw-r--r--src/bench/rpc_blockchain.cpp2
-rw-r--r--src/chain.h5
-rw-r--r--src/chainparams.cpp88
-rw-r--r--src/crypto/scrypt-sse2.cpp140
-rw-r--r--src/crypto/scrypt.cpp576
-rw-r--r--src/crypto/scrypt.h49
-rw-r--r--src/init.cpp14
-rw-r--r--src/net_processing.cpp2
-rw-r--r--src/primitives/block.cpp9
-rw-r--r--src/primitives/block.h2
-rw-r--r--src/qt/test/rpcnestedtests.cpp2
-rw-r--r--src/rpc/mining.cpp2
-rw-r--r--src/rpc/rawtransaction_util.cpp2
-rw-r--r--src/test/blockencodings_tests.cpp4
-rw-r--r--src/test/blockfilter_index_tests.cpp2
-rw-r--r--src/test/miner_tests.cpp76
-rw-r--r--src/test/scrypt_tests.cpp34
-rw-r--r--src/test/util/mining.cpp2
-rw-r--r--src/test/util/setup_common.cpp2
-rw-r--r--src/test/validation_block_tests.cpp2
-rw-r--r--src/txdb.cpp10
-rw-r--r--src/util/strencodings.h1
-rw-r--r--src/validation.cpp8
-rw-r--r--src/version.h2
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
deleted file mode 100644
index 67d2d5d38..000000000
--- a/src/bench/data/block413567.raw
+++ /dev/null
Binary files differ
diff --git a/src/bench/data/block41385.raw b/src/bench/data/block41385.raw
new file mode 100644
index 000000000..328f7e9af
--- /dev/null
+++ b/src/bench/data/block41385.raw
Binary files differ
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;