Skip to content

Commit

Permalink
Added location parsing for IsWritable and IsSignable on AccountLookups
Browse files Browse the repository at this point in the history
  • Loading branch information
silaslenihan committed Jan 16, 2025
1 parent 0cd58cc commit 731e8c9
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 27 deletions.
211 changes: 204 additions & 7 deletions integration-tests/relayinterface/lookups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ import (
"github.com/smartcontractkit/chainlink-solana/pkg/solana/utils"
)

type InnerAccountArgs struct {
Accounts []*solana.AccountMeta
}

type TestAccountArgs struct {
Inner InnerAccountArgs
}

func TestAccountContant(t *testing.T) {
t.Run("AccountConstant resolves valid address", func(t *testing.T) {
expectedAddr := chainwriter.GetRandomPubKey(t)
Expand Down Expand Up @@ -62,8 +70,8 @@ func TestAccountLookups(t *testing.T) {
lookupConfig := chainwriter.AccountLookup{
Name: "TestAccount",
Location: "Inner.Address",
IsSigner: true,
IsWritable: true,
IsSigner: chainwriter.MetaBool{Value: true},
IsWritable: chainwriter.MetaBool{Value: true},
}
result, err := lookupConfig.Resolve(ctx, testArgs, nil, nil)
require.NoError(t, err)
Expand Down Expand Up @@ -96,8 +104,8 @@ func TestAccountLookups(t *testing.T) {
lookupConfig := chainwriter.AccountLookup{
Name: "TestAccount",
Location: "Inner.Address",
IsSigner: true,
IsWritable: true,
IsSigner: chainwriter.MetaBool{Value: true},
IsWritable: chainwriter.MetaBool{Value: true},
}
result, err := lookupConfig.Resolve(ctx, testArgs, nil, nil)
require.NoError(t, err)
Expand All @@ -117,12 +125,201 @@ func TestAccountLookups(t *testing.T) {
lookupConfig := chainwriter.AccountLookup{
Name: "InvalidAccount",
Location: "Invalid.Directory",
IsSigner: true,
IsWritable: true,
IsSigner: chainwriter.MetaBool{Value: true},
IsWritable: chainwriter.MetaBool{Value: true},
}
_, err := lookupConfig.Resolve(ctx, testArgs, nil, nil)
require.Error(t, err)
})

t.Run("AccountLookup works with MetaBool lookups", func(t *testing.T) {
accounts := [3]*solana.AccountMeta{}

for i := 0; i < 3; i++ {
accounts[i] = &solana.AccountMeta{
PublicKey: chainwriter.GetRandomPubKey(t),
IsSigner: true,
IsWritable: false,
}
}

lookupConfig := chainwriter.AccountLookup{
Name: "InvalidAccount",
Location: "Inner.Accounts.PublicKey",
IsSigner: chainwriter.MetaBool{Location: "Inner.Accounts.IsSigner"},
IsWritable: chainwriter.MetaBool{Location: "Inner.Accounts.IsWritable"},
}

args := TestAccountArgs{
Inner: InnerAccountArgs{
Accounts: accounts[:],
},
}

result, err := lookupConfig.Resolve(ctx, args, nil, nil)
require.NoError(t, err)

for i, meta := range result {
require.Equal(t, accounts[i], meta)
}
})

t.Run("AccountLookup works with MetaBool lookups when a meta field is missing", func(t *testing.T) {
accounts := [3]*solana.AccountMeta{}

for i := 0; i < 3; i++ {
accounts[i] = &solana.AccountMeta{
PublicKey: chainwriter.GetRandomPubKey(t),
IsWritable: true,
}
}

lookupConfig := chainwriter.AccountLookup{
Name: "InvalidAccount",
Location: "Inner.Accounts.PublicKey",
IsSigner: chainwriter.MetaBool{Location: "Inner.Accounts.IsSigner"},
IsWritable: chainwriter.MetaBool{Location: "Inner.Accounts.IsWritable"},
}

args := TestAccountArgs{
Inner: InnerAccountArgs{
Accounts: accounts[:],
},
}

result, err := lookupConfig.Resolve(ctx, args, nil, nil)
require.NoError(t, err)

for i, meta := range result {
require.Equal(t, accounts[i], meta)
}
})

t.Run("AccountLookup works with MetaBool lookups in a different location", func(t *testing.T) {
type TestAccountArgsExtended struct {
Inner InnerAccountArgs
ExternalBool bool
}

accounts := [3]*solana.AccountMeta{}

for i := 0; i < 3; i++ {
accounts[i] = &solana.AccountMeta{
PublicKey: chainwriter.GetRandomPubKey(t),
IsWritable: true,
IsSigner: true,
}
}

lookupConfig := chainwriter.AccountLookup{
Name: "InvalidAccount",
Location: "Inner.Accounts.PublicKey",
IsSigner: chainwriter.MetaBool{Location: "ExternalBool"},
IsWritable: chainwriter.MetaBool{Location: "ExternalBool"},
}

args := TestAccountArgsExtended{
Inner: InnerAccountArgs{
Accounts: accounts[:],
},
ExternalBool: true,
}

result, err := lookupConfig.Resolve(ctx, args, nil, nil)
require.NoError(t, err)

for i, meta := range result {
require.Equal(t, accounts[i], meta)
}
})

t.Run("AccountLookup fails with MetaBool an invalid number of Meta lookups", func(t *testing.T) {
type TestAccountArgsExtended struct {
Inner InnerAccountArgs
ExternalBools []bool
}

accounts := [3]*solana.AccountMeta{}

for i := 0; i < 3; i++ {
accounts[i] = &solana.AccountMeta{
PublicKey: chainwriter.GetRandomPubKey(t),
IsWritable: true,
IsSigner: true,
}
}

lookupConfig := chainwriter.AccountLookup{
Name: "InvalidAccount",
Location: "Inner.Accounts.PublicKey",
IsSigner: chainwriter.MetaBool{Location: "ExternalBools"},
IsWritable: chainwriter.MetaBool{Location: "ExternalBools"},
}

args := TestAccountArgsExtended{
Inner: InnerAccountArgs{
Accounts: accounts[:],
},
ExternalBools: []bool{true, true},
}

_, err := lookupConfig.Resolve(ctx, args, nil, nil)
require.Contains(t, err.Error(), "boolean array length 2 doesn't match pubkey count 3 for location")
})

t.Run("AccountLookup fails with MetaBool with an Invalid Location", func(t *testing.T) {
accounts := [3]*solana.AccountMeta{}

for i := 0; i < 3; i++ {
accounts[i] = &solana.AccountMeta{
PublicKey: chainwriter.GetRandomPubKey(t),
IsWritable: true,
}
}

lookupConfig := chainwriter.AccountLookup{
Name: "InvalidAccount",
Location: "Inner.Accounts.PublicKey",
IsSigner: chainwriter.MetaBool{Location: "Invalid.IsSigner"},
IsWritable: chainwriter.MetaBool{Location: "Invalid.IsWritable"},
}

args := TestAccountArgs{
Inner: InnerAccountArgs{
Accounts: accounts[:],
},
}

_, err := lookupConfig.Resolve(ctx, args, nil, nil)
require.Contains(t, err.Error(), "error reading bools from location")
})

t.Run("AccountLookup fails when MetaBool is an invalid type", func(t *testing.T) {
accounts := [3]*solana.AccountMeta{}

for i := 0; i < 3; i++ {
accounts[i] = &solana.AccountMeta{
PublicKey: chainwriter.GetRandomPubKey(t),
IsWritable: true,
}
}

lookupConfig := chainwriter.AccountLookup{
Name: "InvalidAccount",
Location: "Inner.Accounts.PublicKey",
IsSigner: chainwriter.MetaBool{Location: "Inner"},
IsWritable: chainwriter.MetaBool{Location: "Inner"},
}

args := TestAccountArgs{
Inner: InnerAccountArgs{
Accounts: accounts[:],
},
}

_, err := lookupConfig.Resolve(ctx, args, nil, nil)
require.Contains(t, err.Error(), "invalid value format at path")
})
}

func TestPDALookups(t *testing.T) {
Expand Down Expand Up @@ -435,7 +632,7 @@ func TestLookupTables(t *testing.T) {
Accounts: chainwriter.AccountLookup{
Name: "TestLookupTable",
Location: "Inner.Address",
IsSigner: true,
IsSigner: chainwriter.MetaBool{Value: true},
},
},
},
Expand Down
12 changes: 6 additions & 6 deletions pkg/solana/chainwriter/ccip_example_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ func TestConfig() {
AccountLookup{
Name: "TokenAccount",
Location: "Message.TokenAmounts.DestTokenAddress",
IsSigner: false,
IsWritable: false,
IsSigner: MetaBool{Value: false},
IsWritable: MetaBool{Value: false},
},
// PDA Account Lookup - Based on an account lookup and an address lookup
PDALookups{
Expand All @@ -116,16 +116,16 @@ func TestConfig() {
PublicKey: AccountLookup{
Name: "TokenAccount",
Location: "Message.TokenAmounts.DestTokenAddress",
IsSigner: false,
IsWritable: false,
IsSigner: MetaBool{Value: false},
IsWritable: MetaBool{Value: false},
},
// The seed is the receiver address.
Seeds: []Seed{
{Dynamic: AccountLookup{
Name: "Receiver",
Location: "Message.Receiver",
IsSigner: false,
IsWritable: false,
IsSigner: MetaBool{Value: false},
IsWritable: MetaBool{Value: false},
}},
},
},
Expand Down
8 changes: 4 additions & 4 deletions pkg/solana/chainwriter/chain_writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ func TestChainWriter_GetAddresses(t *testing.T) {
chainwriter.AccountLookup{
Name: "LookupTable",
Location: "LookupTable",
IsSigner: accountLookupMeta.IsSigner,
IsWritable: accountLookupMeta.IsWritable,
IsSigner: chainwriter.MetaBool{Value: accountLookupMeta.IsSigner},
IsWritable: chainwriter.MetaBool{Value: accountLookupMeta.IsWritable},
},
chainwriter.PDALookups{
Name: "DataAccountPDA",
Expand Down Expand Up @@ -463,8 +463,8 @@ func TestChainWriter_SubmitTransaction(t *testing.T) {
chainwriter.AccountLookup{
Name: "LookupTable",
Location: "LookupTable",
IsSigner: false,
IsWritable: false,
IsSigner: chainwriter.MetaBool{Value: false},
IsWritable: chainwriter.MetaBool{Value: false},
},
chainwriter.PDALookups{
Name: "DataAccountPDA",
Expand Down
8 changes: 7 additions & 1 deletion pkg/solana/chainwriter/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,14 @@ func GetValuesAtLocation(args any, location string) ([][]byte, error) {
buf := make([]byte, 8)
binary.LittleEndian.PutUint64(buf, num)
vals = append(vals, buf)
} else if boolean, ok := value.(bool); ok {
if boolean {
vals = append(vals, []byte{0x01})
} else {
vals = append(vals, []byte{0x00})
}
} else {
return nil, fmt.Errorf("invalid value format at path: %s", location)
return nil, fmt.Errorf("invalid value format at path: %s, type: %s", location, reflect.TypeOf(value).String())
}
}

Expand Down
Loading

0 comments on commit 731e8c9

Please sign in to comment.