-
Notifications
You must be signed in to change notification settings - Fork 12
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
Service transactions consume account nonces! #97
Comments
Unfortunately, this won't help us because there can be a case when validator had reported but after that was removed from the set of validators (at the end of staking epoch). In that case,
It seems each validator needs to have three addresses: 1. Mining address. This address could be used to call As far as I understand, calling those functions in the same block with correct 2. Reporting address. This address could be used only for calling With 3. Staking address. This address could be used by validator for calling The only caveat here is about |
Another question here: we expect that It seems that an ideal solution for this whole situation would be to call At the moment |
Good idea! Three addresses would solve the issue, I think. 👍
Yes, I think so. The node would just need to keep count of the transactions it sent.
If the validator somehow manually creates a transaction using the reporting address, then they (the human) misbehaved, and thus cause their node to misbehave (fail to make another report). Not sure if we need to handle this case explicitly.
I'd say it's basically impossible, for the reason you gave above: the node may try to make the report towards the end of the staking epoch, and never create a block again. So it would be unable to report as the system, even if we put the information into the block header. (Except if it sent it to another validator and that validator would make the system call—but that would essentially mean duplicating transaction and queue functionality.)
Right, we need to make the gas price zero there (and whitelist it, if it isn't already). |
Let's assume that we have some malicious validator The validator Assume, that in such a case the validator Then, the malicious validator So, I think this might be a problem. However, on the other hand, the malicious validator Also, instead of that scheme, the friends of the malicious validator This problem seems to be mostly related to a 51% attack. What do you think?
Let's assume that the current staking epoch finishes at the block Assume that some malicious validator Also assume that we have some honest validator It seems that the regular transaction Could you check Parity code to confirm this is true? In the case of the system call for the situation above the
Yes, we have already done it in #59 and the validators' addresses are whitelisted by |
And again: is it really possible in Parity code for those regular transactions of |
If we're going to implement the above scheme of three addresses, maybe we could use two addresses instead, joining the In this case, we could take a value of To guarantee that the transactions of commitHash/revealSecret/emitInitiateChange will succeed, we could replace Besides that, we could allow the The main questions here are:
|
I'm not worried about that scenario: If someone is malicious they might as well modify their node's source code so that the node never reports their friends. There's no point differentiating between the human and the software here: If a validator is malicious, we need to simply assume that their node does whatever they want it to do.
It depends on what you mean by "on the block
It is possible to pick any nonce for a transaction you make. After that, the usual rules apply, i.e. transactions can only be added to a block at a point where their nonce matches the sender's account nonce.
The problem is: With the current code, we know exactly which block a transaction with
So I guess my answer to both your questions is: "Yes, but terms and conditions apply." |
Maybe then it is possible to call I saw that Thus, when someone misbehaves, as far as I understand, all other nodes know about it and call
I agree, but I wrote that maybe we could take an incremented value of Is it possible to take that incremented
Seems the same problem still exists for this method 👆 :
Or I missed something? |
I'm not sure what you mean by that: If we discover misbehavior in block
I agree, for that objective kind of misbehavior, we should be able to use system calls.
Yes, I think that's essentially the last bullet point in my comment above. It's just a bit difficult to track both the pending transactions and the other calls, and get the nonces right in all cases.
I don't think so: We'd also send our malice reports as transactions to other nodes, so even if we don't author another block, someone else would probably commit our transactions. |
Got it.
That would be great. |
Sorry for the back and forth, but I still see huge problems with the global nonce counter, especially if a validator is running more than one node. I think it's more robust to keep a cache of malice reports, i.e. But we'd need a similar getter for benign reports: If a contract doesn't use benign reports at all, |
Sorry, but I don't understand what exactly changes you need to be implemented in contracts for At the moment, Also, |
Right, sorry! Then what I should have said above is that we need to check whether that return value contains our own mining key, and if it does, we can remove our malice report from the cache. Regarding benign reports: If we don't remove them entirely from the code, we should add a |
Let's just comment out calling |
Is this still actual? (your very first comment 👆) |
For this point, for each list entry we must firstly check if we already called We could use |
No, you're right. I updated it.
I'd actually just resend all the pending reports periodically, and restart with the current account nonce. Yes, this will replace some of the other transactions that might be in flight, but we'd just keep retrying until they get through.
Yes, that's exactly what I'm proposing: Once that returns our own mining address, we can remove the tuple from the cache and don't need to call |
Is this something I can begin working on? Or is there something else I
should be working on?
…On Wed, Feb 13, 2019, 2:49 PM Andreas Fackler ***@***.*** wrote:
Is this still actual?
No, you're right. I updated it.
If we did, we shouldn't call reportMalicious for that tuple again because
this will increment the nonce
I'd actually just resend *all* the pending reports periodically, and
restart with the current account nonce. Yes, this will replace some of the
other transactions that might be in flight, but we'd just keep retrying
until they get through.
We could use maliceReportedForBlock for that checking
Yes, that's exactly what I'm proposing: Once that returns our own mining
address, we can remove the tuple from the cache and don't need to call
reportMalicious with it again.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#97 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AGGWB7XZ_BHMlyyq352UAf5jmKJ-wKlbks5vNGxLgaJpZM4a2mq4>
.
|
Maybe I misunderstood this point:
Does this happen in Imagine that we have 2 tuples in the list and the current nonce is Let's assume that for the first tuple When you call When right after that you try to call |
I think I'd actually call it in But I think what you're describing can always happen: We simply can't control how long it takes from the time where we create a transaction with the That's why we'll just periodically retry: If one of the transactions fails to be committed, an equivalent transaction, with the same Also, in your example, we'd at some point call |
Yes, you can! 👍 |
@DemiMarie: Feel free to start working on the report retry logic (the checkboxes at the end of the first comment). @varasev is already working on the contracts themselves, to separate mining and staking accounts. |
Is Let's review that situation I described above: So, we have 2 tuples in the list and the current nonce is Let's assume that for the first tuple You can't call When right after that you try to call Then, you handle the list again and call And this situation is repeated until That's why I suggest to use |
But I agree with your suggestion: Let's filter the list using |
Okay. |
Just to make sure the network starts and works fine with the changed posdao-contracts. Related to poanetwork/parity-ethereum#97 and poanetwork/posdao-contracts@d0214e9
Let's add this to the description in the very first comment above for the point |
@DemiMarie: I updated the description; let's reduce the number of redundant reports that way. ⬆️ |
@afck Do we get a convenient callback when a block is finalized? If not, can we just check in |
I don't think there's a callback for that, and I doubt that I think it would be reasonable to remove the entries from the cache earlier (in |
@DemiMarie: Please test your changes with #101 when they're ready. Unfortunately that's a bit cumbersome because obviously we don't want to merge the It would be best to even do two separate test runs in the end, I think: One with the |
Done in #129. |
There are currently at least three sources of transactions for a validator's account:
Whenever one of these is created while another one is still in flight (hasn't been added to a block), they will share the same account nonce and one of them will get rejected.
So firstly, we need to make sure malice reports are handled the same way as the transactions inon_prepare_block
. Instead of being added to the queue as transactions, the node could collect its own pending malice reports and then add them as a transaction as part ofon_prepare_block
(where the account nonce counter is incremented with each new transaction).So firstly, we need to keep count of the number of malice reports that are in flight, to give them distinct nonces. Whenever we author a block, we should push all our own pending malice reports onto it before thecommitHash
/emitInitiateChange
/… calls inon_prepare_block
.Secondly, we should either:
Or we could not use transactions for the nodes' own contract calls at all: Instead, the nodes would put the relevant information into the block header and the contracts would be called implicitly by the system. We would need to find a way around the problem that those can't emit events, forInitiateChange
. We'd also have to handle proper validation of the header data ourselves.Edit:
So the current plan is the following.When making areportMalicious
/reportBenign
transaction, don't use the current account nonce, but keep count of which nonces we already used (in any transaction, not just a report). Both calls useClient::transact
, to which we could just add another optional parameter that would be used as the nonce instead of the "current" one.Either make sure that these transactions stay in our queue until they are confirmed, and find a way to retrieve our own pending transactions (where the sender is the mining address) from the queue; or keep a separate queue with our own transactions.InAuthorityRound::on_prepare_block
, first add all our own pending transactions, in the correct order. (Nonces must always be consecutive!) Then increase the nonce accordingly before adding the randomness and validator set calls. (Should the "global" nonce count be incremented inon_prepare_block
or only after that block has been sealed and added? Probably it has to be the latter, becauseon_prepare_block
is called way too often.)Edit: Or we just keep a list of malice reports, i.e.
(validator, block_number)
tuples inAuthorityRound
. We'd periodically create new transactions with the current nonce for them, knowing that some of them might fail. So:(Address, BlockNumber)
tuples toAuthorityRound
(or the validator set?), possibly with some timeout?(validator, block_number)
in the list for whichmaliceReportedForBlock(validator, block_number)
called on the latest block does not contain our own mining key.maliceReportedForBlock(validator, block_number)
does contain our own mining key.(Let's not do this for benign reports yet. Possibly add a
TODO
to the code to either remove them entirely or later treat them the same way as malice reports.)The text was updated successfully, but these errors were encountered: