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
[HackerOne-2311934] Verify transactions prior to speculation #2376
Conversation
FYI when trying to compile this into snarkOS for testing I get the error:
|
As for the object safety issue, it's not ideal, but we could work around it by having 2 versions of |
synthesizer/src/vm/finalize.rs
Outdated
_ => { | ||
let rngs = (0..candidate_transactions.len()).map(|_| StdRng::from_seed(rng.gen())).collect::<Vec<_>>(); | ||
// Verify the transactions and collect the error message if there is one. | ||
let checked_transactions: Vec<_> = cfg_into_iter!(candidate_transactions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment still applies: AleoHQ/snarkOS#3083 (comment)
I was able to kill all the nodes with some big batch proposals in a test suite.
With the system allocator (which is heavier than jemalloc):
- The maximum RAM to verify a 1M constraint program is 2GB.
- The maximum RAM for a 1 or 31-depth 1M constraint call execution is negligible, but to be safe we could assume 10MB
A thorough but brittle approach would be to estimate memory usage based on the number of constraints. But an easier setup would be a separate deploy and an execute verification maximum:
const MAX_PARALLEL_DEPLOY_VERIFICATIONS = 5;
const MAX_PARALLEL_EXECUTE_VERIFICATIONS = 1000;
let (deploys, executions) = candidate_transactions.partition(|tx|tx.is_deploy());
let deploy_iter = deploys.chunks(MAX_PARALLEL_DEPLOY_VERIFICATIONS);
let execution_iter = executions.chunks(MAX_PARALLEL_EXECUTE_VERIFICATIONS);
let tx_iter = deploy_iter.chain(execution_iter);
while let Some(txs) = tx_iter.next() {
cfg_into_iter!(txs.zip(rngs).map(|| ...verify...)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this different from the current approach of transaction verification on the current mainnet
branch in check_next_block
?
Are you saying that fundamentally the verification logic should be updated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that piece of parallel verification logic was prone to the same vulnerability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've implemented the OOM fix here - #2387. If it is approved, we can apply the change to this PR as well.
@vicsn Similar to how we use a |
Thank you, will test it and report back. |
Although both of these issues can be resolved with a single fix, in my opinion, they could be considered separate reports. The snarkOS PR AleoHQ/snarkOS#3104, should address the Fee finding, and this PR should address both of the findings (for added safety). |
Thank you! @raychu86 |
95c7e70
to
aa6811e
Compare
b7f1dbc
to
f83d18b
Compare
Motivation
This PR performs transaction verification in
VM::speculate
and aborts the transactions that are invalid. This is necessary because in snarkOS when we construct subdags, we do not validate transmissions found in proposals, which could lead to block production halting if there are malicious validators. With the new change, we can eliminate the invalid transactions prior to block production and ensure thatBlock::check_next_block
doesn't error.Note that now we perform transaction verification prior to creating the block itself, rather than just before the block is about to be added to storage. Because of the transaction partial verification cache, we do not perform duplicate verification on the execution/deployment, but we do have to perform the (cheaper) uniqueness checks twice.
Related PRs
This PR is related to AleoHQ/snarkOS#3104.
And should replace: AleoHQ/snarkOS#3083 and AleoHQ/snarkOS#3098.
This should fix: AleoHQ/snarkOS#2991 and AleoHQ/snarkOS#2990.