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

feat: signature verification cache #41

Merged
merged 8 commits into from
Jan 7, 2021
Merged

feat: signature verification cache #41

merged 8 commits into from
Jan 7, 2021

Conversation

jinsan-line
Copy link
Contributor

@jinsan-line jinsan-line commented Dec 8, 2020

Closes: https://github.com/line/link/issues/1135, https://github.com/line/link/issues/1136

Description

  • During checking a tx, if it succeed to verify the signatures, keep it in txHashCache as [account_number:sequence]: tx_hash
  • When delivering or rechecking a tx, we could look up txHashCache to check whether it's already verified.
  • When delivering a tx, if txHashCache doesn't have a entry or the txHash is not same, we'll verify it again w/ VerifyBytes()
  • When rechecking a tx, SigVerificationDecorator is executed as well for https://github.com/line/link/issues/1136

Motivation and context

Signature verification is cpu intensive task. It could be executed repeatedly for the same transaction so, if we keep the verified the transactions, it could save cpu time and improve the performance.

How has this been tested?

Checklist:

  • I followed the contributing guidelines.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.

@jinsan-line jinsan-line self-assigned this Dec 8, 2020
@jinsan-line jinsan-line requested a review from whylee259 December 8, 2020 11:10
Copy link
Contributor

@whylee259 whylee259 left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@wetcod wetcod left a comment

Choose a reason for hiding this comment

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

LGTM

if !pubKey.VerifyBytes(sigTx.GetSignBytes(ctx, signerAcc), sig) {
return false
}
svd.txHashCache.Store(sigKey, txHash)
Copy link

@egonspace egonspace Dec 9, 2020

Choose a reason for hiding this comment

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

It seems like some tx's signature will not be removed from the cache if it does not meet DeliverTx. If the mempool is full, the tx will not be able to enter the mempool after passing checkTx, so it will not be able to meet DeliverTx.

Copy link
Contributor Author

@jinsan-line jinsan-line Dec 9, 2020

Choose a reason for hiding this comment

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

You're correct. A tx couldn't be removed from the cache if the tx is not added to mempool. But I'd like to care it w/ missing transaction issue. Currently, I assume that the tx must be added to mempool if it passes checkTx.

Copy link
Contributor Author

@jinsan-line jinsan-line Dec 9, 2020

Choose a reason for hiding this comment

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

As another approach, we could remove a tx from the cache when we fail to add a tx to mempool.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another thought, even though we fail to add a tx to mempool after adding it to the cache, it could be removed when same account w/ the same sequence broadcasts a tx again. So, finally after thinking deeply, I have a conclusion that it's not a big deal. Could you agree on it?

Copy link
Contributor

@kukugi kukugi left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@jinsan-line jinsan-line changed the base branch from develop to feat/perf December 9, 2020 03:57
Copy link
Contributor

@kfangw kfangw left a comment

Choose a reason for hiding this comment

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

I am afraid 2 point.

  • a cached key may not be removed
    -> can we add ttl feature to the cache?
  • the assumption cause potential fault
    -> please see the details in the below comment

x/auth/ante/sigverify.go Outdated Show resolved Hide resolved
x/auth/ante/sigverify.go Outdated Show resolved Hide resolved
@kfangw
Copy link
Contributor

kfangw commented Dec 24, 2020

I strongly recommend you get a review from @whylee259 before merging it.

@whylee259
Copy link
Contributor

I've thrown approve before.

During the review, I worried about cache clear logic.

  1. After checkTx passed, deliverTx or recheckTx will be always called?
  2. What if checkTx is not passed after adding cache?

From the mempool logic.

  • TXs will be removed from the mempool
    1. when deliverTx has been done.
    2. when recheckTx returns failure.
  • so the cache will be clear before TXs is removed from the mempool.

From the Ante Chain

  • SigVerificationDecorator is the last verification.

For these two reason, I've clicked the approve button.

However, after hearing @egonspace's comments, I agree with his opinion.
The current implementation is coupled with the mempool logic and the ante order.

@jinsan-line
Copy link
Contributor Author

jinsan-line commented Dec 24, 2020

I think it's a key topic to discuss.

The current implementation is coupled with the mempool logic and the ante order.

  • I think it need to be coupled with the mempool because signature verification cache is conceptually a part of mempool. On the other hand, I think we could implement this cache in tendermint to more clearly be bound. But I suspect whether it's good idea because cosmos-sdk should let tendermint know account number and sequence.

  • I think checkTx (ante handlers) is already bound with the mempool. For example, if the mempool doesn't add the tx that is passed checkTx, the sequence is already increased during ante so an account might be broken. I think it's better to set up CONTRACT explicitly that we must add a tx if it's passed checkTx. It looks like already assumed in cosmos-sdk implicitly.

@egonspace
Copy link

egonspace commented Dec 24, 2020

The problem I raised is relatively easy to reproduce. If we fire a large number of txs continuously with a client such as a vulcan after setting the mempool small, it will continue to accumulate signatures in the cache, but txs will fail to reach the DeliveryTx. How can we keep this code when we can't defend this problem?

@jinsan-line
Copy link
Contributor Author

jinsan-line commented Dec 24, 2020

The problem I raised is relatively easy to reproduce

As I already said, I couldn't agree on it especially on easy. I think the idea assumes that account never send a tx again. We need huge accounts to impact on the memory size practically and also the idea depends on race condition or bug behavior of mempool. I think it's better to fix bug behavior of mempool.

If it's really easy to produce it and impact on the memory, please could you give me an example? I think it might really help me to try to defense it. Thanks!

@whylee259
Copy link
Contributor

If recheckTx is failed due to another ante decor(fee deduction, etc.), it does not reach svd.txHashCache.Delete, isn't it?

@jinsan-line
Copy link
Contributor Author

If recheckTx is failed due to another ante decor(fee deduction, etc.), it does not reach svd.txHashCache.Delete, isn't it?

No (Yes or no is not intuitive for Korean, at least to me. T_T), it doesn't reach to delete even though the tx is deleted from the mempool. But I think, when some time the account will send tx again, the cache will be deleted finally. I think the key challenge is whether this idea is acceptable or not.

@egonspace
Copy link

egonspace commented Dec 24, 2020

If it's really easy to produce it and impact on the memory, please could you give me an example?

Isn't that exactly how the vulcan works?

@jinsan-line
Copy link
Contributor Author

Isn't that exactly how the vulcan works?

I don't think so because vulcan uses same account (address) by HDWallet between test and test.

@jinsan-line
Copy link
Contributor Author

If recheckTx is failed due to another ante decor(fee deduction, etc.), it does not reach svd.txHashCache.Delete, isn't it?

#41 (comment)

I think we could remove the signature verification cache when a tx is removed from mempool by a new abci. If you'd like to review it all together, I'll try it.

@jinsan-line jinsan-line marked this pull request as draft January 6, 2021 07:59
@jinsan-line
Copy link
Contributor Author

jinsan-line commented Jan 6, 2021

w/ https://github.com/line/link/issues/1153, a tx must be added to mempool if checkTx is passed so we don't need to care of missing tx case any more.

The only case that we should revert cache is failure of ante handler. I implement it at 865bc14.

Please take a look at again.
Thanks,

@jinsan-line jinsan-line marked this pull request as ready for review January 6, 2021 09:21
Copy link

@egonspace egonspace left a comment

Choose a reason for hiding this comment

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

Good job!

Copy link
Contributor

@wetcod wetcod left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@whylee259 whylee259 left a comment

Choose a reason for hiding this comment

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

LGTM

@jinsan-line jinsan-line merged commit 4946a48 into Finschia:feat/perf Jan 7, 2021
@jinsan-line jinsan-line deleted the sig-cache branch January 7, 2021 08:41
@wetcod wetcod mentioned this pull request Feb 4, 2021
3 tasks
wetcod added a commit that referenced this pull request Feb 4, 2021
* feat: signature verification cache

* chore: recover to skip to sigverify

* chore: rename `ok` to `exist` of `checkCache()` return var

* chore: remove txHashCash if got an error

* chore: revise `verifySignatureWithCache()` for readability

* chore: remove naked return

* fix: lint error

Co-authored-by: KIm, JinSan <jinsan@linecorp.com>
jinsan-line added a commit that referenced this pull request Apr 23, 2021
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

Successfully merging this pull request may close these issues.

6 participants