"Contract" terminology - a dissenting opinion

True, but I don’t think we want to separate those steps in practice. We currently call the last step “finalize,” but I think “complete” or “completar” (in Spanish) is more in line with what the last step really means. It should be a trade-off, I don’t believe those 10 principles are the 10 Commandments, but I have seen these principles put into practice and the results are surprisingly positive.

Let me be more specific.

Sender creates the transaction:

$ grin-wallet transaction draft

(the output is an incomplete slate or draft)

Recipient accepts the transaction:

$ grin-wallet transaction accept 

(the input here is an incomplete slate or draft)
(the output is a partially signed transaction, is not a draft because it is “reviewed” and then “accepted”)

Sender completes the transaction:

$ grin-wallet transaction complete

(the input is a partially signed transaction)

In the last step the transaction is finalized or “completed”, which means “signed by sender and broadcasted”.

This could be also well translated into a GUI based on a more intuitive API. If SRS and RSR is unified this also applies. Then we could have one single consistent flow: Draft - Accept - Complete or DAC.

2 Likes

If it starts with transaction I like it… I think “transaction new” might be more conservative but draft looks ok when I see it like this.

But I’ll bow out of the discussion beyond the first part of the command, because I don’t know the mechanics of the transaction building process well enough to form an opinion on the rest.

2 Likes

Let me start with reminding why we want to introduce the word Sign in the terminology. The reason why want to let people see this word is because ‘Signing’ is a universal concept, its unambiguous and it does not focus on the process or order of steps but on the product, a collection of signatures. Signing generalizes/unifies all type of transactions and transaction flows. Everyone knows that if you sign a contract, bank statement, transaction, draft, or even an agreement on the napkin in a restaurant, you use your power of authority by signing. So in my opinion it is one of the most universally accepted words and concepts there are. The reason why we do not want to focus on the step in the process is because no matter what the complexity of the process is, signing is what matters. You can sign a contract with many people, you can sign a MultiSig draft | transaction | contract or whatever. Here the focus is not on the steps but on the signatures. For example, we have a MultiSig and the transaction slate is being send forward between multiple parties many times. Is someone accepting the transaction…, or sending… it becomes very confusing. No, the person is signing the draft | transaction | contract !

But hold on, why is no else using the word “Sign” than if it is so universal? Well, they are. If you ever signed a transaction in the Bitcoin Electrum wallet, the steps are as follows. You import a .psbt file or psbt text (sounds familiar right, very similar to transaction slates) and you click the…wait for it… :drum:“Sign” button.
So in all the years of its existence, you see that the Bitcoin community came up with exactly the same terminology we now propose since it works so well for transactions that require multiple Signatures. So keep in mind that Bitcoin uses a “Sign” button for any transaction that involves more than 1 signature.
But why then would we use a “Sign” button for regular transactions in Grin? Because unlike Bitcoin, Grin always involves multiple Signatures. In Bitcoin you have a “Sign” Button for any transaction with more than 1 signature, hence it would be very logical to use “Sign” as word in a button or command in Grin since we always need multiple signatures for a transaction.

You do have a good point about Sign having different implications for signing a Send or Receive transaction. Although I am personally convinced “Sign” should be the primary word here, we could use an extra word in buttons or wallet commands to show this information. E.g.

“Contract Send” | “Draft Transaction contract”
“Sing & Send” |
“Sign & Receive” | “Sign & Accept” | Sign & Complete|

Alternatively, we can also use the generalized “Sign” button everywhere, but show very clearly Send: amount, or Receive amount to make it clear to the user if he is sending or receiving something.
For more complex transactions that require more than 2 signatures, always using the “Sign” button without extra words makes sense, just like Bitcoin does right now.

This is exactly the reason why I am so convinced of using the word Sign. If you would just use “Accept”, “Receive”,“complete”, “finalize”, all these extra terminologies hide what truly matters for a transaction and a user, you signed for something. No one should care about the under the hood details of transaction flows, or steps involved. Transactions should be simple. If you sign, you agree, if you do not sign, you do not agree. For simple transactions we can add the context words such as ‘Send’ and ‘Receive’, I would not change these.

This is an argument for “Sign”, a simple word expresses all that really matters, the action of signing a transaction | contract.

