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

[Wallet] Add support for 8 digits verification codes #5925

Merged
merged 9 commits into from
Nov 25, 2020

Conversation

i1skn
Copy link
Contributor

@i1skn i1skn commented Nov 19, 2020

Description

This PR implements short verification codes. See the demo below.
To enable this feature we need all the validators to support https, which is not the case atm, so this feature are disabled by feature flag.

Short code

Essentially, short code, which user receives consist of two parts: prefix and security code (e.g. 12345678: 1 - prefix, 2345678 - security code).

We use prefix to identify which issuer has sent the code. Because we can not store persistent mapping of prefix<>issuer on the client side (will be gone after reinstall), we are doing the following:

  • Set prefix to issuer's address mod 10 ([0,9]) and pass it with reveal request.
  • When we receive a short code with a prefix back, we create a list of validators which map to the same prefix.
  • We send security code to obtain attestation code to all issuers from the previous step
  • One of them should return a full attestation code, all others should fail.

This approach allows us to scale for more than 10 actionable attestations at the same time and to avoid changing Attestation.sol contract to store mapping prefix<>issuer in it.

Caveat

We do occasionally redundant requests with security code to wrong validators and those exposing the code itself and increasing waiting time for the user. For 3 SMSs the probability of this happening is 30%.

For more information see this discussion https://discord.com/channels/600834479145353243/732977310101405736/778336853505081344

Demo

screen-20201119-212100~2

Tested

With short codes enabled/disabled.

Related issues

Backwards compatibility

Yes

*/
getAttestationForSecurityCode(serviceURL: string, body: AttesationServiceCodeForSecurityRequest) {
const urlParams = new URLSearchParams({ ...body })
return fetch(appendPath(serviceURL, 'get_attestations') + '?' + urlParams, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this include any retry logic? We should add this (with exponential backoff) if not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having a hard time to understand when do we want to do that. Basically the fact that we are not 100% sure that current validator is the one who sent the code brings some complexity here. Possible cases I see:

  • Timeout - is it really worth trying it once again considering that it might not be the one we need.
  • 4xx - we expect this to happen for some validators.
  • 5xx - something went really wrong on the attestation service side. Probably, it make sense to try it later, but how much time we want to spend on each validator in total?

Any thoughts? cc: @aslawson @timmoreton @codyborn

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can parallelize the requests.. if we get a 200 response from one of them we return immediately. Otherwise, for each 500 or timeout we retry a couple times before giving up.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be an optimization. We do have manual retry by the user. If there is a failure and user selects "resend", it will try the existing actionable issuer first again. We allow the user to do this after 1 min, but if we receive either a timeout or a failure (other than expected failure on "already sent too many times" or "wrong code") we could resend the request within that minute.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually i suppose that's for the initial request for get the security code, so really only "wrong code" would be the acceptable error

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be nice if we can retry with backoff except on cases where we get 4xx -- especially 403 (security code invalid, or attempts exceeded) or 404 (attestation not found -- i.e it was a hash collision and this is the wrong service). However I feel it is an optimization if time is tight

Copy link
Contributor

@codyborn codyborn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Added some suggestions about organization.

@i1skn i1skn requested a review from asaj as a code owner November 20, 2020 11:23
@i1skn i1skn force-pushed the i1skn/8-digits-verification branch from 3ec416a to 16d71d8 Compare November 20, 2020 11:24
Copy link
Contributor

@codyborn codyborn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! There's still the open question on the retry logic.. let me know what you think.

Copy link
Contributor

@aslawson aslawson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks really good. and love the demo -- so beautiful!

just a couple comments/ideas, but nothing blocking

packages/contractkit/src/wrappers/Attestations.ts Outdated Show resolved Hide resolved
packages/env-tests/package.json Outdated Show resolved Hide resolved
packages/mobile/src/identity/securityCode.ts Outdated Show resolved Hide resolved
packages/mobile/src/identity/securityCode.ts Outdated Show resolved Hide resolved
*/
getAttestationForSecurityCode(serviceURL: string, body: AttesationServiceCodeForSecurityRequest) {
const urlParams = new URLSearchParams({ ...body })
return fetch(appendPath(serviceURL, 'get_attestations') + '?' + urlParams, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually i suppose that's for the initial request for get the security code, so really only "wrong code" would be the acceptable error

packages/mobile/src/identity/securityCode.ts Outdated Show resolved Hide resolved
@i1skn
Copy link
Contributor Author

i1skn commented Nov 23, 2020

@aslawson @codyborn I've addressed all the feedback. Also, decided to make requests to obtain attestation code in parallel to all matching issuers in case of a collision, but without a retry.

@i1skn i1skn force-pushed the i1skn/8-digits-verification branch from ac56b17 to 46fc901 Compare November 23, 2020 19:38
Comment on lines 20 to 23
if (!cache[issuerAddress]) {
cache[issuerAddress] = `${hashAddressToSingleDigit(issuerAddress)}`
}
return cache[issuerAddress]
Copy link
Contributor

@aslawson aslawson Nov 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't actually think this is providing that much gain, hashAddressToSingleDigit doesn't seem too computationally complex. I was thinking we could have a cache like you originally suggested that was key:digit --> List<IssuerAddresses>. That way when you receive a code, you can just check the cache for the list of issuers to send to rather than iterating through each issuer. Though, it would require more maintenance -- eg. removing entries whenever you remove entries from the existing ActiveAttestations cache

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not include it in the current PR. We can handle it later as an improvement to the current solution.

packages/mobile/src/identity/securityCode.ts Outdated Show resolved Hide resolved
// for reject and resolve to achieve what we need
async function raceUntilSuccess<T>(promises: Array<Promise<T>>) {
try {
const errors = await Promise.all(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use Promise.any and not have to switch the definitions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@i1skn i1skn force-pushed the i1skn/8-digits-verification branch from cc68f9e to 2e3899a Compare November 24, 2020 19:36
@i1skn
Copy link
Contributor Author

i1skn commented Nov 24, 2020

I've addressed all the feedback. Lmk if there anything else, otherwise I would like to merge it tomorrow before 1.6.0 cut. Thanks!

Copy link
Contributor

@aslawson aslawson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shipit 🐑

@i1skn i1skn added the automerge Have PR merge automatically when checks pass label Nov 25, 2020
@mergify mergify bot merged commit 486a02e into master Nov 25, 2020
@mergify mergify bot deleted the i1skn/8-digits-verification branch November 25, 2020 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge Have PR merge automatically when checks pass wallet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Valora process 8-digit numerical codes [Valora] Valora processes 8 digit numeric digital codes
6 participants