Skip to content

Commit

Permalink
Improve Solana address codec modifier to handle all valid base58 keys (
Browse files Browse the repository at this point in the history
  • Loading branch information
ilija42 authored Dec 20, 2024
1 parent 77a448b commit 99fd0e4
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 7 deletions.
12 changes: 8 additions & 4 deletions pkg/solana/codec/byte_string_modifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,19 @@ func (s SolanaAddressModifier) EncodeAddress(bytes []byte) (string, error) {

// DecodeAddress decodes a Base58-encoded Solana address into a 32-byte array.
func (s SolanaAddressModifier) DecodeAddress(str string) ([]byte, error) {
if len(str) != 44 {
return nil, fmt.Errorf("%w: got length %d, expected 44 for address %s", commontypes.ErrInvalidType, len(str), str)
}

pubkey, err := solana.PublicKeyFromBase58(str)
if err != nil {
return nil, fmt.Errorf("%w: failed to decode Base58 address: %s", commontypes.ErrInvalidType, err)
}

if pubkey.IsZero() {
return nil, fmt.Errorf("%w: zero-value address", commontypes.ErrInvalidType)
}

if !pubkey.IsOnCurve() {
return nil, fmt.Errorf("%w: address %q with length of %d is not on the ed25519 curve", commontypes.ErrInvalidType, str, len(str))
}

return pubkey.Bytes(), nil
}

Expand Down
13 changes: 13 additions & 0 deletions pkg/solana/codec/byte_string_modifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ func TestSolanaAddressModifier(t *testing.T) {
assert.Contains(t, err.Error(), commontypes.ErrInvalidType.Error())
})

t.Run("DecodeAddress returns error for address under 32 chars", func(t *testing.T) {
// < than 32 chars
_, err := modifier.DecodeAddress("1111111111111111111111111111111")
assert.Error(t, err)
assert.Contains(t, err.Error(), commontypes.ErrInvalidType.Error())
})

t.Run("DecodeAddress returns error for valid length address not on the ed25519 curve", func(t *testing.T) {
_, err := modifier.DecodeAddress("AddressLookupTab1e11111111111111111111111111")
assert.Error(t, err)
assert.Contains(t, err.Error(), commontypes.ErrInvalidType.Error())
})

t.Run("Length returns 32 for Solana addresses", func(t *testing.T) {
assert.Equal(t, solana.PublicKeyLength, modifier.Length())
})
Expand Down
14 changes: 11 additions & 3 deletions pkg/solana/codec/codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
_ "embed"
"slices"
"sync"
"testing"

bin "github.com/gagliardetto/binary"
Expand Down Expand Up @@ -52,15 +53,22 @@ func FuzzCodec(f *testing.F) {
}

type codecInterfaceTester struct {
accountBytesMu sync.Mutex
accountBytes []byte
TestSelectionSupport
}

func (it *codecInterfaceTester) Setup(_ *testing.T) {}

func (it *codecInterfaceTester) GetAccountBytes(_ int) []byte {
// TODO solana base58 string can be of variable length, this value is always 44, but it should be able to handle any length 32-44
pk := solana.PublicKeyFromBytes([]byte{220, 108, 195, 188, 166, 6, 163, 39, 197, 131, 44, 38, 154, 177, 232, 80, 141, 50, 7, 65, 28, 65, 182, 165, 57, 5, 176, 68, 46, 181, 58, 245})
return pk.Bytes()
it.accountBytesMu.Lock()
defer it.accountBytesMu.Unlock()
if len(it.accountBytes) != 32 {
pk, _ := solana.NewRandomPrivateKey()
it.accountBytes = pk.PublicKey().Bytes()
}

return it.accountBytes
}

func (it *codecInterfaceTester) GetAccountString(i int) string {
Expand Down

0 comments on commit 99fd0e4

Please sign in to comment.