Skip to content

Commit 3d11be5

Browse files
committed
Updated MetaBool to use a bitmap location rather than a bool location
1 parent e5a8ace commit 3d11be5

File tree

3 files changed

+53
-128
lines changed

3 files changed

+53
-128
lines changed

integration-tests/relayinterface/lookups_test.go

Lines changed: 22 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
type InnerAccountArgs struct {
2525
Accounts []*solana.AccountMeta
26+
Bitmap uint64
2627
}
2728

2829
type TestAccountArgs struct {
@@ -132,27 +133,29 @@ func TestAccountLookups(t *testing.T) {
132133
require.Error(t, err)
133134
})
134135

135-
t.Run("AccountLookup works with MetaBool lookups", func(t *testing.T) {
136+
t.Run("AccountLookup works with MetaBool bitmap lookups", func(t *testing.T) {
136137
accounts := [3]*solana.AccountMeta{}
137138

138139
for i := 0; i < 3; i++ {
139140
accounts[i] = &solana.AccountMeta{
140141
PublicKey: chainwriter.GetRandomPubKey(t),
141-
IsSigner: i%2 == 0,
142-
IsWritable: (i+1)%2 == 0,
142+
IsSigner: (i)%2 == 0,
143+
IsWritable: (i)%2 == 0,
143144
}
144145
}
145146

146147
lookupConfig := chainwriter.AccountLookup{
147148
Name: "InvalidAccount",
148149
Location: "Inner.Accounts.PublicKey",
149-
IsSigner: chainwriter.MetaBool{Location: "Inner.Accounts.IsSigner"},
150-
IsWritable: chainwriter.MetaBool{Location: "Inner.Accounts.IsWritable"},
150+
IsSigner: chainwriter.MetaBool{BitmapLocation: "Inner.Bitmap"},
151+
IsWritable: chainwriter.MetaBool{BitmapLocation: "Inner.Bitmap"},
151152
}
152153

153154
args := TestAccountArgs{
154155
Inner: InnerAccountArgs{
155156
Accounts: accounts[:],
157+
// should be 101... so {true, false, true}
158+
Bitmap: 5,
156159
},
157160
}
158161

@@ -164,79 +167,10 @@ func TestAccountLookups(t *testing.T) {
164167
}
165168
})
166169

167-
t.Run("AccountLookup works with MetaBool lookups when a meta field is missing", func(t *testing.T) {
168-
accounts := [3]*solana.AccountMeta{}
169-
170-
for i := 0; i < 3; i++ {
171-
accounts[i] = &solana.AccountMeta{
172-
PublicKey: chainwriter.GetRandomPubKey(t),
173-
IsWritable: true,
174-
}
175-
}
176-
177-
lookupConfig := chainwriter.AccountLookup{
178-
Name: "InvalidAccount",
179-
Location: "Inner.Accounts.PublicKey",
180-
IsSigner: chainwriter.MetaBool{Location: "Inner.Accounts.IsSigner"},
181-
IsWritable: chainwriter.MetaBool{Location: "Inner.Accounts.IsWritable"},
182-
}
183-
184-
args := TestAccountArgs{
185-
Inner: InnerAccountArgs{
186-
Accounts: accounts[:],
187-
},
188-
}
189-
190-
result, err := lookupConfig.Resolve(ctx, args, nil, nil)
191-
require.NoError(t, err)
192-
193-
for i, meta := range result {
194-
require.Equal(t, accounts[i], meta)
195-
}
196-
})
197-
198-
t.Run("AccountLookup works with MetaBool lookups in a different location", func(t *testing.T) {
199-
type TestAccountArgsExtended struct {
200-
Inner InnerAccountArgs
201-
ExternalBool bool
202-
}
203-
204-
accounts := [3]*solana.AccountMeta{}
205-
206-
for i := 0; i < 3; i++ {
207-
accounts[i] = &solana.AccountMeta{
208-
PublicKey: chainwriter.GetRandomPubKey(t),
209-
IsWritable: true,
210-
IsSigner: true,
211-
}
212-
}
213-
214-
lookupConfig := chainwriter.AccountLookup{
215-
Name: "InvalidAccount",
216-
Location: "Inner.Accounts.PublicKey",
217-
IsSigner: chainwriter.MetaBool{Location: "ExternalBool"},
218-
IsWritable: chainwriter.MetaBool{Location: "ExternalBool"},
219-
}
220-
221-
args := TestAccountArgsExtended{
222-
Inner: InnerAccountArgs{
223-
Accounts: accounts[:],
224-
},
225-
ExternalBool: true,
226-
}
227-
228-
result, err := lookupConfig.Resolve(ctx, args, nil, nil)
229-
require.NoError(t, err)
230-
231-
for i, meta := range result {
232-
require.Equal(t, accounts[i], meta)
233-
}
234-
})
235-
236-
t.Run("AccountLookup fails with MetaBool due to an invalid number of Meta lookups", func(t *testing.T) {
170+
t.Run("AccountLookup fails with MetaBool due to an invalid number of bitmaps", func(t *testing.T) {
237171
type TestAccountArgsExtended struct {
238-
Inner InnerAccountArgs
239-
ExternalBools []bool
172+
Inner InnerAccountArgs
173+
Bitmaps []uint64
240174
}
241175

242176
accounts := [3]*solana.AccountMeta{}
@@ -252,22 +186,22 @@ func TestAccountLookups(t *testing.T) {
252186
lookupConfig := chainwriter.AccountLookup{
253187
Name: "InvalidAccount",
254188
Location: "Inner.Accounts.PublicKey",
255-
IsSigner: chainwriter.MetaBool{Location: "ExternalBools"},
256-
IsWritable: chainwriter.MetaBool{Location: "ExternalBools"},
189+
IsSigner: chainwriter.MetaBool{BitmapLocation: "Bitmaps"},
190+
IsWritable: chainwriter.MetaBool{BitmapLocation: "Bitmaps"},
257191
}
258192

259193
args := TestAccountArgsExtended{
260194
Inner: InnerAccountArgs{
261195
Accounts: accounts[:],
262196
},
263-
ExternalBools: []bool{true, true},
197+
Bitmaps: []uint64{5, 3},
264198
}
265199

266200
_, err := lookupConfig.Resolve(ctx, args, nil, nil)
267-
require.Contains(t, err.Error(), "boolean array length 2 doesn't match pubkey count 3 for location")
201+
require.Contains(t, err.Error(), "bitmap value is not a single value")
268202
})
269203

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

273207
for i := 0; i < 3; i++ {
@@ -280,8 +214,8 @@ func TestAccountLookups(t *testing.T) {
280214
lookupConfig := chainwriter.AccountLookup{
281215
Name: "InvalidAccount",
282216
Location: "Inner.Accounts.PublicKey",
283-
IsSigner: chainwriter.MetaBool{Location: "Invalid.IsSigner"},
284-
IsWritable: chainwriter.MetaBool{Location: "Invalid.IsWritable"},
217+
IsSigner: chainwriter.MetaBool{BitmapLocation: "Invalid.Bitmap"},
218+
IsWritable: chainwriter.MetaBool{BitmapLocation: "Invalid.Bitmap"},
285219
}
286220

287221
args := TestAccountArgs{
@@ -291,10 +225,10 @@ func TestAccountLookups(t *testing.T) {
291225
}
292226

293227
_, err := lookupConfig.Resolve(ctx, args, nil, nil)
294-
require.Contains(t, err.Error(), "error reading bools from location")
228+
require.Contains(t, err.Error(), "error reading bitmap from location")
295229
})
296230

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

300234
for i := 0; i < 3; i++ {
@@ -307,8 +241,8 @@ func TestAccountLookups(t *testing.T) {
307241
lookupConfig := chainwriter.AccountLookup{
308242
Name: "InvalidAccount",
309243
Location: "Inner.Accounts.PublicKey",
310-
IsSigner: chainwriter.MetaBool{Location: "Inner"},
311-
IsWritable: chainwriter.MetaBool{Location: "Inner"},
244+
IsSigner: chainwriter.MetaBool{BitmapLocation: "Inner"},
245+
IsWritable: chainwriter.MetaBool{BitmapLocation: "Inner"},
312246
}
313247

314248
args := TestAccountArgs{

pkg/solana/chainwriter/helpers.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,6 @@ func GetValuesAtLocation(args any, location string) ([][]byte, error) {
5151
buf := make([]byte, 8)
5252
binary.LittleEndian.PutUint64(buf, num)
5353
vals = append(vals, buf)
54-
} else if boolean, ok := value.(bool); ok {
55-
if boolean {
56-
vals = append(vals, []byte{0x01})
57-
} else {
58-
vals = append(vals, []byte{0x00})
59-
}
6054
} else {
6155
return nil, fmt.Errorf("invalid value format at path: %s, type: %s", location, reflect.TypeOf(value).String())
6256
}

pkg/solana/chainwriter/lookups.go

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package chainwriter
22

33
import (
44
"context"
5+
"encoding/binary"
56
"fmt"
67
"reflect"
78

@@ -29,14 +30,14 @@ type AccountConstant struct {
2930
type AccountLookup struct {
3031
Name string
3132
Location string
32-
// IsSigner and IsWritable can either be a constant bool or a location to a bool
33+
// IsSigner and IsWritable can either be a constant bool or a location to a bitmap which decides the bools
3334
IsSigner MetaBool
3435
IsWritable MetaBool
3536
}
3637

3738
type MetaBool struct {
38-
Value bool
39-
Location string
39+
Value bool
40+
BitmapLocation string
4041
}
4142

4243
type Seed struct {
@@ -107,18 +108,22 @@ func (al AccountLookup) Resolve(
107108
}
108109

109110
var metas []*solana.AccountMeta
111+
signerIndexes, err := resolveBitMap(al.IsSigner, args, len(derivedValues))
112+
if err != nil {
113+
return nil, err
114+
}
115+
116+
writerIndexes, err := resolveBitMap(al.IsWritable, args, len(derivedValues))
117+
if err != nil {
118+
return nil, err
119+
}
120+
110121
for i, address := range derivedValues {
111122
// Resolve isSigner for this particular pubkey
112-
isSigner, err := resolveMetaBool(al.IsSigner, args, i, len(derivedValues))
113-
if err != nil {
114-
return nil, err
115-
}
123+
isSigner := signerIndexes[i]
116124

117125
// Resolve isWritable
118-
isWritable, err := resolveMetaBool(al.IsWritable, args, i, len(derivedValues))
119-
if err != nil {
120-
return nil, err
121-
}
126+
isWritable := writerIndexes[i]
122127

123128
metas = append(metas, &solana.AccountMeta{
124129
PublicKey: solana.PublicKeyFromBytes(address),
@@ -130,38 +135,30 @@ func (al AccountLookup) Resolve(
130135
return metas, nil
131136
}
132137

133-
func resolveMetaBool(mb MetaBool, args any, pubkeyIndex, pubkeysCount int) (bool, error) {
134-
if mb.Location == "" {
135-
return mb.Value, nil
138+
func resolveBitMap(mb MetaBool, args any, length int) ([]bool, error) {
139+
result := make([]bool, length)
140+
if mb.BitmapLocation == "" {
141+
for i := 0; i < length; i++ {
142+
result[i] = mb.Value
143+
}
144+
return result, nil
136145
}
137146

138-
boolVals, err := GetValuesAtLocation(args, mb.Location)
147+
bitmapVals, err := GetValuesAtLocation(args, mb.BitmapLocation)
139148
if err != nil {
140-
return false, fmt.Errorf("error reading bools from location '%s': %w", mb.Location, err)
149+
return []bool{}, fmt.Errorf("error reading bitmap from location '%s': %w", mb.BitmapLocation, err)
141150
}
142151

143-
if len(boolVals) == 0 {
144-
return false, fmt.Errorf("no boolean found at location '%s'", mb.Location)
152+
if len(bitmapVals) != 1 {
153+
return []bool{}, fmt.Errorf("bitmap value is not a single value: %v, length: %d", bitmapVals, len(bitmapVals))
145154
}
146155

147-
// boolVals should always equal the number of pubkeys or 1
148-
if len(boolVals) != pubkeysCount && len(boolVals) != 1 {
149-
return false, fmt.Errorf(
150-
"boolean array length %d doesn't match pubkey count %d for location '%s'",
151-
len(boolVals), pubkeysCount, mb.Location,
152-
)
156+
bitmapInt := binary.LittleEndian.Uint64(bitmapVals[0])
157+
for i := 0; i < length; i++ {
158+
result[i] = bitmapInt&(1<<i) > 0
153159
}
154160

155-
// a single boolean value is valid to apply to all pubkeys
156-
data := boolVals[0]
157-
158-
if len(boolVals) > 1 {
159-
data = boolVals[pubkeyIndex]
160-
}
161-
if len(data) == 0 {
162-
return false, fmt.Errorf("missing data for boolean at index %d in location '%s'", pubkeyIndex, mb.Location)
163-
}
164-
return data[0] != 0, nil
161+
return result, nil
165162
}
166163

167164
func (alt AccountsFromLookupTable) Resolve(_ context.Context, _ any, derivedTableMap map[string]map[string][]*solana.AccountMeta, _ client.Reader) ([]*solana.AccountMeta, error) {

0 commit comments

Comments
 (0)