def test_exercise_4(self):
     last_block_hex = '000000000d65610b5af03d73ed67704713c9b734d87cf4b970d39a0416dd80f9'
     last_block = bytes.fromhex(last_block_hex)
     secret = little_endian_to_int(
         hash256(b'Jimmy Song Programming Blockchain'))
     private_key = PrivateKey(secret=secret)
     addr = private_key.point.address(testnet=True)
     h160 = decode_base58(addr)
     target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv'
     self.assertEqual(addr, target_address)
     filter_size = 30
     filter_num_functions = 5
     filter_tweak = 90210  # FILL THIS IN
     target_h160 = decode_base58(target_address)
     target_script = p2pkh_script(target_h160)
     fee = 5000  # fee in satoshis
     node = SimpleNode('tbtc.programmingblockchain.com',
                       testnet=True,
                       logging=False)
     bf = BloomFilter(filter_size, filter_num_functions, filter_tweak)
     bf.add(h160)
     node.handshake()
     node.send(b'filterload', bf.filterload())
     getheaders_message = GetHeadersMessage(start_block=last_block)
     node.send(getheaders_message.command, getheaders_message.serialize())
     headers_envelope = node.wait_for_commands([HeadersMessage.command])
     stream = headers_envelope.stream()
     headers = HeadersMessage.parse(stream)
     get_data_message = GetDataMessage()
     for block in headers.blocks:
         self.assertTrue(block.check_pow())
         if last_block is not None:
             self.assertEqual(block.prev_block, last_block)
         last_block = block.hash()
         get_data_message.add_data(FILTERED_BLOCK_DATA_TYPE, last_block)
     node.send(get_data_message.command, get_data_message.serialize())
     prev_tx = None
     while prev_tx is None:
         envelope = node.wait_for_commands([b'merkleblock', b'tx'])
         stream = envelope.stream()
         if envelope.command == b'merkleblock':
             mb = MerkleBlock.parse(stream)
             self.assertTrue(mb.is_valid())
         else:
             prev = Tx.parse(stream, testnet=True)
             for i, tx_out in enumerate(prev.tx_outs):
                 if tx_out.script_pubkey.address(testnet=True) == addr:
                     prev_tx = prev.hash()
                     prev_index = i
                     prev_amount = tx_out.amount
                     break
     tx_in = TxIn(prev_tx, prev_index)
     output_amount = prev_amount - fee
     tx_out = TxOut(output_amount, target_script)
     tx_obj = Tx(1, [tx_in], [tx_out], 0, testnet=True)
     tx_obj.sign_input(0, private_key)
     self.assertEqual(
         tx_obj.serialize().hex(),
         '010000000194e631abb9e1079ec72a1616a3aa0111c614e65b96a6a4420e2cc6af9e6cc96e000000006a47304402203cc8c56abe1c0dd043afa9eb125dafbebdde2dd4cd7abf0fb1aae0667a22006e02203c95b74d0f0735bbf1b261d36e077515b6939fc088b9d7c1b7030a5e494596330121021cdd761c7eb1c90c0af0a5963e94bf0203176b4662778d32bd6d7ab5d8628b32ffffffff01f8829800000000001976a914ad346f8eb57dee9a37981716e498120ae80e44f788ac00000000'
     )