I get where you are coming from, but this is procedural thinking. Personally I do not want the user to think about procedures, since the procedures are more complex than just collecting a set of signatures/check-marks. If you emphasize the procedure, this would becomes very complex for more complex transactions involving many steps that could be performed in many different orders, such as MultiSig transactions. The user does not need to know or care, about the order of steps, or number of steps, the user only needs to care about collecting the signatures/check-marks.

We could also let naming be guided be more general n party transactions. In that case, the simplest slate flow is a forward pass followed by a backward pass

party1 → party2 → … → partyN → partyN-1 → … → party 1

and the steps could be called

new → addkey1 → addkey2 → … → addkeyN → signkeyN → … → signkey1 → broadcast

(one could also designate the relay of a slate to the next party as a separate step).
new and addkey1 are both done by party1 and would thus be joined, as are addkeyN and signkeyN, and signkey1 and broadcast.
Thus we end up with 2*N-1 steps:

new_addkey1 → … → addkeyN-1 → … → addsignkeyN → signkeyN-1 → … → signkey2 → signkey1broadcast

In the simple case of 2 parties, this becomes the 3 steps

new_addkey1 → addsignkey2 → signkey1broadcast

Now, if you name these Draft, Accept and Complete, does that mean the general case is named

Draft → Accept2 → … → AcceptN-1 → CompleteN → … → Complete1 ?

That would violate the principle of the same name denoting the same steps.

2 Likes

No, nobody has talked about the “setup” phase so far in this topic since there was no 3+ multisig example. Assume we have 3 people, 1 sender and 2 receivers (R1, R2) where the sender (S1) starts the tx. There are multiple ways to create a valid tx.

  1. S1 setup - R1 setup - R2 setup&sign - R1 sign - S1 sign
  2. S1 setup - R2 setup - R1 setup&sign - R2 sign - S1 sign
  3. S1 setup - R1 setup - R2 setup&sign - S1 sign - R2 sign
    Etc etc.
    So whoever is the last person to sign is not known in advance and when you get a contract you need to know whether you are or not to know whether to call accept or complete. To me it seems much simpler to just sign and if it’s the last one also broadcast since in almost all cases you want tx to go through immediately after it gets all of the required signatures. UX would of notify the user that tx has been broadcasted and before he would click sign he would see 2/3, so he would know only his signature is missing. For cases where you don’t want to broadcast you can have a flag/checkbox. To me slatepack1 is not a draft when the only thing missing is signatures, otherwise every contract would also be a draft which sounds very confusing to me. If it is a draft then it’s a draft only until it gets through all “setup” phases (so it changes from draft to a completed doc before you start signing).
1 Like

Good discussion. I suggest to take transaction broadcast out of the debate and focus on building a transaction. Broadcasting it to the network is a separate thing and the process should not assume who broadcasts it as it could be sent to a mixer or whatever.

One important thing that was mentioned above is that each party does 2 things:

  1. adds keys - this is what I referred to as setup
  2. signs - this is what I referred to as sign

So for each party, it must be the case they went through these two phases regardless of how we call them. The new is separate from setup because you can’t do setup if you have nowhere to add the keys. Someone has to create a slate. So new is a create slate and perform setup. I think whatever we agree on, it must be true that the words are “self-isolated”. They must not assume any order of execution. Why is this a requirement? Because transaction building doesn’t have a strict order. Let’s take SRS as an example and describe it with the two phases above:

   setupS -> setupR -> signR -> signS
=> setupS -> (setupR -> signR) -> signS

We were able to join two consecutive phases because they could be done at the same time by the receiver. This is what we call SRS. But this order isn’t strict to the process or inherent. It could be

setupS -> setupR -> signS -> signR

This would also produce a valid transaction. Receiver did the setup phase separately from the sign phase. You only need to satisfy that before the first party signs, everyone else must have performed the setup phase. This means that you can have any party permutation during setup phases and similarly, any party permutation during the sign phase.

      any permutation here               any permutation here
--------------------------------    -----------------------------
(setupX -> setupY -> ... setupU) -> (SignZ -> signY -> ... signK)

