diff options
| author | Max K <[email protected]> | 2019-07-14 19:35:30 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2019-07-14 19:35:30 +0200 |
| commit | cee13699a5676355487f8eb2d91985f63438eae4 (patch) | |
| tree | cf12be6180f950a25ee2ee7f3f2126542835d6e3 /test/functional/test_framework | |
| parent | Correct build and test net seed (diff) | |
| parent | Handle legacy v2 block at #66064 (diff) | |
| download | discoin-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.py | 104 | ||||
| -rw-r--r-- | test/functional/test_framework/auxpow_testing.py | 82 |
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) |