Example #2
0
 def test_exercise_2(self):
     block_hash = bytes.fromhex(
         '0000000053787814ed9dd8c029d0a0a9af4ab8ec0591dc31bdc4ab31fae88ce9')
     passphrase = b'Jimmy Song Programming Blockchain'  # FILL THIS IN
     secret = little_endian_to_int(hash256(passphrase))
     private_key = PrivateKey(secret=secret)
     addr = private_key.point.address(testnet=True)
     filter_size = 30
     filter_num_functions = 5
     filter_tweak = 90210  # FILL THIS IN
     h160 = decode_base58(addr)
     bf = BloomFilter(filter_size, filter_num_functions, filter_tweak)
     bf.add(h160)
     node = SimpleNode('tbtc.programmingblockchain.com',
                       testnet=True,
                       logging=False)
     node.handshake()
     node.send(bf.filterload())
     getdata = GetDataMessage()
     getdata.add_data(FILTERED_BLOCK_DATA_TYPE, block_hash)
     node.send(getdata)
     mb = node.wait_for(MerkleBlock)
     tx = node.wait_for(Tx)
     self.assertEqual(
         tx.serialize().hex(),
         '0100000002a663815ab2b2ba5f53e442f9a2ea6cc11bbcd98fb1585e48a134bd870dbfbd6a000000006a47304402202151107dc2367cf5a9e2429cde0641c252374501214ce52069fbca1320180aa602201a43b5d4f91e48514c00c01521dc04f02c57f15305adc4eaad01c418f6e7a1180121031dbe3aff7b9ad64e2612b8b15e9f5e4a3130663a526df91abfb7b1bd16de5d6effffffff618b00a343488bd62751cf21f368ce3be76e3a0323fdc594a0d24f27a1155cd2000000006a473044022024c4dd043ab8637c019528b549e0b10333b2dfa83e7ca66776e401ad3fc31b6702207d4d1d73ac8940c59c57c0b7daf084953324154811c10d06d0563947a88f99b20121031dbe3aff7b9ad64e2612b8b15e9f5e4a3130663a526df91abfb7b1bd16de5d6effffffff0280969800000000001976a914ad346f8eb57dee9a37981716e498120ae80e44f788aca0ce6594000000001976a9146e13971913b9aa89659a9f53d327baa8826f2d7588ac00000000'
     )
Example #3
0
def get_block(block_hash, btc_client=None):
    try:
        if btc_client is not None:
            node = btc_client
        else:
            if tor:
                logging.info("[-] Initiating tor used by main process function: get block")
            node = connect_bitcoin(host, port, tor=tor)
        get_data_msg = GetDataMessage()
        get_data_msg.add_data(BLOCK_DATA_TYPE, block_hash)
        node.send(get_data_msg)
        block_msg = node.wait_for(BlockMessage)
        logging.info("[-] Block download completed: hash {}".format(block_hash.hex()))
        if btc_client is None:
            if node.tor:
                logging.info("[-] Killing tor used by main process function: get block")
            disconnect_btc_client(node)
        return Block_Full(
            block_msg.version,
            block_msg.prev_block,
            block_msg.merkle_root,
            block_msg.timestamp,
            block_msg.bits,
            block_msg.nonce,
            block_msg.txs
        )
    except RuntimeError as err:
        raise RuntimeError("[-] Block {} download has failed".format(block_hash.hex()))
Example #4
0
 def test_exercise_6(self):
     last_block_hex = '000000000d65610b5af03d73ed67704713c9b734d87cf4b970d39a0416dd80f9'
     secret = little_endian_to_int(
         hash256(b'Jimmy Song Programming Blockchain'))
     private_key = PrivateKey(secret=secret)
     addr = private_key.point.address(testnet=True)
     h160 = decode_base58(addr)
     target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv'
     self.assertEqual(addr, target_address)
     target_h160 = decode_base58(target_address)
     target_script = p2pkh_script(target_h160)
     fee = 5000
     node = SimpleNode('tbtc.programmingblockchain.com', testnet=True)
     bf = BloomFilter(30, 5, 90210)
     bf.add(h160)
     node.handshake()
     node.send(bf.filterload())
     start_block = bytes.fromhex(last_block_hex)
     getheaders = GetHeadersMessage(start_block=start_block)
     node.send(getheaders)
     headers = node.wait_for(HeadersMessage)
     last_block = None
     getdata = GetDataMessage()
     for b in headers.blocks:
         if not b.check_pow():
             raise RuntimeError('proof of work is invalid')
         if last_block is not None and b.prev_block != last_block:
             raise RuntimeError('chain broken')
         getdata.add_data(FILTERED_BLOCK_DATA_TYPE, b.hash())
         last_block = b.hash()
     node.send(getdata)
     prev_tx, prev_index, prev_tx_obj = None, None, None
     while prev_tx is None:
         message = node.wait_for(MerkleBlock, Tx)
         if message.command == b'merkleblock':
             if not message.is_valid():
                 raise RuntimeError('invalid merkle proof')
         else:
             message.testnet = True
             for i, tx_out in enumerate(message.tx_outs):
                 if tx_out.script_pubkey.address(testnet=True) == addr:
                     prev_tx = message.hash()
                     prev_index = i
                     prev_amount = tx_out.amount
                     self.assertEqual(
                         message.id(),
                         '6ec96c9eafc62c0e42a4a6965be614c61101aaa316162ac79e07e1b9ab31e694'
                     )
                     self.assertEqual(i, 0)
                     break
     tx_in = TxIn(prev_tx, prev_index)
     output_amount = prev_amount - fee
     tx_out = TxOut(output_amount, target_script)
     tx_obj = Tx(1, [tx_in], [tx_out], 0, testnet=True)
     tx_obj.sign_input(0, private_key)
     self.assertEqual(
         tx_obj.serialize().hex(),
         '010000000194e631abb9e1079ec72a1616a3aa0111c614e65b96a6a4420e2cc6af9e6cc96e000000006a47304402203cc8c56abe1c0dd043afa9eb125dafbebdde2dd4cd7abf0fb1aae0667a22006e02203c95b74d0f0735bbf1b261d36e077515b6939fc088b9d7c1b7030a5e494596330121021cdd761c7eb1c90c0af0a5963e94bf0203176b4662778d32bd6d7ab5d8628b32ffffffff01f8829800000000001976a914ad346f8eb57dee9a37981716e498120ae80e44f788ac00000000'
     )
