def genesis() -> Block: args = (0, "0", int(time.time()), "Genesis Block") nonce = 0 # suppose this target's difficulty = 1 target = "00000ffff0000000000000000000000000000000000000000000000000000000" while True: hash = Block.calculate_hash(*args, nonce=nonce, target=target) if Block.validate_difficulty(hash, target): break else: nonce += 1 return Block(*args, nonce=nonce, target=target, hash=hash)
def generate_next(self, data: str) -> Block: lb = self.latest_block args = (lb.index + 1, lb.hash, int(time.time()), data) nonce = 0 target = self.retarget() while True: hash = Block.calculate_hash(*args, nonce=nonce, target=target) if Block.validate_difficulty(hash, target): break else: nonce += 1 return Block(*args, nonce=nonce, target=target, hash=hash)
def genesis_block(self): transactions = [] for i in range(1, 51): transactions.append(Transaction(outputs=[(i, BASE_VALUE)])) genesis_block = Block(transactions=transactions, previous_hash="genesis") self.__blockchain = Blockchain(block=genesis_block)
def __init__(self, creation_time): self.timestamp = creation_time self.prev_hashes = [] self.system_txs = [] self.payment_txs = [] self.precalculated_genesis_hash = Block.get_hash(self)
def add_transaction(self, tx): if self.validate_transaction(tx): self.unconfirmed_tx_pool.append(tx) self.__inputs_set.add((tx.get_inputs()[0].get_transaction_hash(), tx.get_inputs()[0].get_index())) if self.mining_mode == 'pow': if len(self.unconfirmed_tx_pool) >= CHAIN_SIZE and ( self.__mining_thread is None or not self.is_mining()): self.__mining_thread = MiningThread(self) self.__mining_thread.start() elif self.mining_mode == 'bft': if len( self.unconfirmed_tx_pool ) >= CHAIN_SIZE and self.bft_context.leader and self.bft_context.state.__class__ == IdleState: transactions = self.unconfirmed_tx_pool[0:CHAIN_SIZE] self.unconfirmed_tx_pool[0:CHAIN_SIZE] = [] prev_hash = self.blockchain.get_head_of_chain( ).block.block_hash block = Block(transactions=transactions, previous_hash=prev_hash, nonce=0) self.bft_context.pre_prepare_message = block self.bft_context.transition_to(PrePreparedState) self.broadcast_pre_prepare(PrePrepareMessage(block))
def genesis_block(self): transactions = [] my_trans = [] for peer in self.peers_database: if peer.pk is not None: for count in range(CHAIN_SIZE // 2): if peer.pk == self.peer_data.pk: trans = Transaction(outputs=[(peer.pk, BASE_VALUE)], timestamp=count) my_trans.append(trans) transactions.append(trans) else: transactions.append( Transaction(outputs=[(peer.pk, BASE_VALUE)], timestamp=count)) if self.mode == 'client': for tx in my_trans: input_utxo = tx.get_outputs()[0] input_utxo.set_prev_tx_hash(tx) input_utxo.sign(self.sk) self.__wallet.append(input_utxo) genesis_block = Block(transactions=transactions, previous_hash="genesis", height=0, timestamp=0) self.blockchain = Blockchain(block=genesis_block)
def run(self): self.__transactions = self.__model.unconfirmed_tx_pool[0:CHAIN_SIZE] self.__prev_hash = self.__model.blockchain.get_head_of_chain( ).block.block_hash pow_found = False nonce = 0 block = None while not pow_found: if self.stopped(): break block = Block(transactions=self.__transactions, previous_hash=self.__prev_hash, nonce=nonce) if block.hash_difficulty() == self.__diff: pow_found = True nonce += 1 if pow_found: self.__model.unconfirmed_tx_pool[0:CHAIN_SIZE] = [] self.__model.blockchain.add_block(block) self.__model.broadcast_new_block(block) print(str(block))
class SignedBlock(): def parse(self, raw_data): self.signature = int.from_bytes(raw_data[0:128], byteorder='big') block_length = struct.unpack_from("h", raw_data, 128)[0] raw_block = raw_data[130:130 + block_length] self.block = Block() self.block.parse(raw_block) def pack(self): raw_block = self.block.pack() raw_signed_block = self.signature.to_bytes(128, byteorder='big') raw_signed_block += struct.pack("h", len(raw_block)) raw_signed_block += raw_block return raw_signed_block def set_block(self, block): self.block = block def set_signature(self, signature): self.signature = signature def verify_signature(self, pubkey): block_hash = self.block.get_hash().digest() return pubkey.verify(block_hash, (self.signature, ))
def sign_block(self, private): #TODO move somewhere more approptiate block = Block() block.prev_hashes = [*self.get_top_blocks()] block.timestamp = int(datetime.datetime.now().timestamp()) block.randoms = [] block_hash = block.get_hash().digest() signature = private.sign(block_hash, 0)[ 0] #for some reason it returns tuple with second item being None signed_block = SignedBlock() signed_block.set_block(block) signed_block.set_signature(signature) current_block_number = self.get_current_timeframe_block_number() self.add_signed_block(current_block_number, signed_block) print(block_hash.hex(), " was added to blockchain under number ", current_block_number) return signed_block
def test_private_keys_extraction(self): dag = Dag(0) epoch = Epoch(dag) node_private = Private.generate() prev_hash = dag.genesis_block().get_hash() round_start, round_end = Epoch.get_round_bounds(1, Round.PRIVATE) for i in range(1, round_start): block = BlockFactory.create_block_with_timestamp([prev_hash], BLOCK_TIME * i) signed_block = BlockFactory.sign_block(block, node_private) dag.add_signed_block(i, signed_block) prev_hash = block.get_hash() generated_private_keys = [] for i in range(round_start, round_end): # intentionally skip last block of round generated_private = Private.generate() generated_private_keys.append(Keys.to_bytes(generated_private)) private_key_tx = PrivateKeyTransaction() private_key_tx.key = Keys.to_bytes(generated_private) block = Block() block.system_txs = [private_key_tx] block.prev_hashes = dag.get_top_blocks_hashes() block.timestamp = i * BLOCK_TIME signed_block = BlockFactory.sign_block(block, node_private) dag.add_signed_block(i, signed_block) prev_hash = block.get_hash() ChainGenerator.fill_with_dummies(dag, prev_hash, Epoch.get_round_range(1, Round.FINAL)) epoch_hash = dag.blocks_by_number[ROUND_DURATION * 6 + 1][0].get_hash() extracted_privates = epoch.get_private_keys_for_epoch(epoch_hash) for i in range(0, ROUND_DURATION - 1): self.assertEqual(extracted_privates[i], generated_private_keys[i])
def genesis_block(self): block = Block() block.timestamp = self.genesis_creation_time block.prev_hashes = [SHA256.new(b"0").digest()] return block
def test_top_blocks(self): block1 = Block() block1.prev_hashes = [self.genesis_block().get_hash().digest()] block1.timestamp = 32452345234 block1.randoms = [] signed_block1 = SignedBlock() signed_block1.set_block(block1) self.add_signed_block(1, signed_block1) block2 = Block() block2.prev_hashes = [block1.get_hash().digest()] block2.timestamp = 32452345 block2.randoms = [] signed_block2 = SignedBlock() signed_block2.set_block(block2) self.add_signed_block(2, signed_block2) block3 = Block() block3.prev_hashes = [block1.get_hash().digest()] block3.timestamp = 1231827398 block3.randoms = [] signed_block3 = SignedBlock() signed_block3.set_block(block3) self.add_signed_block(3, signed_block3) for keyhash in self.blocks_by_hash: print(binascii.hexlify(keyhash)) top_hashes = self.get_top_blocks() print("tops") for keyhash in top_hashes: print(binascii.hexlify(keyhash))
def create_block_with_timestamp(prev_hashes, timestamp): block = Block() block.prev_hashes = prev_hashes block.timestamp = timestamp block.system_txs = [] return block
def deserialize(other: dict) -> "BlockChain": blocks = [Block(**b) for b in other["blocks"]] return BlockChain(blocks=blocks)
def deserialize(cls, other: dict): blocks = [Block(**b) for b in other["blocks"]] return cls(blocks=blocks)
def create_block_dummy(prev_hashes): block = Block() block.prev_hashes = prev_hashes block.timestamp = Time.get_current_time() block.system_txs = [] return block
from time import time from chain.block import Block from chain.chain import Chain from chain.tx import Tx # import argparse # parser = argparse.ArgumentParser(description='Add some integers.') # parser.add_argument('integers', metavar='N', type=int, nargs='+', # help='interger list') # parser.add_argument('--sum', action='store_const', # const=sum, default=max, # help='sum the integers (default: find the max)') # args = parser.parse_args() # print(args.sum(args.integers)) if __name__ == '__main__': chain = Chain() chain.addBlock( Block(str(time()), Tx('addr1', 'addr2', 14.2245, 'Hello there'), chain.chain[-1].hash)) chain.addBlock( Block(str(time()), Tx('addr1', 'addr2', 42.22, 'Hey there you'), chain.chain[-1].hash)) chain.print() chain.writeJSON()
def test_secret_sharing_rounds(self): dag = Dag(0) epoch = Epoch(dag) dummy_private = Private.generate() signers = [] for i in range(0, ROUND_DURATION + 1): signers.append(Private.generate()) private_keys = [] block_number = 1 genesis_hash = dag.genesis_block().get_hash() prev_hash = genesis_hash signer_index = 0 for i in Epoch.get_round_range(1, Round.PUBLIC): private = Private.generate() private_keys.append(private) signer = signers[signer_index] pubkey_tx = PublicKeyTransaction() pubkey_tx.generated_pubkey = Private.publickey(private) pubkey_tx.pubkey_index = signer_index pubkey_tx.signature = Private.sign( pubkey_tx.get_signing_hash(genesis_hash), signer) block = Block() block.timestamp = i * BLOCK_TIME block.prev_hashes = [prev_hash] block.system_txs = [pubkey_tx] signed_block = BlockFactory.sign_block(block, signer) dag.add_signed_block(i, signed_block) signer_index += 1 prev_hash = block.get_hash() prev_hash = ChainGenerator.fill_with_dummies( dag, prev_hash, Epoch.get_round_range(1, Round.COMMIT)) public_keys = [] for private in private_keys: public_keys.append(Private.publickey(private)) randoms_list = [] expected_random_pieces = [] for i in Epoch.get_round_range(1, Round.SECRETSHARE): random_bytes = os.urandom(32) random_value = int.from_bytes(random_bytes, byteorder='big') split_random_tx = SplitRandomTransaction() splits = split_secret(random_bytes, 2, 3) encoded_splits = encode_splits(splits, public_keys) split_random_tx.pieces = encoded_splits split_random_tx.pubkey_index = 0 expected_random_pieces.append(split_random_tx.pieces) split_random_tx.signature = Private.sign(pubkey_tx.get_hash(), dummy_private) block = Block() block.timestamp = i * BLOCK_TIME block.prev_hashes = [prev_hash] block.system_txs = [split_random_tx] signed_block = BlockFactory.sign_block(block, dummy_private) dag.add_signed_block(i, signed_block) randoms_list.append(random_value) prev_hash = block.get_hash() expected_seed = sum_random(randoms_list) prev_hash = ChainGenerator.fill_with_dummies( dag, prev_hash, Epoch.get_round_range(1, Round.REVEAL)) signer_index = 0 private_key_index = 0 raw_private_keys = [] for i in Epoch.get_round_range(1, Round.PRIVATE): private_key_tx = PrivateKeyTransaction() private_key_tx.key = Keys.to_bytes(private_keys[private_key_index]) raw_private_keys.append(private_key_tx.key) signer = signers[signer_index] block = Block() block.system_txs = [private_key_tx] block.prev_hashes = [prev_hash] block.timestamp = block_number * BLOCK_TIME signed_block = BlockFactory.sign_block(block, signer) dag.add_signed_block(i, signed_block) signer_index += 1 private_key_index += 1 prev_hash = block.get_hash() prev_hash = ChainGenerator.fill_with_dummies( dag, prev_hash, Epoch.get_round_range(1, Round.FINAL)) top_block_hash = dag.get_top_blocks_hashes()[0] random_splits = epoch.get_random_splits_for_epoch(top_block_hash) self.assertEqual(expected_random_pieces, random_splits) restored_randoms = [] for i in range(0, len(random_splits)): random = decode_random(random_splits[i], Keys.list_from_bytes(raw_private_keys)) restored_randoms.append(random) self.assertEqual(randoms_list, restored_randoms) seed = epoch.extract_shared_random(top_block_hash) self.assertEqual(expected_seed, seed)
def createGenesis(self): genesis = Block(str(time()), Tx('', '', 1.0, 'Genesis'), '') self.addBlock(genesis) self.lastindex = genesis.index
def parse(self, raw_data): self.signature = int.from_bytes(raw_data[0:128], byteorder='big') block_length = struct.unpack_from("h", raw_data, 128)[0] raw_block = raw_data[130:130 + block_length] self.block = Block() self.block.parse(raw_block)
def add_block(self, block: Block) -> bool: if block.is_valid() and self.is_next_block(block): self.blocks.append(block) return True else: return False
def are_blocks_adjacent(block: Block, prev_block: Block) -> bool: is_valid_block = block.is_valid() is_valid_next = ( block.index == prev_block.index + 1 and block.prev_hash == prev_block.hash ) return is_valid_block and is_valid_next
def test_pack_parse(self): original_block = Block() original_block.timestamp = 2344 original_block.prev_hashes = [ SHA256.new(b"323423").digest(), SHA256.new(b"0").digest() ] original_block.system_txs = [] tx = CommitRandomTransaction() data, _ = enc_part_random(SHA256.new(b"era_hash").digest()) tx.rand = data original_block.system_txs.append(tx) raw = original_block.pack() restored = Block() restored.parse(raw) self.assertEqual(original_block.get_hash().digest(), restored.get_hash().digest())