Only allow designated participants to send transactions

This commit is contained in:
Luke Parker
2023-04-12 12:42:23 -04:00
parent be947ce152
commit 8c8232516d
6 changed files with 99 additions and 47 deletions

View File

@@ -12,19 +12,25 @@ use crate::{
tests::{ProvidedTransaction, SignedTransaction, random_provided_transaction},
};
fn new_blockchain<T: Transaction>() -> ([u8; 32], Blockchain<T>) {
fn new_genesis() -> [u8; 32] {
let mut genesis = [0; 32];
OsRng.fill_bytes(&mut genesis);
genesis
}
let blockchain = Blockchain::new(genesis);
fn new_blockchain<T: Transaction>(
genesis: [u8; 32],
participants: &[<Ristretto as Ciphersuite>::G],
) -> Blockchain<T> {
let blockchain = Blockchain::new(genesis, participants);
assert_eq!(blockchain.tip(), genesis);
(genesis, blockchain)
blockchain
}
#[test]
fn block_addition() {
let (genesis, mut blockchain) = new_blockchain::<SignedTransaction>();
let genesis = new_genesis();
let mut blockchain = new_blockchain::<SignedTransaction>(genesis, &[]);
let block = blockchain.build_block(HashMap::new());
assert_eq!(block.header.parent, genesis);
assert_eq!(block.header.transactions, [0; 32]);
@@ -35,7 +41,8 @@ fn block_addition() {
#[test]
fn invalid_block() {
let (genesis, blockchain) = new_blockchain::<SignedTransaction>();
let genesis = new_genesis();
let blockchain = new_blockchain::<SignedTransaction>(genesis, &[]);
let block = blockchain.build_block(HashMap::new());
@@ -55,10 +62,36 @@ fn invalid_block() {
}
let key = Zeroizing::new(<Ristretto as Ciphersuite>::F::random(&mut OsRng));
let tx = crate::tests::signed_transaction(&mut OsRng, genesis, &key, 0);
// Not a participant
{
// Manually create the block to bypass build_block's checks
let block = Block::new(
blockchain.tip(),
&ProvidedTransactions::new(),
HashMap::from([(tx.hash(), tx.clone())]),
);
assert_eq!(block.header.transactions, merkle(&[tx.hash()]));
assert!(blockchain.verify_block(&block).is_err());
}
// Run the rest of the tests with them as a participant
let blockchain = new_blockchain(genesis, &[tx.1.signer]);
// Re-run the not a participant block to make sure it now works
{
let block = Block::new(
blockchain.tip(),
&ProvidedTransactions::new(),
HashMap::from([(tx.hash(), tx.clone())]),
);
assert_eq!(block.header.transactions, merkle(&[tx.hash()]));
blockchain.verify_block(&block).unwrap();
}
{
// Add a valid transaction
let tx = crate::tests::signed_transaction(&mut OsRng, genesis, &key, 0);
let mut block = blockchain.build_block(HashMap::from([(tx.hash(), tx.clone())]));
assert_eq!(block.header.transactions, merkle(&[tx.hash()]));
blockchain.verify_block(&block).unwrap();
@@ -79,7 +112,6 @@ fn invalid_block() {
{
// Invalid signature
let tx = crate::tests::signed_transaction(&mut OsRng, genesis, &key, 0);
let mut block = blockchain.build_block(HashMap::from([(tx.hash(), tx)]));
blockchain.verify_block(&block).unwrap();
block.transactions[0].1.signature.s += <Ristretto as Ciphersuite>::F::ONE;
@@ -93,11 +125,14 @@ fn invalid_block() {
#[test]
fn signed_transaction() {
let (genesis, mut blockchain) = new_blockchain::<SignedTransaction>();
let genesis = new_genesis();
let key = Zeroizing::new(<Ristretto as Ciphersuite>::F::random(&mut OsRng));
let tx = crate::tests::signed_transaction(&mut OsRng, genesis, &key, 0);
let signer = tx.1.signer;
assert_eq!(blockchain.next_nonce(signer), 0);
let mut blockchain = new_blockchain::<SignedTransaction>(genesis, &[signer]);
assert_eq!(blockchain.next_nonce(signer), Some(0));
let test = |blockchain: &mut Blockchain<SignedTransaction>, mempool: HashMap<_, _>| {
let mut hashes = mempool.keys().cloned().collect::<HashSet<_>>();
@@ -126,7 +161,7 @@ fn signed_transaction() {
// Test with a single nonce
test(&mut blockchain, HashMap::from([(tx.hash(), tx)]));
assert_eq!(blockchain.next_nonce(signer), 1);
assert_eq!(blockchain.next_nonce(signer), Some(1));
// Test with a flood of nonces
let mut mempool = HashMap::new();
@@ -140,12 +175,12 @@ fn signed_transaction() {
mempool.insert(tx.hash(), tx);
}
test(&mut blockchain, mempool);
assert_eq!(blockchain.next_nonce(signer), 64);
assert_eq!(blockchain.next_nonce(signer), Some(64));
}
#[test]
fn provided_transaction() {
let (_, mut blockchain) = new_blockchain::<ProvidedTransaction>();
let mut blockchain = new_blockchain::<ProvidedTransaction>(new_genesis(), &[]);
let tx = random_provided_transaction(&mut OsRng);
let mut txs = ProvidedTransactions::new();