The wording used needs to avoid having relation between the previous or the next step. It should be self contained. My understanding is this is needed to scale transaction building to more than 2 parties without having that be an edge case. The following are all valid:

setupA -> setupB -> setupC -> signC -> signB -> signA

setupA -> setupB -> setupC -> signC -> signA -> signB

setupA -> setupB -> setupC -> signA -> signB -> signC
...

Introducing order through names of actions breaks this flexibility and introduces problems and inconsistency when more than 2 parties are involved or less than 2 parties. Ideally, a self-spend would not be an edge case. Perhaps it’s better to try to come up with words in the context of a 3-party transaction and find a solution that works in that setting. Such a solution is more likely to work well for also for 2-party or 1-party transaction. One of the things I’d want is that a self-spend or a transaction between 3+ parties isn’t an edge case, ideally these would “just work” and be no different process than building any other transaction.

1 Like

Why you guys think bringing Electrum is making you any favors? In fact, it’s the opposite. Electrum’s popularity is based on longevity, its first commit was in November 2011 and then Bitcoin forks continued reusing the same code base; from the pool of wallets out there the worst option to pick is Electrum in terms of UX/UI. if you want to look into the future of usability look at DEXes, like SundaeSwap, ShushiSwap, 1inch, MetaMask, etc., the way these guys hid all the complexity behind a nice looking and easy to use interface is a total win. By bringing the CLI or Electrum is actually proving my point: you guys are too much focused on technicalities, and that focus is not doing you any favor in terms of usability.

What Bitcoin decided to use is irrelevant, no importante, mi amigo. I mentioned this many times. In general, people are not understanding what is the slatepack address used for. I don’t remember how many times I have had to explain to users how transactions works over and over again during the past years, and this is because users have Bitcoin in mind. We must embrace the uniqueness of Grin especially Interactivity. Grin is not Bitcoin 2.0 or anything like that, the further we move away from Bitcoin the better.

If we try to fit Grin on any of the Bitcoin UI/UX what we will end-up doing is limiting Grin.

I said this and I will say it again: “adding signatures” is not the only thing happening. Maybe you want to “simplify” things only using “Sign” but this means nothing but only adding a signature. This means nothing to the state of the entity in question, which is Transaction not a Contract. Nobody in the real world takes contracts out of their wallets. Thinking transaction as a contract is the problem, and if we are talking about contracts rather than transactions, one could be inclined to use Sign, because of course, in that context Sign makes total sense.

My starting point is that we are talking about a transaction. Initially the Transaction is drafted, so the action on the noun is draft. Then the transaction is reviewed and accepted, the transaction is not just signed, and this is important, when a transaction is accepted more happens than just adding a signature. So the action on the noun is accept, not just sign. So, for the Transaction to be completed, the Transaction must be broadcasted. You cannot use “Sign” in the last step because “Sign” in addition to what is already being hidden will also hide the fact that the Transaction is also broadcasted. For the last step, the action on the noun then becomes complete, not sign, because the Transaction is not completed until is broadcasted.

This applies to SRS:

A Transaction is drafted.
A Transaction is accepted.
A Transaction is completed.

This also applies to RSR.

A Transaction is drafted.
A Transaction is accepted.
A Transaction is completed.

Just a single unified self-explanatory flow: Draft - Accept - Complete or DAC.

Also, Signatures could be use in many other context in Grin, example: Authentication. You do not want to limit the Signature concept only to the Transaction, what you want is to make sure users understand that we use Signatures and these Signatures are not limited to the transaction building process.

This is bad UX practice, very bad. The effect of that is pure confusion.

It is not. You don’t want the same word to have several meanings, that is also a bad UX practice. The effect of that is pure confusion.

When S1, to draft (a transaction) is literally what you are doing in many languages, specially on those language derived from Latin, Greek and the Indo-European languages. If you are confused is because you are applying the verb to the wrong noun. “Drafting” means producing something (der Entwurf in German which is Draft) that will incorporate a result.

On S1 the something produced is a draft, but a draft of what? a draft of a transaction. Ask yourself, what is the intention of using a wallet? receive and send transactions, transactions not contracts, right? but what a wallet actually do? store and manage keys for transactions, and communicate with nodes and other wallets (in case of Grin). No one in the real-world is naming wallets as “keys handlers” which could be more technically accurate, people call these tools: “wallets”. These tools are being called wallets because of the nature of the problem they solve.

