def apply_witness_tx( self, block: BamiBlock, witness_tx: Tuple[int, ChainState] ) -> None: state = witness_tx[1] state_hash = take_hash(state) seq_num = witness_tx[0] if not self.should_witness_chain_point(block.com_id, block.public_key, seq_num): # This is invalid witnessing - react raise InvalidWitnessTransactionException( "Received invalid witness transaction", block.com_id, block.public_key, seq_num, ) self.state_db.add_witness_vote( block.com_id, seq_num, state_hash, block.public_key ) self.state_db.add_chain_state(block.com_id, seq_num, state_hash, state) chain_id = block.com_id if self.tracked_blocks.get(chain_id): for block_dot, tracked_block in self.tracked_blocks[chain_id].items(): if ( block_dot[0] <= seq_num and state.get(shorten(tracked_block.public_key)) and state.get(shorten(tracked_block.public_key)) == (True, True) ): self.update_risk(chain_id, block.public_key, block_dot[0])
def _store_status_update(self, dot: Dot, chain_id: bytes): seq_num = dot[0] status = self.get_last_peer_status(chain_id=chain_id) state_hash = take_hash(status) if not self.peer_statuses[chain_id].get(seq_num): self.peer_statuses[chain_id][seq_num] = dict() self.peer_statuses[chain_id][seq_num][state_hash] = status self.prefered_statuses[chain_id][seq_num] = state_hash
def add_chain_state(self, chain_id: bytes, seq_num: int, state_hash: bytes, state: ChainState) -> None: calc_hash = take_hash(state) if calc_hash != state_hash: raise InconsistentStateHashException("State hash not equal", state_hash, calc_hash) if not self.peer_statuses[chain_id].get(seq_num): self.peer_statuses[chain_id][seq_num] = dict() self.peer_statuses[chain_id][seq_num][state_hash] = state
def test_add_chain_state(self): chain_id = self.spender seq_num = 1 state = ChainState({b"t1": (True, True)}) state_hash = take_hash(state) self.state.add_chain_state(chain_id, seq_num, state_hash, state) self.state.prefered_statuses[chain_id][seq_num] = state_hash assert self.state.peer_statuses[chain_id][seq_num][state_hash] == state assert self.state.get_closest_peers_status(chain_id, 1) == (1, state) assert not self.state.get_closest_peers_status(chain_id, 2)
def test_invalid_chain_state(self): # Add chain state with inconsistent hash chain_id = self.spender seq_num = 1 state = ChainState({b"t1": (True, True)}) state_hash = b"fake_hash" real_hash = take_hash(state) with pytest.raises(InconsistentStateHashException): self.state.add_chain_state(chain_id, seq_num, state_hash, state) self.state.add_chain_state(chain_id, seq_num, real_hash, state) assert not self.state.get_closest_peers_status(chain_id, 1)