aboutsummaryrefslogtreecommitdiff
path: root/test/functional/test_framework
diff options
context:
space:
mode:
authorMax K <[email protected]>2019-07-14 19:35:30 +0200
committerGitHub <[email protected]>2019-07-14 19:35:30 +0200
commitcee13699a5676355487f8eb2d91985f63438eae4 (patch)
treecf12be6180f950a25ee2ee7f3f2126542835d6e3 /test/functional/test_framework
parentCorrect build and test net seed (diff)
parentHandle legacy v2 block at #66064 (diff)
downloaddiscoin-1.17-dev.tar.xz
discoin-1.17-dev.zip
Merge pull request #1546 from rnicoll/1.17-auxpow1.17-dev
1.17 AuxPoW support
Diffstat (limited to 'test/functional/test_framework')
-rw-r--r--test/functional/test_framework/auxpow.py104
-rw-r--r--test/functional/test_framework/auxpow_testing.py82
2 files changed, 186 insertions, 0 deletions
diff --git a/test/functional/test_framework/auxpow.py b/test/functional/test_framework/auxpow.py
new file mode 100644
index 000000000..e145e7ce7
--- /dev/null
+++ b/test/functional/test_framework/auxpow.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python3
+# Copyright (c) 2014-2018 Daniel Kraft
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+# Basic code for working with auxpow. This is used for the regtests (e.g. from
+# auxpow_testing.py), but also for contrib/auxpow/getwork-wrapper.py.
+
+import binascii
+import codecs
+import hashlib
+
+def constructAuxpow (block):
+ """
+ Starts to construct a minimal auxpow, ready to be mined. Returns the fake
+ coinbase tx and the unmined parent block header as hex strings.
+ """
+
+ block = codecs.encode (block, 'ascii')
+
+ # Start by building the merge-mining coinbase. The merkle tree
+ # consists only of the block hash as root.
+ coinbase = b"fabe" + binascii.hexlify (b"m" * 2)
+ coinbase += block
+ coinbase += b"01000000" + (b"00" * 4)
+
+ # Construct "vector" of transaction inputs.
+ vin = b"01"
+ vin += (b"00" * 32) + (b"ff" * 4)
+ vin += codecs.encode ("%02x" % (len (coinbase) // 2), "ascii") + coinbase
+ vin += (b"ff" * 4)
+
+ # Build up the full coinbase transaction. It consists only
+ # of the input and has no outputs.
+ tx = b"01000000" + vin + b"00" + (b"00" * 4)
+ txHash = doubleHashHex (tx)
+
+ # Construct the parent block header. It need not be valid, just good
+ # enough for auxpow purposes.
+ header = b"01000000"
+ header += b"00" * 32
+ header += reverseHex (txHash)
+ header += b"00" * 4
+ header += b"00" * 4
+ header += b"00" * 4
+
+ return (tx.decode ('ascii'), header.decode ('ascii'))
+
+def finishAuxpow (tx, header):
+ """
+ Constructs the finished auxpow hex string based on the mined header.
+ """
+
+ blockhash = doubleHashHex (header)
+
+ # Build the MerkleTx part of the auxpow.
+ auxpow = codecs.encode (tx, 'ascii')
+ auxpow += blockhash
+ auxpow += b"00"
+ auxpow += b"00" * 4
+
+ # Extend to full auxpow.
+ auxpow += b"00"
+ auxpow += b"00" * 4
+ auxpow += header
+
+ return auxpow.decode ("ascii")
+
+def doubleHashHex (data):
+ """
+ Perform Bitcoin's Double-SHA256 hash on the given hex string.
+ """
+
+ hasher = hashlib.sha256 ()
+ hasher.update (binascii.unhexlify (data))
+ data = hasher.digest ()
+
+ hasher = hashlib.sha256 ()
+ hasher.update (data)
+
+ return reverseHex (hasher.hexdigest ())
+
+def reverseHex (data):
+ """
+ Flip byte order in the given data (hex string).
+ """
+
+ b = bytearray (binascii.unhexlify (data))
+ b.reverse ()
+
+ return binascii.hexlify (b)
+
+def getworkByteswap (data):
+ """
+ Run the byte-order swapping step necessary for working with getwork.
+ """
+
+ data = bytearray (data)
+ assert len (data) % 4 == 0
+ for i in range (0, len (data), 4):
+ data[i], data[i + 3] = data[i + 3], data[i]
+ data[i + 1], data[i + 2] = data[i + 2], data[i + 1]
+
+ return data
diff --git a/test/functional/test_framework/auxpow_testing.py b/test/functional/test_framework/auxpow_testing.py
new file mode 100644
index 000000000..f1ef056b8
--- /dev/null
+++ b/test/functional/test_framework/auxpow_testing.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+# Copyright (c) 2014-2018 Daniel Kraft
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+# Utility routines for auxpow that are needed specifically by the regtests.
+# This is mostly about actually *solving* an auxpow block (with regtest
+# difficulty) or inspecting the information for verification.
+
+import binascii
+
+from test_framework import auxpow
+
+def computeAuxpow (block, target, ok):
+ """
+ Build an auxpow object (serialised as hex string) that solves
+ (ok = True) or doesn't solve (ok = False) the block.
+ """
+
+ (tx, header) = auxpow.constructAuxpow (block)
+ (header, _) = mineBlock (header, target, ok)
+ return auxpow.finishAuxpow (tx, header)
+
+def mineAuxpowBlock (node):
+ """
+ Mine an auxpow block on the given RPC connection. This uses the
+ createauxblock and submitauxblock command pair.
+ """
+
+ def create ():
+ addr = node.getnewaddress ()
+ return node.createauxblock (addr)
+
+ return mineAuxpowBlockWithMethods (create, node.submitauxblock)
+
+def mineAuxpowBlockWithMethods (create, submit):
+ """
+ Mine an auxpow block, using the given methods for creation and submission.
+ """
+
+ auxblock = create ()
+ target = auxpow.reverseHex (auxblock['_target'])
+ apow = computeAuxpow (auxblock['hash'], target, True)
+ res = submit (auxblock['hash'], apow)
+ assert res
+
+ return auxblock['hash']
+
+def getCoinbaseAddr (node, blockHash):
+ """
+ Extract the coinbase tx' payout address for the given block.
+ """
+
+ blockData = node.getblock (blockHash)
+ txn = blockData['tx']
+ assert len (txn) >= 1
+
+ txData = node.getrawtransaction (txn[0], 1)
+ assert len (txData['vout']) >= 1 and len (txData['vin']) == 1
+ assert 'coinbase' in txData['vin'][0]
+
+ addr = txData['vout'][0]['scriptPubKey']['addresses']
+ assert len (addr) == 1
+ return addr[0]
+
+def mineBlock (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)
+
+ blockhash = auxpow.doubleHashHex (hexData)
+ if (ok and blockhash < target) or ((not ok) and blockhash > target):
+ break
+
+ return (hexData, blockhash)