Using “Contract” instead of “Transaction” is counterproductive because it changes the whole meaning and says nothing about the purpose of the wallet, why is this important? Because a cryptocurrency wallet is not built to “setup contracts” or “sign contracts” or anything like that, why? because wallets are built to send and receive transactions, not contracts, transactions.

Electronic transactions for all” is written in grin.mw because that’s what Grin wants to achieve. Again, transactions, not contracts. Transactions. The fact that we are using signatures to create transactions is not a strong enough argument to alter the meaning of what a wallet or Grin does.

Yeah, this might be the only argument against using DAC, but let’s see if that is true…

I will respond to this separately, thanks for bringing up this.

I do not entirely disagree with this logic, but in practice we do not want to separate the final step from the broadcasting of the transaction because a transaction is not completed until the transaction is broadcasted. Broadcasting the transaction is what closes the transaction circle from the wallet perspective.

1 Like

I think these introduce the ordering concern I mentioned above. “Accept” introduces some order because it assumes “not last && not first” position. Similarly, “Complete” introduces order because it assumes the last sign position. To show the problem with Accept ordering, we can think of how we’d compose a self-spend transaction with these words. It would either be “Draft → Accept” and Complete would never be called, or “Draft → Complete” and it would never be accepted - both seem inconsistent with the understanding of the flow purpose afaict. Complete ordering shows itself as an issue when you have something else than ABA flow (like RSR or SRS). For instance in a 3-party flow you’d need to know at which position you are to decide whether you should call Accept or Complete. For a >2 party flow it would also require introducing a new word that does what setup does which is to only add the keys to the slate. From what I understand, both Accept and Complete do the signing in this scheme so the party that should only add the keys doesn’t have a word to use and hence a new word is required. I find this only partly unifying as it addresses unification of specific two ABA patterns, but it doesn’t unify the process under all conditions which includes self-spends and any longer arbitrary patterns. And it’s possible to unify these as well.

I agree, but for purpose of deciding on names I think this step can be left out. As shown above, as soon as you incorporate broadcasting into a word e.g. Complete, you introduce ordering which seems to be an issue.

Edit: When I say introduce ordering I mean new order assumptions beyond the one that is required which is that keys were added prior to signing.

Nobody is taking transactions out of their wallets either. You sign a contract which results in a transaction creation which moves funds to/from wallets.

What else, important enough that would make you want to change the word, happens?

I’ve explained above why this is not hidden

Nobody wants to limit this, that’s why the command is “contract sign”. Authentication doesn’t need a sign word imo. Now you might argue that there also happens some signing which is true, but the user doesn’t need to know about that one, while for contract signing he does, otherwise he won’t understand safe-cancel

What do you think is confusing about the sign button? Everyone has signed contracts in real life so it should be self explanatory imo

Not only that, afaik it means not all of the terms/details are specified, but in S1 they are (ignore setup, that’s only info related to cryptographic signature).

Wallet should keep your funds and allow you to send/receive them. This is done through transactions. The result of a finished contract can also be a transaction.

Contracts achieve the same thing

The setup phase could also be called “join” or “participate”, although technically setup makes more sense it might be easier for people to grasp the steps

While I agree this is an improvement over the current CLI commands, I think it still leaves the user confused about why the third step is needed. It doesn’t help them understand the crucial property of Grin transactions, namely that they are multisig. Whatever names we use, it needs to be obvious that both parties need to sign. And that once you sign, that transaction can happen at any later time, even if it fails to confirm soon.

Seeing it confirmed is what closes the transaction circle. If it doesn’t get confirmed, it still exists in a state of limbo, where it might need to be rebroadcasted or cancelled.

2 Likes

I agree that whatever Bitcoin uses, does not limit Grin. It is however rather ‘coincidental’ that we as project come up with the same terminology. I am certain there have been brainstorm session as well there about what the right terminology is and I am quite certain they came to the same conclusions as we did, that procedural thinking is problematic since there is not fixed order of steps in multistep/MultiSig transaction.

