Пример #1
0
class BlockWithProof:
    def __init__(self, block):
        self._block = block
        self._proof = []

    def add_proof(self, commit):
        self._proof.append(commit)

    def to_json(self):
        proof_json = []
        for commit in self._proof:
            proof_json.append(commit.to_json())
        block_with_proof_json = {
            'block': self._block.to_json(),
            'proof': proof_json
        }
        return block_with_proof_json

    def from_json(self, proof_json):
        self._block = Block()
        self._block.from_json(proof_json['block'])
        for commit_json in proof_json['proof']:
            commit = Commit()
            commit.from_json(commit_json)
            self._proof.append(commit)
        return
Пример #2
0
    def generate_new_block(self):
        with self._blockchainLock:
            authorizations = self.authorizationPool.get_authorizations()
            operations = self.operationPool.get_operations()

            virtual_state = copy.deepcopy(self.state)

            chosen_authorizations = []
            for authorization in authorizations:
                if virtual_state.check_authorization(authorization):
                    chosen_authorizations.append(authorization)
                    virtual_state.change_from_authorization(authorization)
                    if len(chosen_authorizations) > 500:
                        break

            chosen_operations = []
            for operation in operations:
                if virtual_state.check_operation(operation):
                    chosen_operations.append(operation)
                    virtual_state.change_from_operation(operation)
                    if len(chosen_operations) > 500:
                        break

            new_block = Block(prev_hash=self._blockchain[-1].hash,
                              authorizations=chosen_authorizations,
                              operations=chosen_operations,
                              timestamp=current_time())
            new_block.set_now_hash()
            return new_block
Пример #3
0
 def from_json(self, proof_json):
     self._block = Block()
     self._block.from_json(proof_json['block'])
     for commit_json in proof_json['proof']:
         commit = Commit()
         commit.from_json(commit_json)
         self._proof.append(commit)
     return
Пример #4
0
 def __init__(self, node_id, view_id, block_json=None, signature=None):
     self.infoId = 'PrepareRequest'
     self.nodeId = node_id
     self.viewId = view_id
     self.block = Block()
     if block_json is not None:
         self.block.from_json(block_json)
     self.signature = signature
Пример #5
0
class PrepareRequest:
    def __init__(self, node_id, view_id, block_json=None, signature=None):
        self.infoId = 'PrepareRequest'
        self.nodeId = node_id
        self.viewId = view_id
        self.block = Block()
        if block_json is not None:
            self.block.from_json(block_json)
        self.signature = signature

    def sign(self, signature):
        self.signature = signature

    def get_signature(self):
        return self.signature

    def to_json(self):
        request_json = {
            'infoId': self.infoId,
            'nodeId': self.nodeId,
            'viewId': self.viewId,
            'block': self.block.to_json(),
            'signature': self.signature
        }
        return request_json

    def from_json(self, request_json):
        self.infoId = request_json['infoId']
        self.nodeId = request_json['nodeId']
        self.viewId = request_json['viewId']
        self.block.from_json(request_json['block'])
        self.signature = request_json['signature']
        return

    def calc_hash(self):
        return hash_message(str(self))

    def check_signature(self):
        return verify_signature(PK_list[self.nodeId], self.calc_hash(),
                                self.signature)

    def __str__(self):
        return str(self.infoId) + str(self.nodeId) + str(self.viewId) + str(
            self.block.hash)
Пример #6
0
    def __init__(self,
                 chain_file=None,
                 genesis_file='/genesis_block.json',
                 data_dir='./data/blockchain'):
        self._data_dir = data_dir

        genesis_block_path = data_dir + genesis_file
        # print(genesis_block_path)
        with open(genesis_block_path, 'r') as genesis_block_file:
            genesis_block_str = genesis_block_file.read()
            genesis_block_json = json.loads(genesis_block_str)
            timestamp = genesis_block_json['timestamp']
            self._genesis_block = Block(prev_hash='0' * 64,
                                        timestamp=timestamp)
            self._genesis_block.set_now_hash()

        if chain_file is None:
            self._blockchain = []
            self._blockchain.append(self._genesis_block)
            # print(self._blockchain[0].to_json())
        else:
            chain_path = data_dir + chain_file
            with open(chain_path, 'r') as blockchain_file:
                blockchain_str = blockchain_file.read()
                # print(blockchain_str)
                blockchain_json = json.loads(blockchain_str)
                # print(blockchain_json)
                self.from_json(blockchain_json)
            if self._blockchain[0] is not self._genesis_block:
                logging.error("genesis_block mismatch the blockchain")
                return
        # print(genesis_block_json['governor_list'])
        self.state = State(gm_list=genesis_block_json['governor_list'])
        self.operationPool = OperationPool()
        self.authorizationPool = AuthorizationPool()
        # self.authorizationPool.pre_add_authorization()
        self._mining_timer = MyTimer(name='mining',
                                     interval=BlockInterval,
                                     f=self.mining_new_block)
        self._blockchainLock = threading.Lock()
        return
Пример #7
0
    def from_json(self, chain_json):
        required = ['height', 'blockchain']
        if not all(k in chain_json for k in required):
            logging.warning(f'value missing in {required}')
            return False

        if not isinstance(chain_json['height'], int):
            logging.warning("height should be type<int>")
            return False
        if not isinstance(chain_json['blockchain'], list):
            logging.warning("blockchain should be type<list>")
            return False

        chain = []
        for block_json in chain_json['blockchain']:
            new_block = Block()
            if not new_block.from_json(block_json):
                return False
            chain.append(new_block)
        self._blockchain = chain
        return True
Пример #8
0
class Chain:
    def __init__(self,
                 chain_file=None,
                 genesis_file='/genesis_block.json',
                 data_dir='./data/blockchain'):
        self._data_dir = data_dir

        genesis_block_path = data_dir + genesis_file
        # print(genesis_block_path)
        with open(genesis_block_path, 'r') as genesis_block_file:
            genesis_block_str = genesis_block_file.read()
            genesis_block_json = json.loads(genesis_block_str)
            timestamp = genesis_block_json['timestamp']
            self._genesis_block = Block(prev_hash='0' * 64,
                                        timestamp=timestamp)
            self._genesis_block.set_now_hash()

        if chain_file is None:
            self._blockchain = []
            self._blockchain.append(self._genesis_block)
            # print(self._blockchain[0].to_json())
        else:
            chain_path = data_dir + chain_file
            with open(chain_path, 'r') as blockchain_file:
                blockchain_str = blockchain_file.read()
                # print(blockchain_str)
                blockchain_json = json.loads(blockchain_str)
                # print(blockchain_json)
                self.from_json(blockchain_json)
            if self._blockchain[0] is not self._genesis_block:
                logging.error("genesis_block mismatch the blockchain")
                return
        # print(genesis_block_json['governor_list'])
        self.state = State(gm_list=genesis_block_json['governor_list'])
        self.operationPool = OperationPool()
        self.authorizationPool = AuthorizationPool()
        # self.authorizationPool.pre_add_authorization()
        self._mining_timer = MyTimer(name='mining',
                                     interval=BlockInterval,
                                     f=self.mining_new_block)
        self._blockchainLock = threading.Lock()
        return

    def get_height(self):
        return len(self._blockchain)

    def get_block(self, block_number):
        return self._blockchain[block_number]

    def get_authorization(self, block_number, authorization_number):
        return self.get_block(block_number).get_authorization(
            authorization_number)

    def get_output(self, block_number, authorization_number, output_number):
        try:
            output = self._blockchain[block_number].get_authorization(
                authorization_number).get_output(output_number)
        except IndexError:
            logging.error("index out of range")
            return None
        else:
            return output

    def start_mining(self):
        self._mining_timer.restart()
        return

    def end_mining(self):
        self._mining_timer.stop()
        return

    def mining_new_block(self):
        new_block = self.generate_new_block()
        self.add_new_block(new_block)
        print('mined one new block: ' + new_block.hash)
        self._mining_timer.start()
        return new_block

    def generate_new_block(self):
        with self._blockchainLock:
            authorizations = self.authorizationPool.get_authorizations()
            operations = self.operationPool.get_operations()

            virtual_state = copy.deepcopy(self.state)

            chosen_authorizations = []
            for authorization in authorizations:
                if virtual_state.check_authorization(authorization):
                    chosen_authorizations.append(authorization)
                    virtual_state.change_from_authorization(authorization)
                    if len(chosen_authorizations) > 500:
                        break

            chosen_operations = []
            for operation in operations:
                if virtual_state.check_operation(operation):
                    chosen_operations.append(operation)
                    virtual_state.change_from_operation(operation)
                    if len(chosen_operations) > 500:
                        break

            new_block = Block(prev_hash=self._blockchain[-1].hash,
                              authorizations=chosen_authorizations,
                              operations=chosen_operations,
                              timestamp=current_time())
            new_block.set_now_hash()
            return new_block

    def check_new_block(self, block):
        if block.hash != block.calc_hash():
            logging.warning(
                f'chain.py line 187: block hash not matched block {block.hash} vs {block.calc_hash()}'
            )
            return False

        if block.prevHash != self._blockchain[-1].hash:
            logging.warning(
                f'chain.py line 187: block hash not matched last one {block.prevHash} vs {self._blockchain[-1].hash}'
            )
            return False

        v_state = copy.deepcopy(self.state)
        if not v_state.check_authorizations(block.authorizations):
            logging.warning('chain.py line 190: block authorizations invalid')
            return False

        if not v_state.check_operations(block.operations):
            logging.warning('chain.py line 193: block operations invalid')
            return False
        return True

    def add_new_block(self, block):
        with self._blockchainLock:
            print('add new block into blockchain: ', block.hash)
            # if block.prevHash == self._blockchain[-1].hash:
            self._blockchain.append(block)
            print('after add new block, blockchain is in height: ',
                  len(self._blockchain))
            self.state.change_from_authorizations(block.authorizations)
            self.state.change_from_operations(block.operations)

            self.authorizationPool.delete_authorizations(block.authorizations)
            self.operationPool.delete_operations(block.operations)
        # else:
        #     logging.error("chain.py line 130: the new block does not match the blockchain")
        #     return False
        return True

    def valid(self):
        with self._blockchainLock:
            if self._blockchain[0] != self._genesis_block:
                logging.warning(
                    'the head of blockchain should be GENESIS_BLOCK')
                return False
            for i in range(1, len(self._blockchain)):
                if self._blockchain[i].get_prev_hash() != self._blockchain[
                        i - 1].hash:
                    logging.warning(
                        f'the {i}th block does not match the previous one')
                    return False
            return True

    def contain_block(self, block_hash):
        with self._blockchainLock:
            for block in self._blockchain:
                if block.hash == block_hash:
                    return True
            return False

    def to_json(self):
        chain_json = {'blockchain': []}
        for block in self._blockchain:
            chain_json['blockchain'].append(block.to_json())
        return chain_json

    def from_json(self, chain_json):
        required = ['height', 'blockchain']
        if not all(k in chain_json for k in required):
            logging.warning(f'value missing in {required}')
            return False

        if not isinstance(chain_json['height'], int):
            logging.warning("height should be type<int>")
            return False
        if not isinstance(chain_json['blockchain'], list):
            logging.warning("blockchain should be type<list>")
            return False

        chain = []
        for block_json in chain_json['blockchain']:
            new_block = Block()
            if not new_block.from_json(block_json):
                return False
            chain.append(new_block)
        self._blockchain = chain
        return True

    def chain_store(self, chain_path='BlockchainFile/chain.json'):
        with open(chain_path, 'w') as chain_file:
            chain_file.write(
                json.dumps(self.to_json(), indent=4, separators=(',', ':')))
        return

    def chain_load(self, chain_path='BlockchainFile/chain.json'):
        with open(chain_path, 'r') as chain_file:
            chain_json = chain_file.read()
            self.from_json(json.loads(chain_json))
        return

    def add_authorization(self, authorization):
        input_address = authorization.input_address
        input_account = self.state.get_account_from_address(input_address)
        if input_account is None:
            logging.warning('chain.py line 219: no such input_account')
            return False
        if input_account.nonce > authorization.nonce:
            logging.warning(
                'chain.py line 222: the nonce in authorization expire')
            return False
        return self.authorizationPool.add_authorization(authorization)

    def add_operation(self, operation):
        return self.operationPool.add_operation(operation)

    def get_authorization_pool(self):
        return self.authorizationPool

    def get_operation_pool(self):
        return self.operationPool