From 3acb01914dcd726354a72f466d64fcef5192c5cc Mon Sep 17 00:00:00 2001 From: Tsachi Herman Date: Wed, 22 Jan 2020 16:01:11 -0500 Subject: [PATCH 1/3] Faster stringer implementation. --- data/basics/address.go | 10 +++++++--- data/basics/address_test.go | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/data/basics/address.go b/data/basics/address.go index f9cc8d6381..e3e29a4211 100644 --- a/data/basics/address.go +++ b/data/basics/address.go @@ -75,11 +75,15 @@ func UnmarshalChecksumAddress(address string) (Address, error) { return short, nil } +var base32Encoder = base32.StdEncoding.WithPadding(base32.NoPadding) + // String returns a string representation of Address func (addr Address) String() string { - var addrWithChecksum []byte - addrWithChecksum = append(addr[:], addr.GetChecksum()...) - return base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(addrWithChecksum) + addrWithChecksum := make([]byte, crypto.DigestSize+checksumLength) + copy(addrWithChecksum[:crypto.DigestSize], addr[:]) + shortAddressHash := crypto.Hash(addr[:]) + copy(addrWithChecksum[crypto.DigestSize:], shortAddressHash[len(shortAddressHash)-checksumLength:]) + return base32Encoder.EncodeToString(addrWithChecksum) } // MarshalText returns the address string as an array of bytes diff --git a/data/basics/address_test.go b/data/basics/address_test.go index 5d70e5830b..fc16abf7d6 100644 --- a/data/basics/address_test.go +++ b/data/basics/address_test.go @@ -107,3 +107,18 @@ func TestAddressMarshalUnmarshal(t *testing.T) { require.NoError(t, err) require.Equal(t, testob, nob) } + +func BenchmarkAddressFormatting(b *testing.B) { + addr := "J5YDZLPOHWB5O6MVRHNFGY4JXIQAYYM6NUJWPBSYBBIXH5ENQ4Z5LTJELU" + uaddr, err := UnmarshalChecksumAddress(addr) + require.NoError(b, err) + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + stringed := uaddr.String() + if len(stringed) == 0 { + break + } + } +} From 0e6c7a34c617804cbf577534bfd5ef68396ec26e Mon Sep 17 00:00:00 2001 From: Tsachi Herman Date: Wed, 22 Jan 2020 16:33:22 -0500 Subject: [PATCH 2/3] Optimize UnmarshalChecksumAddress as well. --- data/basics/address.go | 7 ++++--- data/basics/address_test.go | 11 +++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/data/basics/address.go b/data/basics/address.go index e3e29a4211..022c217224 100644 --- a/data/basics/address.go +++ b/data/basics/address.go @@ -33,6 +33,8 @@ const ( checksumLength = 4 ) +var base32Encoder = base32.StdEncoding.WithPadding(base32.NoPadding) + // GetChecksum returns the checksum as []byte // Checksum in Algorand are the last 4 bytes of the shortAddress Hash. H(Address)[28:] func (addr Address) GetChecksum() []byte { @@ -48,7 +50,8 @@ func (addr Address) GetUserAddress() string { // UnmarshalChecksumAddress tries to unmarshal the checksummed address string. func UnmarshalChecksumAddress(address string) (Address, error) { - decoded, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(address) + decoded, err := base32Encoder.DecodeString(address) + if err != nil { return Address{}, fmt.Errorf("failed to decode address %s to base 32", address) } @@ -75,8 +78,6 @@ func UnmarshalChecksumAddress(address string) (Address, error) { return short, nil } -var base32Encoder = base32.StdEncoding.WithPadding(base32.NoPadding) - // String returns a string representation of Address func (addr Address) String() string { addrWithChecksum := make([]byte, crypto.DigestSize+checksumLength) diff --git a/data/basics/address_test.go b/data/basics/address_test.go index fc16abf7d6..485e6c70d3 100644 --- a/data/basics/address_test.go +++ b/data/basics/address_test.go @@ -122,3 +122,14 @@ func BenchmarkAddressFormatting(b *testing.B) { } } } + +func BenchmarkUnmarshalChecksumAddress(b *testing.B) { + addr := "J5YDZLPOHWB5O6MVRHNFGY4JXIQAYYM6NUJWPBSYBBIXH5ENQ4Z5LTJELU" + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := UnmarshalChecksumAddress(addr) + if err != nil { + break + } + } +} From e51d3489f3019df1f580e711a2f717601e1f9444 Mon Sep 17 00:00:00 2001 From: Tsachi Herman Date: Wed, 22 Jan 2020 17:05:24 -0500 Subject: [PATCH 3/3] Add comment. --- data/basics/address.go | 1 + 1 file changed, 1 insertion(+) diff --git a/data/basics/address.go b/data/basics/address.go index 022c217224..c0341517b1 100644 --- a/data/basics/address.go +++ b/data/basics/address.go @@ -82,6 +82,7 @@ func UnmarshalChecksumAddress(address string) (Address, error) { func (addr Address) String() string { addrWithChecksum := make([]byte, crypto.DigestSize+checksumLength) copy(addrWithChecksum[:crypto.DigestSize], addr[:]) + // calling addr.GetChecksum() here takes 20ns more than just rolling it out, so we'll just repeat that code. shortAddressHash := crypto.Hash(addr[:]) copy(addrWithChecksum[crypto.DigestSize:], shortAddressHash[len(shortAddressHash)-checksumLength:]) return base32Encoder.EncodeToString(addrWithChecksum)