Signatures are a very general concept, so using that as a term is not technical, ask a random bum on a street if he know what a signature is and that if he puts his signature on a document that he uses this to authorize something.

Adding broadcast to the last step, e.g.

sign --broadcast

Or as button ‘Sign and broadcast’ should be fine. No problem with that. If you think about a transaction involving more than 2 parties, the broadcast would however not appear since not all required signatures are there. Hence you would end up with just ‘Sign’. Personally I think that makes very much sense.
I actually like your Draf - Accept - Complete (DAC) terminology if it were not that it does not scale for non-standard transactions or if a transaction is performed in a different order. Personally I really want to move away from SRS, RSR and all this kind of procedural thinking. .

For me Electrum has a great UX/UI. It shows well-arranged the transaction while you build it. It separates signing and broadcasting. With importing and exporting keys, signed- and unsigned- transactions a user can make insightful air-gap offline signing from cold wallet. In fact with Electrum I realized the only insightful air-gap offline signing so far. With trezor and ledger I need to believe that an air-gap exists. I can not experience it. I can make 20 clicks in a few seconds, that’s not the problem for me in terms of UX/UI. It really depends on the user and the context what is seen as a great UX/UI.

2 Likes

I agree. This doesn’t seem like a “contract” any more than a Venmo transaction is a “contract”.

Users are accustomed to Venmo and Cashapp flows now. Grin can easily mimmick this flow in almost the same way.

I assumed that payment proofs were only for fulfilling invoices AKA payment requests (“please send me $20”). They will be optional, right?

What about:

Draft
Approve
Execute

When people are "sign"ing, they are signing them for a purpose. The first sign is essentially an approval like “I agree to this transaction”. The second sign is saying, “ok we are going through with it. execute it.”

3 Likes

You can try to do the following with these names:

  1. express a self-spend naturally through a combination of Draft, Approve, Execute
  2. express a 3-party transaction naturally through a combination of Draft, Approve, Execute

Once you try to make these examples work, I think it will become more obvious why some of us landed with names that try to not have a position information in them. Btw, I too agree with you guys that these suggestions unify things compared to what we have today. I just believe we can make an even more unifying flow which covers also these two examples.

3 Likes

Wouldn’t it be a 2-party transaction?

Person A: Draft
Person B: Approve
Person A: Execute

Isn’t this always the flow?

You’re right that today’s flow is among 2 participants. Let’s define N as the number of participants in a transaction. There are two dimensions over which we can unify transaction building:

  1. we can unify flows/patterns inside a specific N e.g. N=2 which is a transaction between two parties. This way we unify flows like payment & invoice to be a single flow which is great
  2. we can generalize the flow further to work for any N which includes N=1, N=3, N=4,.. so it generalizes also over any number of participants.

My hope is that we make a single flow that works not just for N=2 but for any N which is what I’m trying to do with the contract thing (or whatever word we end up using). Then a user can send to themselves (make a self-spend) over the API (or CLI) in the same way you’d send to 2 parties or 5.

1 Like

As @oryhp noted, this is not just the simplest slate flow. It is the only one that is safe against key cancellation attacks. Any party that picks their key after party i, could pick theirs with PK_i subtracted from it. Since they cannot know the corresponding private key, they cannot sign with it. But if party i has to sign with PK_i before that happens, then the payment proof of party i is compromised. The other parties can collude to do a transaction with the kernel satisfying the payment proof, while leaving party i out of the payment.
The only way to prevent is, is to have all parties that pick their key after party i, also sign their key before party i needs to. When party i verifies all these partial signatures, it can be sure its key was not cancelled.

In summary, if the kernel key is simply the sum of the partial keys of the parties, then keys must be signed in the reverse order of the key additions.

To support any other order, we would need to define the kernel key in a more complicated way, e.g. as a weighted sum of partial keys with weights depending on all keys.

3 Likes

I’m trying to see how far we can push this idea and whether a more general secure Schnorr multisig can be done this way mini_multisig.md · GitHub

I do wonder if this idea of securing against rogue key attacks through remembering the order/state is still not safe against different attacks like the attack in section 2.1 The Challenge of Constructing Two-Round Schemes in Musig2 paper https://eprint.iacr.org/2020/1261.pdf

1 Like