def test_to_dict(): actual_transaction = 'transaction' actual_previous_block = 'previous_block' block = Block(actual_transaction, actual_previous_block) assert isinstance(block.to_dict(), dict) == True assert block.to_dict()['transaction'] == json.dumps(actual_transaction) assert block.to_dict()['previous_block'] == actual_previous_block
def test_is_valid_bad_difficulty(self): self.block.difficulty = 10 # Set correct number of leading zeros to prevent pow error and ensure testing difficulty deviation. self.block.hash = "0" * self.block.difficulty with self.assertRaises(DifficultyDeviationError): Block.is_valid(self.previous_block, self.block)
def add_data(self, data: str) -> bool: """ Adds a new Block to the Blockchain. Returns a bool indicating success or failure. Parameters: data -- the data (represented as a string) to be stored. """ timestamp = time.time() # The previous hash is important since this is what helps us ensure # that our Blockchain has not lost its integrity. Each block will # keep track of the block before it, using its hash, thus we # will know that no block has been tamperered with. previous_hash = self.blocks[-1].generate_hash() block = Block() block.data = data block.timestamp = timestamp block.previous_hash = previous_hash self.blocks.append(block) # We validate the entire Blockchain to ensure that # the block we just inserted did not break our # Blockchain integrity. if not self.validate(): self.blocks.remove(block) return False return True
def continuously_index(self) -> None: """ Runs the indexer to fill in transactions in the past and new ones as they come in """ our_chainhead = 0 # Block.get_latest_block_number() network_chainhead = self.blockchain.get_latest_block_number() # Round up as it never hurts to do more than necessary blocks_per_thread = math.ceil( (network_chainhead - our_chainhead) / self.block_threads) for i in range(self.block_threads): start = our_chainhead + (i * blocks_per_thread) end = our_chainhead + ((i + 1) * blocks_per_thread) thread = Thread(target=self.index, args=(start, end), daemon=True) thread.start() while True: # wait a lil bit for more blocks to come in time.sleep(self.chainhead_sleep_time_s) previous = network_chainhead network_chainhead = self.blockchain.get_latest_block_number() # check if our old chainhead is still correct, if not... fix reorg if Block.has_block(previous): block = Block.get_block(previous) our_block_hash = block.get_hash().get() network_block = self.blockchain.get_block(previous) network_block_hash = network_block.get_hash().get() if network_block_hash != our_block_hash: previous = self.handle_reorg(previous) thread = Thread(target=self.index, args=(previous, network_chainhead), daemon=True) thread.start()
def test_mineBlock(): # testing mine block data ='test' block = Block.mineBlock(Block.genesisBlock(),data) assert isinstance(block, Block) assert block.previousHash==GENESIS_DATA['hash'] assert block.data==data assert block.hash[0:block.difficulty]=='0'*block.difficulty
def create_genesis_block(self): genesis_block = Block(index=0, transactions=[], timestamp=time.time(), previous_hash='0') genesis_block.hash = genesis_block.compute_hash() self.chain.append(genesis_block)
def test_isValidBlockJumpDifficulty(lastBlock, block): jump_difficulty = 10 block.difficulty = jump_difficulty block.__hash__ = f'{"0" * jump_difficulty}111abbc' with pytest.raises(Exception,match='difficulty change is more than 1'): Block.isValidBlock(lastBlock, block)
def test_get_hash(): bm = BlockchainManager(None) block = Block('transaction', 'prev_block_hash') block_json = json.dumps(block.to_dict(), sort_keys=True) hash_b = hashlib.sha256( hashlib.sha256(block_json.encode('utf-8')).digest()).digest() actual_hash = binascii.hexlify(hash_b).decode('ascii') assert bm.get_hash(block.to_dict()) == actual_hash
def test_difficulty_when_block_mined_too_quickly(self): previous_block = Block.mine(self.previous_block, "Ethereum") # New block mined immediately, quicker than the MINE_RATE. mined_block = Block.mine(previous_block, "Verge") # Assert that difficulty has increased by increment of one self.assertEqual(mined_block.difficulty, previous_block.difficulty + 1)
def test_block_hash(self): """ Test hashing blocks """ block = Block(1, [], 0, '0') # If we recalculate the hash on the block we should get the same result as we have stored self.assertEqual(block.hash, block.hash_block())
def __proof_of_work(self, dictionary): """ Increment a property 'nonce' until the resulting hash has a leading amount of zeros equal to Blockchain.__difficulty """ hashed = Block.sha(dictionary) while hashed[:self.__difficulty[0]] != '0' * self.__difficulty[0]: dictionary['nonce'] += 1 hashed = Block.sha(dictionary) return dictionary
def test_difficulty_when_block_mined_too_slowly(self): previous_block = Block.mine(self.previous_block, "TRX") time.sleep(MINE_RATE / SECOND) # New block mined too slowly, slower that the MINE_RATE. mined_block = Block.mine(previous_block, "Stellar") # Assert that difficulty has decreased by increment of one self.assertEqual(mined_block.difficulty, previous_block.difficulty - 1)
def isValidLedger(ledger): ''' validate the ledger ''' if ledger[0] != Block.genesisBlock(): raise Exception('genesis block must be valid') for i in range(1, len(ledger)): block = ledger[i] lastBlock = ledger[i - 1] Block.isValidBlock(lastBlock, block)
def test_mine_block_difficulty_not_less_than_1(self): previous_block = Block.mine(self.previous_block, "Dragonchain") # Ensure previous block difficulty is 1 previous_block.difficulty = 1 time.sleep(MINE_RATE / SECOND) # New block mined too slowly, slower that the MINE_RATE. mined_block = Block.mine(previous_block, "Some more data") # Assert than even though the block mined slowly, # the difficulty is not decreased as it cannot be less than 1 self.assertEqual(mined_block.difficulty, 1)
def new_block(genesis): new_block = Block(genesis.get_block_information(), PUBLIC_KEY) new_block.add_transaction("tx1") new_block.add_transaction("tx2") new_block.sign(PRIVATE_KEY) new_block.update_hash() yield new_block
def add_chain_data(self, chain_data: list): """ Takes a list of blocks, usually ingested from a JSON file, and adds them to the chain. Parameters: chain_data -- a list of dicts with "data", "previous_hash", "timestamp". """ for chain_item in chain_data: block = Block() block.data = chain_item["data"] block.previous_hash = chain_item["previous_hash"] block.timestamp = chain_item["timestamp"] self.blocks.append(block)
def write_default_blockchain() -> str: """Returns the string representation of the default Blockchain data.""" genesis_block = Block() genesis_block.data = "This is the sickest Blockchain implementation ever." genesis_block.timestamp = time.time() genesis_block.previous_hash = "" # Create a temporary chain which we can convert to JSON. default_chain = Blockchain([]) default_chain.blocks.append(genesis_block) save_chain(default_chain) return default_chain.to_json()
def test_genesis(self): expected = Block( Block.GENESIS["timestamp"], Block.GENESIS["previous_hash"], Block.GENESIS["hash"], Block.GENESIS["data"], Block.GENESIS["difficulty"], Block.GENESIS["nonce"], ) result = Block.genesis() self.assertIsInstance(result, Block) self.assertEqual(expected.__dict__, result.__dict__)
def mine(self, reward_address): """ Mines a new block into the chain :param reward_address: <str> address where the reward coin will be transferred to :return: result of the mining attempt and the new block """ last_block = self.last_block index = last_block.index + 1 previous_hash = last_block.hash # Let's start with the heavy duty, generating the proof of work nonce = self.generate_proof_of_work(last_block) # In the next step we will create a new transaction to reward the miner # In this particular case, the miner will receive coins that are just "created", so there is no sender self.create_transaction( sender="0", recipient=reward_address, amount=1, ) # Add the block to the new chain block = Block(index, self.__current_transactions, nonce, previous_hash) if self.add_block(block): return block return None
def __init__(self): self.chain = list() self.chain.append( Block( 0, '0000000000000000000000000000000000000000000000000000000000000000', 'first Block'))
def test_genesis_block(genesis_block): blockchain_mview = memoryview(genesis_block) block = Block.from_binary_data(blockchain_mview, offset=0) assert block.header.magic_number == Network.mainnet.value assert block.header.block_size == 285 assert block.header.version == 1 assert block.header.previous_hash == ( '0000000000000000000000000000000000000000000000000000000000000000' ) assert block.header.merkle_hash == ( '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b' ) assert block.header.time == datetime(2009, 1, 3, 18, 15, 5) assert block.header.bits == 486604799 assert block.header.bits == 0x1d00ffff assert block.header.nonce == 2083236893 assert block.total_size == 293 assert block.hashcash == ( '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f' ) assert len(block.transactions) == 1 # NOQA https://blockchain.info/tx/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b txn = block.transactions[0] assert txn.version == 1 assert len(txn.inputs) == 1 assert txn.lock_time == datetime(1970, 1, 1, 0, 0) assert txn.txn_hash == ( '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b' ) txn_input = txn.inputs[0] assert txn_input.is_coinbase assert txn_input.previous_hash == ( '0000000000000000000000000000000000000000000000000000000000000000' ) assert txn_input.seq_no == 0xffffffff assert txn_input.txn_out_id == 0xffffffff assert txn_input.signature_script.hex() == ( '04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e6' '3656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f75742066' '6f722062616e6b73' ) assert txn_input.signature_script.endswith( b'The Times 03/Jan/2009 Chancellor on ' b'brink of second bailout for banks' ) assert len(txn.outputs) == 1 txn_output = txn.outputs[0] assert txn_output.value == 50 * (10 ** 8) assert txn_output.script_pub_key.hex() == ( '4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb' '649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac' ) assert txn_output.address == '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'
def test_genesisBlock(): # testing genesis block block = Block(**GENESIS_DATA) assert isinstance(block,Block) assert block.timestamp==GENESIS_DATA['timestamp'] assert block.data==GENESIS_DATA['data'] assert block.hash==GENESIS_DATA['hash'] assert block.previousHash==GENESIS_DATA['previousHash']
def test_init(): actual_transaction = 'transaction' actual_previous_block = 'previous_block' block = Block(actual_transaction, actual_previous_block) assert block.timestamp is not None assert block.transaction is actual_transaction assert block.previous_block is actual_previous_block
def test_block_fromjson(): sender, recipient = Key(), Key() trx = Transaction(sender.address, sender.public_key, recipient.address, 'Hello world') trx.sign(sender.private_key) block = Node.mine_block(0, 0, [trx]) block2 = Block.from_json(block.json()) assert block.index == block2.index
def test_set_new_block(): genesis = GenesisBlock() bm = BlockchainManager(genesis.to_dict()) block = Block('transaction', 'prev_block_hash') bm.set_new_block(block) assert len(bm.chain) == 2 assert bm.chain[0] == genesis.to_dict() assert bm.chain[1] == block
def test_mine(self): result = Block.mine(self.previous_block, "Bitcoin") self.assertIsInstance(result, Block) self.assertEqual(result.data, "Bitcoin") self.assertEqual(result.previous_hash, self.previous_block.hash) self.assertEqual(result.hash[0:result.difficulty], "0" * result.difficulty)
def run_contract(self): accounts, txs, validators, contract_accounts = self.blockCallBack.blockchain.get_state( Block.calc_hash(self.blockCallBack.blockchain.get_highest_block())) if self.vk.to_string().hex() in contract_accounts: tx = Transaction(0, self.vk.to_string().hex(), RUN_ADDR, 0, 0) self.txCallBack.publish(tx) return True return False
def check_chain(self, entry_pool): if self.chain[0] != Block.genesis(): raise Exception("Kein gültiger Genesis-Block") for i in range(1, len(self.chain)): block = self.chain[i] last_block = self.chain[i-1] block.check_block(last_block) self.check_entries(entry_pool)
def run(type_op): highest_block = self.blockchain.get_highest_block() accounts, txs, validators, contract_accounts = self.blockchain.get_state( Block.calc_hash(highest_block)) new_state, shard_num = Transaction.run_contract(contract_accounts[from_vk], vk, type_op) new_tx = Transaction(0, vk, from_vk, 0, 0, shard_num=shard_num) new_tx.new_state = new_state publish(new_tx)
def test_block_setup(self): previous_hash = '0000000000000000000000000000000000000000000000000000000000000000' block = Block(0, previous_hash, 'TestBlock') assert block.index == 0 assert block.previous_hash == previous_hash assert block.data == 'TestBlock' assert len(block.hash) == 64
def create_genesis(self): """ Creates the Genesis block and passes it to the chain :return: None """ genesis_block = Block(0, self.__current_transactions, 0, '00') self.__chain.append(genesis_block)
def next_block_branch2(chain): block_information = chain.genesis_block.get_block_information() next_block_branch2 = Block(block_information, PUBLIC_KEY) next_block_branch2.timestamp = chain.genesis_block.timestamp + CONFIG.block_time + 1 next_block_branch2.sign(PRIVATE_KEY) next_block_branch2.update_hash() yield next_block_branch2
def post(self): #: find the longest chain max_height, target_peer = 0, None for peer in peers: res = requests.get(peer + "/chain/height/") height = int(res.json()['data']) if height > max_height: max_height, target_peer = height, peer #: fetch the blocks from target peer if max_height > node.chain.height: logging.info('found longer chain %d. replace mine %d', max_height, node.chain.height) res = requests.get(target_peer + '/block/') block_docs = res.json()['data'] node.chain.blocks = [Block.from_json(doc) for doc in block_docs] self.write(ok())
def test_block_170(block_170): blockchain_mview = memoryview(block_170) block = Block.from_binary_data(blockchain_mview, offset=0) assert block.header.magic_number == Network.mainnet.value assert block.header.block_size == 490 assert block.header.version == 1 assert block.header.previous_hash == ( '000000002a22cfee1f2c846adbd12b3e183d4f97683f85dad08a79780a84bd55' ) assert block.header.merkle_hash == ( '7dac2c5666815c17a3b36427de37bb9d2e2c5ccec3f8633eb91a4205cb4c10ff' ) assert block.header.time == datetime(2009, 1, 12, 3, 30, 25) assert block.header.bits == 486604799 assert block.header.bits == 0x1d00ffff assert block.header.nonce == 1889418792 assert block.total_size == 498 assert block.hashcash == ( '00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee' ) assert len(block.transactions) == 2 coinbase_txn = block.transactions[0] assert coinbase_txn.version == 1 assert len(coinbase_txn.inputs) == 1 assert coinbase_txn.lock_time == datetime(1970, 1, 1, 0, 0) assert coinbase_txn.txn_hash == ( 'b1fea52486ce0c62bb442b530a3f0132b826c74e473d1f2c220bfa78111c5082' ) coinbase_txn_input = coinbase_txn.inputs[0] assert coinbase_txn_input.is_coinbase assert coinbase_txn_input.previous_hash == ( '0000000000000000000000000000000000000000000000000000000000000000' ) assert coinbase_txn_input.seq_no == 0xffffffff assert coinbase_txn_input.txn_out_id == 0xffffffff assert coinbase_txn_input.signature_script.hex() == ( '04ffff001d0102' ) assert len(coinbase_txn.outputs) == 1 coinbase_txn_output = coinbase_txn.outputs[0] assert coinbase_txn_output.value == 50 * (10 ** 8) assert coinbase_txn_output.script_pub_key.hex() == ( '4104d46c4968bde02899d2aa0963367c7a6ce34eec332b32e42e5f3407e052d64ac' '625da6f0718e7b302140434bd725706957c092db53805b821a85b23a7ac61725bac' ) assert coinbase_txn_output.address == '1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc' real_txn = block.transactions[1] assert real_txn.version == 1 assert len(real_txn.inputs) == 1 assert real_txn.lock_time == datetime(1970, 1, 1, 0, 0) assert real_txn.txn_hash == ( 'f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16' ) real_txn_input = real_txn.inputs[0] assert not real_txn_input.is_coinbase assert real_txn_input.previous_hash == ( '0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9' ) assert not real_txn_input.is_coinbase assert real_txn_input.txn_out_id == 0 assert real_txn_input.signature_script.hex() == ( '47304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb' '8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d' '1d0901' ) assert len(real_txn.outputs) == 2 real_txn_output1 = real_txn.outputs[0] assert real_txn_output1.value == 10 * (10 ** 8) assert real_txn_output1.script_pub_key.hex() == ( '4104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa2841' '4e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac' ) assert real_txn_output1.address == '1Q2TWHE3GMdB6BZKafqwxXtWAWgFt5Jvm3' real_txn_output2 = real_txn.outputs[1] assert real_txn_output2.value == 40 * (10 ** 8) assert real_txn_output2.script_pub_key.hex() == ( '410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5' 'cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac' ) assert real_txn_output2.address == '12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S'