Example #5
0
 def test_exercise_10(self):
     block_hex = '0000000000044b01a9440b34f582fe171c7b8642fedd0ebfccf8fdf6a1810900'
     block_hash = bytes.fromhex(block_hex)
     node = SimpleNode('tbtc.programmingblockchain.com', testnet=True)
     node.handshake()
     getdata = GetDataMessage()
     getdata.add_data(BLOCK_DATA_TYPE, block_hash)
     node.send(getdata)
     b = node.wait_for(Block)
     self.assertTrue(b.check_pow())
     self.assertTrue(b.validate_merkle_root())
Example #6
0
    def request_blocks(self):
        # request 100 blocks
        next_height = len(self.blocks)
        headers = self.headers[next_height:next_height + 100]
        getdata = GetDataMessage()
        for header in headers:
            getdata.add_block(header.hash())
        self.peer.send(getdata)

        # wait for 10 blocks (FIXME)
        for _ in range(100):
            block_message = self.peer.wait_for(BlockMessage)
            self.receive_block(block_message.block)
        print(f'we now have {len(self.blocks)} blocks')
Example #7
0
def get_filtered_txs(self, block_hashes):
    getdata = GetDataMessage()
    for block_hash in block_hashes:
        getdata.add_data(FILTERED_BLOCK_DATA_TYPE, block_hash)
    self.send(getdata)
    results = []
    for block_hash in block_hashes:
        mb = self.wait_for(MerkleBlock)
        if mb.hash() != block_hash:
            raise RuntimeError('Wrong block sent')
        if not mb.is_valid():
            raise RuntimeError('Merkle Proof is invalid')
        for tx_hash in mb.proved_txs():
            tx_obj = self.wait_for(Tx)
            if tx_obj.hash() != tx_hash:
                raise RuntimeError('Wrong tx sent {} vs {}'.format(tx_hash.hex(), tx_obj.id()))
            results.append(tx_obj)
    return results
Example #8
0
 def test_exercise_10(self):
     block_hex = '0000000000044b01a9440b34f582fe171c7b8642fedd0ebfccf8fdf6a1810900'
     block_hash = bytes.fromhex(block_hex)
     node = SimpleNode('tbtc.programmingblockchain.com', testnet=True)
     node.handshake()
     getdata = GetDataMessage()
     getdata.add_data(BLOCK_DATA_TYPE, block_hash)
     node.send(getdata.command, getdata.serialize())
     block_envelope = node.wait_for_commands([b'block'])
     stream = block_envelope.stream()
     b = Block.parse(stream)
     self.assertTrue(b.check_pow())
     num_txs = read_varint(stream)
     tx_hashes = []
     for _ in range(num_txs):
         t = Tx.parse(stream)
         tx_hashes.append(t.hash())
     b.tx_hashes = tx_hashes
     self.assertTrue(b.validate_merkle_root())
