Marked as deprecated but still used in many pool implementations, as well as rpc-tests. This restores AuxPoW compatibility to 100%.
106 lines
3 KiB
Python
106 lines
3 KiB
Python
#!/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)))
|