From 08a3da44b100c86b71a41fbd33d23abb26b7a646 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 20 Aug 2024 11:01:29 -0400 Subject: [PATCH] feat(schema/indexer): add address codec param (#21361) --- schema/addressutil/codec.go | 8 +++++ schema/addressutil/hex.go | 24 +++++++++++++++ schema/addressutil/hex_test.go | 54 ++++++++++++++++++++++++++++++++++ schema/indexer/indexer.go | 5 ++++ schema/indexer/manager.go | 6 ++++ 5 files changed, 97 insertions(+) create mode 100644 schema/addressutil/codec.go create mode 100644 schema/addressutil/hex.go create mode 100644 schema/addressutil/hex_test.go diff --git a/schema/addressutil/codec.go b/schema/addressutil/codec.go new file mode 100644 index 000000000000..cadde8e516cd --- /dev/null +++ b/schema/addressutil/codec.go @@ -0,0 +1,8 @@ +package addressutil + +type AddressCodec interface { + // StringToBytes decodes text to bytes + StringToBytes(text string) ([]byte, error) + // BytesToString encodes bytes to text + BytesToString(bz []byte) (string, error) +} diff --git a/schema/addressutil/hex.go b/schema/addressutil/hex.go new file mode 100644 index 000000000000..1d6ecae467ce --- /dev/null +++ b/schema/addressutil/hex.go @@ -0,0 +1,24 @@ +package addressutil + +import ( + "encoding/hex" + "fmt" +) + +// HexAddressCodec is a basic address codec that encodes and decodes addresses as hex strings. +// It is intended to be used as a fallback codec when no other codec is provided. +type HexAddressCodec struct{} + +func (h HexAddressCodec) StringToBytes(text string) ([]byte, error) { + if len(text) < 2 || text[:2] != "0x" { + return nil, fmt.Errorf("invalid hex address: %s", text) + } + + return hex.DecodeString(text[2:]) +} + +func (h HexAddressCodec) BytesToString(bz []byte) (string, error) { + return fmt.Sprintf("0x%x", bz), nil +} + +var _ AddressCodec = HexAddressCodec{} diff --git a/schema/addressutil/hex_test.go b/schema/addressutil/hex_test.go new file mode 100644 index 000000000000..e4a0f0ee01f9 --- /dev/null +++ b/schema/addressutil/hex_test.go @@ -0,0 +1,54 @@ +package addressutil + +import ( + "bytes" + "testing" +) + +func TestHexAddressCodec(t *testing.T) { + tt := []struct { + text string + bz []byte + err bool + }{ + { + text: "0x1234", + bz: []byte{0x12, 0x34}, + }, + { + text: "0x", + bz: []byte{}, + }, + { + text: "0x123", + err: true, + }, + { + text: "1234", + err: true, + }, + } + + h := HexAddressCodec{} + for _, tc := range tt { + bz, err := h.StringToBytes(tc.text) + if tc.err && err == nil { + t.Fatalf("expected error, got none") + } + if !tc.err && err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !tc.err && !bytes.Equal(bz, tc.bz) { + t.Fatalf("expected %v, got %v", tc.bz, bz) + } + + // check address rendering if no error + if !tc.err { + if str, err := h.BytesToString(tc.bz); err != nil { + t.Fatalf("unexpected error: %v", err) + } else if str != tc.text { + t.Fatalf("expected %s, got %s", tc.text, str) + } + } + } +} diff --git a/schema/indexer/indexer.go b/schema/indexer/indexer.go index 57ada8bb80c1..3b82e3254e5a 100644 --- a/schema/indexer/indexer.go +++ b/schema/indexer/indexer.go @@ -3,6 +3,7 @@ package indexer import ( "context" + "cosmossdk.io/schema/addressutil" "cosmossdk.io/schema/appdata" "cosmossdk.io/schema/logutil" "cosmossdk.io/schema/view" @@ -62,6 +63,10 @@ type InitParams struct { // Logger is a logger the indexer can use to write log messages. It may be nil if the indexer does not need // to write logs. Logger logutil.Logger + + // AddressCodec is the address codec that the indexer can use to encode and decode addresses. It is + // expected to be non-nil. + AddressCodec addressutil.AddressCodec } // InitResult is the indexer initialization result and includes the indexer's listener implementation. diff --git a/schema/indexer/manager.go b/schema/indexer/manager.go index 5a7e39faad0a..60c19b4dd5c7 100644 --- a/schema/indexer/manager.go +++ b/schema/indexer/manager.go @@ -3,6 +3,7 @@ package indexer import ( "context" + "cosmossdk.io/schema/addressutil" "cosmossdk.io/schema/appdata" "cosmossdk.io/schema/decoding" "cosmossdk.io/schema/logutil" @@ -29,6 +30,11 @@ type ManagerOptions struct { // be used to pass down other parameters to indexers if necessary. If it is omitted, context.Background // will be used. Context context.Context + + // AddressCodec is the address codec that indexers can use to encode and decode addresses. It should always be + // provided, but if it is omitted, the indexer manager will use a default codec which encodes and decodes addresses + // as hex strings. + AddressCodec addressutil.AddressCodec } // ManagerConfig is the configuration of the indexer manager and contains the configuration for each indexer target.