Giter Site home page Giter Site logo

Comments (3)

orodio avatar orodio commented on July 19, 2024

So good news, this is a thing we know about and are thinking about; and I love that you have picked up on it as a thing.

We are thinking about this in a couple of ways. But probably the most realistic way is to look at it, is as the various permutations of a transaction. From simplest to most complicated, conceptually below capital letters will be variables representing a composite identity of a Flow address and KeyId for the given Flow address. A = (FlowAddr1, KeyId1), B = (FlowAddr1, KeyId2) C = (FlowAddr2, KeyId1) We do not mean at this point in time that A represents a concept like the current user, we are working a layer below that on the address/key pair layer. We will also be using the following function to express a transaction tx(proposer, payer, authorizers = []). For the purposes here we will assume that all keys have full weight unless otherwise mentioned (this gets far more complicated when the keys don't have full weight).

The simplest transaction is tx(A, A), in this case the proposer and payer are the same, it Requires a single signature on the envelope message by A. The sequence number of A is used, and A will also be paying for the transaction.

We think that the next simplest transaction is tx(A, A, [A]) as it still only requires a single signature on the envelope message. In this case we are still using A for the sequence number and payer, but this transaction will be able to destructively modify (given a full weight of A) resources owned by A. We believe that (at least in the beginning) these will be the most prominent transactions as they are the closest to what people are already doing.

Conceptually (not technologically) the next simplest is probably tx(A, A, [A, B]), it's fundamentally the same as the last one but now we can destructively modify resources (Given a full weight of B) owned by B as well. This transaction is our first requiring two signatures, A signing the envelope message while B is signing the payload message. Technologically, if B is a different person, we are a little ways away from being able to pull this one off, we have some ideas of how to do this though and may not be as far off as people think. One of the main reasons this comes next in our simplest hierarchy is conceptually this concept hopefully still makes sense to most people, its use-cases could still be explained quickly and shortly and the other party understanding fairly quickly whats going on.

Let's drop a couple variables and go to the next simplest, tx(A, B). Using the sequence number for A while B pays for things, meaning A signs the payload message, while B signs the envelope message. A cool thing can happen here, if A has a weight of zero, it has no authority, but its sequence number can still be used (a payload signature will still be required from it), internally we have been calling this a zero weight proposer. If a flow account has multiple keys, a couple of which have zero weight, they can be used to help avoid a sequence number mismatch, ie the wallet could give different dapps different keyIds meaning a dapp itself wouldn't need to worry about race conditions for the sequence number do to other transactions happening elsewhere at the same time.

Next are tx(A, B, [B]), tx(A, B, [A]), tx(A, B, [A, B]) they both have the same number and the same signatures as before, the main difference being that these transaction can destructively modify resources for the authorizers if they have full weight. In all of them the sequence number for A will be used while B pays.

tx(A, B, [C]), tx(A, B, [C, A]), tx(A, B, [C, B]), tx(A, B, [C, A, B]) here are when things start getting interesting, these are our first examples that requires three signatures. A and C need to sign the payload message, while B needs to sign the envelope message. This is probably the main case that a wallet provider wanting to pay for transactions for their users will be dealing with. Unfortunately there is an additional case that makes that more complicated, which is...

These tx(A, B, [C, D]), tx(A, B, [C, D, E]), tx(A, B, [C, D, ...n]) require 4+ signatures. We will look at the first example (tx(A, B, [C, D])) as we will be able to see why this can be an issue regarding intention and when a wallet provider might want to pay for the transaction. The SDK has no concept of a current user because Flow has no concept of a current user, so a wallet deciding to pay if the current user is one of their users can't be expressed at a SDK level, but FCL does have this concept, which means we need a way to know how to substitute in a payer that is the wallet given certain situations.

The above idea that you supplied as a possible solution is a really great proposal, it means you are already thinking in terms of the wallet telling FCL how to behave, but it is slightly off to what we had in mind to solve this problem, none of this is set in stone and any of it can be changed if needed so work with us to make this better please, but this is what we were thinking, the beginning of which is already sort of there, but like I said, it can definitely change. All feedback is welcome.

Currently there are three resolvers. We care about a single one of them which is resolveAccounts. resolveAccounts takes that fcl.currentUser().authorization, and tries to turn it into an account that can be used to sign transactions (also get the sequence numbers if its a proposer). It doesn't do any of the work though, it passes the fcl.currentUser().authorization function an empty account that includes the role. fcl.currentUser().authorization is then responsible to return a valid account that can perform that role, if it can't there will be an invariant error. In our mind fcl.currentUser().authorization is where that logic of outputting a wallet providers payer address and key and signing function should go.

So what if during the handshake there were additional hooks that had to do with deciding the account, if present we can call out to it and request for the account information, needed to build out a proposer/payer/authorizer?

{
  addr: "0x7gfafg563defg2cd",
  keyId: 0, 
  identity: {},
  authorizations: [],
  account: { // would be used to fetch the account/authorization hooks
    type: "HTTP/POST",
    endpoint: "https://porto...",
    params: { id: "asdfadsfasdf" }
  },
}

This would put these aspects of the transaction in the wallets control if required, but would default back to how things are now if not present.

Currently the resolveAccounts is made of two smaller resolvers, one that does the resolution and one that does the deduping. We would probably want to keep the current logic how it is, but add in a third smaller resolver that handles exclusively this aspect, currently I would put it after the initial account resolving but before the deduping, eventually we could maybe have it after the deduping and have the response of the hook be able to return multiple values that can be used as necessary.

As stated earlier all of this can change if needed, and diverse opinions from diverse perspectives like yours are incredibly important to produce the best results, we put immense value on all feedback we get so don't hesitate with your thoughts and concerns on this approach, or even proposing other approaches all together.

@boczeratul thoughts? Would something like this solve your issues? Are we missing something? What are your thought in general on this approach? How can we make this better? Are we missing some aspect of the pain/burden you are trying to alleviate?

from fcl-js.

boczeratul avatar boczeratul commented on July 19, 2024

@orodio Thank you so much for the detailed answer. You've it clear to me what are the scenarios you have in mind for account resolution.

I've thought about putting the logic in fcl.currentUser().authorization as well, but wasn't sure which is more aligned with the overall FCL design you have in mind.

Your solution proposal looks pretty good to me. It is general enough to work with the various use cases you've mentioned and it certainly solves the issue.

from fcl-js.

orodio avatar orodio commented on July 19, 2024

Closing this, there will be some fairly comprehensive docs that will cover all of this soon. @boczeratul I will ping you on discord when they become available.

from fcl-js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.