-
Notifications
You must be signed in to change notification settings - Fork 494
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
base: master
Are you sure you want to change the base?
Conversation
This shouldn't need a new AVM version, correct? Since AVM9 we've had group resource sharing, which means an app has no way of knowing what resources are available. Although I suppose it could check if it's an outer call and check the rest of the group, but seems highly improbable to account for all the sharing rules even if an app wanted to do that. |
I think you're asking "will only new programs, AVM v12, be able to use this?" I think it should be ok to let old programs use this, including letting these resources be accessed by other programs in the same group that are a low version. I'm pretty sure we made the same decision with resource pooling. After the consensus upgrade, programs suddenly got access to things they didn't "know" they had access to by looking into the arrays. I'll have to confirm whether we put in any limitations. For example, I think it would be unsafe to let v3 (!) programs see extra ASAs. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6286 +/- ##
==========================================
+ Coverage 51.68% 51.81% +0.13%
==========================================
Files 649 651 +2
Lines 86857 87236 +379
==========================================
+ Hits 44893 45204 +311
- Misses 39099 39169 +70
+ Partials 2865 2863 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Right that's what I would think as well. The main reason I ask is because if we don't require a specific AVM version existing applications, even if immutable, can leverage this feature by simply updating their client-side code. |
This commit ensures that assets are made available properly with tx.Access
Having worked on it some more: Yes, any transaction can use As for sharing, we only enabled sharing for v9 programs and higher, so I made that true here as well. Your v9 or higher programs will be able to see the resources made available from other transactions, whether those transactions made the resources available with the "old-style" foreign arrays or with Like |
98e1981
to
1573e6b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Left some comments
- Empty box ref in Access gaining extra reads budged should be somehow better documented
data/transactions/application.go
Outdated
rr.Holding.Empty() && rr.Locals.Empty() && rr.Box.Empty() | ||
} | ||
|
||
// wellFormed checks that a ResourceRef is either empty or of only one kind, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably requires some clarification that rr
is one of access
elements. Maybe a better interface would be a free function taking access
and looping over it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some clarification.
The main wellFormed() function for app calls is pretty much what you're describing (though it has other checks too.
It does this:
for _, rr := range ac.Access {
if err := rr.wellFormed(ac.Access, proto); err != nil {
return err
}
}
Would you like it better if the whole loop was pulled into it's own function, instead of the "inner" part of the loop as rr.wellFormed()
?
return basics.AppIndex(cx.txn.Txn.ForeignApps[ref-1]), nil | ||
return cx.txn.Txn.ForeignApps[ref-1], nil | ||
} | ||
// it seems most consistent to allow slot access into tx.Access if it is used with an old app. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks inconsistent - we do not allow both ForeignApps and Access use in a transaction but here (and in resolveApp
below) both are checked
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could not decide which makes for clearer code. Only one of A or B can be true, so is it nice to write:
if isA {
A
} else {
B
}
or nice to just write
A
B
I decided to go with the later to save space. Either A or B becomes a no-op because the length of one of the arrays is 0.
@@ -117,6 +118,10 @@ func (tx *Txn) internalCopy() { | |||
for i := 0; i < len(tx.Boxes); i++ { | |||
tx.Boxes[i].Name = append([]byte(nil), tx.Boxes[i].Name...) | |||
} | |||
tx.Access = append([]transactions.ResourceRef(nil), tx.Access...) | |||
for i := 0; i < len(tx.Access); i++ { | |||
tx.Access[i].Box.Name = append([]byte(nil), tx.Access[i].Box.Name...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check for non-empty tx.Access[i].Box
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just copying the name for immutability. If it's nil, it stays nil. That's why I used the weird construct of append
onto nil
. That function does it a lot, for the Note
, ApplicationArgs
etc.
Check out this beauty, co-authored by chatgpt.
// 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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a simple random test creating a struct with reflect with a few fields of random type and make sure this function returns that exact number of element in a slice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean a test for NearZeros
itself? I agree, I'll write some.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
f04ef4d
to
9371062
Compare
This required changes to libgoal interfaces that we previously designed to take all the foreign arrays, ready for packing into the transaction. Now they receive a "RefBundle" of things the tx needs access to, so it should be possible to change that to use tx.Access. Still needs final e2e subs tests using goal.
Summary
Today, app developers find it frustrating that they can only list 8 resources in a transaction. This number is artificially low because there are rules that allow access to many more than 8 items when, for example, 4 account and 4 apps are listed.
This PR introduced a single unified
Access
field on app calls, which contains all accounts, apps, asas, and boxes that the transaction can touch. Because no extra rules allow access to extra resources, we can expand the allowable size of such a list. 32 seems likely. (edit: currently thinking 16, but also upping the box quota per reference to 2k)This will probably increase performance, since it will now be reasonable to perform perfect prefetching of all resources an app call might touch.
This PR does not yet augment
goal
to create such transactions. It probably should, as that is also the best way to write e2e tests.This PR does not actually implement the improved pre-fetching. Should it?
Test Plan