Skip to content

Commit

Permalink
Almost done with createTestChain reorg unit test
Browse files Browse the repository at this point in the history
Not sure I'm going to be able to compute real nonces...doing it
in Python is slow as dirt:  about 25s/million hashes:  almost a
full day to compute difficulty-1.0 block!
  • Loading branch information
etotheipi committed Oct 12, 2011
1 parent 81cffdc commit 18dd9db
Show file tree
Hide file tree
Showing 2 changed files with 344 additions and 218 deletions.
209 changes: 104 additions & 105 deletions createTestChain.py
Original file line number Diff line number Diff line change
@@ -1,136 +1,135 @@
#! /usr/bin/python
from pybtcengine import *
import os
from time import time


blkfile = open('/home/alan/.bitcoin/blk0001.dat','r')
blkfile.seek(8,0)
genBlock = PyBlockHeader().unserialize(blkfile.read(80))
numTx = blkfile.read(1)
genTx = PyTx().unserialize(blkfile.read(285))
genBlock = PyBlock().unserialize(blkfile.read(80 + 1 + 285))
blkfile.close()

print 'Genesis block header:'
genBlock.pprint()
genBlock.blockHeader.pprint()
print 'Genesis block tx:'
genTx.pprint()
genBlock.blockData.txList[0].pprint()


################################################################################
def findDiff1Nonce(blkHeader):
for n in range(2**33):
h.nonce = n
theHash = hash256(h.serialize())
if theHash[-4:] == '\x00\x00\x00\x00':
return h
print 'No nonce found!'

################################################################################
# We will reference src TxOuts by the blkNum and TxIndex
# Src TxOut ~ {tx, txoutIndex, BtcAddr} / COINBASE = -1
# Dst TxOut ~ {BtcAddr, value}
def createTx(srcTxOuts, dstAddrVal):
tx = PyTx()
tx.numInputs = len(srcTxOuts)
tx.numOutputs = len(dstAddrs)
tx.inputs = []
tx.outputs = []

coinbaseTx = False
if tx.numInputs==1 and srcTxOuts[0] == -1:
coinbaseTx = True


####################
for i in range(tx.numOutputs):
txout = PyTxOut()
txout.value = dstAddrVal[i][1]
dstAddr160 = dstAddr[i][0].getAddr160()
if(coinbaseTx):
txout.binPKScript = ''.join(['\x41', \
dstAddr160,
opCodeLookup['OP_CHECKSIG']])
else:
txout.binPKScript = ''.join([opCodeLookup['OP_DUP'], \
opCodeLookup['OP_HASH160'], \
'\x14', \
dstAddr160,
opCodeLookup['OP_EQUALVERIFY'], \
opCodeLookup['OP_CHECKSIG']])
tx.outputs.append(txout)


####################
for i in range(tx.inputs):
txin = PyTxIn()
txin.outpoint = PyOutPoint()
if(coinbaseTx):
txin.outpoint.txOutHash = '\x00'*32
txin.outpoint.index = '\xff'*4
else:
txin.outpoint.txOutHash = hash256(srcTxOuts[0][0].serialize())
txin.outpoint.index = srcTxOuts[0][1]
txin.binScript = ''.join(['\xaa\xbb\xcc\xdd'])
txin.intSeq = 2**32-1
tx.inputs.append(txin)



####################
# Now we apply the ultra-complicated signature procedure
# We need a copy of the Tx with all the txin scripts blanked out
txCopySerialized = tx.serialize()
for i in range(tx.inputs):
if coinbaseTx:
pass # no sig on coinbase txs
else:
txCopy = PyTx().unserialize(txCopySerialized)
thisTxIn = txCopy.inputs[i]
txoutIdx = srcTxOuts[i][1]
prevTxOut = srcTxOuts[i][0].outputs[txoutIdx]
btcAddr = srcTxOuts[i][2]
hashCode = int_to_binary(hashtype, widthBytes=4)
binToSign = ''

# Copy the script of the TxOut we're spending, into the txIn script
thisTxIn.binScript = prevTxOut.binPKScript
binToSign = hash256(txCopy.serialize() + hashCode)
signature = addrPrivKey.generateDERSignature(binToSign) + '\x01'
if len(prevTxOut.binPKScript) > 26:
#Spend-CB: only Sig needed
tx.inputs[i].binScript = signature
else
tx.inputs[i].binScript = signature + '\x41' + addrPrivKey

return tx
satoshiPubKey = hex_to_binary('04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f')


txlist = []


AddrA = PyBtcAddress().createFromPublicKey(hex_to_binary('04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f'))
# We have to have a
AddrA = PyBtcAddress().createFromPublicKey(satoshiPubKey)
AddrB = PyBtcAddress().generateNew()
AddrC = PyBtcAddress().generateNew()
AddrD = PyBtcAddress().generateNew()
print 'Addr A:', AddrA.getAddrStr(), ' (Satoshi)'
print 'Addr B:', AddrB.getAddrStr()
print 'Addr C:', AddrC.getAddrStr()
print 'Addr D:', AddrD.getAddrStr()

btcValue = lambda btc: btc*(10**8)


def btcValue(btc):
return btc*(10**8)
#Block 1
Blk1_Tx0 = PyCreateAndSignTx( [-1], [[AddrB, btcValue(50)]] )

