创世区块参数生成脚本genesis.py:
1.获取命令行输入的参数
options = get_args()
-t 时间 默认为当前系统时间
-z 一个字符串 默认为The Times 03/Jan/2009 Chancellor on brink of second bailout for banks
-n nonce值 默认为0
-a hash加密算法 默认为SHA256
-p 有效的随机公钥 默认为"04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"
-v 版本号 默认为5000000000
def get_args():
parser = optparse.OptionParser()
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]")
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,
type="int", help="the value in coins for the output, full value (exp. in bitcoin 5000000000 - To get other coins value: Block Value * 100000000)")
(options, args) = parser.parse_args()
return options
2.通过命令行的-a 获取对应的加密算法,默认为SHA256
algorithm = get_algorithm(options)
def get_algorithm(options):
supported_algorithms = ["SHA256", "scrypt", "X11", "X13", "X15"]
if options.algorithm in supported_algorithms:
return options.algorithm
else:
sys.exit("Error: Given algorithm must be one of: " + str(supported_algorithms))
3.通过2步骤中获取到的算法算出对应的nbits和target值
bits, target = get_difficulty(algorithm)
def get_difficulty(algorithm):
if algorithm == "scrypt":
return 0x1e0ffff0, 0x0ffff0 * 2**(8*(0x1e - 3))
elif algorithm == "SHA256":
return 0x1d00ffff, 0x00ffff * 2**(8*(0x1d - 3))
elif algorithm == "X11" or algorithm == "X13" or algorithm == "X15":
return 0x1e0ffff0, 0x0ffff0 * 2**(8*(0x1e - 3))
4.创建输入输出脚本:
通过时间戳创建输入脚本,通过公钥创建输出脚本。
input_script = create_input_script(options.timestamp)
output_script = create_output_script(options.pubkey)
输入脚本创建:
def create_input_script(psz_timestamp):
psz_prefix = ""
#use OP_PUSHDATA1 if required
if len(psz_timestamp) > 76: psz_prefix = '4c' #若psz_timestamp长度大于76,则加上前缀4c(76的十六进制)
script_prefix = '04ffff001d0104' + psz_prefix + chr(len(psz_timestamp)).encode('hex') #将它们链接起来成一个脚本前缀
print (script_prefix + psz_timestamp.encode('hex')) #打印04ffff001d010436323031382f332f32302057726974656e206279205374616e77617920456d61696c3a7374616e77617939323040676d61696c2e636f6d
return (script_prefix + psz_timestamp.encode('hex')).decode('hex') #函数返回整个脚本
输出脚本创建:
def create_output_script(pubkey):
script_len = '41'
OP_CHECKSIG = 'ac'
return (script_len + pubkey + OP_CHECKSIG).decode('hex')
#通过公钥创建输出脚本
5.通过输入输出脚本以及各参数创建交易
def create_transaction(input_script, output_script,options):
transaction = Struct("transaction",
Bytes("version", 4),
Byte("num_inputs"),
StaticField("prev_output", 32),
UBInt32('prev_out_idx'),
Byte('input_script_len'),
Bytes('input_script', len(input_script)),
UBInt32('sequence'),
Byte('num_outputs'),
Bytes('out_value', 8),
Byte('output_script_len'),
Bytes('output_script', 0x43),
UBInt32('locktime'))
tx = transaction.parse('\x00'*(127 + len(input_script)))
tx.version = struct.pack('<I', 1) #将1转成4字节integer型
tx.num_inputs = 1 #1个输入
tx.prev_output = struct.pack('<qqqq', 0,0,0,0) #转成8字节integer型
tx.prev_out_idx = 0xFFFFFFFF
tx.input_script_len = len(input_script)
tx.input_script = input_script
tx.sequence = 0xFFFFFFFF
tx.num_outputs = 1
tx.out_value = struct.pack('<q' ,options.value)#0x000005f5e100)#012a05f200) #50 coins
#tx.out_value = struct.pack('<q' ,0x000000012a05f200) #50 coins
tx.output_script_len = 0x43 #十进制67
tx.output_script = output_script
tx.locktime = 0
return transaction.build(tx) #构建交易结构体
6.生成merkle root哈希,对tx进行二次哈希
hash_merkle_root = hashlib.sha256(hashlib.sha256(tx).digest()).digest()
7.创建区块头,使用merkle root哈希,时间戳,难度值创建一个区块头
block_header = create_block_header(hash_merkle_root, options.time, bits, options.nonce)
def create_block_header(hash_merkle_root, time, bits, nonce):
block_header = Struct("block_header",
Bytes("version",4),
Bytes("hash_prev_block", 32),
Bytes("hash_merkle_root", 32),
Bytes("time", 4),
Bytes("bits", 4),
Bytes("nonce", 4))
genesisblock = block_header.parse('\x00'*80)
genesisblock.version = struct.pack('<I', 1)
genesisblock.hash_prev_block = struct.pack('<qqqq', 0,0,0,0)
genesisblock.hash_merkle_root = hash_merkle_root
genesisblock.time = struct.pack('<I', time)
genesisblock.bits = struct.pack('<I', bits)
genesisblock.nonce = struct.pack('<I', nonce)
return block_header.build(genesisblock)
8.通过区块头,算法,nonce值和目标值生成创世区块哈希和新难度值
genesis_hash, nonce = generate_hash(block_header, algorithm, options.nonce, target)
def generate_hash(data_block, algorithm, start_nonce, target):
print 'Searching for genesis hash..'
nonce = start_nonce
last_updated = time.time() #最后更新时间
difficulty = float(0xFFFF) * 2**208 / target #难度值计算,此时难度值为1
update_interval = int(1000000 * difficulty)
while True:
sha256_hash, header_hash = generate_hashes_from_block(data_block, algorithm) #生成区块哈希
last_updated = calculate_hashrate(nonce, update_interval, difficulty, last_updated) #计算哈希率
if is_genesis_hash(header_hash, target): #若找到比target小的值,则返回sha256哈希和nonce值
if algorithm == "X11" or algorithm == "X13" or algorithm == "X15":
return (header_hash, nonce)
return (sha256_hash, nonce)
else: #若没找到比target小的值,则增大nonce值,并将nonce值加入到数据区块中去
nonce = nonce + 1
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] #生成sha256哈希
header_hash = ""
if algorithm == 'scrypt':
header_hash = scrypt.hash(data_block,data_block,1024,1,1,32)[::-1]
elif algorithm == 'SHA256':
header_hash = sha256_hash
elif algorithm == 'X11':
try:
exec('import %s' % "xcoin_hash")
except ImportError:
sys.exit("Cannot run X11 algorithm: module xcoin_hash not found")
header_hash = xcoin_hash.getPoWHash(data_block)[::-1]
elif algorithm == 'X13':
try:
exec('import %s' % "x13_hash")
except ImportError:
sys.exit("Cannot run X13 algorithm: module x13_hash not found")
header_hash = x13_hash.getPoWHash(data_block)[::-1]
elif algorithm == 'X15':
try:
exec('import %s' % "x15_hash")
except ImportError:
sys.exit("Cannot run X15 algorithm: module x15_hash not found")
header_hash = x15_hash.getPoWHash(data_block)[::-1]
return sha256_hash, header_hash
def calculate_hashrate(nonce, update_interval, difficulty, last_updated): #计算哈希率
if nonce % update_interval == update_interval - 1:
now = time.time()
hashrate = round(update_interval/(now - last_updated))
generation_time = round(difficulty * pow(2, 32) / hashrate / 3600, 1)
sys.stdout.write("\r%s hash/s, estimate: %s h"%(str(hashrate), str(generation_time))) #在终端显示的哈希率和所需生成时间
sys.stdout.flush()
return now
else:
return last_updated
def is_genesis_hash(header_hash, target):
return int(header_hash.encode('hex_codec'), 16) < target #判断哈希值小于目标值
9.宣布获得创世区块哈希
announce_found_genesis(genesis_hash, nonce)
def announce_found_genesis(genesis_hash, nonce):
print "genesis hash found!"
print "nonce: " + str(nonce)
print "genesis hash: " + genesis_hash.encode('hex_codec')