Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for quark hashing algorithm as well as unittests #32

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pyc
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ A python script for creating the parameters required for a unique genesis block.
### Dependencies
sudo pip install scrypt construct==2.5.2

To create geneses based on X11 algorithm you will also need to install the [xcoin-hash](https://github.com/lhartikk/xcoin-hash) module.
For X13 you will need the [x13_hash](https://github.com/sherlockcoin/X13-PythonHash) module and for X15 the [x15_hash](https://github.com/minings/x15_hash) module.
To create geneses based on X11 algorithm you will also need to install the [xcoin-hash](https://github.com/lhartikk/xcoin-hash) module.
For X13 you will need the [x13_hash](https://github.com/sherlockcoin/X13-PythonHash) module and for X15 the [x15_hash](https://github.com/minings/x15_hash) module. For quark you will additionally need the [quark_hash](https://github.com/Neisklar/quarkcoin-hash-python) module.

### Examples
Create the original genesis hash found in Bitcoin

Expand All @@ -30,24 +30,24 @@ Create the regtest genesis hash found in Bitcoin
Create the original genesis hash found in Litecoin

python genesis.py -a scrypt -z "NY Times 05/Oct/2011 Steve Jobs, Apple’s Visionary, Dies at 56" -p "040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9" -t 1317972665 -n 2084524493

Create a unique genesis hash with custom pszTimestamp

python genesis.py -a scrypt -z "Time flies like an arrow. Fruit flies like a banana."

Create the original genesis hash found in DarkCoin. (requires [xcoin-hash](https://github.com/lhartikk/xcoin-hash))

python genesis.py -a X11 -z "Wired 09/Jan/2014 The Grand Experiment Goes Live: Overstock.com Is Now Accepting Bitcoins" -t 1317972665 -p "040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9" -n 28917698 -t 1390095618 -v 5000000000

Create the original genesis hash found in HiroCoin (requires [xcoin-hash](https://github.com/lhartikk/xcoin-hash)).

python genesis.py -a X11 -z "JapanToday 13/Mar/2014 Ways eyed to make planes easier to find in ocean" -p "040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9" -n 1234746574 -t 1394723131 -v 40000000000



### Options
Usage: genesis.py [options]

Options:
-h, --help show this help message and exit
-t TIME, --time=TIME the (unix) time when the genesisblock is created
Expand All @@ -64,4 +64,3 @@ Create the original genesis hash found in HiroCoin (requires [xcoin-hash](https:
the value in coins for the output, full value (exp. in bitcoin 5000000000 - To get other coins value: Block Value * 100000000)
-b BITS, --bits=BITS
the target in compact representation, associated to a difficulty of 1

47 changes: 29 additions & 18 deletions genesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,39 @@

from construct import *

supported_algorithms = ["SHA256", "scrypt", "X11", "X13", "X15", "quark"]

def main():
print 'Searching for genesis hash...'
options = get_args()
merkle_hash, nonce, genesis_hash = get_genesis(options)
print_block_info(options, merkle_hash)
announce_found_genesis(genesis_hash, nonce)

def get_genesis(options):
algorithm = get_algorithm(options)

input_script = create_input_script(options.timestamp)
output_script = create_output_script(options.pubkey)
# hash merkle root is the double sha256 hash of the transaction(s)
# hash merkle root is the double sha256 hash of the transaction(s)
tx = create_transaction(input_script, output_script,options)
hash_merkle_root = hashlib.sha256(hashlib.sha256(tx).digest()).digest()
print_block_info(options, hash_merkle_root)

block_header = create_block_header(hash_merkle_root, options.time, options.bits, options.nonce)
genesis_hash, nonce = generate_hash(block_header, algorithm, options.nonce, options.bits)
announce_found_genesis(genesis_hash, nonce)
return hash_merkle_root[::-1].encode('hex_codec'), str(nonce), genesis_hash.encode('hex_codec')


def get_args():
parser = optparse.OptionParser()
parser.add_option("-t", "--time", dest="time", default=int(time.time()),
parser.add_option("-t", "--time", dest="time", default=int(time.time()),
type="int", help="the (unix) time when the genesisblock is created")
parser.add_option("-z", "--timestamp", dest="timestamp", default="The Times 03/Jan/2009 Chancellor on brink of second bailout for banks",
type="string", help="the pszTimestamp found in the coinbase of the genesisblock")
parser.add_option("-n", "--nonce", dest="nonce", default=0,
type="int", help="the first value of the nonce that will be incremented when searching the genesis hash")
parser.add_option("-a", "--algorithm", dest="algorithm", default="SHA256",
help="the PoW algorithm: [SHA256|scrypt|X11|X13|X15]")
help="the PoW algorithm: [SHA256|scrypt|X11|X13|X15|quark]")
parser.add_option("-p", "--pubkey", dest="pubkey", default="04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f",
type="string", help="the pubkey found in the output script")
parser.add_option("-v", "--value", dest="value", default=5000000000,
Expand All @@ -40,14 +45,13 @@ def get_args():

(options, args) = parser.parse_args()
if not options.bits:
if options.algorithm == "scrypt" or options.algorithm == "X11" or options.algorithm == "X13" or options.algorithm == "X15":
options.bits = 0x1e0ffff0
else:
if options.algorithm == 'SHA256':
options.bits = 0x1d00ffff
else:
options.bits = 0x1e0ffff0
return options

def get_algorithm(options):
supported_algorithms = ["SHA256", "scrypt", "X11", "X13", "X15"]
if options.algorithm in supported_algorithms:
return options.algorithm
else:
Expand All @@ -59,7 +63,7 @@ def create_input_script(psz_timestamp):
if len(psz_timestamp) > 76: psz_prefix = '4c'

script_prefix = '04ffff001d0104' + psz_prefix + chr(len(psz_timestamp)).encode('hex')
print (script_prefix + psz_timestamp.encode('hex'))
# print (script_prefix + psz_timestamp.encode('hex'))
return (script_prefix + psz_timestamp.encode('hex')).decode('hex')


Expand Down Expand Up @@ -97,7 +101,7 @@ def create_transaction(input_script, output_script,options):
#tx.out_value = struct.pack('<q' ,0x000000012a05f200) #50 coins
tx.output_script_len = 0x43
tx.output_script = output_script
tx.locktime = 0
tx.locktime = 0
return transaction.build(tx)


Expand All @@ -122,7 +126,6 @@ def create_block_header(hash_merkle_root, time, bits, nonce):

# https://en.bitcoin.it/wiki/Block_hashing_algorithm
def generate_hash(data_block, algorithm, start_nonce, bits):
print 'Searching for genesis hash..'
nonce = start_nonce
last_updated = time.time()
# https://en.bitcoin.it/wiki/Difficulty
Expand All @@ -132,19 +135,19 @@ def generate_hash(data_block, algorithm, start_nonce, bits):
sha256_hash, header_hash = generate_hashes_from_block(data_block, algorithm)
last_updated = calculate_hashrate(nonce, last_updated)
if is_genesis_hash(header_hash, target):
if algorithm == "X11" or algorithm == "X13" or algorithm == "X15":
if algorithm == "X11" or algorithm == "X13" or algorithm == "X15" or algorithm == "quark":
return (header_hash, nonce)
return (sha256_hash, nonce)
else:
nonce = nonce + 1
data_block = data_block[0:len(data_block) - 4] + struct.pack('<I', nonce)
data_block = data_block[0:len(data_block) - 4] + struct.pack('<I', nonce)


def generate_hashes_from_block(data_block, algorithm):
sha256_hash = hashlib.sha256(hashlib.sha256(data_block).digest()).digest()[::-1]
header_hash = ""
if algorithm == 'scrypt':
header_hash = scrypt.hash(data_block,data_block,1024,1,1,32)[::-1]
header_hash = scrypt.hash(data_block,data_block,1024,1,1,32)[::-1]
elif algorithm == 'SHA256':
header_hash = sha256_hash
elif algorithm == 'X11':
Expand All @@ -165,9 +168,16 @@ def generate_hashes_from_block(data_block, algorithm):
except ImportError:
sys.exit("Cannot run X15 algorithm: module x15_hash not found")
header_hash = x15_hash.getPoWHash(data_block)[::-1]
elif algorithm == 'quark':
try:
import quark_hash
header_hash = quark_hash.getPoWHash(data_block)[::-1]
except ImportError:
sys.exit("Cannot run quark algorithm: module quark_hash not found")
return sha256_hash, header_hash



def is_genesis_hash(header_hash, target):
return int(header_hash.encode('hex_codec'), 16) < target

Expand Down Expand Up @@ -195,9 +205,10 @@ def print_block_info(options, hash_merkle_root):

def announce_found_genesis(genesis_hash, nonce):
print "genesis hash found!"
print "nonce: " + str(nonce)
print "genesis hash: " + genesis_hash.encode('hex_codec')
print "nonce: " + nonce
print "genesis hash: " + genesis_hash


# GOGOGO!
main()
if __name__ == '__main__':
main()
73 changes: 73 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
import unittest
from genesis import get_genesis
import optparse

COIN = 100000000

class TestGenesis(unittest.TestCase):
def test_sha256_bitcoin(self):
options = OptionsHelper({
'nonce': 2083236893,
'algorithm': 'SHA256',
'timestamp':
'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks',
'value': 50 * COIN,
'time': 1231006505,
'bits': 0x1d00ffff,
'pubkey': '04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f'
})
merkle_hash, nonce, genesis_hash = get_genesis(options)
self.assertEqual((merkle_hash, nonce, genesis_hash), ('4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b', '2083236893', '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'))

def test_scrypt_litecoin(self):
options = OptionsHelper({
'nonce': 2084524493,
'algorithm': 'scrypt',
'timestamp':
"NY Times 05/Oct/2011 Steve Jobs, Apple’s Visionary, Dies at 56",
'value': 50 * COIN,
'time': 1317972665,
'bits': 0x1e0ffff0,
'pubkey': '040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9'
})
merkle_hash, nonce, genesis_hash = get_genesis(options)
self.assertEqual((merkle_hash, nonce, genesis_hash), ('97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9', '2084524493', '12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2'))

def test_x11_dash(self):
options = OptionsHelper({
'nonce': 28917698,
'algorithm': 'X11',
'timestamp':
"Wired 09/Jan/2014 The Grand Experiment Goes Live: Overstock.com Is Now Accepting Bitcoins",
'value': 50 * COIN,
'time': 1390095618,
'bits': 0x1e0ffff0,
'pubkey': '040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9'
})
merkle_hash, nonce, genesis_hash = get_genesis(options)
self.assertEqual((merkle_hash, nonce, genesis_hash), ('e0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7', '28917698', '00000ffd590b1485b3caadc19b22e6379c733355108f107a430458cdf3407ab6'))

def test_quark_pivx(self):
options = OptionsHelper({
'nonce': 2402015,
'algorithm': 'quark',
'timestamp':
'U.S. News & World Report Jan 28 2016 With His Absence, Trump Dominates Another Debate',
'value': 250 * COIN,
'time': 1454124731,
'bits': 504365040,
'pubkey': '04c10e83b2703ccf322f7dbd62dd5855ac7c10bd055814ce121ba32607d573b8810c02c0582aed05b4deb9c4b77b26d92428c61256cd42774babea0a073b2ed0c9'
})
merkle_hash, nonce, genesis_hash = get_genesis(options)
self.assertEqual((merkle_hash, nonce, genesis_hash), ('1b2ef6e2f28be914103a277377ae7729dcd125dfeb8bf97bd5964ba72b6dc39b', '2402015', '0000041e482b9b9691d98eefb48473405c0b8ec31b76df3797c74a78680ef818'))

class OptionsHelper(dict):
def __getattr__(self, attr):
return self.get(attr)

def __setattr__(self, attr, value):
return self.update({attr: value})

if __name__ == '__main__':
unittest.main()