stacks-network / stacks-core

The Stacks blockchain implementation
https://docs.stacks.co
GNU General Public License v3.0
3.01k stars 666 forks source link

Principals should not start with a quote #1519

Closed njordhov closed 3 years ago

njordhov commented 4 years ago

Clarity principals like contract names currently starts with a quote character ' as in:

'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR

The current use of a single quote is unexpected. To avoid confusion, single quote should not start a principal. One option is to instead start principals with another character such as @ or $ as in:

@SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR

In languages such as Javascript, single quotes can be used to start and end string literals. The use of single quotes starting principals will be confusing for developers from such languages.

In Lisp languages, quote is typically used as a special operator returning a form without evaluation. While the current principal syntax may appear on the surface like a quoted lisp symbol, such limited support for quoted forms is unexpected.

njordhov commented 4 years ago

Clarity principals have multiple syntaxes to express the same concept. This complicates the lexer, which applies several relatively complex expressions to match the different productions:

https://github.com/blockstack/stacks-blockchain/blob/aa2d4ffd3d4e07877bc86ee34d918f731dcb5e43/src/vm/ast/parser/mod.rs#L83-L87 https://github.com/blockstack/stacks-blockchain/blob/aa2d4ffd3d4e07877bc86ee34d918f731dcb5e43/src/vm/ast/parser/mod.rs#L112-L118

jcnelson commented 4 years ago

Clarity principals have multiple syntaxes to express the same concept.

Are you talking about contract principals and standard principals? Because, these are not the same concept. In particular, a contract principal cannot sign transactions.

jcnelson commented 4 years ago

The current use of a single quote is unexpected.

I think @ or $ is even more unexpected (at least, is no less surprising than '). LISPs use 'x as short-hand for (quote x), and at a high level, that's what we want here -- we're not ever going to evaluate the principal's value, since the representation of that value could also refer to a bound variable. So no matter what, we'll need some kind of sigil character to distinguish principal values from variable names. I'd prefer to not introduce new sigil characters if we don't need to.

In languages such as Javascript, single quotes can be used to start and end string literals. The use of single quotes starting principals will be confusing for developers from such languages.

Clarity isn't based on Javascript, so I don't see how this is relevant? The single-quote is going to be the least of their worries when learning Clarity, since it's already so different from Javascript.

In Lisp languages, quote is typically used as a special operator returning a form without evaluation. While the current principal syntax may appear on the surface like a quoted lisp symbol, such limited support for quoted forms is unexpected.

Maybe the right answer here is to add first-class support for ' and to define (quote ...). I'm not entirely convinced of this either, though.

njordhov commented 4 years ago

Are you talking about contract principals and standard principals? Because, these are not the same concept. In particular, a contract principal cannot sign transactions.

Contract principals have multiple syntaxes for the same concept, respectively starting with a single quote ' and a period . for different productions.

Moreover, contract principals and standard principals have confusingly similar syntaxes despite being different concepts. Both a standard principal and a fully qualified contract identifier start with a single quote:

https://github.com/blockstack/stacks-blockchain/blob/aa2d4ffd3d4e07877bc86ee34d918f731dcb5e43/src/vm/ast/parser/mod.rs#L116 https://github.com/blockstack/stacks-blockchain/blob/aa2d4ffd3d4e07877bc86ee34d918f731dcb5e43/src/vm/ast/parser/mod.rs#L118

Maybe the right answer here is to add first-class support for ' and to define (quote ...).

Supporting the quote operator generally is an interesting idea and could have been an improvement. Unfortunately, quoted principals would still be uncanny and inconsistent, as they can contain different characters than symbols:

https://github.com/blockstack/stacks-blockchain/blob/aa2d4ffd3d4e07877bc86ee34d918f731dcb5e43/src/vm/ast/parser/mod.rs#L119

Also, a principal is supposed to be a type not just an encoding. Providing an explicit principal constructor could be an alternative to literals, as in:

(principal "SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR")

Using an explicit constructor is a bit more verbose than a literal, but reduces cognitive burden and avoids introducing a new sigil character.

Developers can define principals as constants on toplevel, which works well for explicit constructors:

(define-constant receiver (principal "SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR"))
jcnelson commented 4 years ago

Contract principals have multiple syntaxes for the same concept, respectively starting with a single quote ' and a period . for different productions.

Right. .foo is short-hand for the fully-qualified representation, such as SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR.foo. This representation is only allowed in contract-call?. However, the address component of the fully-qualified representation is known to the reader in this case -- it's the same as the address that deployed the contract in which the contract-call? resides.

I mentioned in another thread that I strongly prefer there to be only a single representation for each Clarity object, for the purposes of minimizing cognitive overhead for the reader. I should clarify two points: (1) this is a design principal, not a suicide pact, and (2) this is sufficient but not necessary. That said, I don't think the short-hand representation in contract-call? violates the spirit of this principle (but it does violate the letter as you point out), because in this case adding the address to the representation doesn't improve the reader's understanding of the code -- the address is already known to the reader. Clarity originally required the fully-qualified representation in contract-call?s, but it was dropped when it became apparent that doing so made code harder to read in the common case where the developer is simply calling into other contracts (s)he deployed (e.g. complex blockchain programs span multiple smart contracts, and are often deployed as a succession of transactions).

Using an explicit constructor is a bit more verbose than a literal, but reduces cognitive burden and avoids introducing a new sigil character.

I can get behind having a (principal ...) constructor, but only if (quote ...) is fully fleshed out (in which case, using ' to identify principal values would make the code harder to understand).

njordhov commented 4 years ago

I can get behind having a (principal ...) constructor, but only if (quote ...) is fully fleshed out (in which case, using ' to identify principal values would make the code harder to understand).

@jcnelson Having a (principal "...") constructor is a good resolution, but what do you mean by the second clause "but only if (quote ...) is fully fleshed out"?

friedger commented 4 years ago

Should be moved to clarity lang repo

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 3 years ago

This issue has been automatically closed. Please reopen if needed.