1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#!/usr/bin/env python
# Copyright (c) 2014 Daniel Kraft
# Copyright (c) 2015-2018 The Discoin 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
from .auxpow import *
import ltc_scrypt
import binascii
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((b"m" * 2)).decode("ascii")
coinbase += block
coinbase += "01000000" + ("00" * 4)
# Construct "vector" of transaction inputs.
vin = "01"
vin += ("00" * 32) + ("ff" * 4)
vin += ("%02x" % int(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 = 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 += 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 = reverseHex (auxblock['target'])
apow = computeAuxpowWithChainId (auxblock['hash'], target, chainid, ok)
res = node.getauxblock (auxblock['hash'], apow)
return res
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).decode("ascii")
scrypt = getScryptPoW(hexData)
if (ok and scrypt < target) or ((not ok) and scrypt > target):
break
blockhash = doubleHashHex (hexData)
return (hexData, blockhash)
def getScryptPoW(hexData):
"""
Actual scrypt pow calculation
"""
data = binascii.unhexlify(hexData)
return reverseHex(binascii.hexlify(ltc_scrypt.getPoWHash(data)).decode("ascii"))
|