From 0a93a5554022dece1129fc2da641a48868256afc Mon Sep 17 00:00:00 2001 From: Angelo Laub Date: Mon, 22 Jan 2018 10:25:39 +0100 Subject: [PATCH 1/5] add support for quark hash --- genesis.py | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/genesis.py b/genesis.py index 1eacc15..68621ae 100644 --- a/genesis.py +++ b/genesis.py @@ -3,6 +3,7 @@ from construct import * +supported_algorithms = ["SHA256", "scrypt", "X11", "X13", "X15", "quark"] def main(): options = get_args() @@ -11,7 +12,7 @@ def main(): 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) @@ -30,7 +31,7 @@ def get_args(): 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, @@ -40,14 +41,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": + if options.algorithm in supported_algorithms: options.bits = 0x1e0ffff0 else: options.bits = 0x1d00ffff return options def get_algorithm(options): - supported_algorithms = ["SHA256", "scrypt", "X11", "X13", "X15"] if options.algorithm in supported_algorithms: return options.algorithm else: @@ -129,43 +129,45 @@ def generate_hash(data_block, algorithm, start_nonce, bits): target = (bits & 0xffffff) * 2**(8*((bits >> 24) - 3)) while True: - sha256_hash, header_hash = generate_hashes_from_block(data_block, algorithm) + 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": - return (header_hash, nonce) - return (sha256_hash, nonce) + return (header_hash, nonce) else: nonce = nonce + 1 - data_block = data_block[0:len(data_block) - 4] + struct.pack(' Date: Mon, 22 Jan 2018 12:09:24 +0100 Subject: [PATCH 2/5] refactor to make it testable --- genesis.py | 55 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/genesis.py b/genesis.py index 68621ae..1b191ee 100644 --- a/genesis.py +++ b/genesis.py @@ -6,8 +6,13 @@ 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) @@ -15,16 +20,15 @@ def main(): # 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") @@ -41,10 +45,10 @@ def get_args(): (options, args) = parser.parse_args() if not options.bits: - if options.algorithm in supported_algorithms: - options.bits = 0x1e0ffff0 - else: + if options.algorithm == 'SHA256': options.bits = 0x1d00ffff + else: + options.bits = 0x1e0ffff0 return options def get_algorithm(options): @@ -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') @@ -97,7 +101,7 @@ def create_transaction(input_script, output_script,options): #tx.out_value = struct.pack('> 24) - 3)) while True: - header_hash = generate_hashes_from_block(data_block, algorithm) + 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): - return (header_hash, nonce) + 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(' Date: Mon, 22 Jan 2018 12:09:30 +0100 Subject: [PATCH 3/5] add unittests --- test.py | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 test.py diff --git a/test.py b/test.py new file mode 100644 index 0000000..376111c --- /dev/null +++ b/test.py @@ -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() From af60c5f1bace515931eca161232595018b7f67fc Mon Sep 17 00:00:00 2001 From: Angelo Laub Date: Mon, 22 Jan 2018 12:28:21 +0100 Subject: [PATCH 4/5] add .pyc files to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e99e36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc \ No newline at end of file From 019312aa897ab94350e4147aca707c2fcb46b5e1 Mon Sep 17 00:00:00 2001 From: Angelo Laub Date: Mon, 22 Jan 2018 12:29:50 +0100 Subject: [PATCH 5/5] update readme to include reference for new dependancy --- README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 846c933..d64f396 100644 --- a/README.md +++ b/README.md @@ -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 @@ -30,11 +30,11 @@ 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 @@ -42,12 +42,12 @@ Create the original genesis hash found in DarkCoin. (requires [xcoin-hash](https 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 @@ -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 -