#Top Authorizations

51 messages · Page 1 of 1 (latest)

random nexus
#

What's the motivation for only exposing top-authorizations in the recorded_top_authorizations, vs exposing every instance that require_auth is called?

I'm wondering if it would be okay to expand it to be all authorizations, rather than just top ones.

cc @sharp maple

sharp maple
#

usability and usefulness: it's much easier to specify the flat list on one hand and most of the time the inner authorizations are not relevant. the tree version should be there as well, but I never really had time for it.

#

e.g. if a contract calls token transfer you, of course could verify that the token authorization has been called, but that would just cover SAC code in your test

random nexus
#

I'm less interested in a tree. The flat list is easier, but afaict if I'm trying to test that a require_auth occurs in a subcontract call, my test has to assert that the auth happened in the root call, which is confusing.

sharp maple
#

yeah, we definitely need a tree version

random nexus
#

We could have a flat list of all require_auth's, so instead of including the root, it'd be the subcontract call in the list.

#

If both the root and subcontract call require_auth, then both can be in the list.

sharp maple
#

(topologically; the format can be whatever is convenient)

#

flattening tree to a list would be somewhat inconvenient as every vertex has to be duplicated. but maybe that's better than recursive structure - not really sure here...

#

i.e. list would be [A, A->B, A->B->C], while tree is just A->B->C

random nexus
#

For a call tree A->B->C where A and C call require_auth, I think the list can be: [A, C]

#

But yeah, exposing the full call tree would provide that info too.

sharp maple
#

sure; what I mean is that if the factual tree is A->B->C ,then with the list-based approach you need to specify the whole tree path for every item, which is a bit verbose

random nexus
#

Actually, I'm getting confused, I see a comment saying that the "top authorization" is the first to have called require_auth.

sharp maple
#

yes, that's the tree root

random nexus
#

So AuthorizationTrackers root invocation is always the first in a call tree who called require_auth? Even in enforced auth?

sharp maple
#

the name kind of sucks

#

yes, that's intentional

#

and allows batching operations or doing routing

random nexus
#

So if I specify ContractAuth call tree of A->B->C, and only C calls require_auth, then the AuthorizationTracker for that call tree will have a root invocation of C?

sharp maple
#

yes

random nexus
sharp maple
#

right, but the mapping from the tree to the actual call stack is performed by the auth manager

#

'root' in ContractAuth tree refers to the root of the tree you're authorizing on your behalf. it doesn't need to match to the root of the contract invocation

random nexus
#

Ok got it. So the top level authorization could be a contract that didn't call require_auth, if a developer included calls higher in the call tree than they needed. Is that accurate?

#

In recording mode it will always be the first point where require_auth is called, but when used on a network, someone could pass a ContractAuth containing a root that never needed auth and that never called require_auth. And in our definition of the top-level authorization, it would be the ContractAuth root?

sharp maple
#

doesn't seem so, but I might misunderstand this. the top authorization matches the 'first' require_auth call(s) in the tree (i.e .roots of the 'condensed' trees in the forest, as per doc above)

#

someone could pass a ContractAuth containing a root that never needed auth
this would not be matches to the invocations and hence the transaction will fail

#

. And in our definition of the top-level authorization, it would be the ContractAuth root?
yes, these are roots of the ContractAuth entries, which might or might not coincide with the top-level call

#

I know this is hard to digest; I guess that's the cost of flexibility. I hope 95+% of the time only the simple trees are needed and there is no need to understand all the intricacies...

random nexus
#

I don't think I understand this yet, but I'll try writing a few tests to see if I can piece together from the behavior I see what the invariants and principles are.

#

I think auth is an area we need to find a way for every intricacy to be easily understood.

cloud oasis
random nexus
cloud oasis
#

BTW, not entirely relevant, but since "declarative" was used at some point to explain auth, I always wondered why we didn't use decorators for fn, like #[private] and #[payable] to restrict the invokercaller? (like NEAR)

sharp maple
#

this has been a consideration, but rust doesn't really have decorators

#

something might be doable with macros though...

cloud oasis
random nexus
#

You can have private functions, just drop the pub, and other contracts won't be able to call them.

cloud oasis
sharp maple
#

yeah, sure. I didn't succeed at trying to do 'decorator' style macro attributes inside contractimpl, but I'm not proficient enough at proc macros though

#

but it definitely cause at least some friction due to macro nesting

random nexus
#

We could add decorators for require_auth on addresses I guess, but I think what we've landed on is already as simple, and the decorator raises more questions as a reader.

sharp maple
#

like macro could auto-generate an address argument... but at that point it seems to be more confusing than readable

cloud oasis
#

thank you both for answering! I just had that question on the back of my mind for way too long 🙂

cloud oasis
sharp maple
#

well, there were a few threads regarding the 'invoker' (not in a decorator context, just in general)... but really I'm not sure if introducing it artificially would make things simpler. also for the simple cases it's 1 line of code (decorator) vs 1 line of code (require_auth)

cloud oasis