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

GetCandidates is prone to Denial of Service #2683

Closed
shargon opened this issue Apr 4, 2022 · 15 comments
Closed

GetCandidates is prone to Denial of Service #2683

shargon opened this issue Apr 4, 2022 · 15 comments

Comments

@shargon
Copy link
Member

shargon commented Apr 4, 2022

If there are 1024 or more candidates registered and the smart contract call GetCandidates a denial of service will occur.

public (ECPoint PublicKey, BigInteger Votes)[] GetCandidates(DataCache snapshot)

@Jim8y
Copy link
Contributor

Jim8y commented Apr 4, 2022

A lot of issues are caused by this ToArray() or ToJson(), is that possible to add a maximum size limit to it?

@shargon
Copy link
Member Author

shargon commented Apr 5, 2022

We should limit the return to the first X candidates

@ixje
Copy link
Contributor

ixje commented Apr 6, 2022

We should limit the return to the first X candidates

Isn't the point of this method that you can get ALL candidates. Perhaps we need a GetCandidatesCount() and add a start_position and count (with an upper limit) to GetCandidates.

Alternatively, change the way registration works so you can limit the max stored candidates. E.g. You can register as candidate, you then have t time to collect sufficient votes to get in the top 1024 (assuming the top is filled). If you fail to make the top, your registration will be removed.

@Jim8y
Copy link
Contributor

Jim8y commented Apr 6, 2022

If we can limit the maximum size of toarray(), then problems caused with toarray will be solved and prevented. If we just do find one solve one, it might be endless.

@roman-khimov
Copy link
Contributor

Perhaps we need a GetCandidatesCount() and add a start_position and count (with an upper limit) to GetCandidates.

System.Iterator.Next? If we're changing this API of course which is a bit weird with mainnet running.

@ixje
Copy link
Contributor

ixje commented Apr 6, 2022

I guess it comes down to being able to update native contracts to begin with.

@devhawk
Copy link
Contributor

devhawk commented Apr 6, 2022

Perhaps we need a GetCandidatesCount() and add a start_position and count (with an upper limit) to GetCandidates.

System.Iterator.Next? If we're changing this API of course which is a bit weird with mainnet running.

Updating GetCandidates to return an iterator would not solve the problem entirely. RpcServer only returns the first RpcServerSettings.MaxIteratorResultItems values from the iterator and provides no mechanism for the caller to specify how many results to return or to skip. Using an iterator would effectively limit the caller to getting the first 'MaxIteratorResultItems` which defaults to 100.

More info in neo-project/neo-modules#629 and neo-project/neo-devpack-dotnet#647

@shargon
Copy link
Member Author

shargon commented Apr 7, 2022

I made a possible solution for it, please check it #2686

@erikzhang
Copy link
Member

I think returning an iterator is the best solution.

@devhawk
Copy link
Contributor

devhawk commented Apr 21, 2022

I think returning an iterator is the best solution.

Agree 100%, as long as we provide a mechanism for RpcClient to iterator to access the full iterated collection, not just first MaxIteratorResultItems

@erikzhang
Copy link
Member

MaxIteratorResultItems is configurable. And we can solve the RPC issue in the future.

@shargon
Copy link
Member Author

shargon commented Apr 21, 2022

I think returning an iterator is the best solution.

New syscall?

@devhawk
Copy link
Contributor

devhawk commented Apr 22, 2022

MaxIteratorResultItems is configurable. And we can solve the RPC issue in the future.

Not by the caller

@shargon
Copy link
Member Author

shargon commented Apr 27, 2022

I think returning an iterator is the best solution.

For the new syscall is ok, but for the previous one, just limit?

@erikzhang
Copy link
Member

but for the previous one, just limit?

Both are fine for me, limit it, or wait until it exceeds 2048 items to automatically throw an exception.

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

No branches or pull requests

6 participants