-
Notifications
You must be signed in to change notification settings - Fork 505
Apps: txn.Access list for access to more resources #6286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 9 commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
e19795b
Initial stuctures and consensus flags for txn.Access
jannotti 98272a3
Committing before some state delta cleanup
jannotti b8578c3
TestAssets test coverage for tx.Access
jannotti 872e497
wellFormed for tx.Acccess checks internal indices
jannotti dbbd1bd
Testing and fixes for cross-product resources
jannotti 2ad657d
Many app call well-formed tests for tx.Access
jannotti 13bf5c7
Reflection based testing for Empty() completeness
jannotti 4609198
Correctly check and test for handling multiple types in one elt
jannotti 62751b6
Test fixes for quota bump
jannotti 728815a
NearZero testing
jannotti 5b820c5
Add goal switches to populate access list transactions.
jannotti 3e12d5a
Merge remote-tracking branch 'upstream/master' into access-list
jannotti 3bcbb16
Merge remote-tracking branch 'upstream/master' into access-list
jannotti 0bbfc58
Fixup Empty check
jannotti 357404c
Shorter wait for deprecation window
jannotti aff49f2
Export the newly added types for access list
jannotti edadbff
Merge remote-tracking branch 'upstream/master' into access-list
jannotti 1bac31f
goal e2e sub tests
jannotti a4831f7
Don't let pre resource sharing programs use tx.Access
jannotti 7972351
Add checks for version / access
jannotti 6551371
Merge remote-tracking branch 'upstream/master' into access-list
jannotti 4628e98
Give a txn so checkprograms doesn't panic in test
jannotti b31d52e
Repeat app-assets e2e test, btu for --access
jannotti 656e398
Fixups to use ver9 to test access, and shellcheck problems
jannotti 3e00dbc
Use `exit 1` after bare use of `[[ ... ]]`
jannotti 93cdf2f
Remove code that is useless since ver >= sharedResourcesVersion
jannotti db6cd4e
Use + to separate parts of a holding or local.
jannotti c1ea94b
Merge remote-tracking branch 'upstream/master' into access-list
jannotti 481ce3b
Update data/transactions/logic/evalStateful_test.go
jannotti 6d01ada
Describe availaibility under tx.Access
jannotti be9f82d
Unit test for cliAddress
jannotti f3b2375
Update scripts/export_sdk_types.py
jannotti 658ac8f
clarity
jannotti 801dc21
Remove inadvertant changes
jannotti 82b6abb
No need for separate subtests, just assert in loop
jannotti 81ae84a
CR typos
jannotti f806cb2
Don't use XXX in comment since people use it to mean TODO
jannotti 7434d1f
comment on 0 interpretation
jannotti 59e60b7
comment on 0 interpretation
jannotti dd13b79
Remove bad comment
jannotti b0e1211
CR updates
jannotti a28efb3
remove unneeded empty tests
jannotti bde4541
Merge remote-tracking branch 'upstream/master' into access-list
jannotti 819129d
Merge remote-tracking branch 'upstream/master' into access-list
jannotti 35572ee
Update data/transactions/logic/resources.go
jannotti File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
// Copyright (C) 2019-2025 Algorand, Inc. | ||
// This file is part of go-algorand | ||
// | ||
// go-algorand is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU Affero General Public License as | ||
// published by the Free Software Foundation, either version 3 of the | ||
// License, or (at your option) any later version. | ||
// | ||
// go-algorand is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU Affero General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU Affero General Public License | ||
// along with go-algorand. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
package testing | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
"time" | ||
) | ||
|
||
// NearZeros takes a sample in order to retrieve its type. It returns a slice of | ||
// the same type in which each element of the slice is the same type as the | ||
// sample, but exactly one field (or sub-field) is set to a non-zero value. It | ||
// returns one example for every sub-field. | ||
func NearZeros(t *testing.T, sample any) []any { | ||
jannotti marked this conversation as resolved.
Show resolved
Hide resolved
|
||
typ := reflect.TypeOf(sample) | ||
// If sample is a pointer, work with the underlying type. | ||
if typ.Kind() == reflect.Ptr { | ||
typ = typ.Elem() | ||
} | ||
if typ.Kind() != reflect.Struct { | ||
t.Fatalf("NearZeros: sample must be a struct, got %s", typ.Kind()) | ||
} | ||
paths := CollectPaths(typ, []int{}) | ||
var results []any | ||
for _, path := range paths { | ||
inst := makeInstanceWithNonZeroField(typ, path) | ||
results = append(results, inst) | ||
} | ||
return results | ||
} | ||
|
||
// CollectPaths walks over the struct type (recursively) and returns a slice of | ||
// index paths. Each path points to exactly one (exported) sub-field. | ||
func CollectPaths(typ reflect.Type, prefix []int) [][]int { | ||
var paths [][]int | ||
|
||
switch typ.Kind() { | ||
case reflect.Ptr, reflect.Slice, reflect.Array: | ||
// Look through container to the element | ||
return CollectPaths(typ.Elem(), prefix) | ||
|
||
case reflect.Map: | ||
// Only collect paths into the value, not the key | ||
return CollectPaths(typ.Elem(), prefix) | ||
|
||
case reflect.Struct: | ||
// Special case: skip known value-type structs like time.Time | ||
if typ == reflect.TypeOf(time.Time{}) { | ||
return [][]int{prefix} | ||
} | ||
|
||
for i := 0; i < typ.NumField(); i++ { | ||
field := typ.Field(i) | ||
if !field.IsExported() { | ||
continue | ||
} | ||
newPath := append(append([]int(nil), prefix...), i) | ||
subPaths := CollectPaths(field.Type, newPath) | ||
|
||
// If recursion yielded deeper paths, use them | ||
if len(subPaths) > 0 { | ||
paths = append(paths, subPaths...) | ||
} else { | ||
// Otherwise, it's a leaf field — include it | ||
paths = append(paths, newPath) | ||
} | ||
} | ||
|
||
default: | ||
// Primitive type — record this as a leaf | ||
paths = append(paths, prefix) | ||
} | ||
|
||
return paths | ||
} | ||
|
||
// makeInstanceWithNonZeroField creates a new instance of type typ and sets exactly one | ||
// field (identified by the fieldPath) to a non-zero value. | ||
func makeInstanceWithNonZeroField(typ reflect.Type, fieldPath []int) any { | ||
// Create a new instance (as a value, not pointer). | ||
inst := reflect.New(typ).Elem() | ||
setFieldToNonZero(inst, fieldPath) | ||
return inst.Interface() | ||
} | ||
|
||
// setFieldToNonZero navigates along the given path in the value v and sets that | ||
// field to a non-zero value. The path is a slice of field indices. | ||
func setFieldToNonZero(v reflect.Value, path []int) { | ||
// Walk down the struct fields until the final field. | ||
for i := 0; i < len(path)-1; i++ { | ||
v = v.Field(path[i]) | ||
switch v.Kind() { | ||
case reflect.Ptr: | ||
if v.IsNil() { | ||
v.Set(reflect.New(v.Type().Elem())) | ||
} | ||
v = v.Elem() | ||
case reflect.Slice: | ||
if v.Len() == 0 { | ||
slice := reflect.MakeSlice(v.Type(), 1, 1) | ||
v.Set(slice) | ||
} | ||
v = v.Index(0) | ||
case reflect.Array: | ||
v = v.Index(0) // Already allocated, just descend | ||
} | ||
} | ||
// Set the final field to an appropriate non-zero value. | ||
field := v.Field(path[len(path)-1]) | ||
if field.CanSet() { | ||
field.Set(exampleValue(field.Type())) | ||
} | ||
} | ||
|
||
// exampleValue returns a non-zero value for a given type. | ||
// For composite types (like arrays), it sets one element. | ||
func exampleValue(t reflect.Type) reflect.Value { | ||
switch t.Kind() { | ||
case reflect.String: | ||
return reflect.ValueOf("non-zero").Convert(t) | ||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
return reflect.ValueOf(1).Convert(t) | ||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||
return reflect.ValueOf(1).Convert(t) | ||
case reflect.Bool: | ||
return reflect.ValueOf(true).Convert(t) | ||
case reflect.Float32, reflect.Float64: | ||
return reflect.ValueOf(1.23).Convert(t) | ||
case reflect.Ptr: | ||
// For pointers, allocate a new element and set it to non-zero. | ||
elem := reflect.New(t.Elem()) | ||
elem.Elem().Set(exampleValue(t.Elem())) | ||
return elem | ||
case reflect.Slice: | ||
// Create a slice with one element. | ||
slice := reflect.MakeSlice(t, 1, 1) | ||
slice.Index(0).Set(exampleValue(t.Elem())) | ||
return slice | ||
case reflect.Map: | ||
// Create a map with one key-value pair. | ||
m := reflect.MakeMap(t) | ||
m.SetMapIndex(exampleValue(t.Key()), exampleValue(t.Elem())) | ||
return m | ||
case reflect.Array: | ||
// Create an array and set the first element. | ||
arr := reflect.New(t).Elem() | ||
if t.Len() > 0 { | ||
arr.Index(0).Set(exampleValue(t.Elem())) | ||
} | ||
return arr | ||
case reflect.Struct: | ||
// For structs, set the first exported field (if any). | ||
s := reflect.New(t).Elem() | ||
for i := 0; i < t.NumField(); i++ { | ||
f := t.Field(i) | ||
if f.IsExported() { | ||
fv := s.Field(i) | ||
if fv.CanSet() { | ||
fv.Set(exampleValue(f.Type)) | ||
break | ||
} | ||
} | ||
} | ||
return s | ||
default: | ||
panic("unable to make a non-zero: " + t.String()) | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.