Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functional tests for floresta-wire/chain_selector #180

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

lla-dane
Copy link
Contributor

Changes made: floresta-wire/p2p_wire/tests

Simulated a peer to take in requests from the Chain Selector node instance, and then send in the appropriate responses to the node.

@lla-dane lla-dane force-pushed the test/node-cs branch 3 times, most recently from bd3206e to d0055b1 Compare June 28, 2024 06:33
@lla-dane lla-dane force-pushed the test/node-cs branch 2 times, most recently from 8c4de42 to 6f8e3da Compare June 29, 2024 14:54
@lla-dane
Copy link
Contributor Author

lla-dane commented Jul 1, 2024

@Davidson-Souza I think I am done with chain-selector here. Please review this.

crates/floresta-wire/src/p2p_wire/chain_selector.rs Outdated Show resolved Hide resolved
crates/floresta-wire/src/p2p_wire/mod.rs Show resolved Hide resolved
crates/floresta-wire/src/p2p_wire/tests/chain_selector.rs Outdated Show resolved Hide resolved
)
.await;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add cases where a block is actually invalid?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please correct if I am going wrong here, When the chain selector node is run, it first achieves the best block headers from all its peers. Then if pow_fraud_proofs is enabled the check_tips function is executed, and all the peers have to give their best utreexo states, and if they differ then someone is lying.

The only time the whole UtreexoBlock data is used in .update_acc function where I think we calculate the immediate next utreexo acc on our own codebase.

I couldn't find any code in chain_selector.rs where the block is actually validated according to the consensus rules.

Maybe the tests for validity of blocks could be done in the running_node or the sync_node. I am a little confused here.

Copy link
Contributor Author

@lla-dane lla-dane Jul 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking, like 3 different testing environments could be made, just like for chain_selector is done here, for running_node and sync_node and covering all their functionalities in their respective test codebases.

So I think each and every function in chain_selector.rs is tested along, except .is_our_chain_invalid here :

    async fn check_tips(&mut self) -> Result<(), WireError> {
        ...
        ...
        ...
        
            // if we have more than one tip, we need to check if our best chain has an invalid block
            tips.remove(0); // no need to check our best one
            for tip in tips {
                self.is_our_chain_invalid(tip).await?;
            }

            return Ok(());
        }

        ...
        ...
        
        Ok(())
    }

because I could not figure out how to create different tips in our chain, I need a little help there.

After this, maybe I could move forward with writing tests for the other two remaining nodes ?? @Davidson-Souza your thoughts ?

Copy link
Collaborator

@Davidson-Souza Davidson-Souza Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function will check if our current best chain has an invalid block.

I was thinking, like 3 different testing environments could be made, just like for chain_selector is done here, for running_node and sync_node and covering all their functionalities in their respective test codebases.

I agree

because I could not figure out how to create different tips in our chain, I need a little help there.

By having peers following different tips. They need to be forks, no only lag a few blocks. When poke_peers is called, it'll download the other tips.


let mut peers = Vec::new();

for _ in 0..10 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In some cases where the tip is different, could you please make them an actual fork? Like:

1 -> 2 -> 3
  \-> 2a

on regtest you can easily create those with invalidateblock. Just mine a couple of blocks, take the headers and roots. Then you invalidate some in the middle and mine some more

@lla-dane
Copy link
Contributor Author

lla-dane commented Jul 12, 2024

I have a doubt here @Davidson-Souza, in this function we are requesting the utreexo block from peer1 always, but what if peer1 is the liar and peer2 is honest. If the honesty of both the peers is in question how can we rely on only one of them to get the UtreexoBlock and judge who is honest. I am a little confused here -_-

    async fn find_who_is_lying(
        &mut self,
        peer1: PeerId,
        peer2: PeerId,
    ) -> Result<Option<PeerId>, WireError> {
    
    ...
    ...
    ...
    
      let block = self.chain.get_block_hash(fork + 1).unwrap();
      self.send_to_peer(peer1, NodeRequest::GetBlock((vec![block], true)))
          .await?;

      let NodeNotification::FromPeer(_, PeerMessages::Block(block)) =
          self.node_rx.recv().await.unwrap()
      else {
          return Ok(None);
      };

      let acc1 = self.update_acc(agreed, block, fork + 1)?;
      let peer1_acc = Self::parse_acc(peer1_acc)?;
      let peer2_acc = Self::parse_acc(peer2_acc)?;

      if peer1_acc != acc1 && peer2_acc != acc1 {
          return Ok(None);
      }

      if peer1_acc != acc1 {
          return Ok(Some(peer1));
      }

      Ok(Some(peer2))
    }

@Davidson-Souza
Copy link
Collaborator

@lla-dane the block we ask for is the last one they agree on. Also, if they send an invalid proof, this is make self.update_acc(agreed, block, fork + 1)? error. If we have an error here, we should mark this peer as the one lying?

@lla-dane
Copy link
Contributor Author

@lla-dane the block we ask for is the last one they agree on. Also, if they send an invalid proof, this is make self.update_acc(agreed, block, fork + 1)? error. If we have an error here, we should mark this peer as the one lying?

Oh, Okay, right, I thought we ask for the block they disagreed on, got a little confused. Thanks !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants