New alternate contract language

We are in the middle of creating a proposal to the Aeternity foundation about designing and implementing an alternate contract language to Sophia. The idea is that it would have other features but still able to interact with Sophia. The question is what features should we experiment with in order to do quantitative and qualitative analysis?

Which features would be important in a new language?
Do people, developers and users, feel that there is need of a new contract language? What do people complain about in Sophia, if anything?

Any thoughts or comments on this are welcome.

Final question is whether this topic should be somewhere else and, if so, where?
Robert

5 Likes

Why do you want to create a new lang if you have no idea what features does it need to have? It is a reverse of what it should be…

1 Like

I’m also confused on why have intent to propose something before knowing (or at least explaining) why to propose anything. Is there a problem with Sophia… or is this just a shot at improving smart contract language options in general?

@rvirding can correct me here, but as far as I get it, the idea is: to create a new langage that is compatible with Sophia but that provides an extended functionality, while not polluting the nice clean syntax Sophia currently has.

I understand the proposal as an easy way of writing librarie and small contracts and now @rvirding is polling for ideas regarding what would be helpful to have.

1 Like

I know that it would be nice to have an array type. But maybe that is against functional way of coding.

The answer to drag0x - while I understand the angle - is really, if someone like Robert proposes to work on the language design-side in your ecosystem, you get overjoyed and excited because they know how to create something brilliant. And if they even ask what people would like – so much more awesome. Robert is one of the two creators of Erlang (the language & ecosystem Aeternity is implemented with), created a lisp-flavored Erlang and a Lua on top of Erlang, and that’s only what I know from the top of my hat.

Knowing Robert, I have no doubt that his starting point is going to be pretty Lispy with a shot of Prolog, unless you give input.

I’ll say that I think that Sophia is challenging for the blockchain crowd. I love it but there are things in there that are exactly why Elixir exists (a Ruby-style, well, version of Erlang): to make the learning curve for Erlang milder. Robert happens to have given intensive seminars in Elixir, too.

3 Likes

With array-type you mean update-in-place I guess? It’s not against functional coding when you the VM invalidate the old reference after the update. It’s a decision. I once advocated for it in Erlang and it was actually Robert who told me that they had planned such ‘vectors’ in Erlang but never got around implementing them because no-one was really asking for them.

1 Like

I would like a smart-contract language that is similar to the Scala language, of course not 100% but fine-tuned to the blockchain use cases. I consider Scala syntax relatively cleaner and easier to read, write and understand than other functional languages. And the way it combine procedural, functional and object oriented programming is the advantage IMO as everybody can apply its way of coding. Apart of that protocols and libraries, so kind of interfaces would still can be written in the best way possible.

Ruby syntax is great as well, but what I don’t like is that functions/methods are not first-class citizens as in functional languages or even in JavaScript.

Also it would be nice if you could use the language outside the blockchain use. So creating standalone programs, libraries, etc. It would make testing easier and it would lead to a rich ecosystem of libraries where you can have a collaborative explosion of small libraries/snippets/projects written without the overhead of configuring a testing blockchain environment.

In version OTP 22 we now have the modules persistent_term, atomics and counters which implement global and mutable data under very special circumstances so it is mutable but appears to be immutable. Again they are very specific and not general.

1 Like

OK, to try and come with some comments here.

So we have a number of interesting ideas of what features a new language could have, for example a language in which it would be much easier to predict the cost of evaluating contracts. It must be possible for it to interact with Sophia so one question is what is the best way to do this. This is partially an implementation detail but it also affects the language itself.

This would mean that there would be a lot of experimenting and prototyping and then some analysis of the results before the “final” language design was fixed. We are also interested in what users think of Sophia today and what they would like in a new language to make it more usable and easier to use.

Hence my questions to users. While implementing a new language would be fun :wink: it would be infinitely better if it solved a real problem and was actually usable.

3 Likes

Do you mean simulating a blockchain environment of having a more general purpose language which could be used for “other” things as well?

No, I thought about a language that you can use as a general purpose language if you will not use blockchain-specific features. So just imagine a simple math library or whatever library that will not touch blockchain specific things. You don’t even need to simulate a blockchain environment for it to work. It would be nice if you can write such libraries, test them and even import them to, compile and run as a command-line program. Currently Sophia code is compiled to the æternity VM bytecode and I am not sure if it will be possible to further run it as a linux executable for example. Probably it would be easier to do that if AE VM were designed for that from the beginning. I am not sure if it is worth to thing about that, just giving an idea.

The other thing, I am very curious what syntax do you want to use. More like ruby, elixir or scala? Do you have any draft?

I am not a developer, but what I continually hear from the community is that we should try making it easier for smart contract (SC) devs from other blockchains to start building on aeternity. I am not sure exactly how this feedback could be useful, but it is something to keep in mind. The most popular SC language out there is Solidity.

2 Likes

Regarding ease: it’s not clear to me, if Solidity made Smart Contract programming look too easy but it certainly set the standard = it’s what people expect and what they measure new things against. Not too many people have a lot of experience with functional programming.

I love Sophia and its true advantages regarding safety, and enforcing robust apps, but also speed might not be immediately apparent. It can be quite difficult to get the more demanding stuff out without losing the advantages but Elixir kind-of showed the way.

I think for inspiration it should make sense to look at the language that Vitalik Buterin favors, Viper GitHub - vyperlang/vyper: Pythonic Smart Contract Language for the EVM . He wrote this after Solidity was already a success, continuing his Python-leaning bent from the first language he made for Ethereum, Serpent.

Solidity had actually been started to make it easier to have formal verification right in the language but it never really arrived where it was supposed to go, or at least very much too late.

For convenience, this is how Viper looks
https://github.com/ethereum/vyper/blob/master/examples/voting/ballot.vy:

# Voting with delegation.

# Information about voters
struct Voter:
    # weight is accumulated by delegation
    weight: int128
    # if true, that person already voted (which includes voting by delegating)
    voted: bool
    # person delegated to
    delegate: address
    # index of the voted proposal, which is not meaningful unless `voted` is True.
    vote: int128

# Users can create proposals
struct Proposal:
    # short name (up to 32 bytes)
    name: bytes32
    # number of accumulated votes
    voteCount: int128

voters: public(map(address, Voter))
proposals: public(map(int128, Proposal))
voterCount: public(int128)
chairperson: public(address)
int128Proposals: public(int128)


@private
@constant
def _delegated(addr: address) -> bool:
    return self.voters[addr].delegate != ZERO_ADDRESS


@public
@constant
def delegated(addr: address) -> bool:
    return self._delegated(addr)


@private
@constant
def _directlyVoted(addr: address) -> bool:
    return self.voters[addr].voted and (self.voters[addr].delegate == ZERO_ADDRESS)


@public
@constant
def directlyVoted(addr: address) -> bool:
    return self._directlyVoted(addr)


# Setup global variables
@public
def __init__(_proposalNames: bytes32[2]):
    self.chairperson = msg.sender
    self.voterCount = 0
    for i in range(2):
        self.proposals[i] = Proposal({
            name: _proposalNames[i],
            voteCount: 0
        })
        self.int128Proposals += 1

# Give a `voter` the right to vote on this ballot.
# This may only be called by the `chairperson`.
@public
def giveRightToVote(voter: address):
    # Throws if the sender is not the chairperson.
    assert msg.sender == self.chairperson
    # Throws if the voter has already voted.
    assert not self.voters[voter].voted
    # Throws if the voter's voting weight isn't 0.
    assert self.voters[voter].weight == 0
    self.voters[voter].weight = 1
    self.voterCount += 1

# Used by `delegate` below, callable externally via `forwardWeight`
@private
def _forwardWeight(delegate_with_weight_to_forward: address):
    assert self._delegated(delegate_with_weight_to_forward)
    # Throw if there is nothing to do:
    assert self.voters[delegate_with_weight_to_forward].weight > 0

    target: address = self.voters[delegate_with_weight_to_forward].delegate
    for i in range(4):
        if self._delegated(target):
            target = self.voters[target].delegate
            # The following effectively detects cycles of length <= 5,
            # in which the delegation is given back to the delegator.
            # This could be done for any int128ber of loops,
            # or even infinitely with a while loop.
            # However, cycles aren't actually problematic for correctness;
            # they just result in spoiled votes.
            # So, in the production version, this should instead be
            # the responsibility of the contract's client, and this
            # check should be removed.
            assert target != delegate_with_weight_to_forward
        else:
            # Weight will be moved to someone who directly voted or
            # hasn't voted.
            break

    weight_to_forward: int128 = self.voters[delegate_with_weight_to_forward].weight
    self.voters[delegate_with_weight_to_forward].weight = 0
    self.voters[target].weight += weight_to_forward

    if self._directlyVoted(target):
        self.proposals[self.voters[target].vote].voteCount += weight_to_forward
        self.voters[target].weight = 0

    # To reiterate: if target is also a delegate, this function will need
    # to be called again, similarly to as above.

# Public function to call _forwardWeight
@public
def forwardWeight(delegate_with_weight_to_forward: address):
    self._forwardWeight(delegate_with_weight_to_forward)

# Delegate your vote to the voter `to`.
@public
def delegate(to: address):
    # Throws if the sender has already voted
    assert not self.voters[msg.sender].voted
    # Throws if the sender tries to delegate their vote to themselves or to
    # the default address value of 0x0000000000000000000000000000000000000000
    # (the latter might not be problematic, but I don't want to think about it).
    assert to != msg.sender
    assert to != ZERO_ADDRESS

    self.voters[msg.sender].voted = True
    self.voters[msg.sender].delegate = to

    # This call will throw if and only if this delegation would cause a loop
        # of length <= 5 that ends up delegating back to the delegator.
    self._forwardWeight(msg.sender)

# Give your vote (including votes delegated to you)
# to proposal `proposals[proposal].name`.
@public
def vote(proposal: int128):
    # can't vote twice
    assert not self.voters[msg.sender].voted
    # can only vote on legitimate proposals
    assert proposal < self.int128Proposals

    self.voters[msg.sender].vote = proposal
    self.voters[msg.sender].voted = True

    # transfer msg.sender's weight to proposal
    self.proposals[proposal].voteCount += self.voters[msg.sender].weight
    self.voters[msg.sender].weight = 0

# Computes the winning proposal taking all
# previous votes into account.
@private
@constant
def _winningProposal() -> int128:
    winning_vote_count: int128 = 0
    winning_proposal: int128 = 0
    for i in range(2):
        if self.proposals[i].voteCount > winning_vote_count:
            winning_vote_count = self.proposals[i].voteCount
            winning_proposal = i
    return winning_proposal

@public
@constant
def winningProposal() -> int128:
    return self._winningProposal()


# Calls winningProposal() function to get the index
# of the winner contained in the proposals array and then
# returns the name of the winner
@public
@constant
def winnerName() -> bytes32:
    return self.proposals[self._winningProposal()].name
2 Likes

Has anyone with AE considered somehow/where asking smart contract developer outside of the AE ecosystem (e.g. Ethereum SC developers) to see what their issues are in Solidity, dev tools and/or integration of tools…?

And in Viper they use assert keyword which is most obvious way to assert conditions in programming language. Aeternity extended Sophia language with keyword require:

I don’t like it as it is like blindly mimic trends in Solidity - the language that at some stage might be deprecated.

I think require keyword should be reserved for other purposes.

I don’t know if anyone has done a study on what users from other blockchains would like to see. I guess that it very much depends on what they think of the contract they are using now: if they like then they would probably prefer to see a similar language, while if they hate it then anything else would be better.

The interesting question is in what way Solidity is the most popular SC language. Is it because it is the most commonly used (is it?) or because people really like it?

2 Likes

I am guessing here that FATE, the aeternity VM, could be used as a general purpose language. It is however a VM designed for Sophia, a functional language, so you would have these restrictions on you could do. For example data is immutable, except for the state record, which you would then see in your language. However as soon as you do something related to blockchains then you would automatically be in the aeternity world. Contracts as such are on the blockchain so calling another contract means you are in the aeternity world.

I don’t think that anyone has attempted to make a stand-alone implementation.

About syntax I can say I am not that enthusiastic about Ruby, elixir or Scala. In general I don’t really like languages in which line breaks and indentation are significant, which rules out Python. I also prefer simple syntaxes with too many special cases or other cruft. The erlang syntax follows these goals even if it does look a bit strange. :grinning:

I did start work in Aeternity on another contract language which would have been called Varna. The syntax I started with was Lua based but the project was put on hold.

Of course the absolutely best syntax is LISP. :wink: It is simple, consistent, powerful and extremely versatile. Unfortunately not everyone gets it. :cry:

2 Likes

Viper looks way too much like Python. :wink:

2 Likes

I think next to a language, we are especially looking for a solution to run Erlang in the browser. That would solve many client side trust problems.

Best

1 Like