Cosmos-sdk: x/auth: Make the only requirement on sequence number be increasing

Created on 14 Jul 2018  Â·  9Comments  Â·  Source: cosmos/cosmos-sdk

Summary

Currently we require each sequence number increment by 1. (e.g. if the next sequence number is 10, I can't enter 20 as my sequence number, only 10)

Problem Definition


Suppose I just want to broadcast my own tx, but don't have access the most recent state / am unsure if I've sent a couple txs since my last one. I could just increment my sequence number by like 50, broadcast it, and reasonably assume it to be able to go on-chain.

The issue with us now no longer incrementing by one is that conceivably we have to worry about someone maxing out their sequence number. I'm conflicted on what to do in that situation. The option I like best is that we drop replay protection for you if you've maxed out you're sequence number. (You presumably send your money to a new address you own in this scenario, so replay isn't a huge concern) This means that you can't get locked out of your account due to sequence number (whereas you currently can, its just infeasible to get there)

Another option (which I like less), only allow the sequence number to by in the range [current sequence + 1, current sequence + 100]. The 100 being arbitrary, but up to governance to set. This means that one would still have to send an infeasible amount of txs to max out their sequence number (and be effectively locked out of their account). (approx 2^58 txs incrementing by 100 each time)

Proposal


Change wherever we check sequence number from being an equality check to being a greater than check. (I believe this check is an auth) Add an or statement to ensure that the sequence number isn't the max value of an integer. (We drop replay protection in that setting)


For Admin Use

  • [ ] Not duplicate issue
  • [x] Appropriate labels applied
  • [ ] Appropriate contributors tagged
  • [ ] Contributor assigned/self-assigned
proposal

Most helpful comment

It's worth thinking about how we can improve account and sequence structure but I don't think we should do this right now.

"I dont know the state and dont want to check so I'm just going to do something that seems good enough" does not seem like a solid approach for engaging with cryptographic protocols, and isn't something we should encourage at the protocol level, so I'm not a big fan of the particular approach being proposed here.

Folks have been dealing with this in ethereum for a long time and it seems fine and well understood. Surely improvements could be made, but I'm not sure if this is the right way, or that we should do it now. If anything, I would prefer to allow a new kind of account that uses a random sequence say, but pays for the extra cost of having to store / lookup that value.

Anyways, I'm going to close this for now. We should try to move these larger protocol design questions to the forum and keep github focused on the immediate needs of the software. Please feel free to pick this up there.

Thanks guys!

All 9 comments

Interesting thought @ValarDragon. Regarding your example, would the user simply not be able to query the latest state if they forget (command line, API, etc..)?

I agree thought that if we do allow arbitrary values, they should be within a small-ish range.

I'd like to be able to broadcast a Tx without needing the latest state. (I would just need a vague notion of approximately where my sequence number is)

A more compelling reason, which i just though of is the following. Suppose I'm sending out a ton of txs b/c I'm doing something automated. Txs 1-10 go through, tx 11 gets dropped. (Network connectivity issues) 12-20 go through. 12-20 can't be included in a block, since 11 wasn't there. This is a bad situation for my bot that needed high throughput.

I agree thought that if we do allow arbitrary values, they should be within a small-ish range.

I went back and forth on this point a bit before posting the issue. (Actually changed my mind after I posted it, if you see the edits haha)

My thinking is that its cleaner if we drop replay protection on maxed account sequence number. (Its something I think we should do anyway, just right now it seems entirely unfeasible to occur) With that in mind, allowing any increasing sequence number is cleaner, and takes less computation. (Therefore each tx in principle requires less gas)

I don't like the arbitraryness of fixed sequence number within a range, but I can't think of a real use case where that becomes a problem.

I see...interesting. I could see how having the range would add some unnecessary and potentially ugly complexity. Do we have to worry about any attack vectors here?

Good point. Noone can make you sign a tx you didn't agree to. So the only concerns would be applications that set your sequence number too high, so that you would hit the 2**64 limit, and then lose replay protection. We can't rely on this being clear from looking at an applications source code, since you can do super cool obfuscated stuff with metaprogramming. (Espec. with closed source applications)

The threat model is something like a ledger app that just doesn't display the sequence number when asking you to sign. (Something that can query your privkey) Any app that holds your private key already has the ability to do much worse than this. Anything that queries your privkey to sign though should display the entire sequence number for you to confirm. If the threat model is the adversary wrote the code you use to display the tx when querying the privkey, then this is all a moot point as they could just display the tx you want, and send all the funds elsewhere. This is just a slightly more subtle attack.

I guess we need to agree on if were fine with this more subtle attack vector existing on tx display code. I think its fine, since they could already do the more obvious "send all funds to my own acct instead of what I displayed" trick.

If we're not fine with it, I think we should definitely use ranges. (Every thing else that I could think of had more complexity + another arbitrary parameter)

Suppose I'm sending out a ton of txs b/c I'm doing something automated.

In most cases, one multi-Msg transaction is probably a better solution, but I agree that we should still change the sequence logic.

I guess we need to agree on if were fine with this more subtle attack vector existing on tx display code. I think its fine, since they could already do the more obvious "send all funds to my own acct instead of what I displayed" trick.

This is an attack that already requires a great deal of access, but I still think it's worth worrying about - users are well-trained to read destination addresses on Ledger screens, less so sequence numbers. If I can trick you once into signing with a maximum sequence, I can then replay that transaction any number of times.

If we're not fine with it, I think we should definitely use ranges. (Every thing else that I could think of had more complexity + another arbitrary parameter)

Agreed, the range doesn't even really need to be a governance parameter, it can just be a constant (say 100) to avoid store reads. It's unlikely anyone would ever need more than that - if they did, it could be changed by a SoftwareUpgradeProposal.

Fair point. I propose that we make the constant 256. (There isn't a solid defense for this number in particular, it is just an arbitrary parameter)

The security then becomes 2^56 txs signed on such a malicious display device.

@sunnya97 made a good point.
You may want to be able to guarantee that txs are processed in a certain order. However that is still possible here (as noted by @cwgoes). If tx 1 has sequence number 0, then give tx 2 has sequence number 1 + max sequence_num_increment, which will guarantee tx 1 must come before tx 2.

But that would only work if the increment was done by sequence_num_increment, right? What if the increment was done by a small factor?

It's worth thinking about how we can improve account and sequence structure but I don't think we should do this right now.

"I dont know the state and dont want to check so I'm just going to do something that seems good enough" does not seem like a solid approach for engaging with cryptographic protocols, and isn't something we should encourage at the protocol level, so I'm not a big fan of the particular approach being proposed here.

Folks have been dealing with this in ethereum for a long time and it seems fine and well understood. Surely improvements could be made, but I'm not sure if this is the right way, or that we should do it now. If anything, I would prefer to allow a new kind of account that uses a random sequence say, but pays for the extra cost of having to store / lookup that value.

Anyways, I'm going to close this for now. We should try to move these larger protocol design questions to the forum and keep github focused on the immediate needs of the software. Please feel free to pick this up there.

Thanks guys!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ValarDragon picture ValarDragon  Â·  3Comments

rigelrozanski picture rigelrozanski  Â·  3Comments

rigelrozanski picture rigelrozanski  Â·  3Comments

adrianbrink picture adrianbrink  Â·  3Comments

fedekunze picture fedekunze  Â·  3Comments