cosmos-sdk: perf: bech32 library, implement a decode algorithm that doesn't check the checksum

Summary

Now that we are using bech32 strings in several locations within the state machine (e.g. all the proto structs for staking), we should be mindful of the efficiency. Bech32 decoding for checksum checks with the current implementation checks isn’t negligible time at scale, especially if your doing a large operation over state. (E.g. in epoch based models)

Any bech32 address that makes it into state should be a correct bech32 address. Therefore, we do not need to check its checksum upon decoding. We should implement a method in our bech32 library for DecodeAssumingValidChecksum

Problem Definition

This feature helps improve performance of going to and fro ‘native’ data representation, and bech32 strings, for objects within the state machine.

The downside of this feature is it may add some additional thinking to relevant parts of the logic, for something that in the “standard” path of the SDK (e.g. not a large batch computation), will not be high impact.

Proposal

In the bech32 library we currently use, add a method for DecodeAssumingValidChecksum that simply omits the bech32verifychecksum call


For Admin Use

  • Not duplicate issue
  • Appropriate labels applied
  • Appropriate contributors tagged
  • Contributor assigned/self-assigned

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 19 (12 by maintainers)

Most upvoted comments

@ValarDragon

In original version (enigmampc/btcutil), memory allocation always happens multiple times due to string copy. https://github.com/enigmampc/btcutil/blob/e2fb6adb2a25f868283c4f243c873ad6b4894974/bech32/bech32.go#L35-L36

By merging the latest version (btcsuite/btcutil), memory allocation only happens when a given bech32 string consists of upper case letters. https://github.com/cosmos/btcutil/blob/a68c44d216624107f23b6c8e66704ff4ecee879a/bech32/bech32.go#L176-L179

Now all tests have 1 allocs/op.

goos: darwin
goarch: amd64
pkg: github.com/cosmos/cosmos-sdk/types/bech32
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
name iteration time
BenchmarkDecode-16 1506727 807.4 ns/op
BenchmarkDecodeAssumingValidChecksum-16 2391042 494.4 ns/op
BenchmarkDecodeUnsafe-16 2923123 410.4 ns/op

Tested three cases:

  • Decode: Normalization + ChecksumValidation
  • DecodeAssumingValidChecksum: Normalization
  • DecodeUnsafe: -

Normalization here is checking and changing address to have only lower-case letters. If we normalize address when it is stored within state machine, normalization can be omitted too.

@marbar3778 @robert-zaremba OK, I will check it. Thank you.

DecodeAssumingValidChecksum. So now we need someone to update SDK to use that function when we deserialize things from state. Anything else?