Blk0_Tx0 = createTx( [-1], [[AddrA, btcValue(50)]] )
Blk1_Tx0 = createTx( [-1], [[AddrB, btcValue(50)]] )
Blk2_Tx0 = createTx( [-1], [[AddrB, btcValue(50)]] )
Blk2_Tx1 = createTx( [[Blk1_Tx0, 0, AddrB]], [[ AddrC, btcValue(10)],
[ AddrB, btcValue(40)]] )
Blk3_Tx0 = createTx( [-1], [[AddrC, btcValue(50)]] )
Blk3_Tx1 = createTx( [[Blk2_Tx1, 1, AddrB]] [[AddrD, btcValue(40)]] )
Blk3_Tx2 = createTx( [[Blk2_Tx1, 0, AddrC]] [[AddrD, btcValue(10)]] )
#Block 2
Blk2_Tx0 = PyCreateAndSignTx( [-1], [[AddrB, btcValue(50)]] )
Blk2_Tx1 = PyCreateAndSignTx( [[AddrB, Blk1_Tx0, 0]], [[AddrC, btcValue(10)], \
[AddrB, btcValue(40)]] )

#Block 3
Blk3_Tx0 = PyCreateAndSignTx( [-1], [[AddrC, btcValue(50)]] )
Blk3_Tx1 = PyCreateAndSignTx( [[AddrB, Blk2_Tx1, 1]], [[AddrD, btcValue(40)]] )
Blk3_Tx2 = PyCreateAndSignTx( [[AddrC, Blk2_Tx1, 0]], [[AddrD, btcValue(10)]] )

#Block 4
Blk4_Tx0 = PyCreateAndSignTx( [-1], [[AddrA, btcValue(50)]] )

#Block 3-alternate
Blk3A_Tx0 = PyCreateAndSignTx( [-1], [[AddrA, btcValue(50)]] )
Blk3A_Tx1 = PyCreateAndSignTx( [[AddrB, Blk2_Tx1, 1]], [[AddrD, btcValue(40)]] )
Blk3A_Tx2 = PyCreateAndSignTx( [[AddrC, Blk2_Tx1, 0]], [[AddrB, btcValue(10)]] )

#Block 4-alternate
Blk4A_Tx0 = PyCreateAndSignTx( [-1], [[AddrA, btcValue(50)]] )

#Block 5-alternate
Blk5A_Tx0 = PyCreateAndSignTx( [-1], [[AddrA, btcValue(50)]] )


################################################################################
# Finally, actually create the blocks

################################################################################
def findNonce(blkHeader, nZeros=4):
startTime = time()
for n in xrange(0):
blkHeader.nonce = n
theHash = hash256(blkHeader.serialize())
if theHash[-nZeros:] == '\x00'*nZeros:
break
print 'Time to execute nonce search:', (time() - startTime), 'sec'
return blkHeader.nonce

def printHashEnds(theHash):
intList = [ord(c) for c in theHash]
print 'First 4 LE bytes:', intList[:4], 'First 4 BE bytes:', intList[::-1][:4]

################################################################################
def createPyBlock(prevBlkHeader, txlist):
print 'Creating block (%d tx): Computing nonce...' % len(txlist),
blk = PyBlock(prevBlkHeader, txlist)
aGoodNonce = findNonce(blk.blockHeader, 4)
blk.blockHeader.nonce = aGoodNonce
print 'Done! (%d)' % aGoodNonce
print ' Header:', binary_to_hex(blk.blockHeader.getHash())
print ' :', printHashEnds(blk.blockHeader.getHash())
print ' Prev :', binary_to_hex(blk.blockHeader.prevBlkHash)
for i,tx in enumerate(txlist):
print ' Tx %d :'%i, binary_to_hex(tx.getHash())
print ' :', printHashEnds(tx.getHash())
return blk


Blk1 = createPyBlock(genBlock.blockHeader, [Blk1_Tx0] )
Blk2 = createPyBlock(Blk1.blockHeader, [Blk2_Tx0, Blk2_Tx1] )
Blk3 = createPyBlock(Blk2.blockHeader, [Blk3_Tx0, Blk3_Tx1, Blk3_Tx2] )
Blk4 = createPyBlock(Blk3.blockHeader, [Blk4_Tx0] )

Blk3A = createPyBlock(Blk2.blockHeader, [Blk3A_Tx0, Blk3A_Tx1, Blk3A_Tx2] )
Blk4A = createPyBlock(Blk3A.blockHeader, [Blk4A_Tx0])
Blk5A = createPyBlock(Blk4A.blockHeader, [Blk5A_Tx0])


################################################################################
# Now serialize the block data into .dat files so we can feed them into a
# program that claims to handle reorgs

def writeBlk(fileHandle, blk):
blkFirstChain.write( hex_to_binary('f9beb4d9') )
blkFirstChain.write( int_to_binary(blk.getSize(), widthBytes=4) )
blkFirstChain.write( blk.serialize() )
print 'Block:'
print ' ', 'f9beb4d9'
print ' ', int_to_hex(blk.getSize(), widthBytes=4)
print ' ', prettyHex(binary_to_hex(blk.blockHeader.serialize()), ' ', False)
print ' ', int_to_hex(blk.getNumTx(), widthBytes=1)
for tx in blk.blockData.txList:
print ' ', prettyHex(binary_to_hex(tx.serialize()), ' ', False)


print '\n\nWriting blocks to ReorgTest/ directory'
blkFirstChain = open('ReorgTest/blk_0_to_4.dat','wb')
for blk in [genBlock, Blk1, Blk2, Blk3, Blk4]:
writeBlk(blkFirstChain, blk)
blkFirstChain.close()

for blk,suffix in [[Blk3A,'3A'], [Blk4A, '4A'], [Blk5A, '5A']]:
blkAlt = open('ReorgTest/blk_%s.dat'%suffix,'wb')
writeBlk(blkAlt, blk)
blkAlt.close()

print '\nDone!'
Loading

0 comments on commit 18dd9db

Please sign in to comment.