83 lines
2.3 KiB
Python
83 lines
2.3 KiB
Python
|
#!/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)
|