aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rwxr-xr-xqa/pull-tester/install-deps.sh10
-rwxr-xr-xqa/pull-tester/rpc-tests.sh1
-rwxr-xr-xqa/rpc-tests/auxpow.py80
-rw-r--r--qa/rpc-tests/test_framework/scrypt_auxpow.py105
5 files changed, 197 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml
index 4a0c792fa..33b473ff4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -85,6 +85,7 @@ matrix:
before_script:
- unset CC; unset CXX
- mkdir -p depends/SDKs depends/sdk-sources
+ - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/install-deps.sh; fi
- if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then wget $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -O depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
- if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
- make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
diff --git a/qa/pull-tester/install-deps.sh b/qa/pull-tester/install-deps.sh
new file mode 100755
index 000000000..3941031bc
--- /dev/null
+++ b/qa/pull-tester/install-deps.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# installs test dependencies
+
+wget https://pypi.python.org/packages/source/l/ltc_scrypt/ltc_scrypt-1.0.tar.gz
+#echo "7d019c3c98f16eb466a272e518ffb014 ltc_scrypt-1.0.tar.gz" | md5sum -c
+tar zxf ltc_scrypt-1.0.tar.gz
+pushd ltc_scrypt-1.0
+python setup.py install --user
+popd
diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh
index f7aa15015..750ffc3ce 100755
--- a/qa/pull-tester/rpc-tests.sh
+++ b/qa/pull-tester/rpc-tests.sh
@@ -16,6 +16,7 @@ fi
#Run the tests
testScripts=(
+ 'auxpow.py'
'wallet.py'
'listtransactions.py'
'mempool_resurrect_test.py'
diff --git a/qa/rpc-tests/auxpow.py b/qa/rpc-tests/auxpow.py
new file mode 100755
index 000000000..e194a217c
--- /dev/null
+++ b/qa/rpc-tests/auxpow.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python2
+# Copyright (c) 2015 The Dogecoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Test AuxPOW RPC interface and constraints
+#
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+from struct import *
+import binascii
+import json
+import StringIO
+from test_framework import scrypt_auxpow
+
+class AuxPOWTest (BitcoinTestFramework):
+ REWARD = 500000 # reward per block
+ CHAIN_ID = "62"
+ DIGISHIELD_START = 10 # nHeight when digishield starts
+ AUXPOW_START = 20 # nHeight when auxpow starts
+ MATURITY_HEIGHT = 60 # number of blocks for mined transactions to mature
+
+ def setup_chain(self):
+ print("Initializing test directory " + self.options.tmpdir)
+ initialize_chain_clean(self.options.tmpdir, 2)
+
+ def setup_network(self, split=False):
+ self.nodes = start_nodes(2, self.options.tmpdir)
+ connect_nodes_bi(self.nodes,0,1)
+ self.is_network_split=False
+ self.sync_all()
+
+ def run_test(self):
+ print "Mining blocks..."
+
+ # 1. mine an auxpow block before auxpow is allowed, expect: fail
+ scrypt_auxpow.mineScryptAux(self.nodes[0], "00", True)
+ self.sync_all()
+
+ # 2. mine a non-auxpow block, just to ensure that this node
+ # can mine at all, expect: success
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ # 3. mine blocks until we're in digishield era
+ self.nodes[1].generate(self.DIGISHIELD_START - 1 - 1)
+ self.sync_all()
+
+ # 4. mine an auxpow block before auxpow is allowed, attempt 2
+ # expect: fail
+ scrypt_auxpow.mineScryptAux(self.nodes[0], "00", True)
+ self.sync_all()
+
+ # 5. mine blocks until we're in in auxpow era
+ self.nodes[1].generate(self.AUXPOW_START - self.DIGISHIELD_START)
+ self.sync_all()
+
+ # 6. mine a valid auxpow block, expect: success
+ scrypt_auxpow.mineScryptAux(self.nodes[0], "00", True)
+
+ # 7. mine an auxpow block with high pow, expect: fail
+ scrypt_auxpow.mineScryptAux(self.nodes[0], "00", False)
+
+ # 8. mine a valid auxpow block with the parent chain being us
+ # expect: fail
+ scrypt_auxpow.mineScryptAux(self.nodes[0], self.CHAIN_ID, True)
+ self.sync_all()
+
+ # 9. mine enough blocks to mature all node 0 rewards
+ self.nodes[1].generate(self.MATURITY_HEIGHT)
+ self.sync_all()
+
+ # node 0 should have block rewards for 2 blocks,
+ # One from step 2 and one from step 6.
+ assert_equal(self.nodes[0].getbalance(), self.REWARD * 2)
+
+if __name__ == '__main__':
+ AuxPOWTest ().main ()
diff --git a/qa/rpc-tests/test_framework/scrypt_auxpow.py b/qa/rpc-tests/test_framework/scrypt_auxpow.py
new file mode 100644
index 000000000..0d85062a9
--- /dev/null
+++ b/qa/rpc-tests/test_framework/scrypt_auxpow.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 Daniel Kraft
+# Copyright (c) 2015 The Dogecoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+# General code for scrypt auxpow testing. This includes routines to
+# solve an auxpow header and to generate auxpow blocks with scrypt.
+# extends and modifies auxpow module by Daniel Kraft.
+
+# This module requires a built and installed version of the ltc_scrypt
+# package, which can be downloaded from:
+# https://pypi.python.org/packages/source/l/ltc_scrypt/ltc_scrypt-1.0.tar.gz
+
+import binascii
+import hashlib
+import auxpow
+import ltc_scrypt
+
+def computeAuxpowWithChainId (block, target, chainid, ok):
+ """
+ Build an auxpow object (serialised as hex string) that solves the
+ block, for a given chain id.
+ """
+
+ # Start by building the merge-mining coinbase. The merkle tree
+ # consists only of the block hash as root.
+ coinbase = "fabe" + binascii.hexlify ("m" * 2)
+ coinbase += block
+ coinbase += "01000000" + ("00" * 4)
+
+ # Construct "vector" of transaction inputs.
+ vin = "01"
+ vin += ("00" * 32) + ("ff" * 4)
+ vin += ("%02x" % (len (coinbase) / 2)) + coinbase
+ vin += ("ff" * 4)
+
+ # Build up the full coinbase transaction. It consists only
+ # of the input and has no outputs.
+ tx = "01000000" + vin + "00" + ("00" * 4)
+ txHash = auxpow.doubleHashHex (tx)
+
+ # Construct the parent block header. It need not be valid, just good
+ # enough for auxpow purposes.
+ header = "0100" + chainid + "00"
+ header += "00" * 32
+ header += auxpow.reverseHex (txHash)
+ header += "00" * 4
+ header += "00" * 4
+ header += "00" * 4
+
+ # Mine the block.
+ (header, blockhash) = mineScryptBlock (header, target, ok)
+
+ # Build the MerkleTx part of the auxpow.
+ output = tx
+ output += blockhash
+ output += "00"
+ output += "00" * 4
+
+ # Extend to full auxpow.
+ output += "00"
+ output += "00" * 4
+ output += header
+
+ return output
+
+# for now, just offer hashes to rpc until it matches the work we need
+def mineScryptAux (node, chainid, ok):
+ """
+ Mine an auxpow block on the given RPC connection.
+ """
+
+ auxblock = node.getauxblock ()
+ target = auxpow.reverseHex (auxblock['_target'])
+
+ apow = computeAuxpowWithChainId (auxblock['hash'], target, chainid, ok)
+ res = node.getauxblock (auxblock['hash'], apow)
+
+def mineScryptBlock (header, target, ok):
+ """
+ Given a block header, update the nonce until it is ok (or not)
+ for the given target.
+ """
+
+ data = bytearray (binascii.unhexlify (header))
+ while True:
+ assert data[79] < 255
+ data[79] += 1
+ hexData = binascii.hexlify (data)
+
+ scrypt = getScryptPoW(hexData)
+ if (ok and scrypt < target) or ((not ok) and scrypt > target):
+ break
+
+ blockhash = auxpow.doubleHashHex (hexData)
+ return (hexData, blockhash)
+
+def getScryptPoW(hexData):
+ """
+ Actual scrypt pow calculation
+ """
+
+ data = binascii.unhexlify(hexData)
+ return auxpow.reverseHex(binascii.hexlify(ltc_scrypt.getPoWHash(data)))