Example #9
0
 def test_example_5(self):
     last_block_hex = '00000000000538d5c2246336644f9a4956551afb44ba47278759ec55ea912e19'
     address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv'
     h160 = decode_base58(address)
     node = SimpleNode('tbtc.programmingblockchain.com',
                       testnet=True,
                       logging=False)
     bf = BloomFilter(30, 5, 90210)
     bf.add(h160)
     node.handshake()
     node.send(b'filterload', bf.filterload())
     start_block = bytes.fromhex(last_block_hex)
     getheaders_message = GetHeadersMessage(start_block=start_block)
     node.send(b'getheaders', getheaders_message.serialize())
     headers_envelope = node.wait_for_commands({b'headers'})
     stream = headers_envelope.stream()
     headers = HeadersMessage.parse(stream)
     get_data_message = GetDataMessage()
     for b in headers.blocks:
         if not b.check_pow():
             raise RuntimeError('proof of work is invalid')
         get_data_message.add_data(FILTERED_BLOCK_DATA_TYPE, b.hash())
     node.send(b'getdata', get_data_message.serialize())
     found = False
     while not found:
         envelope = node.wait_for_commands({b'merkleblock', b'tx'})
         stream = envelope.stream()
         if envelope.command == b'merkleblock':
             mb = MerkleBlock.parse(stream)
             if not mb.is_valid():
                 raise RuntimeError('invalid merkle proof')
         else:
             prev_tx_obj = Tx.parse(stream, testnet=True)
             for i, tx_out in enumerate(prev_tx_obj.tx_outs):
                 if tx_out.script_pubkey.address(testnet=True) == address:
                     self.assertEqual(
                         prev_tx_obj.id(),
                         'e3930e1e566ca9b75d53b0eb9acb7607f547e1182d1d22bd4b661cfe18dcddf1'
                     )
                     self.assertEqual(i, 0)
                     found = True
                     break
Example #10
0
# found = False
# while not found:
#     message = node.wait_for(MerkleBlock, Tx)
#     if message.command == b'merkleblock':
#         if not message.is_valid():
#             raise RuntimeError('invalid merkle proof')
#     else:
#         for i, tx_out in enumerate(message.tx_outs):
#             if tx_out.script_pubkey.address(testnet=True) == utxo_address:
#                 print('found: {}:{}'.format(message.id(), i))
#                 found = True
#                 break

node.handshake()
getdata = GetDataMessage()
t = '1ca6b09df876b19f37548986f331a5360a472fc8a3604b19877dda83a6bfe326'
t_bytes = bytes.fromhex(t)
#getdata.add_data(BLOCK_DATA_TYPE, bytes.fromhex(block_hash_hex))
getdata.add_data(TX_DATA_TYPE, t_bytes)
node.send(getdata)

received_tx = node.wait_for(Tx)
print(received_tx.id() == t_bytes.hex())

# print("Given:  ", block_hash_hex)
# while not found:
#     message = node.wait_for(Block)
#     if message.command == b'block':
#        received_block_hash = message.hash().hex()
Example #11
0
h160 = decode_base58(address)
node = SimpleNode('testnet.programmingbitcoin.com',
                  testnet=True,
                  logging=False)
bf = BloomFilter(size=30, function_count=5, tweak=90210)
bf.add(h160)
node.handshake()
node.send(bf.filterload())
start_block = bytes.fromhex(last_block_hex)
getheaders = GetHeadersMessage(start_block=start_block)
node.send(getheaders)
print('ok2')
headers = node.wait_for(HeadersMessage)
print('ok3')
getdata = GetDataMessage()
for b in headers.blocks:
    if not b.check_pow():
        raise RuntimeError('proof of work is invalid')
    getdata.add_data(FILTERED_BLOCK_DATA_TYPE, b.hash())
node.send(getdata)
found = False
while not found:
    print('ok1')
    message = node.wait_for(MerkleBlock, Tx)
    if message.command == b'merkleblock':
        if not message.is_valid():
            raise RuntimeError('invalid merkle proof')
    else:
        for i, tx_out in enumerate(message.tx_outs):
            if tx_out.script_pubkey.address(testnet=True) == address:
Example #12
0
 def test_exercise_6(self):
     last_block_hex = '00000000000538d5c2246336644f9a4956551afb44ba47278759ec55ea912e19'
     secret = little_endian_to_int(
         hash256(b'Jimmy Song Programming Blockchain'))
     private_key = PrivateKey(secret=secret)
     addr = private_key.point.address(testnet=True)
     h160 = decode_base58(addr)
     target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv'
     self.assertEqual(addr, target_address)
     target_h160 = decode_base58(target_address)
     target_script = p2pkh_script(target_h160)
     fee = 5000
     node = SimpleNode('tbtc.programmingblockchain.com', testnet=True)
     bf = BloomFilter(30, 5, 90210)
     bf.add(h160)
     node.handshake()
     node.send(b'filterload', bf.filterload())
     start_block = bytes.fromhex(last_block_hex)
     getheaders_message = GetHeadersMessage(start_block=start_block)
     node.send(getheaders_message.command, getheaders_message.serialize())
     headers_envelope = node.wait_for_commands({HeadersMessage.command})
     stream = headers_envelope.stream()
     headers = HeadersMessage.parse(stream)
     last_block = None
     get_data_message = GetDataMessage()
     for b in headers.blocks:
         if not b.check_pow():
             raise RuntimeError('proof of work is invalid')
         if last_block is not None and b.prev_block != last_block:
             raise RuntimeError('chain broken')
         get_data_message.add_data(FILTERED_BLOCK_DATA_TYPE, b.hash())
         last_block = b.hash()
     node.send(get_data_message.command, get_data_message.serialize())
     prev_tx, prev_index, prev_tx_obj = None, None, None
     while prev_tx is None:
         envelope = node.wait_for_commands({b'merkleblock', b'tx'})
         stream = envelope.stream()
         if envelope.command == b'merkleblock':
             mb = MerkleBlock.parse(stream)
             if not mb.is_valid():
                 raise RuntimeError('invalid merkle proof')
         else:
             prev_tx_obj = Tx.parse(stream, testnet=True)
             for i, tx_out in enumerate(prev_tx_obj.tx_outs):
                 if tx_out.script_pubkey.address(testnet=True) == addr:
                     prev_tx = prev_tx_obj.hash()
                     prev_index = i
                     self.assertEqual(
                         prev_tx_obj.id(),
                         'e3930e1e566ca9b75d53b0eb9acb7607f547e1182d1d22bd4b661cfe18dcddf1'
                     )
                     self.assertEqual(i, 0)
     tx_in = TxIn(prev_tx, prev_index, Script([]), 0xffffff)
     TxFetcher.cache[prev_tx] = prev_tx_obj
     tx_ins = [tx_in]
     total = prev_tx_obj.tx_outs[prev_index].amount
     tx_outs = [TxOut(total - fee, target_script)]
     tx_obj = Tx(1, tx_ins, tx_outs, 0, testnet=True)
     tx_obj.sign_input(0, private_key)
     self.assertEqual(
         tx_obj.serialize().hex(),
         '0100000001f1dddc18fe1c664bbd221d2d18e147f50776cb9aebb0535db7a96c561e0e93e3000000006a473044022046a49962540a89e83da0636455b6c81c11c2844b7f3cd414c02e1a13741f4d15022006eed4eeda994d2bfebb9f1a494bfa3c8bab96e7e4c82623f4a29736dfe309e70121021cdd761c7eb1c90c0af0a5963e94bf0203176b4662778d32bd6d7ab5d8628b32ffffff0001a1629ef5000000001976a914ad346f8eb57dee9a37981716e498120ae80e44f788ac00000000'
     )
node.handshake()
# load the bloom filter with the filterload command
node.send(bf.filterload())

# set start block to last_block from above
start_block = bytes.fromhex(last_block_hex)
# send a getheaders message with the starting block
getheaders = GetHeadersMessage(start_block=start_block)
node.send(getheaders)

# wait for the headers message
headers = node.wait_for(HeadersMessage)
# store the last block as None
last_block = None
# initialize the GetDataMessage
getdata = GetDataMessage()
# loop through the blocks in the headers
for b in headers.blocks:
    # check that the proof of work on the block is valid
    if not b.check_pow():
        raise RuntimeError('proof of work is invalid')
    # check that this block's prev_block is the last block
    if last_block is not None and b.prev_block != last_block:
        raise RuntimeError('chain broken')
    # add a new item to the get_data_message
    # should be FILTERED_BLOCK_DATA_TYPE and block hash
    get_data_message.add_data(FILTERED_BLOCK_DATA_TYPE, b.hash())
    # set the last block to the current hash
    last_block = b.hash()
# send the getdata message
node.send(getdata)
Example #14
0
def get_block(self, block_hash):
    getdata = GetDataMessage()
    getdata.add_data(BLOCK_DATA_TYPE, block_hash)
    self.send(getdata)
    return self.wait_for(Block)