Compare commits

..

6 Commits

Author SHA1 Message Date
Hans Svensson 8e191b0c88 [Ceres]: Document generic all names delegation signatures (#440) 2023-03-22 08:55:57 +01:00
Hans Svensson f70fc56df8 Ceres: document changes to Auth.tx_hash (#439) 2023-03-03 10:06:45 +01:00
Hans Svensson 4ae24722f4 Remove unused variable in AENSCompat 2022-12-01 08:33:59 +01:00
Hans Svensson 55a97852ed Introduce AENSv2 namespace to introduce raw data pointers (#426) 2022-11-16 21:31:44 +01:00
Hans Svensson 1380142082 Add bitwise operations, Address.to_bytes and Crypto.poseidon 2022-11-11 16:15:05 +01:00
Hans Svensson 1754763e23 Let CERES compiler be v8.0.0 tentatively 2022-11-04 10:30:04 +01:00
39 changed files with 373 additions and 577 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
mkdocs==1.4.2 mkdocs==1.2.4
mkdocs-simple-hooks==0.1.5 mkdocs-simple-hooks==0.1.5
mkdocs-material==9.0.9 mkdocs-material==7.3.6
mike==1.1.2 mike==1.1.2
pygments==2.14.0 pygments==2.12.0
+17 -9
View File
@@ -4,13 +4,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## [CERES 8.0.0]
### Added ### Added
- Bitwise operations for integers: `band`, `bor`, `bxor`, `bnot`, `<<` and `>>`.
- `Int.mulmod` - combined builtin operation for multiplication and modulus.
- `Crypto.poseidon` - a ZK/SNARK-friendly hash function (over the BLS12-381 scalar field).
- `Address.to_bytes` - convert an address to its binary representation (for hashing, etc.).
- Raw data pointers added to AENS. In short we have introduced a new namespace
`AENSv2`; they contain types similar to the old `AENS`; `AENS.name` and
`AENS.pointee`, where the latter now has a constructor `DataPt(string)`. All
AENS actions have been moved to `AENSv2`, and `AENSv2.lookup` and
`AENSv2.update` consume and produce the new types. The old `AENS` namespace
only contains the old datatypes, that can be used to interface existing
contracts. Standard library `AENSCompat` is added to convert between old and
new pointers.
### Changed ### Changed
### Removed ### Removed
### Fixed - `Bitwise.aes` standard library is removed - the builtin operations are superior.
## [7.1.0] ## [Unreleased]
### Added ### Added
- Options to enable/disable certain optimizations. - Options to enable/disable certain optimizations.
- The ability to call a different instance of the current contract - The ability to call a different instance of the current contract
@@ -20,12 +32,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
entrypoint f(c : Main) : int = c.spend(10) entrypoint f(c : Main) : int = c.spend(10)
``` ```
- Return a mapping from variables to FATE registers in the compilation output. - Return a mapping from variables to FATE registers in the compilation output.
- Hole expression.
### Changed ### Changed
- Type definitions serialised to ACI as `typedefs` field instead of `type_defs` to increase compatibility. - Type definitions serialised to ACI as `typedefs` field instead of `type_defs` to increase compatibility.
- Check contracts and entrypoints modifiers when implementing interfaces. ### Removed
- Contracts can no longer be used as namespaces.
- Do not show unused stateful warning for functions that call other contracts with a non-zero value argument.
### Fixed ### Fixed
- Typechecker crashes if Chain.create or Chain.clone are used without arguments. - Typechecker crashes if Chain.create or Chain.clone are used without arguments.
@@ -380,8 +389,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Simplify calldata creation - instead of passing a compiled contract, simply - Simplify calldata creation - instead of passing a compiled contract, simply
pass a (stubbed) contract string. pass a (stubbed) contract string.
[Unreleased]: https://github.com/aeternity/aesophia/compare/v7.1.0...HEAD [Unreleased]: https://github.com/aeternity/aesophia/compare/v7.0.1...HEAD
[7.1.0]: https://github.com/aeternity/aesophia/compare/v7.0.1...v7.1.0
[7.0.1]: https://github.com/aeternity/aesophia/compare/v7.0.0...v7.0.1 [7.0.1]: https://github.com/aeternity/aesophia/compare/v7.0.0...v7.0.1
[7.0.0]: https://github.com/aeternity/aesophia/compare/v6.1.0...v7.0.0 [7.0.0]: https://github.com/aeternity/aesophia/compare/v6.1.0...v7.0.0
[6.1.0]: https://github.com/aeternity/aesophia/compare/v6.0.2...v6.1.0 [6.1.0]: https://github.com/aeternity/aesophia/compare/v6.0.2...v6.1.0
+12 -28
View File
@@ -191,17 +191,6 @@ contract interface X : Z =
entrypoint z() = 1 entrypoint z() = 1
``` ```
#### Adding or removing modifiers
When a `contract` or a `contract interface` implements another `contract interface`, the `payable` and `stateful` modifiers can be kept or changed, both in the contract and in the entrypoints, according to the following rules:
1. A `payable` contract or interface can implement a `payable` interface or a non-`payable` interface.
2. A non-`payable` contract or interface can only implement a non-`payable` interface, and cannot implement a `payable` interface.
3. A `payable` entrypoint can implement a `payable` entrypoint or a non-`payable` entrypoint.
4. A non-`payable` entrypoint can only implement a non-`payable` entrypoint, and cannot implement a `payable` entrypoint.
5. A non-`stateful` entrypoint can implement a `stateful` entrypoint or a non-`stateful` entrypoint.
6. A `stateful` entrypoint can only implement a `stateful` entrypoint, and cannot implement a non-`stateful` entrypoint.
#### Subtyping and variance #### Subtyping and variance
Subtyping in Sophia follows common rules that take type variance into account. As described by [Wikipedia](https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)), Subtyping in Sophia follows common rules that take type variance into account. As described by [Wikipedia](https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)),
@@ -256,10 +245,10 @@ datatype bi('a) = Bi // bi is bivariant on 'a
The following facts apply here: The following facts apply here:
- `co('a)` is a subtype of `co('b)` when `'a` is a subtype of `'b` - `co('a)` is a subtype of `co('b) when `'a` is a subtype of `'b`
- `ct('a)` is a subtype of `ct('b)` when `'b` is a subtype of `'a` - `ct('a)` is a subtype of `ct('b) when `'b` is a subtype of `'a`
- `in('a)` is a subtype of `in('b)` when `'a` is equal to `'b` - `in('a)` is a subtype of `in('b) when `'a` is equal to `'b`
- `bi('a)` is a subtype of `bi('b)` always - `bi('a)` is a subtype of `bi('b) always
That altogether induce the following rules of subtyping in Sophia: That altogether induce the following rules of subtyping in Sophia:
@@ -560,19 +549,6 @@ Sophia has the following types:
| oracle_query('a, 'b) | `oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY` | | oracle_query('a, 'b) | `oq_2oRvyowJuJnEkxy58Ckkw77XfWJrmRgmGaLzhdqb67SKEL1gPY` |
| contract | `ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` | | contract | `ct_Ez6MyeTMm17YnTnDdHTSrzMEBKmy7Uz2sXu347bTDPgVH2ifJ` |
## Hole expression
Hole expressions, written as `???`, are expressions that are used as a placeholder. During compilation, the compiler will generate a type error indication the type of the hole expression.
```
include "List.aes"
contract C =
entrypoint f() =
List.sum(List.map(???, [1,2,3]))
```
A hole expression found in the example above will generate the error `` Found a hole of type `(int) => int` ``. This says that the compiler expects a function from `int` to `int` in place of the `???` placeholder.
## Arithmetic ## Arithmetic
Sophia integers (`int`) are represented by arbitrary-sized signed words and support the following Sophia integers (`int`) are represented by arbitrary-sized signed words and support the following
@@ -588,6 +564,14 @@ All operations are *safe* with respect to overflow and underflow.
The division and modulo operations throw an arithmetic error if the The division and modulo operations throw an arithmetic error if the
right-hand operand is zero. right-hand operand is zero.
Sophia arbitrary-sized integers (FATE) also supports the following bitwise operations:
- bitwise and (`x band y`)
- bitwise or (`x bor y`)
- bitwise xor (`x bxor y`)
- bitwise not (`bnot x`)
- arithmetic bitshift left (`x << n`)
- arithmetic bitshift right (`x >> n`)
## Bit fields ## Bit fields
Sophia integers do not support bit arithmetic. Instead there is a separate Sophia integers do not support bit arithmetic. Instead there is a separate
+105 -96
View File
@@ -14,6 +14,7 @@ The out-of-the-box namespaces are:
- [Address](#address) - [Address](#address)
- [AENS](#aens) - [AENS](#aens)
- [AENSv2](#aensv2)
- [Auth](#auth) - [Auth](#auth)
- [Bits](#bits) - [Bits](#bits)
- [Bytes](#bytes) - [Bytes](#bytes)
@@ -31,6 +32,7 @@ The following ones need to be included as regular files with `.aes` suffix, for
include "List.aes" include "List.aes"
``` ```
- [AENSCompat](#aenscompat)
- [Bitwise](#bitwise) - [Bitwise](#bitwise)
- [BLS12_381](#bls12_381) - [BLS12_381](#bls12_381)
- [Func](#func) - [Func](#func)
@@ -90,13 +92,10 @@ Cast address to contract type C (where `C` is a contract)
### AENS ### AENS
The following functionality is available for interacting with the æternity The old AENS namespace, kept in the compiler to be able to interact with
naming system (AENS). contracts from before Ceres, compiled using aesophia compiler version 7.x and
If `owner` is equal to `Contract.address` the signature `signature` is earlier. Used in [AENSCompat](#aenscompat) when converting between old and new
ignored, and can be left out since it is a named argument. Otherwise we need pointers.
a signature to prove that we are allowed to do AENS operations on behalf of
`owner`. The [signature is tied to a network id](https://github.com/aeternity/protocol/blob/iris/consensus/consensus.md#transaction-signature),
i.e. the signature material should be prefixed by the network id.
#### Types #### Types
@@ -113,12 +112,41 @@ datatype pointee = AccountPt(address) | OraclePt(address)
| ContractPt(address) | ChannelPt(address) | ContractPt(address) | ChannelPt(address)
``` ```
### AENSv2
Note: introduced in v8.0
The following functionality is available for interacting with the æternity
naming system (AENS). If `owner` is equal to `Contract.address` the signature
`signature` is ignored, and can be left out since it is a named argument.
Otherwise we need a signature to prove that we are allowed to do AENS
operations on behalf of `owner`. The [signature is tied to a network
id](https://github.com/aeternity/protocol/blob/iris/consensus/consensus.md#transaction-signature),
i.e. the signature material should be prefixed by the network id.
#### Types
##### name
```
datatype name = Name(address, Chain.ttl, map(string, AENSv2.pointee))
```
##### pointee
```
datatype pointee = AccountPt(address) | OraclePt(address)
| ContractPt(address) | ChannelPt(address) | DataPt(string)
```
Note: on-chain there is a maximum length enforced for `DataPt`, it is 1024 bytes.
Sophia itself does _not_ enforce this.
#### Functions #### Functions
##### resolve ##### resolve
``` ```
AENS.resolve(name : string, key : string) : option('a) AENSv2.resolve(name : string, key : string) : option('a)
``` ```
Name resolution. Here `name` should be a registered name and `key` one of the attributes Name resolution. Here `name` should be a registered name and `key` one of the attributes
@@ -129,41 +157,53 @@ type checked against this type at run time.
##### lookup ##### lookup
``` ```
AENS.lookup(name : string) : option(AENS.name) AENSv2.lookup(name : string) : option(AENSv2.name)
``` ```
If `name` is an active name `AENS.lookup` returns a name object. If `name` is an active name `AENSv2.lookup` returns a name object.
The three arguments to `Name` are `owner`, `expiry` and a map of the The three arguments to `Name` are `owner`, `expiry` and a map of the
`pointees` for the name. Note: the expiry of the name is always a fixed TTL. `pointees` for the name. Note: the expiry of the name is always a fixed TTL.
For example: For example:
``` ```
let Some(Name(owner, FixedTTL(expiry), ptrs)) = AENS.lookup("example.chain") let Some(AENSv2.Name(owner, FixedTTL(expiry), ptrs)) = AENSv2.lookup("example.chain")
``` ```
Note: Changed to produce `AENSv2.name` in v8.0 (Ceres protocol upgrade).
##### preclaim ##### preclaim
``` ```
AENS.preclaim(owner : address, commitment_hash : hash, <signature : signature>) : unit AENSv2.preclaim(owner : address, commitment_hash : hash, <signature : signature>) : unit
``` ```
The [signature](./sophia_features.md#delegation-signature) should be over The [signature](./sophia_features.md#delegation-signature) should be over
`network id` + `owner address` + `Contract.address` (concatenated as byte arrays). `network id` + `owner address` + `Contract.address` (concatenated as byte arrays).
From Ceres (i.e. FATE VM version 3) the
[signature](./sophia_features.md#delegation-signature) can also be generic
(allowing _all_, existing and future, names to be delegated with one
signature), i.e. over `network id` + `owner address` + `string "AENS"` +
`Contract.address`.
##### claim ##### claim
``` ```
AENS.claim(owner : address, name : string, salt : int, name_fee : int, <signature : signature>) : unit AENSv2.claim(owner : address, name : string, salt : int, name_fee : int, <signature : signature>) : unit
``` ```
The [signature](./sophia_features.md#delegation-signature) should be over The [signature](./sophia_features.md#delegation-signature) should be over
`network id` + `owner address` + `name_hash` + `Contract.address` `network id` + `owner address` + `name_hash` + `Contract.address` (concatenated
(concatenated as byte arrays) as byte arrays) using the private key of the `owner` account for signing.
using the private key of the `owner` account for signing.
From Ceres (i.e. FATE VM version 3) the
[signature](./sophia_features.md#delegation-signature) can also be generic
(allowing _all_, existing and future, names to be delegated with one
signature), i.e. over `network id` + `owner address` + `string "AENS"` +
`Contract.address`.
##### transfer ##### transfer
``` ```
AENS.transfer(owner : address, new_owner : address, name : string, <signature : signature>) : unit AENSv2.transfer(owner : address, new_owner : address, name : string, <signature : signature>) : unit
``` ```
Transfers name to the new owner. Transfers name to the new owner.
@@ -173,10 +213,16 @@ The [signature](./sophia_features.md#delegation-signature) should be over
(concatenated as byte arrays) (concatenated as byte arrays)
using the private key of the `owner` account for signing. using the private key of the `owner` account for signing.
From Ceres (i.e. FATE VM version 3) the
[signature](./sophia_features.md#delegation-signature) can also be generic
(allowing _all_, existing and future, names to be delegated with one
signature), i.e. over `network id` + `owner address` + `string "AENS"` +
`Contract.address`.
##### revoke ##### revoke
``` ```
AENS.revoke(owner : address, name : string, <signature : signature>) : unit AENSv2.revoke(owner : address, name : string, <signature : signature>) : unit
``` ```
Revokes the name to extend the ownership time. Revokes the name to extend the ownership time.
@@ -186,17 +232,24 @@ The [signature](./sophia_features.md#delegation-signature) should be over
(concatenated as byte arrays) (concatenated as byte arrays)
using the private key of the `owner` account for signing. using the private key of the `owner` account for signing.
From Ceres (i.e. FATE VM version 3) the
[signature](./sophia_features.md#delegation-signature) can also be generic
(allowing _all_, existing and future, names to be delegated with one
signature), i.e. over `network id` + `owner address` + `string "AENS"` +
`Contract.address`.
##### update ##### update
``` ```
AENS.update(owner : address, name : string, expiry : option(Chain.ttl), client_ttl : option(int), AENSv2.update(owner : address, name : string, expiry : option(Chain.ttl), client_ttl : option(int),
new_ptrs : map(string, AENS.pointee), <signature : signature>) : unit new_ptrs : map(string, AENSv2.pointee), <signature : signature>) : unit
``` ```
Updates the name. If the optional parameters are set to `None` that parameter Updates the name. If the optional parameters are set to `None` that parameter
will not be updated, for example if `None` is passed as `expiry` the expiry will not be updated, for example if `None` is passed as `expiry` the expiry
block of the name is not changed. block of the name is not changed.
Note: Changed to consume `AENSv2.pointee` in v8.0 (Ceres protocol upgrade).
### Auth ### Auth
@@ -236,7 +289,10 @@ namespace Chain =
Auth.tx_hash : option(hash) Auth.tx_hash : option(hash)
``` ```
Gets the transaction hash during authentication. Gets the transaction hash during authentication. Note: `Auth.tx_hash`
computation differs between protocol versions (changed in Ceres!), see
[aeserialisation](https://github.com/aeternity/protocol/blob/master/serializations.md)
specification for details.
### Bits ### Bits
@@ -381,6 +437,12 @@ Call.gas_price : int
The gas price of the current call. The gas price of the current call.
#### mulmod
```
Int.mulmod : (a : int, b : int, q : int) : int
```
Combined multiplication and modulus, returns `(a * b) mod q`.
#### fee #### fee
``` ```
@@ -469,6 +531,13 @@ Chain.block_height : int"
The height of the current block (i.e. the block in which the current call will be included). The height of the current block (i.e. the block in which the current call will be included).
#### to_bytes
```
Address.to_bytes(a : address) : bytes(32)
```
The binary representation of the address.
##### coinbase ##### coinbase
``` ```
@@ -483,7 +552,7 @@ The address of the account that mined the current block.
Chain.timestamp : int Chain.timestamp : int
``` ```
The timestamp of the current block (unix time, milliseconds). The timestamp of the current block.
##### difficulty ##### difficulty
@@ -538,6 +607,13 @@ charging the calling contract. Note that this won't be visible in `Call.value`
in the `init` call of the new contract. It will be included in in the `init` call of the new contract. It will be included in
`Contract.balance`, however. `Contract.balance`, however.
#### poseidon
```
Crypto.poseidon(x1 : int, x2 : int) : int
```
Hash two integers (in the scalar field of BLS12-381) to another integer (in the scalar
field of BLS12-281). This is a ZK/SNARK-friendly hash function.
The type `'c` must be instantiated with a contract. The type `'c` must be instantiated with a contract.
@@ -914,88 +990,21 @@ It returns `true` iff the oracle query exist and has the expected type.
These need to be explicitly included (with `.aes` suffix) These need to be explicitly included (with `.aes` suffix)
### Bitwise ### AENSCompat
Bitwise operations on arbitrary precision integers. #### pointee\_to\_V2
#### bsr
``` ```
Bitwise.bsr(n : int, x : int) : int AENSCompat.pointee_to_V2(p : AENS.pointee) : AENSv2.pointee
``` ```
Logical bit shift `x` right `n` positions. Translate old pointee format to new, this is always possible.
#### pointee\_from\_V2
#### bsl
``` ```
Bitwise.bsl(n : int, x : int) : int AENSCompat.pointee_from_V2(p2 : AENSv2.pointee) : option(AENS.pointee)
``` ```
Logical bit shift `x` left `n` positions. Translate new pointee format to old, `DataPt` can't be translated, so `None` is returned in this case.
#### bsli
```
Bitwise.bsli(n : int, x : int, lim : int) : int
```
Logical bit shift `x` left `n` positions, limit to `lim` bits.
#### band
```
Bitwise.band(x : int, y : int) : int
```
Bitwise `and` of `x` and `y`.
#### bor
```
Bitwise.bor(x : int, y : int) : int
```
Bitwise `or` of `x` and `y`.
#### bxor
```
Bitwise.bxor(x : int, y : int) : int
```
Bitwise `xor` of `x` and `y`.
#### bnot
```
Bitwise.bnot(x : int) : int
```
Bitwise `not` of `x`. Defined and implemented as `bnot(x) = bxor(x, -1)`.
#### uband
```
Bitwise.uband(x : int, y : int) : int
```
Bitwise `and` of _non-negative_ numbers `x` and `y`.
#### ubor
```
Bitwise.ubor(x : int, y : int) : int
```
Bitwise `or` of _non-negative_ `x` and `y`.
#### ubxor
```
Bitwise.ubxor(x : int, y : int) : int
```
Bitwise `xor` of _non-negative_ `x` and `y`.
### BLS12\_381 ### BLS12\_381
+8 -4
View File
@@ -238,7 +238,6 @@ Expr ::= '(' LamArgs ')' '=>' Block(Stmt) // Anonymous function (x) => x +
| Int | Bytes | String | Char // Literals 123, 0xff, #00abc123, "foo", '%' | Int | Bytes | String | Char // Literals 123, 0xff, #00abc123, "foo", '%'
| AccountAddress | ContractAddress // Chain identifiers | AccountAddress | ContractAddress // Chain identifiers
| OracleAddress | OracleQueryId // Chain identifiers | OracleAddress | OracleQueryId // Chain identifiers
| '???' // Hole expression 1 + ???
Generator ::= Pattern '<-' Expr // Generator Generator ::= Pattern '<-' Expr // Generator
| 'if' '(' Expr ')' // Guard | 'if' '(' Expr ')' // Guard
@@ -255,8 +254,8 @@ Path ::= Id // Record field
BinOp ::= '||' | '&&' | '<' | '>' | '=<' | '>=' | '==' | '!=' BinOp ::= '||' | '&&' | '<' | '>' | '=<' | '>=' | '==' | '!='
| '::' | '++' | '+' | '-' | '*' | '/' | 'mod' | '^' | '::' | '++' | '+' | '-' | '*' | '/' | 'mod' | '^'
| '|>' | 'band' | 'bor' | 'bxor' | '<<' | '>>' | '|>'
UnOp ::= '-' | '!' UnOp ::= '-' | '!' | 'bnot'
``` ```
## Operators types ## Operators types
@@ -265,6 +264,7 @@ UnOp ::= '-' | '!'
| --- | --- | --- | ---
| `-` `+` `*` `/` `mod` `^` | arithmetic operators | `-` `+` `*` `/` `mod` `^` | arithmetic operators
| `!` `&&` `||` | logical operators | `!` `&&` `||` | logical operators
| `band` `bor` `bxor` `bnot` `<<` `>>` | bitwise operators
| `==` `!=` `<` `>` `=<` `>=` | comparison operators | `==` `!=` `<` `>` `=<` `>=` | comparison operators
| `::` `++` | list operators | `::` `++` | list operators
| `|>` | functional operators | `|>` | functional operators
@@ -275,13 +275,17 @@ In order of highest to lowest precedence.
| Operators | Associativity | Operators | Associativity
| --- | --- | --- | ---
| `!` | right | `!` `bnot`| right
| `^` | left | `^` | left
| `*` `/` `mod` | left | `*` `/` `mod` | left
| `-` (unary) | right | `-` (unary) | right
| `+` `-` | left | `+` `-` | left
| `<<` `>>` | left
| `::` `++` | right | `::` `++` | right
| `<` `>` `=<` `>=` `==` `!=` | none | `<` `>` `=<` `>=` `==` `!=` | none
| `band` | left
| `bxor` | left
| `bor` | left
| `&&` | right | `&&` | right
| `||` | right | `||` | right
| `|>` | left | `|>` | left
+17
View File
@@ -0,0 +1,17 @@
namespace AENSCompat =
// Translate old format to new format - always possible
function pointee_to_V2(p : AENS.pointee) : AENSv2.pointee =
switch(p)
AENS.AccountPt(a) => AENSv2.AccountPt(a)
AENS.OraclePt(a) => AENSv2.OraclePt(a)
AENS.ContractPt(a) => AENSv2.ContractPt(a)
AENS.ChannelPt(a) => AENSv2.ChannelPt(a)
// Translate new format to old format - option type!
function pointee_from_V2(p2 : AENSv2.pointee) : option(AENS.pointee) =
switch(p2)
AENSv2.AccountPt(a) => Some(AENS.AccountPt(a))
AENSv2.OraclePt(a) => Some(AENS.OraclePt(a))
AENSv2.ContractPt(a) => Some(AENS.ContractPt(a))
AENSv2.ChannelPt(a) => Some(AENS.ChannelPt(a))
AENSv2.DataPt(_) => None
-126
View File
@@ -1,126 +0,0 @@
@compiler >= 4.3
namespace Bitwise =
// bit shift 'x' right 'n' postions
function bsr(n : int, x : int) : int =
let step = 2^n
let res = x / step
if (x >= 0 || x mod step == 0)
res
else
res - 1
// bit shift 'x' left 'n' positions
function bsl(n : int, x : int) : int =
x * 2^n
// bit shift 'x' left 'n' positions, limit at 'lim' bits
function bsli(n : int, x : int, lim : int) : int =
(x * 2^n) mod (2^lim)
// bitwise 'and' for arbitrary precision integers
function band(a : int, b : int) : int =
if (a >= 0 && b >= 0)
uband_(a, b)
elif (b >= 0)
ubnand_(b, -1 - a)
elif (a >= 0)
ubnand_(a, -1 - b)
else
-1 - ubor_(-1 - a, -1 - b)
// bitwise 'or' for arbitrary precision integers
function
bor : (int, int) => int
bor(0, b) = b
bor(a, 0) = a
bor(a : int, b : int) : int =
if (a >= 0 && b >= 0)
ubor_(a, b)
elif (b >= 0)
-1 - ubnand_(-1 - a, b)
elif (a >= 0)
-1 - ubnand_(-1 - b, a)
else
-1 - uband_(-1 - a, -1 - b)
// bitwise 'xor' for arbitrary precision integers
function
bxor : (int, int) => int
bxor(0, b) = b
bxor(a, 0) = a
bxor(a, b) =
if (a >= 0 && b >= 0)
ubxor_(a, b)
elif (b >= 0)
-1 - ubxor_(-1 - a, b)
elif (a >= 0)
-1 - ubxor_(a, -1 - b)
else
ubxor_(-1 - a, -1 - b)
// bitwise 'not' for arbitrary precision integers
function bnot(a : int) = bxor(a, -1)
// Bitwise 'and' for non-negative integers
function uband(a : int, b : int) : int =
require(a >= 0 && b >= 0, "uband is only defined for non-negative integers")
switch((a, b))
(0, _) => 0
(_, 0) => 0
_ => uband__(a, b, 1, 0)
private function uband_(a, b) = uband__(a, b, 1, 0)
private function
uband__(0, b, val, acc) = acc
uband__(a, 0, val, acc) = acc
uband__(a, b, val, acc) =
switch (a mod 2 + b mod 2)
2 => uband__(a / 2, b / 2, val * 2, acc + val)
_ => uband__(a / 2, b / 2, val * 2, acc)
// Bitwise 'or' for non-negative integers
function ubor(a, b) =
require(a >= 0 && b >= 0, "ubor is only defined for non-negative integers")
switch((a, b))
(0, _) => b
(_, 0) => a
_ => ubor__(a, b, 1, 0)
private function ubor_(a, b) = ubor__(a, b, 1, 0)
private function
ubor__(0, 0, val, acc) = acc
ubor__(a, b, val, acc) =
switch (a mod 2 + b mod 2)
0 => ubor__(a / 2, b / 2, val * 2, acc)
_ => ubor__(a / 2, b / 2, val * 2, acc + val)
//Bitwise 'xor' for non-negative integers
function
ubxor : (int, int) => int
ubxor(0, b) = b
ubxor(a, 0) = a
ubxor(a, b) =
require(a >= 0 && b >= 0, "ubxor is only defined for non-negative integers")
ubxor__(a, b, 1, 0)
private function ubxor_(a, b) = ubxor__(a, b, 1, 0)
private function
ubxor__(0, 0, val, acc) = acc
ubxor__(a, b, val, acc) =
switch(a mod 2 + b mod 2)
1 => ubxor__(a / 2, b / 2, val * 2, acc + val)
_ => ubxor__(a / 2, b / 2, val * 2, acc)
private function ubnand_(a, b) = ubnand__(a, b, 1, 0)
private function
ubnand__(0, b, val, acc) = acc
ubnand__(a, b, val, acc) =
switch((a mod 2, b mod 2))
(1, 0) => ubnand__(a / 2, b / 2, val * 2, acc + val)
_ => ubnand__(a / 2, b / 2, val * 2, acc)
+1 -1
View File
@@ -14,7 +14,7 @@
{base_plt_apps, [erts, kernel, stdlib, crypto, mnesia]} {base_plt_apps, [erts, kernel, stdlib, crypto, mnesia]}
]}. ]}.
{relx, [{release, {aesophia, "7.1.0"}, {relx, [{release, {aesophia, "8.0.0"},
[aesophia, aebytecode, getopt]}, [aesophia, aebytecode, getopt]},
{dev_mode, true}, {dev_mode, true},
+54 -109
View File
@@ -229,7 +229,7 @@ force_bind_fun(X, Type, Env = #env{ what = What }) ->
NoCode = get_option(no_code, false), NoCode = get_option(no_code, false),
Entry = if X == "init", What == contract, not NoCode -> Entry = if X == "init", What == contract, not NoCode ->
{reserved_init, Ann, Type}; {reserved_init, Ann, Type};
What == contract; What == contract_interface -> {contract_fun, Ann, Type}; What == contract_interface -> {contract_fun, Ann, Type};
true -> {Ann, Type} true -> {Ann, Type}
end, end,
on_current_scope(Env, fun(Scope = #scope{ funs = Funs }) -> on_current_scope(Env, fun(Scope = #scope{ funs = Funs }) ->
@@ -426,7 +426,6 @@ lookup_env(Env, Kind, Ann, Name) ->
lookup_env1(#env{ namespace = Current, used_namespaces = UsedNamespaces, scopes = Scopes }, Kind, Ann, QName) -> lookup_env1(#env{ namespace = Current, used_namespaces = UsedNamespaces, scopes = Scopes }, Kind, Ann, QName) ->
Qual = lists:droplast(QName), Qual = lists:droplast(QName),
Name = lists:last(QName), Name = lists:last(QName),
QNameIsEvent = lists:suffix(["Chain", "event"], QName),
AllowPrivate = lists:prefix(Qual, Current), AllowPrivate = lists:prefix(Qual, Current),
%% Get the scope %% Get the scope
case maps:get(Qual, Scopes, false) of case maps:get(Qual, Scopes, false) of
@@ -442,8 +441,6 @@ lookup_env1(#env{ namespace = Current, used_namespaces = UsedNamespaces, scopes
{reserved_init, Ann1, Type} -> {reserved_init, Ann1, Type} ->
type_error({cannot_call_init_function, Ann}), type_error({cannot_call_init_function, Ann}),
{QName, {Ann1, Type}}; %% Return the type to avoid an extra not-in-scope error {QName, {Ann1, Type}}; %% Return the type to avoid an extra not-in-scope error
{contract_fun, Ann1, Type} when AllowPrivate orelse QNameIsEvent ->
{QName, {Ann1, Type}};
{contract_fun, Ann1, Type} -> {contract_fun, Ann1, Type} ->
type_error({contract_treated_as_namespace, Ann, QName}), type_error({contract_treated_as_namespace, Ann, QName}),
{QName, {Ann1, Type}}; {QName, {Ann1, Type}};
@@ -543,6 +540,8 @@ global_env() ->
TTL = {qid, Ann, ["Chain", "ttl"]}, TTL = {qid, Ann, ["Chain", "ttl"]},
Pointee = {qid, Ann, ["AENS", "pointee"]}, Pointee = {qid, Ann, ["AENS", "pointee"]},
AENSName = {qid, Ann, ["AENS", "name"]}, AENSName = {qid, Ann, ["AENS", "name"]},
PointeeV2 = {qid, Ann, ["AENSv2", "pointee"]},
AENSNameV2 = {qid, Ann, ["AENSv2", "name"]},
Fr = {qid, Ann, ["MCL_BLS12_381", "fr"]}, Fr = {qid, Ann, ["MCL_BLS12_381", "fr"]},
Fp = {qid, Ann, ["MCL_BLS12_381", "fp"]}, Fp = {qid, Ann, ["MCL_BLS12_381", "fp"]},
Fp2 = {tuple_t, Ann, [Fp, Fp]}, Fp2 = {tuple_t, Ann, [Fp, Fp]},
@@ -678,14 +677,7 @@ global_env() ->
AENSScope = #scope AENSScope = #scope
{ funs = MkDefs( { funs = MkDefs(
[{"resolve", Fun([String, String], option_t(Ann, A))}, [%% AENS pointee constructors
{"preclaim", SignFun([Address, Hash], Unit)},
{"claim", SignFun([Address, String, Int, Int], Unit)},
{"transfer", SignFun([Address, Address, String], Unit)},
{"revoke", SignFun([Address, String], Unit)},
{"update", SignFun([Address, String, Option(TTL), Option(Int), Option(Map(String, Pointee))], Unit)},
{"lookup", Fun([String], option_t(Ann, AENSName))},
%% AENS pointee constructors
{"AccountPt", Fun1(Address, Pointee)}, {"AccountPt", Fun1(Address, Pointee)},
{"OraclePt", Fun1(Address, Pointee)}, {"OraclePt", Fun1(Address, Pointee)},
{"ContractPt", Fun1(Address, Pointee)}, {"ContractPt", Fun1(Address, Pointee)},
@@ -695,6 +687,26 @@ global_env() ->
]) ])
, types = MkDefs([{"pointee", 0}, {"name", 0}]) }, , types = MkDefs([{"pointee", 0}, {"name", 0}]) },
AENSv2Scope = #scope
{ funs = MkDefs(
[{"resolve", Fun([String, String], option_t(Ann, A))},
{"preclaim", SignFun([Address, Hash], Unit)},
{"claim", SignFun([Address, String, Int, Int], Unit)},
{"transfer", SignFun([Address, Address, String], Unit)},
{"revoke", SignFun([Address, String], Unit)},
{"update", SignFun([Address, String, Option(TTL), Option(Int), Option(Map(String, PointeeV2))], Unit)},
{"lookup", Fun([String], option_t(Ann, AENSNameV2))},
%% AENS pointee constructors v2
{"AccountPt", Fun1(Address, PointeeV2)},
{"OraclePt", Fun1(Address, PointeeV2)},
{"ContractPt", Fun1(Address, PointeeV2)},
{"ChannelPt", Fun1(Address, PointeeV2)},
{"DataPt", Fun1(String, PointeeV2)},
%% Name object constructor v2
{"Name", Fun([Address, TTL, Map(String, PointeeV2)], AENSNameV2)}
])
, types = MkDefs([{"pointee", 0}, {"name", 0}]) },
MapScope = #scope MapScope = #scope
{ funs = MkDefs( { funs = MkDefs(
[{"from_list", Fun1(List(Pair(K, V)), Map(K, V))}, [{"from_list", Fun1(List(Pair(K, V)), Map(K, V))},
@@ -714,7 +726,8 @@ global_env() ->
{"ecrecover_secp256k1", Fun([Hash, Bytes(65)], Option(Bytes(20)))}, {"ecrecover_secp256k1", Fun([Hash, Bytes(65)], Option(Bytes(20)))},
{"sha3", Fun1(A, Hash)}, {"sha3", Fun1(A, Hash)},
{"sha256", Fun1(A, Hash)}, {"sha256", Fun1(A, Hash)},
{"blake2b", Fun1(A, Hash)}]) }, {"blake2b", Fun1(A, Hash)},
{"poseidon", Fun([Int, Int], Int)}]) },
%% Fancy BLS12-381 crypto operations %% Fancy BLS12-381 crypto operations
MCL_BLS12_381_Scope = #scope MCL_BLS12_381_Scope = #scope
@@ -799,14 +812,16 @@ global_env() ->
]) }, ]) },
%% Conversion %% Conversion
IntScope = #scope{ funs = MkDefs([{"to_str", Fun1(Int, String)}]) }, IntScope = #scope{ funs = MkDefs([{"to_str", Fun1(Int, String)},
{"mulmod", Fun([Int, Int, Int], Int)}]) },
AddressScope = #scope{ funs = MkDefs([{"to_str", Fun1(Address, String)}, AddressScope = #scope{ funs = MkDefs([{"to_str", Fun1(Address, String)},
{"to_bytes", Fun1(Address, Bytes(32))},
{"to_contract", FunC(address_to_contract, [Address], A)}, {"to_contract", FunC(address_to_contract, [Address], A)},
{"is_oracle", Fun1(Address, Bool)}, {"is_oracle", Fun1(Address, Bool)},
{"is_contract", Fun1(Address, Bool)}, {"is_contract", Fun1(Address, Bool)},
{"is_payable", Fun1(Address, Bool)}]) }, {"is_payable", Fun1(Address, Bool)}]) },
#env{ scopes = #env{ scopes =
#{ [] => TopScope #{ [] => TopScope
, ["Chain"] => ChainScope , ["Chain"] => ChainScope
@@ -814,6 +829,7 @@ global_env() ->
, ["Call"] => CallScope , ["Call"] => CallScope
, ["Oracle"] => OracleScope , ["Oracle"] => OracleScope
, ["AENS"] => AENSScope , ["AENS"] => AENSScope
, ["AENSv2"] => AENSv2Scope
, ["Map"] => MapScope , ["Map"] => MapScope
, ["Auth"] => AuthScope , ["Auth"] => AuthScope
, ["Crypto"] => CryptoScope , ["Crypto"] => CryptoScope
@@ -909,7 +925,6 @@ infer1(Env0, [Contract0 = {Contract, Ann, ConName, Impls, Code} | Rest], Acc, Op
contract -> ets_insert(defined_contracts, {qname(ConName)}); contract -> ets_insert(defined_contracts, {qname(ConName)});
contract_interface -> ok contract_interface -> ok
end, end,
check_contract_preserved_payability(Env, ConName, Ann, Impls, Acc, What),
populate_functions_to_implement(Env, ConName, Impls, Acc), populate_functions_to_implement(Env, ConName, Impls, Acc),
Env1 = bind_contract(untyped, Contract0, Env), Env1 = bind_contract(untyped, Contract0, Env),
{Env2, Code1} = infer_contract_top(push_scope(contract, ConName, Env1), What, Code, Options), {Env2, Code1} = infer_contract_top(push_scope(contract, ConName, Env1), What, Code, Options),
@@ -935,25 +950,6 @@ infer1(Env, [{pragma, _, _} | Rest], Acc, Options) ->
%% Pragmas are checked in check_modifiers %% Pragmas are checked in check_modifiers
infer1(Env, Rest, Acc, Options). infer1(Env, Rest, Acc, Options).
-spec check_contract_preserved_payability(env(), Con, Ann, Impls, Contracts, Kind) -> ok | no_return() when
Con :: aeso_syntax:con(),
Ann :: aeso_syntax:ann(),
Impls :: [Con],
Contracts :: [aeso_syntax:decl()],
Kind :: contract | contract_interface.
check_contract_preserved_payability(Env, ContractName, ContractAnn, Impls, DefinedContracts, Kind) ->
Payable = proplists:get_value(payable, ContractAnn, false),
ImplsNames = [ name(I) || I <- Impls ],
Interfaces = [ Con || I = {contract_interface, _, Con, _, _} <- DefinedContracts,
lists:member(name(Con), ImplsNames),
aeso_syntax:get_ann(payable, I, false) ],
create_type_errors(),
[ type_error({unpreserved_payablity, Kind, ContractName, I}) || I <- Interfaces, Payable == false ],
destroy_and_report_type_errors(Env),
ok.
%% Report all functions that were not implemented by the contract ContractName. %% Report all functions that were not implemented by the contract ContractName.
-spec report_unimplemented_functions(env(), ContractName) -> ok | no_return() when -spec report_unimplemented_functions(env(), ContractName) -> ok | no_return() when
ContractName :: aeso_syntax:con(). ContractName :: aeso_syntax:con().
@@ -1257,10 +1253,6 @@ check_usings(Env = #env{ used_namespaces = UsedNamespaces }, [{using, Ann, Con,
create_type_errors(), create_type_errors(),
type_error({using_undefined_namespace, Ann, qname(Con)}), type_error({using_undefined_namespace, Ann, qname(Con)}),
destroy_and_report_type_errors(Env); destroy_and_report_type_errors(Env);
#scope{kind = contract} ->
create_type_errors(),
type_error({using_undefined_namespace, Ann, qname(Con)}),
destroy_and_report_type_errors(Env);
Scope -> Scope ->
Nsp = case Parts of Nsp = case Parts of
none -> none ->
@@ -1514,37 +1506,19 @@ check_reserved_entrypoints(Funs) ->
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type = {fun_t, _, _, _, _}}) -> check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type = {fun_t, _, _, _, _}}) ->
Type1 = {fun_t, _, Named, Args, Ret} = check_type(Env, Type), Type1 = {fun_t, _, Named, Args, Ret} = check_type(Env, Type),
TypeSig = {type_sig, Ann, none, Named, Args, Ret}, TypeSig = {type_sig, Ann, none, Named, Args, Ret},
register_implementation(Id, TypeSig), register_implementation(Name),
{{Name, TypeSig}, {fun_decl, Ann, Id, Type1}}; {{Name, TypeSig}, {fun_decl, Ann, Id, Type1}};
check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) -> check_fundecl(Env, {fun_decl, Ann, Id = {id, _, Name}, Type}) ->
type_error({fundecl_must_have_funtype, Ann, Id, Type}), type_error({fundecl_must_have_funtype, Ann, Id, Type}),
{{Name, {type_sig, Ann, none, [], [], Type}}, check_type(Env, Type)}. {{Name, {type_sig, Ann, none, [], [], Type}}, check_type(Env, Type)}.
%% Register the function FunId as implemented by deleting it from the functions %% Register the function FunName as implemented by deleting it from the functions
%% to be implemented table if it is included there, or return true otherwise. %% to be implemented table if it is included there, or return true otherwise.
-spec register_implementation(FunId, FunSig) -> true | no_return() when -spec register_implementation(FunName) -> true | no_return() when
FunId :: aeso_syntax:id(), FunName :: string().
FunSig :: typesig(). register_implementation(Name) ->
register_implementation(Id, Sig) ->
Name = name(Id),
case ets_lookup(functions_to_implement, Name) of case ets_lookup(functions_to_implement, Name) of
[{Name, Interface, Decl = {fun_decl, _, DeclId, _}}] -> [{Name, _, {fun_decl, _, _, _}}] ->
DeclStateful = aeso_syntax:get_ann(stateful, Decl, false),
DeclPayable = aeso_syntax:get_ann(payable, Decl, false),
SigEntrypoint = aeso_syntax:get_ann(entrypoint, Sig, false),
SigStateful = aeso_syntax:get_ann(stateful, Sig, false),
SigPayable = aeso_syntax:get_ann(payable, Sig, false),
[ type_error({function_should_be_entrypoint, Id, DeclId, Interface})
|| not SigEntrypoint ],
[ type_error({entrypoint_cannot_be_stateful, Id, DeclId, Interface})
|| SigStateful andalso not DeclStateful ],
[ type_error({entrypoint_must_be_payable, Id, DeclId, Interface})
|| not SigPayable andalso DeclPayable ],
ets_delete(functions_to_implement, Name); ets_delete(functions_to_implement, Name);
[] -> [] ->
true; true;
@@ -1554,9 +1528,9 @@ register_implementation(Id, Sig) ->
infer_nonrec(Env, LetFun) -> infer_nonrec(Env, LetFun) ->
create_constraints(), create_constraints(),
NewLetFun = {{_, Sig}, _} = infer_letfun(Env, LetFun), NewLetFun = {{FunName, _}, _} = infer_letfun(Env, LetFun),
check_special_funs(Env, NewLetFun), check_special_funs(Env, NewLetFun),
register_implementation(get_letfun_id(LetFun), Sig), register_implementation(FunName),
solve_then_destroy_and_report_unsolved_constraints(Env), solve_then_destroy_and_report_unsolved_constraints(Env),
Result = {TypeSig, _} = instantiate(NewLetFun), Result = {TypeSig, _} = instantiate(NewLetFun),
print_typesig(TypeSig), print_typesig(TypeSig),
@@ -1585,8 +1559,8 @@ infer_letrec(Env, Defs) ->
ExtendEnv = bind_funs(Funs, Env), ExtendEnv = bind_funs(Funs, Env),
Inferred = Inferred =
[ begin [ begin
Res = {{Name, TypeSig}, LetFun} = infer_letfun(ExtendEnv, LF), Res = {{Name, TypeSig}, _} = infer_letfun(ExtendEnv, LF),
register_implementation(get_letfun_id(LetFun), TypeSig), register_implementation(Name),
Got = proplists:get_value(Name, Funs), Got = proplists:get_value(Name, Funs),
Expect = typesig_to_fun_t(TypeSig), Expect = typesig_to_fun_t(TypeSig),
unify(Env, Got, Expect, {check_typesig, Name, Got, Expect}), unify(Env, Got, Expect, {check_typesig, Name, Got, Expect}),
@@ -1638,9 +1612,6 @@ infer_letfun1(Env0 = #env{ namespace = NS }, {letfun, Attrib, Fun = {id, NameAtt
{{Name, TypeSig}, {{Name, TypeSig},
{letfun, Attrib, {id, NameAttrib, Name}, TypedArgs, ResultType, NewGuardedBodies}}. {letfun, Attrib, {id, NameAttrib, Name}, TypedArgs, ResultType, NewGuardedBodies}}.
get_letfun_id({fun_clauses, _, Id, _, _}) -> Id;
get_letfun_id({letfun, _, Id, _, _, _}) -> Id.
desugar_clauses(Ann, Fun, {type_sig, _, _, _, ArgTypes, RetType}, Clauses) -> desugar_clauses(Ann, Fun, {type_sig, _, _, _, ArgTypes, RetType}, Clauses) ->
NeedDesugar = NeedDesugar =
case Clauses of case Clauses of
@@ -1718,14 +1689,10 @@ check_stateful(#env { current_function = Fun }, _Id, _Type) ->
%% Hack: don't allow passing the 'value' named arg if not stateful. This only %% Hack: don't allow passing the 'value' named arg if not stateful. This only
%% works since the user can't create functions with named arguments. %% works since the user can't create functions with named arguments.
check_stateful_named_arg(#env{ stateful = Stateful, current_function = Fun }, {id, _, "value"}, Default) -> check_stateful_named_arg(#env{ stateful = false, current_function = Fun }, {id, _, "value"}, Default) ->
case Default of case Default of
{int, _, 0} -> ok; {int, _, 0} -> ok;
_ -> _ -> type_error({value_arg_not_allowed, Default, Fun})
case Stateful of
true -> when_warning(warn_unused_stateful, fun() -> used_stateful(Fun) end);
false -> type_error({value_arg_not_allowed, Default, Fun})
end
end; end;
check_stateful_named_arg(_, _, _) -> ok. check_stateful_named_arg(_, _, _) -> ok.
@@ -1843,10 +1810,6 @@ infer_expr(_Env, Body={contract_pubkey, As, _}) ->
{typed, As, Body, Con}; {typed, As, Body, Con};
infer_expr(_Env, Body={id, As, "_"}) -> infer_expr(_Env, Body={id, As, "_"}) ->
{typed, As, Body, fresh_uvar(As)}; {typed, As, Body, fresh_uvar(As)};
infer_expr(_Env, Body={id, As, "???"}) ->
T = fresh_uvar(As),
type_error({hole_found, As, T}),
{typed, As, Body, T};
infer_expr(Env, Id = {Tag, As, _}) when Tag == id; Tag == qid -> infer_expr(Env, Id = {Tag, As, _}) when Tag == id; Tag == qid ->
{QName, Type} = lookup_name(Env, As, Id), {QName, Type} = lookup_name(Env, As, Id),
{typed, As, QName, Type}; {typed, As, QName, Type};
@@ -1936,7 +1899,7 @@ infer_expr(Env, {app, Ann, Fun, Args0} = App) ->
unify(Env, FunType, {fun_t, [], NamedArgsVar, ArgTypes, GeneralResultType}, When), unify(Env, FunType, {fun_t, [], NamedArgsVar, ArgTypes, GeneralResultType}, When),
when_warning(warn_negative_spend, fun() -> warn_potential_negative_spend(Ann, NewFun1, NewArgs) end), when_warning(warn_negative_spend, fun() -> warn_potential_negative_spend(Ann, NewFun1, NewArgs) end),
[ add_constraint({aens_resolve_type, GeneralResultType}) [ add_constraint({aens_resolve_type, GeneralResultType})
|| element(3, FunName) =:= ["AENS", "resolve"] ], || element(3, FunName) =:= ["AENSv2", "resolve"] ],
[ add_constraint({oracle_type, Ann, OType}) [ add_constraint({oracle_type, Ann, OType})
|| OType <- [get_oracle_type(FunName, ArgTypes, GeneralResultType)], || OType <- [get_oracle_type(FunName, ArgTypes, GeneralResultType)],
OType =/= false ], OType =/= false ],
@@ -2223,6 +2186,11 @@ infer_infix({IntOp, As})
IntOp == '^'; IntOp == 'mod' -> IntOp == '^'; IntOp == 'mod' ->
Int = {id, As, "int"}, Int = {id, As, "int"},
{fun_t, As, [], [Int, Int], Int}; {fun_t, As, [], [Int, Int], Int};
infer_infix({BitOp, As})
when BitOp == 'band'; BitOp == 'bor'; BitOp == 'bxor';
BitOp == '<<'; BitOp == '>>' ->
Int = {id, As, "int"},
{fun_t, As, [], [Int, Int], Int};
infer_infix({RelOp, As}) infer_infix({RelOp, As})
when RelOp == '=='; RelOp == '!='; when RelOp == '=='; RelOp == '!=';
RelOp == '<'; RelOp == '>'; RelOp == '<'; RelOp == '>';
@@ -2250,6 +2218,9 @@ infer_infix({'|>', As}) ->
infer_prefix({'!',As}) -> infer_prefix({'!',As}) ->
Bool = {id, As, "bool"}, Bool = {id, As, "bool"},
{fun_t, As, [], [Bool], Bool}; {fun_t, As, [], [Bool], Bool};
infer_prefix({BitOp,As}) when BitOp =:= 'bnot' ->
Int = {id, As, "int"},
{fun_t, As, [], [Int], Int};
infer_prefix({IntOp,As}) when IntOp =:= '-' -> infer_prefix({IntOp,As}) when IntOp =:= '-' ->
Int = {id, As, "int"}, Int = {id, As, "int"},
{fun_t, As, [], [Int], Int}. {fun_t, As, [], [Int], Int}.
@@ -3400,9 +3371,6 @@ mk_error({cannot_unify, A, B, Cxt, When}) ->
[pp(instantiate(A)), pp(instantiate(B))]), [pp(instantiate(A)), pp(instantiate(B))]),
{Pos, Ctxt} = pp_when(When), {Pos, Ctxt} = pp_when(When),
mk_t_err(Pos, Msg, Ctxt); mk_t_err(Pos, Msg, Ctxt);
mk_error({hole_found, Ann, Type}) ->
Msg = io_lib:format("Found a hole of type `~s`", [pp(instantiate(Type))]),
mk_t_err(pos(Ann), Msg);
mk_error({unbound_variable, Id}) -> mk_error({unbound_variable, Id}) ->
Msg = io_lib:format("Unbound variable `~s`", [pp(Id)]), Msg = io_lib:format("Unbound variable `~s`", [pp(Id)]),
case Id of case Id of
@@ -3718,7 +3686,7 @@ mk_error({empty_record_definition, Ann, Name}) ->
Msg = io_lib:format("Empty record definitions are not allowed. Cannot define the record `~s`", [Name]), Msg = io_lib:format("Empty record definitions are not allowed. Cannot define the record `~s`", [Name]),
mk_t_err(pos(Ann), Msg); mk_t_err(pos(Ann), Msg);
mk_error({unimplemented_interface_function, ConId, InterfaceName, FunName}) -> mk_error({unimplemented_interface_function, ConId, InterfaceName, FunName}) ->
Msg = io_lib:format("Unimplemented entrypoint `~s` from the interface `~s` in the contract `~s`", [FunName, InterfaceName, pp(ConId)]), Msg = io_lib:format("Unimplemented function `~s` from the interface `~s` in the contract `~s`", [FunName, InterfaceName, pp(ConId)]),
mk_t_err(pos(ConId), Msg); mk_t_err(pos(ConId), Msg);
mk_error({referencing_undefined_interface, InterfaceId}) -> mk_error({referencing_undefined_interface, InterfaceId}) ->
Msg = io_lib:format("Trying to implement or extend an undefined interface `~s`", [pp(InterfaceId)]), Msg = io_lib:format("Trying to implement or extend an undefined interface `~s`", [pp(InterfaceId)]),
@@ -3750,7 +3718,7 @@ mk_error({higher_order_entrypoint, Ann, {id, _, Name}, Thing}) ->
[ThingS, Name, Bad]), [ThingS, Name, Bad]),
mk_t_err(pos(Ann), Msg); mk_t_err(pos(Ann), Msg);
mk_error({invalid_aens_resolve_type, Ann, T}) -> mk_error({invalid_aens_resolve_type, Ann, T}) ->
Msg = io_lib:format("Invalid return type of `AENS.resolve`:\n" Msg = io_lib:format("Invalid return type of `AENSv2.resolve`:\n"
"~s`\n" "~s`\n"
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)", "It must be a `string` or a pubkey type (`address`, `oracle`, etc)",
[pp_type(" `", T)]), [pp_type(" `", T)]),
@@ -3766,29 +3734,6 @@ mk_error({interface_implementation_conflict, Contract, I1, I2, Fun}) ->
"the contract `~s` have a function called `~s`", "the contract `~s` have a function called `~s`",
[name(I1), name(I2), name(Contract), name(Fun)]), [name(I1), name(I2), name(Contract), name(Fun)]),
mk_t_err(pos(Contract), Msg); mk_t_err(pos(Contract), Msg);
mk_error({function_should_be_entrypoint, Impl, Base, Interface}) ->
Msg = io_lib:format("`~s` must be declared as an entrypoint instead of a function "
"in order to implement the entrypoint `~s` from the interface `~s`",
[name(Impl), name(Base), name(Interface)]),
mk_t_err(pos(Impl), Msg);
mk_error({entrypoint_cannot_be_stateful, Impl, Base, Interface}) ->
Msg = io_lib:format("`~s` cannot be stateful because the entrypoint `~s` in the "
"interface `~s` is not stateful",
[name(Impl), name(Base), name(Interface)]),
mk_t_err(pos(Impl), Msg);
mk_error({entrypoint_must_be_payable, Impl, Base, Interface}) ->
Msg = io_lib:format("`~s` must be payable because the entrypoint `~s` in the "
"interface `~s` is payable",
[name(Impl), name(Base), name(Interface)]),
mk_t_err(pos(Impl), Msg);
mk_error({unpreserved_payablity, Kind, ContractCon, InterfaceCon}) ->
KindStr = case Kind of
contract -> "contract";
contract_interface -> "interface"
end,
Msg = io_lib:format("Non-payable ~s `~s` cannot implement payable interface `~s`",
[KindStr, name(ContractCon), name(InterfaceCon)]),
mk_t_err(pos(ContractCon), Msg);
mk_error(Err) -> mk_error(Err) ->
Msg = io_lib:format("Unknown error: ~p", [Err]), Msg = io_lib:format("Unknown error: ~p", [Err]),
mk_t_err(pos(0, 0), Msg). mk_t_err(pos(0, 0), Msg).
+27 -13
View File
@@ -32,12 +32,13 @@
-type op() :: '+' | '-' | '*' | '/' | mod | '^' | '++' | '::' | -type op() :: '+' | '-' | '*' | '/' | mod | '^' | '++' | '::' |
'<' | '>' | '=<' | '>=' | '==' | '!=' | '!' | '<' | '>' | '=<' | '>=' | '==' | '!=' | '!' |
'band' | 'bor' | 'bxor' | 'bnot' | '<<' | '>>' |
map_get | map_get_d | map_set | map_from_list | map_to_list | map_get | map_get_d | map_set | map_from_list | map_to_list |
map_delete | map_member | map_size | string_length | map_delete | map_member | map_size | string_length |
string_concat | bits_set | bits_clear | bits_test | bits_sum | string_concat | bits_set | bits_clear | bits_test | bits_sum |
bits_intersection | bits_union | bits_difference | bits_intersection | bits_union | bits_difference |
contract_to_address | address_to_contract | crypto_verify_sig | crypto_verify_sig_secp256k1 | contract_to_address | address_to_contract | crypto_verify_sig | crypto_verify_sig_secp256k1 |
crypto_sha3 | crypto_sha256 | crypto_blake2b | crypto_sha3 | crypto_sha256 | crypto_blake2b | crypto_poseidon |
crypto_ecverify_secp256k1 | crypto_ecrecover_secp256k1 | crypto_ecverify_secp256k1 | crypto_ecrecover_secp256k1 |
mcl_bls12_381_g1_neg | mcl_bls12_381_g1_norm | mcl_bls12_381_g1_valid | mcl_bls12_381_g1_neg | mcl_bls12_381_g1_norm | mcl_bls12_381_g1_valid |
mcl_bls12_381_g1_is_zero | mcl_bls12_381_g1_add | mcl_bls12_381_g1_mul | mcl_bls12_381_g1_is_zero | mcl_bls12_381_g1_add | mcl_bls12_381_g1_mul |
@@ -214,6 +215,12 @@ init_env(Options) ->
["AENS", "ContractPt"] => #con_tag{ tag = 2, arities = [1, 1, 1, 1] }, ["AENS", "ContractPt"] => #con_tag{ tag = 2, arities = [1, 1, 1, 1] },
["AENS", "ChannelPt"] => #con_tag{ tag = 3, arities = [1, 1, 1, 1] }, ["AENS", "ChannelPt"] => #con_tag{ tag = 3, arities = [1, 1, 1, 1] },
["AENS", "Name"] => #con_tag{ tag = 0, arities = [3] }, ["AENS", "Name"] => #con_tag{ tag = 0, arities = [3] },
["AENSv2", "AccountPt"] => #con_tag{ tag = 0, arities = [1, 1, 1, 1, 1] },
["AENSv2", "OraclePt"] => #con_tag{ tag = 1, arities = [1, 1, 1, 1, 1] },
["AENSv2", "ContractPt"] => #con_tag{ tag = 2, arities = [1, 1, 1, 1, 1] },
["AENSv2", "ChannelPt"] => #con_tag{ tag = 3, arities = [1, 1, 1, 1, 1] },
["AENSv2", "DataPt"] => #con_tag{ tag = 4, arities = [1, 1, 1, 1, 1] },
["AENSv2", "Name"] => #con_tag{ tag = 0, arities = [3] },
["Chain", "GAMetaTx"] => #con_tag{ tag = 0, arities = [2] }, ["Chain", "GAMetaTx"] => #con_tag{ tag = 0, arities = [2] },
["Chain", "PayingForTx"] => #con_tag{ tag = 0, arities = [2] }, ["Chain", "PayingForTx"] => #con_tag{ tag = 0, arities = [2] },
["Chain", "SpendTx"] => #con_tag{ tag = 0, arities = ChainTxArities }, ["Chain", "SpendTx"] => #con_tag{ tag = 0, arities = ChainTxArities },
@@ -245,8 +252,11 @@ init_env(Options) ->
-spec builtins() -> builtins(). -spec builtins() -> builtins().
builtins() -> builtins() ->
MkName = fun(NS, Fun) -> MkName = fun
list_to_atom(string:to_lower(string:join(NS ++ [Fun], "_"))) (["AENSv2"], Fun) ->
list_to_atom(string:to_lower("AENS_" ++ Fun));
(NS, Fun) ->
list_to_atom(string:to_lower(string:join(NS ++ [Fun], "_")))
end, end,
Scopes = [{[], [{"abort", 1}, {"require", 2}, {"exit", 1}]}, Scopes = [{[], [{"abort", 1}, {"require", 2}, {"exit", 1}]},
{["Chain"], [{"spend", 2}, {"balance", 1}, {"block_hash", 1}, {"coinbase", none}, {["Chain"], [{"spend", 2}, {"balance", 1}, {"block_hash", 1}, {"coinbase", none},
@@ -258,13 +268,13 @@ builtins() ->
{["Oracle"], [{"register", 4}, {"expiry", 1}, {"query_fee", 1}, {"query", 5}, {"get_question", 2}, {["Oracle"], [{"register", 4}, {"expiry", 1}, {"query_fee", 1}, {"query", 5}, {"get_question", 2},
{"respond", 4}, {"extend", 3}, {"get_answer", 2}, {"respond", 4}, {"extend", 3}, {"get_answer", 2},
{"check", 1}, {"check_query", 2}]}, {"check", 1}, {"check_query", 2}]},
{["AENS"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 5}, {"transfer", 4}, {["AENSv2"], [{"resolve", 2}, {"preclaim", 3}, {"claim", 5}, {"transfer", 4},
{"revoke", 3}, {"update", 6}, {"lookup", 1}]}, {"revoke", 3}, {"update", 6}, {"lookup", 1}]},
{["Map"], [{"from_list", 1}, {"to_list", 1}, {"lookup", 2}, {["Map"], [{"from_list", 1}, {"to_list", 1}, {"lookup", 2},
{"lookup_default", 3}, {"delete", 2}, {"member", 2}, {"size", 1}]}, {"lookup_default", 3}, {"delete", 2}, {"member", 2}, {"size", 1}]},
{["Crypto"], [{"verify_sig", 3}, {"verify_sig_secp256k1", 3}, {["Crypto"], [{"verify_sig", 3}, {"verify_sig_secp256k1", 3},
{"ecverify_secp256k1", 3}, {"ecrecover_secp256k1", 2}, {"ecverify_secp256k1", 3}, {"ecrecover_secp256k1", 2},
{"sha3", 1}, {"sha256", 1}, {"blake2b", 1}]}, {"sha3", 1}, {"sha256", 1}, {"blake2b", 1}, {"poseidon", 2}]},
{["MCL_BLS12_381"], [{"g1_neg", 1}, {"g1_norm", 1}, {"g1_valid", 1}, {"g1_is_zero", 1}, {"g1_add", 2}, {"g1_mul", 2}, {["MCL_BLS12_381"], [{"g1_neg", 1}, {"g1_norm", 1}, {"g1_valid", 1}, {"g1_is_zero", 1}, {"g1_add", 2}, {"g1_mul", 2},
{"g2_neg", 1}, {"g2_norm", 1}, {"g2_valid", 1}, {"g2_is_zero", 1}, {"g2_add", 2}, {"g2_mul", 2}, {"g2_neg", 1}, {"g2_norm", 1}, {"g2_valid", 1}, {"g2_is_zero", 1}, {"g2_add", 2}, {"g2_mul", 2},
{"gt_inv", 1}, {"gt_add", 2}, {"gt_mul", 2}, {"gt_pow", 2}, {"gt_is_one", 1}, {"gt_inv", 1}, {"gt_add", 2}, {"gt_mul", 2}, {"gt_pow", 2}, {"gt_is_one", 1},
@@ -277,8 +287,9 @@ builtins() ->
{["Bits"], [{"set", 2}, {"clear", 2}, {"test", 2}, {"sum", 1}, {"intersection", 2}, {["Bits"], [{"set", 2}, {"clear", 2}, {"test", 2}, {"sum", 1}, {"intersection", 2},
{"union", 2}, {"difference", 2}, {"none", none}, {"all", none}]}, {"union", 2}, {"difference", 2}, {"none", none}, {"all", none}]},
{["Bytes"], [{"to_int", 1}, {"to_str", 1}, {"concat", 2}, {"split", 1}]}, {["Bytes"], [{"to_int", 1}, {"to_str", 1}, {"concat", 2}, {"split", 1}]},
{["Int"], [{"to_str", 1}]}, {["Int"], [{"to_str", 1}, {"mulmod", 2}]},
{["Address"], [{"to_str", 1}, {"to_contract", 1}, {"is_oracle", 1}, {"is_contract", 1}, {"is_payable", 1}]} {["Address"], [{"to_str", 1}, {"to_bytes", 1}, {"to_contract", 1},
{"is_oracle", 1}, {"is_contract", 1}, {"is_payable", 1}]}
], ],
maps:from_list([ {NS ++ [Fun], {MkName(NS, Fun), Arity}} maps:from_list([ {NS ++ [Fun], {MkName(NS, Fun), Arity}}
|| {NS, Funs} <- Scopes, || {NS, Funs} <- Scopes,
@@ -313,11 +324,13 @@ init_type_env() ->
["Chain", "ttl"] => ?type({variant, [[integer], [integer]]}), ["Chain", "ttl"] => ?type({variant, [[integer], [integer]]}),
["AENS", "pointee"] => ?type({variant, [[address], [address], [address], [address]]}), ["AENS", "pointee"] => ?type({variant, [[address], [address], [address], [address]]}),
["AENS", "name"] => ?type({variant, [[address, {variant, [[integer], [integer]]}, {map, string, {variant, [[address], [address], [address], [address]]}}]]}), ["AENS", "name"] => ?type({variant, [[address, {variant, [[integer], [integer]]}, {map, string, {variant, [[address], [address], [address], [address]]}}]]}),
["AENSv2", "pointee"] => ?type({variant, [[address], [address], [address], [address], [string]]}),
["AENSv2", "name"] => ?type({variant, [[address, {variant, [[integer], [integer]]}, {map, string, {variant, [[address], [address], [address], [address], [string]]}}]]}),
["Chain", "ga_meta_tx"] => ?type({variant, [[address, integer]]}), ["Chain", "ga_meta_tx"] => ?type({variant, [[address, integer]]}),
["Chain", "paying_for_tx"] => ?type({variant, [[address, integer]]}), ["Chain", "paying_for_tx"] => ?type({variant, [[address, integer]]}),
["Chain", "base_tx"] => ?type(BaseTx), ["Chain", "base_tx"] => ?type(BaseTx),
["MCL_BLS12_381", "fr"] => ?type({bytes, 32}), ["MCL_BLS12_381", "fr"] => ?type({bytes, 32}),
["MCL_BLS12_381", "fp"] => ?type({bytes, 48}) ["MCL_BLS12_381", "fp"] => ?type({bytes, 48})
}. }.
is_no_code(Env) -> is_no_code(Env) ->
@@ -694,8 +707,9 @@ expr_to_fcode(Env, Type, {app, Ann, {Op, _}, [A, B]}) when is_atom(Op) ->
end; end;
expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) -> expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) ->
case Op of case Op of
'-' -> {op, '-', [{lit, {int, 0}}, expr_to_fcode(Env, A)]}; '-' -> {op, '-', [{lit, {int, 0}}, expr_to_fcode(Env, A)]};
'!' -> {op, '!', [expr_to_fcode(Env, A)]} 'bnot' -> {op, 'bnot', [expr_to_fcode(Env, A)]};
'!' -> {op, '!', [expr_to_fcode(Env, A)]}
end; end;
%% Function calls %% Function calls
@@ -1086,9 +1100,9 @@ op_builtins() ->
stringinternal_sha3, stringinternal_sha256, stringinternal_blake2b, stringinternal_sha3, stringinternal_sha256, stringinternal_blake2b,
char_to_int, char_from_int, stringinternal_to_lower, stringinternal_to_upper, char_to_int, char_from_int, stringinternal_to_lower, stringinternal_to_upper,
bits_set, bits_clear, bits_test, bits_sum, bits_intersection, bits_union, bits_set, bits_clear, bits_test, bits_sum, bits_intersection, bits_union,
bits_difference, int_to_str, address_to_str, crypto_verify_sig, bits_difference, int_to_str, int_mulmod, address_to_str, address_to_bytes, crypto_verify_sig,
address_to_contract, address_to_contract,
crypto_verify_sig_secp256k1, crypto_sha3, crypto_sha256, crypto_blake2b, crypto_verify_sig_secp256k1, crypto_sha3, crypto_sha256, crypto_blake2b, crypto_poseidon,
crypto_ecverify_secp256k1, crypto_ecrecover_secp256k1, crypto_ecverify_secp256k1, crypto_ecrecover_secp256k1,
mcl_bls12_381_g1_neg, mcl_bls12_381_g1_norm, mcl_bls12_381_g1_valid, mcl_bls12_381_g1_neg, mcl_bls12_381_g1_norm, mcl_bls12_381_g1_valid,
mcl_bls12_381_g1_is_zero, mcl_bls12_381_g1_add, mcl_bls12_381_g1_mul, mcl_bls12_381_g1_is_zero, mcl_bls12_381_g1_add, mcl_bls12_381_g1_mul,
+18
View File
@@ -682,6 +682,12 @@ op_to_scode('>=') -> aeb_fate_ops:egt(?a, ?a, ?a);
op_to_scode('==') -> aeb_fate_ops:eq(?a, ?a, ?a); op_to_scode('==') -> aeb_fate_ops:eq(?a, ?a, ?a);
op_to_scode('!=') -> aeb_fate_ops:neq(?a, ?a, ?a); op_to_scode('!=') -> aeb_fate_ops:neq(?a, ?a, ?a);
op_to_scode('!') -> aeb_fate_ops:not_op(?a, ?a); op_to_scode('!') -> aeb_fate_ops:not_op(?a, ?a);
op_to_scode('bnot') -> aeb_fate_ops:bin_not(?a, ?a);
op_to_scode('band') -> aeb_fate_ops:bin_and(?a, ?a, ?a);
op_to_scode('bor') -> aeb_fate_ops:bin_or(?a, ?a, ?a);
op_to_scode('bxor') -> aeb_fate_ops:bin_xor(?a, ?a, ?a);
op_to_scode('<<') -> aeb_fate_ops:bin_sl(?a, ?a, ?a);
op_to_scode('>>') -> aeb_fate_ops:bin_sr(?a, ?a, ?a);
op_to_scode(map_get) -> aeb_fate_ops:map_lookup(?a, ?a, ?a); op_to_scode(map_get) -> aeb_fate_ops:map_lookup(?a, ?a, ?a);
op_to_scode(map_get_d) -> aeb_fate_ops:map_lookup(?a, ?a, ?a, ?a); op_to_scode(map_get_d) -> aeb_fate_ops:map_lookup(?a, ?a, ?a, ?a);
op_to_scode(map_set) -> aeb_fate_ops:map_update(?a, ?a, ?a, ?a); op_to_scode(map_set) -> aeb_fate_ops:map_update(?a, ?a, ?a, ?a);
@@ -706,7 +712,9 @@ op_to_scode(bits_intersection) -> aeb_fate_ops:bits_and(?a, ?a, ?a);
op_to_scode(bits_union) -> aeb_fate_ops:bits_or(?a, ?a, ?a); op_to_scode(bits_union) -> aeb_fate_ops:bits_or(?a, ?a, ?a);
op_to_scode(bits_difference) -> aeb_fate_ops:bits_diff(?a, ?a, ?a); op_to_scode(bits_difference) -> aeb_fate_ops:bits_diff(?a, ?a, ?a);
op_to_scode(address_to_str) -> aeb_fate_ops:addr_to_str(?a, ?a); op_to_scode(address_to_str) -> aeb_fate_ops:addr_to_str(?a, ?a);
op_to_scode(address_to_bytes) -> aeb_fate_ops:addr_to_bytes(?a, ?a);
op_to_scode(int_to_str) -> aeb_fate_ops:int_to_str(?a, ?a); op_to_scode(int_to_str) -> aeb_fate_ops:int_to_str(?a, ?a);
op_to_scode(int_mulmod) -> aeb_fate_ops:mulmod(?a, ?a, ?a, ?a);
op_to_scode(contract_to_address) -> aeb_fate_ops:contract_to_address(?a, ?a); op_to_scode(contract_to_address) -> aeb_fate_ops:contract_to_address(?a, ?a);
op_to_scode(address_to_contract) -> aeb_fate_ops:address_to_contract(?a, ?a); op_to_scode(address_to_contract) -> aeb_fate_ops:address_to_contract(?a, ?a);
op_to_scode(crypto_verify_sig) -> aeb_fate_ops:verify_sig(?a, ?a, ?a, ?a); op_to_scode(crypto_verify_sig) -> aeb_fate_ops:verify_sig(?a, ?a, ?a, ?a);
@@ -716,6 +724,7 @@ op_to_scode(crypto_ecrecover_secp256k1) -> aeb_fate_ops:ecrecover_secp256k1(?a,
op_to_scode(crypto_sha3) -> aeb_fate_ops:sha3(?a, ?a); op_to_scode(crypto_sha3) -> aeb_fate_ops:sha3(?a, ?a);
op_to_scode(crypto_sha256) -> aeb_fate_ops:sha256(?a, ?a); op_to_scode(crypto_sha256) -> aeb_fate_ops:sha256(?a, ?a);
op_to_scode(crypto_blake2b) -> aeb_fate_ops:blake2b(?a, ?a); op_to_scode(crypto_blake2b) -> aeb_fate_ops:blake2b(?a, ?a);
op_to_scode(crypto_poseidon) -> aeb_fate_ops:poseidon(?a, ?a, ?a);
op_to_scode(stringinternal_sha3) -> aeb_fate_ops:sha3(?a, ?a); op_to_scode(stringinternal_sha3) -> aeb_fate_ops:sha3(?a, ?a);
op_to_scode(stringinternal_sha256) -> aeb_fate_ops:sha256(?a, ?a); op_to_scode(stringinternal_sha256) -> aeb_fate_ops:sha256(?a, ?a);
op_to_scode(stringinternal_blake2b) -> aeb_fate_ops:blake2b(?a, ?a); op_to_scode(stringinternal_blake2b) -> aeb_fate_ops:blake2b(?a, ?a);
@@ -913,6 +922,13 @@ attributes(I) ->
{'DIV', A, B, C} -> Pure(A, [B, C]); {'DIV', A, B, C} -> Pure(A, [B, C]);
{'MOD', A, B, C} -> Pure(A, [B, C]); {'MOD', A, B, C} -> Pure(A, [B, C]);
{'POW', A, B, C} -> Pure(A, [B, C]); {'POW', A, B, C} -> Pure(A, [B, C]);
{'MULMOD', A, B, C, D} -> Pure(A, [B, C, D]);
{'BAND', A, B, C} -> Pure(A, [B, C]);
{'BOR', A, B, C} -> Pure(A, [B, C]);
{'BXOR', A, B, C} -> Pure(A, [B, C]);
{'BNOT', A, B} -> Pure(A, [B]);
{'BSL', A, B, C} -> Pure(A, [B, C]);
{'BSR', A, B, C} -> Pure(A, [B, C]);
{'LT', A, B, C} -> Pure(A, [B, C]); {'LT', A, B, C} -> Pure(A, [B, C]);
{'GT', A, B, C} -> Pure(A, [B, C]); {'GT', A, B, C} -> Pure(A, [B, C]);
{'EQ', A, B, C} -> Pure(A, [B, C]); {'EQ', A, B, C} -> Pure(A, [B, C]);
@@ -965,12 +981,14 @@ attributes(I) ->
{'SHA3', A, B} -> Pure(A, [B]); {'SHA3', A, B} -> Pure(A, [B]);
{'SHA256', A, B} -> Pure(A, [B]); {'SHA256', A, B} -> Pure(A, [B]);
{'BLAKE2B', A, B} -> Pure(A, [B]); {'BLAKE2B', A, B} -> Pure(A, [B]);
{'POSEIDON', A, B, C} -> Pure(A, [B, C]);
{'VERIFY_SIG', A, B, C, D} -> Pure(A, [B, C, D]); {'VERIFY_SIG', A, B, C, D} -> Pure(A, [B, C, D]);
{'VERIFY_SIG_SECP256K1', A, B, C, D} -> Pure(A, [B, C, D]); {'VERIFY_SIG_SECP256K1', A, B, C, D} -> Pure(A, [B, C, D]);
{'ECVERIFY_SECP256K1', A, B, C, D} -> Pure(A, [B, C, D]); {'ECVERIFY_SECP256K1', A, B, C, D} -> Pure(A, [B, C, D]);
{'ECRECOVER_SECP256K1', A, B, C} -> Pure(A, [B, C]); {'ECRECOVER_SECP256K1', A, B, C} -> Pure(A, [B, C]);
{'CONTRACT_TO_ADDRESS', A, B} -> Pure(A, [B]); {'CONTRACT_TO_ADDRESS', A, B} -> Pure(A, [B]);
{'ADDRESS_TO_CONTRACT', A, B} -> Pure(A, [B]); {'ADDRESS_TO_CONTRACT', A, B} -> Pure(A, [B]);
{'ADDRESS_TO_BYTES', A, B} -> Pure(A, [B]);
{'AUTH_TX_HASH', A} -> Pure(A, []); {'AUTH_TX_HASH', A} -> Pure(A, []);
{'AUTH_TX', A} -> Pure(A, []); {'AUTH_TX', A} -> Pure(A, []);
{'BYTES_TO_INT', A, B} -> Pure(A, [B]); {'BYTES_TO_INT', A, B} -> Pure(A, [B]);
+8 -6
View File
@@ -333,14 +333,19 @@ expr100() ->
expr150() -> infixl(expr200(), binop('|>')). expr150() -> infixl(expr200(), binop('|>')).
expr200() -> infixr(expr300(), binop('||')). expr200() -> infixr(expr300(), binop('||')).
expr300() -> infixr(expr400(), binop('&&')). expr300() -> infixr(expr325(), binop('&&')).
expr325() -> infixl(expr350(), binop('bor')).
expr350() -> infixl(expr375(), binop('bxor')).
expr375() -> infixl(expr400(), binop('band')).
expr400() -> infix(expr500(), binop(['<', '>', '=<', '>=', '==', '!='])). expr400() -> infix(expr500(), binop(['<', '>', '=<', '>=', '==', '!='])).
expr500() -> infixr(expr600(), binop(['::', '++'])). expr500() -> infixr(expr550(), binop(['::', '++'])).
expr550() -> infixl(expr600(), binop(['<<', '>>'])).
expr600() -> infixl(expr650(), binop(['+', '-'])). expr600() -> infixl(expr650(), binop(['+', '-'])).
expr650() -> ?RULE(many(token('-')), expr700(), prefixes(_1, _2)). expr650() -> ?RULE(many(token('-')), expr700(), prefixes(_1, _2)).
expr700() -> infixl(expr750(), binop(['*', '/', mod])). expr700() -> infixl(expr750(), binop(['*', '/', mod])).
expr750() -> infixl(expr800(), binop(['^'])). expr750() -> infixl(expr800(), binop(['^'])).
expr800() -> ?RULE(many(token('!')), expr900(), prefixes(_1, _2)). expr800() -> ?RULE(many(token('!')), expr850(), prefixes(_1, _2)).
expr850() -> ?RULE(many(token('bnot')), expr900(), prefixes(_1, _2)).
expr900() -> ?RULE(exprAtom(), many(elim()), elim(_1, _2)). expr900() -> ?RULE(exprAtom(), many(elim()), elim(_1, _2)).
exprAtom() -> exprAtom() ->
@@ -359,12 +364,9 @@ exprAtom() ->
, ?RULE(tok('['), Expr, binop('..'), Expr, tok(']'), _3(_2, _4)) , ?RULE(tok('['), Expr, binop('..'), Expr, tok(']'), _3(_2, _4))
, ?RULE(keyword('('), comma_sep(Expr), tok(')'), tuple_e(_1, _2)) , ?RULE(keyword('('), comma_sep(Expr), tok(')'), tuple_e(_1, _2))
, letpat() , letpat()
, hole()
]) ])
end). end).
hole() -> ?RULE(token('???'), {id, get_ann(_1), "???"}).
comprehension_exp() -> comprehension_exp() ->
?LAZY_P(choice( ?LAZY_P(choice(
[ comprehension_bind() [ comprehension_bind()
+10 -4
View File
@@ -436,15 +436,20 @@ bin_prec('=') -> { 0, 0, 0}; %% Always printed inside '[ ]'
bin_prec('@') -> { 0, 0, 0}; %% Only in error messages bin_prec('@') -> { 0, 0, 0}; %% Only in error messages
bin_prec('|>') -> {150, 150, 200}; bin_prec('|>') -> {150, 150, 200};
bin_prec('||') -> {200, 300, 200}; bin_prec('||') -> {200, 300, 200};
bin_prec('&&') -> {300, 400, 300}; bin_prec('&&') -> {300, 325, 300};
bin_prec('bor') -> {325, 350, 325};
bin_prec('bxor') -> {350, 375, 350};
bin_prec('band') -> {375, 400, 375};
bin_prec('<') -> {400, 500, 500}; bin_prec('<') -> {400, 500, 500};
bin_prec('>') -> {400, 500, 500}; bin_prec('>') -> {400, 500, 500};
bin_prec('=<') -> {400, 500, 500}; bin_prec('=<') -> {400, 500, 500};
bin_prec('>=') -> {400, 500, 500}; bin_prec('>=') -> {400, 500, 500};
bin_prec('==') -> {400, 500, 500}; bin_prec('==') -> {400, 500, 500};
bin_prec('!=') -> {400, 500, 500}; bin_prec('!=') -> {400, 500, 500};
bin_prec('++') -> {500, 600, 500}; bin_prec('++') -> {500, 550, 500};
bin_prec('::') -> {500, 600, 500}; bin_prec('::') -> {500, 550, 500};
bin_prec('<<') -> {550, 600, 550};
bin_prec('>>') -> {550, 600, 550};
bin_prec('+') -> {600, 600, 650}; bin_prec('+') -> {600, 600, 650};
bin_prec('-') -> {600, 600, 650}; bin_prec('-') -> {600, 600, 650};
bin_prec('*') -> {700, 700, 750}; bin_prec('*') -> {700, 700, 750};
@@ -454,7 +459,8 @@ bin_prec('^') -> {750, 750, 800}.
-spec un_prec(aeso_syntax:un_op()) -> {integer(), integer()}. -spec un_prec(aeso_syntax:un_op()) -> {integer(), integer()}.
un_prec('-') -> {650, 650}; un_prec('-') -> {650, 650};
un_prec('!') -> {800, 800}. un_prec('!') -> {800, 800};
un_prec('bnot') -> {850, 850}.
equals(Ann, A, B) -> equals(Ann, A, B) ->
{app, [{format, infix} | Ann], {'=', Ann}, [A, B]}. {app, [{format, infix} | Ann], {'=', Ann}, [A, B]}.
+1 -1
View File
@@ -45,7 +45,7 @@ lexer() ->
Keywords = ["contract", "include", "let", "switch", "type", "record", "datatype", "if", "elif", "else", "function", Keywords = ["contract", "include", "let", "switch", "type", "record", "datatype", "if", "elif", "else", "function",
"stateful", "payable", "true", "false", "mod", "public", "entrypoint", "private", "indexed", "namespace", "stateful", "payable", "true", "false", "mod", "public", "entrypoint", "private", "indexed", "namespace",
"interface", "main", "using", "as", "for", "hiding" "interface", "main", "using", "as", "for", "hiding", "band", "bor", "bxor", "bnot"
], ],
KW = string:join(Keywords, "|"), KW = string:join(Keywords, "|"),
+2 -2
View File
@@ -106,8 +106,8 @@
-type bin_op() :: '+' | '-' | '*' | '/' | mod | '^' -type bin_op() :: '+' | '-' | '*' | '/' | mod | '^'
| '++' | '::' | '<' | '>' | '=<' | '>=' | '==' | '!=' | '++' | '::' | '<' | '>' | '=<' | '>=' | '==' | '!='
| '||' | '&&' | '..' | '|>'. | '||' | '&&' | '..' | 'band' | 'bor' | 'bxor' | '>>' | '<<' | '|>'.
-type un_op() :: '-' | '!'. -type un_op() :: '-' | '!' | 'bnot'.
-type expr() -type expr()
:: {lam, ann(), [arg()], expr()} :: {lam, ann(), [arg()], expr()}
+16 -1
View File
@@ -88,7 +88,7 @@ from_fate_builtin(QType, Val) ->
{["AENS", "name"], {variant, [3], 0, {Addr, TTL, Ptrs}}} -> {["AENS", "name"], {variant, [3], 0, {Addr, TTL, Ptrs}}} ->
App(["AENS","Name"], [Chk(Adr, Addr), Chk(Qid(["Chain", "ttl"]), TTL), App(["AENS","Name"], [Chk(Adr, Addr), Chk(Qid(["Chain", "ttl"]), TTL),
Chk(Map(Str, Qid(["AENS", "pointee"])), Ptrs)]); Chk(Map(Str, Qid(["AENS", "pointee"])), Ptrs)]);
{["AENS", "pointee"], {variant, [1, 1, 1, 1], 0, {Addr}}} -> {["AENS", "pointee"], {variant, [1, 1, 1, 1], 0, {Addr}}} ->
App(["AENS","AccountPt"], [Chk(Adr, Addr)]); App(["AENS","AccountPt"], [Chk(Adr, Addr)]);
@@ -99,6 +99,21 @@ from_fate_builtin(QType, Val) ->
{["AENS", "pointee"], {variant, [1, 1, 1, 1], 3, {Addr}}} -> {["AENS", "pointee"], {variant, [1, 1, 1, 1], 3, {Addr}}} ->
App(["AENS","ChannelPt"], [Chk(Adr, Addr)]); App(["AENS","ChannelPt"], [Chk(Adr, Addr)]);
{["AENSv2", "name"], {variant, [3], 0, {Addr, TTL, Ptrs}}} ->
App(["AENSv2","Name"], [Chk(Adr, Addr), Chk(Qid(["Chain", "ttl"]), TTL),
Chk(Map(Str, Qid(["AENSv2", "pointee"])), Ptrs)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 0, {Val}}} ->
App(["AENSv2","AccountPt"], [Chk(Adr, Val)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 1, {Val}}} ->
App(["AENSv2","OraclePt"], [Chk(Adr, Val)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 2, {Val}}} ->
App(["AENSv2","ContractPt"], [Chk(Adr, Val)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 3, {Val}}} ->
App(["AENSv2","ChannelPt"], [Chk(Adr, Val)]);
{["AENSv2", "pointee"], {variant, [1, 1, 1, 1, 1], 4, {Val}}} ->
App(["AENSv2","DataPt"], [Chk(Str, Val)]);
{["Chain", "ga_meta_tx"], {variant, [2], 0, {Addr, X}}} -> {["Chain", "ga_meta_tx"], {variant, [2], 0, {Addr, X}}} ->
App(["Chain","GAMetaTx"], [Chk(Adr, Addr), Chk(Int, X)]); App(["Chain","GAMetaTx"], [Chk(Adr, Addr), Chk(Int, X)]);
+1 -1
View File
@@ -1,6 +1,6 @@
{application, aesophia, {application, aesophia,
[{description, "Compiler for Aeternity Sophia language"}, [{description, "Compiler for Aeternity Sophia language"},
{vsn, "7.1.0"}, {vsn, "8.0.0"},
{registered, []}, {registered, []},
{applications, {applications,
[kernel, [kernel,
+5 -44
View File
@@ -205,9 +205,6 @@ compilable_contracts() ->
"polymorphism_variance_switching_chain_create", "polymorphism_variance_switching_chain_create",
"polymorphism_variance_switching_void_supertype", "polymorphism_variance_switching_void_supertype",
"polymorphism_variance_switching_unify_with_interface_decls", "polymorphism_variance_switching_unify_with_interface_decls",
"polymorphism_preserve_or_add_payable_contract",
"polymorphism_preserve_or_add_payable_entrypoint",
"polymorphism_preserve_or_remove_stateful_entrypoint",
"missing_init_fun_state_unit", "missing_init_fun_state_unit",
"complex_compare_leq", "complex_compare_leq",
"complex_compare", "complex_compare",
@@ -221,6 +218,7 @@ compilable_contracts() ->
"unapplied_contract_call", "unapplied_contract_call",
"unapplied_named_arg_builtin", "unapplied_named_arg_builtin",
"resolve_field_constraint_by_arity", "resolve_field_constraint_by_arity",
"ceres",
"test" % Custom general-purpose test file. Keep it last on the list. "test" % Custom general-purpose test file. Keep it last on the list.
]. ].
@@ -871,7 +869,7 @@ failing_contracts() ->
" - line 9, column 5">>]) " - line 9, column 5">>])
, ?TYPE_ERROR(polymorphism_contract_missing_implementation, , ?TYPE_ERROR(polymorphism_contract_missing_implementation,
[<<?Pos(4,20) [<<?Pos(4,20)
"Unimplemented entrypoint `f` from the interface `I1` in the contract `I2`">> "Unimplemented function `f` from the interface `I1` in the contract `I2`">>
]) ])
, ?TYPE_ERROR(polymorphism_contract_same_decl_multi_interface, , ?TYPE_ERROR(polymorphism_contract_same_decl_multi_interface,
[<<?Pos(7,10) [<<?Pos(7,10)
@@ -1098,19 +1096,19 @@ failing_contracts() ->
]) ])
, ?TYPE_ERROR(polymorphic_aens_resolve, , ?TYPE_ERROR(polymorphic_aens_resolve,
[<<?Pos(4,5) [<<?Pos(4,5)
"Invalid return type of `AENS.resolve`:\n" "Invalid return type of `AENSv2.resolve`:\n"
" `'a`\n" " `'a`\n"
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">> "It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
]) ])
, ?TYPE_ERROR(bad_aens_resolve, , ?TYPE_ERROR(bad_aens_resolve,
[<<?Pos(6,5) [<<?Pos(6,5)
"Invalid return type of `AENS.resolve`:\n" "Invalid return type of `AENSv2.resolve`:\n"
" `list(int)`\n" " `list(int)`\n"
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">> "It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
]) ])
, ?TYPE_ERROR(bad_aens_resolve_using, , ?TYPE_ERROR(bad_aens_resolve_using,
[<<?Pos(7,5) [<<?Pos(7,5)
"Invalid return type of `AENS.resolve`:\n" "Invalid return type of `AENSv2.resolve`:\n"
" `list(int)`\n" " `list(int)`\n"
"It must be a `string` or a pubkey type (`address`, `oracle`, etc)">> "It must be a `string` or a pubkey type (`address`, `oracle`, etc)">>
]) ])
@@ -1155,43 +1153,6 @@ failing_contracts() ->
"to arguments\n" "to arguments\n"
" `Chain.create : (value : int, var_args) => 'c`">> " `Chain.create : (value : int, var_args) => 'c`">>
]) ])
, ?TYPE_ERROR(polymorphism_add_stateful_entrypoint,
[<<?Pos(5,25)
"`f` cannot be stateful because the entrypoint `f` in the interface `I` is not stateful">>
])
, ?TYPE_ERROR(polymorphism_change_entrypoint_to_function,
[<<?Pos(6,14)
"`f` must be declared as an entrypoint instead of a function in order to implement the entrypoint `f` from the interface `I`">>
])
, ?TYPE_ERROR(polymorphism_non_payable_contract_implement_payable,
[<<?Pos(4,10)
"Non-payable contract `C` cannot implement payable interface `I`">>
])
, ?TYPE_ERROR(polymorphism_non_payable_interface_implement_payable,
[<<?Pos(4,20)
"Non-payable interface `H` cannot implement payable interface `I`">>
])
, ?TYPE_ERROR(polymorphism_remove_payable_entrypoint,
[<<?Pos(5,16)
"`f` must be payable because the entrypoint `f` in the interface `I` is payable">>
])
, ?TYPE_ERROR(calling_child_contract_entrypoint,
[<<?Pos(5,20)
"Invalid call to contract entrypoint `F.g`.\n"
"It must be called as `c.g` for some `c : F`.">>])
, ?TYPE_ERROR(using_contract_as_namespace,
[<<?Pos(5,3)
"Cannot use undefined namespace F">>])
, ?TYPE_ERROR(hole_expression,
[<<?Pos(5,13)
"Found a hole of type `bool`">>,
<<?Pos(6,17)
"Found a hole of type `string`">>,
<<?Pos(9,37)
"Found a hole of type `(int) => int`">>,
<<?Pos(13,20)
"Found a hole of type `'a`">>
])
]. ].
validation_test_() -> validation_test_() ->
+1 -1
View File
@@ -53,7 +53,7 @@ simple_contracts_test_() ->
%% associativity %% associativity
[ RightAssoc(Op) || Op <- ["||", "&&", "::", "++"] ], [ RightAssoc(Op) || Op <- ["||", "&&", "::", "++"] ],
[ NonAssoc(Op) || Op <- ["==", "!=", "<", ">", "=<", ">="] ], [ NonAssoc(Op) || Op <- ["==", "!=", "<", ">", "=<", ">="] ],
[ LeftAssoc(Op) || Op <- ["+", "-", "*", "/", "mod"] ], [ LeftAssoc(Op) || Op <- ["+", "-", "*", "/", "mod", "band", "bor", "bxor", "<<", ">>"] ],
%% precedence %% precedence
[ Stronger(Op2, Op1) || [T1 , T2 | _] <- tails(Tiers), Op1 <- T1, Op2 <- T2 ], [ Stronger(Op2, Op1) || [T1 , T2 | _] <- tails(Tiers), Op1 <- T1, Op2 <- T2 ],
+2 -1
View File
@@ -39,7 +39,8 @@ all_tokens() ->
%% Symbols %% Symbols
lists:map(Lit, [',', '.', ';', '|', ':', '(', ')', '[', ']', '{', '}']) ++ lists:map(Lit, [',', '.', ';', '|', ':', '(', ')', '[', ']', '{', '}']) ++
%% Operators %% Operators
lists:map(Lit, ['=', '==', '!=', '>', '<', '>=', '=<', '-', '+', '++', '*', '/', mod, ':', '::', '->', '=>', '||', '&&', '!']) ++ lists:map(Lit, ['=', '==', '!=', '>', '<', '>=', '=<', '-', '+', '++', '*', '/', mod,
':', '::', '->', '=>', '||', '&&', '!', 'band', 'bor', 'bxor', 'bnot' ,'<<', '>>']) ++
%% Keywords %% Keywords
lists:map(Lit, [contract, type, 'let', switch]) ++ lists:map(Lit, [contract, type, 'let', switch]) ++
%% Comment token (not an actual token), just for tests %% Comment token (not an actual token), just for tests
+17 -17
View File
@@ -6,77 +6,77 @@ main contract AENSTest =
// Name resolution // Name resolution
stateful entrypoint resolve_word(name : string, key : string) : option(address) = stateful entrypoint resolve_word(name : string, key : string) : option(address) =
AENS.resolve(name, key) AENSv2.resolve(name, key)
stateful entrypoint resolve_string(name : string, key : string) : option(string) = stateful entrypoint resolve_string(name : string, key : string) : option(string) =
AENS.resolve(name, key) AENSv2.resolve(name, key)
stateful entrypoint resolve_contract(name : string, key : string) : option(C) = stateful entrypoint resolve_contract(name : string, key : string) : option(C) =
AENS.resolve(name, key) AENSv2.resolve(name, key)
stateful entrypoint resolve_oracle(name : string, key : string) : option(oracle(int, int)) = stateful entrypoint resolve_oracle(name : string, key : string) : option(oracle(int, int)) =
AENS.resolve(name, key) AENSv2.resolve(name, key)
stateful entrypoint resolve_oracle_query(name : string, key : string) : option(oracle_query(int, int)) = stateful entrypoint resolve_oracle_query(name : string, key : string) : option(oracle_query(int, int)) =
AENS.resolve(name, key) AENSv2.resolve(name, key)
// Transactions // Transactions
stateful entrypoint preclaim(addr : address, // Claim on behalf of this account (can be Contract.address) stateful entrypoint preclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
chash : hash) : unit = // Commitment hash chash : hash) : unit = // Commitment hash
AENS.preclaim(addr, chash) AENSv2.preclaim(addr, chash)
stateful entrypoint signedPreclaim(addr : address, // Claim on behalf of this account (can be Contract.address) stateful entrypoint signedPreclaim(addr : address, // Claim on behalf of this account (can be Contract.address)
chash : hash, // Commitment hash chash : hash, // Commitment hash
sign : signature) : unit = // Signed by addr (if not Contract.address) sign : signature) : unit = // Signed by addr (if not Contract.address)
AENS.preclaim(addr, chash, signature = sign) AENSv2.preclaim(addr, chash, signature = sign)
stateful entrypoint claim(addr : address, stateful entrypoint claim(addr : address,
name : string, name : string,
salt : int, salt : int,
name_fee : int) : unit = name_fee : int) : unit =
AENS.claim(addr, name, salt, name_fee) AENSv2.claim(addr, name, salt, name_fee)
stateful entrypoint signedClaim(addr : address, stateful entrypoint signedClaim(addr : address,
name : string, name : string,
salt : int, salt : int,
name_fee : int, name_fee : int,
sign : signature) : unit = sign : signature) : unit =
AENS.claim(addr, name, salt, name_fee, signature = sign) AENSv2.claim(addr, name, salt, name_fee, signature = sign)
stateful entrypoint update(owner : address, stateful entrypoint update(owner : address,
name : string, name : string,
ttl : option(Chain.ttl), ttl : option(Chain.ttl),
client_ttl : option(int), client_ttl : option(int),
pointers : option(map(string, AENS.pointee))) : unit = pointers : option(map(string, AENSv2.pointee))) : unit =
AENS.update(owner, name, ttl, client_ttl, pointers) AENSv2.update(owner, name, ttl, client_ttl, pointers)
stateful entrypoint signedUpdate(owner : address, stateful entrypoint signedUpdate(owner : address,
name : string, name : string,
ttl : option(Chain.ttl), ttl : option(Chain.ttl),
client_ttl : option(int), client_ttl : option(int),
pointers : option(map(string, AENS.pointee)), pointers : option(map(string, AENSv2.pointee)),
sign : signature) : unit = sign : signature) : unit =
AENS.update(owner, name, ttl, client_ttl, pointers, signature = sign) AENSv2.update(owner, name, ttl, client_ttl, pointers, signature = sign)
stateful entrypoint transfer(owner : address, stateful entrypoint transfer(owner : address,
new_owner : address, new_owner : address,
name : string) : unit = name : string) : unit =
AENS.transfer(owner, new_owner, name) AENSv2.transfer(owner, new_owner, name)
stateful entrypoint signedTransfer(owner : address, stateful entrypoint signedTransfer(owner : address,
new_owner : address, new_owner : address,
name : string, name : string,
sign : signature) : unit = sign : signature) : unit =
AENS.transfer(owner, new_owner, name, signature = sign) AENSv2.transfer(owner, new_owner, name, signature = sign)
stateful entrypoint revoke(owner : address, stateful entrypoint revoke(owner : address,
name : string) : unit = name : string) : unit =
AENS.revoke(owner, name) AENSv2.revoke(owner, name)
stateful entrypoint signedRevoke(owner : address, stateful entrypoint signedRevoke(owner : address,
name : string, name : string,
sign : signature) : unit = sign : signature) : unit =
AENS.revoke(owner, name, signature = sign) AENSv2.revoke(owner, name, signature = sign)
+24 -11
View File
@@ -1,17 +1,30 @@
contract AENSUpdate = include "Option.aes"
include "AENSCompat.aes"
contract interface OldAENSContract =
entrypoint set : (string, string, AENS.pointee) => unit
entrypoint lookup : (string, string) => AENS.pointee
main contract AENSUpdate =
stateful entrypoint update_name(owner : address, name : string) = stateful entrypoint update_name(owner : address, name : string) =
let p1 : AENS.pointee = AENS.AccountPt(Call.caller) let p1 : AENSv2.pointee = AENSv2.AccountPt(Call.caller)
let p2 : AENS.pointee = AENS.OraclePt(Call.caller) let p2 : AENSv2.pointee = AENSv2.OraclePt(Call.caller)
let p3 : AENS.pointee = AENS.ContractPt(Call.caller) let p3 : AENSv2.pointee = AENSv2.ContractPt(Call.caller)
let p4 : AENS.pointee = AENS.ChannelPt(Call.caller) let p4 : AENSv2.pointee = AENSv2.ChannelPt(Call.caller)
AENS.update(owner, name, None, None, let p5 : AENSv2.pointee = AENSv2.DataPt("any something will do")
Some({ ["account_pubkey"] = p1, ["oracle_pubkey"] = p2, AENSv2.update(owner, name, None, None,
["contract_pubkey"] = p3, ["misc"] = p4 })) Some({ ["account_pubkey"] = p1, ["oracle_pubkey"] = p2,
["contract_pubkey"] = p3, ["misc"] = p4, ["data"] = p5 }))
stateful entrypoint old_interaction(c : OldAENSContract, owner : address, name : string) =
let p : AENS.pointee = c.lookup(name, "key1")
AENSv2.update(owner, name, None, None, Some({ ["key1"] = AENSCompat.pointee_to_V2(p) }))
switch(AENSv2.lookup(name))
Some(AENSv2.Name(_, _, pt_map)) =>
c.set(name, "key2", Option.force(AENSCompat.pointee_from_V2(pt_map["key1"])))
entrypoint get_ttl(name : string) = entrypoint get_ttl(name : string) =
switch(AENS.lookup(name)) switch(AENSv2.lookup(name))
Some(AENS.Name(_, FixedTTL(ttl), _)) => ttl Some(AENSv2.Name(_, FixedTTL(ttl), _)) => ttl
entrypoint expiry(o : oracle(int, int)) : int = entrypoint expiry(o : oracle(int, int)) : int =
Oracle.expiry(o) Oracle.expiry(o)
+1 -1
View File
@@ -3,7 +3,7 @@ contract BadAENSresolve =
type t('a) = option(list('a)) type t('a) = option(list('a))
function fail() : t(int) = function fail() : t(int) =
AENS.resolve("foo.aet", "whatever") AENSv2.resolve("foo.aet", "whatever")
entrypoint main_fun() = () entrypoint main_fun() = ()
+1 -1
View File
@@ -1,5 +1,5 @@
contract BadAENSresolve = contract BadAENSresolve =
using AENS using AENSv2
type t('a) = option(list('a)) type t('a) = option(list('a))
@@ -1,5 +0,0 @@
contract F =
entrypoint g() = 1
main contract C =
entrypoint f() = F.g()
+14
View File
@@ -0,0 +1,14 @@
contract C =
entrypoint test() =
let a : int = 23
let b : int = 52
let c = a bor b
let d = c bxor b
let e = d band b
let f = bnot a
let g = f << 2
let h = g >> 2
let i = Int.mulmod(a, b, h)
let j = Crypto.poseidon(i, a)
let k : bytes(32) = Address.to_bytes(Call.origin)
(a bor b band c bxor a << bnot b >> a, k)
-13
View File
@@ -1,13 +0,0 @@
include "List.aes"
contract C =
entrypoint f() =
let ??? = true
let v = ???
let q = v == "str"
let xs = [1, 2, 3, 4]
switch (List.first(List.map(???, xs)))
Some(x) => x + 1
None => 0
function g() = ???
+1 -1
View File
@@ -1,7 +1,7 @@
contract PolymorphicAENSresolve = contract PolymorphicAENSresolve =
function fail() : option('a) = function fail() : option('a) =
AENS.resolve("foo.aet", "whatever") AENSv2.resolve("foo.aet", "whatever")
entrypoint main_fun() = () entrypoint main_fun() = ()
@@ -1,5 +0,0 @@
contract interface I =
entrypoint f : () => int
contract C : I =
stateful entrypoint f() = 1
@@ -1,6 +0,0 @@
contract interface I =
entrypoint f : () => int
contract C : I =
entrypoint init() = ()
function f() = 1
@@ -1,5 +0,0 @@
payable contract interface I =
payable entrypoint f : () => int
contract C : I =
entrypoint f() = 123
@@ -1,8 +0,0 @@
payable contract interface I =
payable entrypoint f : () => int
contract interface H : I =
payable entrypoint f : () => int
payable contract C : H =
entrypoint f() = 123
@@ -1,14 +0,0 @@
contract interface F =
entrypoint f : () => int
payable contract interface G : F =
payable entrypoint f : () => int
entrypoint g : () => int
payable contract interface H =
payable entrypoint h : () => int
payable contract C : G, H =
payable entrypoint f() = 1
payable entrypoint g() = 2
payable entrypoint h() = 3
@@ -1,7 +0,0 @@
contract interface I =
payable entrypoint f : () => int
entrypoint g : () => int
contract C : I =
payable entrypoint f() = 1
payable entrypoint g() = 2
@@ -1,7 +0,0 @@
contract interface I =
stateful entrypoint f : () => int
stateful entrypoint g : () => int
contract C : I =
stateful entrypoint f() = 1
entrypoint g() = 2
@@ -1,5 +0,0 @@
contract interface I =
payable entrypoint f : () => int
contract C : I =
entrypoint f() = 1
+5 -5
View File
@@ -2,10 +2,10 @@
// Named argument builtins are: // Named argument builtins are:
// Oracle.register // Oracle.register
// Oracle.respond // Oracle.respond
// AENS.preclaim // AENSv2.preclaim
// AENS.claim // AENSv2.claim
// AENS.transfer // AENSv2.transfer
// AENS.revoke // AENSv2.revoke
// Oracle.extend // Oracle.extend
include "String.aes" include "String.aes"
contract UnappliedBuiltins = contract UnappliedBuiltins =
@@ -28,7 +28,7 @@ contract UnappliedBuiltins =
function oracle_get_answer() = Oracle.get_answer : (o, _) => _ function oracle_get_answer() = Oracle.get_answer : (o, _) => _
function oracle_check() = Oracle.check : o => _ function oracle_check() = Oracle.check : o => _
function oracle_check_query() = Oracle.check_query : (o, _) => _ function oracle_check_query() = Oracle.check_query : (o, _) => _
function aens_resolve() = AENS.resolve : (_, _) => option(string) function aens_resolve() = AENSv2.resolve : (_, _) => option(string)
function map_lookup() = Map.lookup : (_, m) => _ function map_lookup() = Map.lookup : (_, m) => _
function map_lookup_default() = Map.lookup_default : (_, m, _) => _ function map_lookup_default() = Map.lookup_default : (_, m, _) => _
function map_member() = Map.member : (_, m) => _ function map_member() = Map.member : (_, m) => _
@@ -1,7 +0,0 @@
contract F =
entrypoint g() = 1
main contract C =
using F for [g]
entrypoint f() = g()
+1 -8
View File
@@ -12,7 +12,7 @@ namespace UnusedNamespace =
// Unused // Unused
private function h() = 3 private function h() = 3
main contract Warnings = contract Warnings =
type state = int type state = int
@@ -58,10 +58,3 @@ namespace FunctionsAsArgs =
private function inc(n : int) : int = n + 1 private function inc(n : int) : int = n + 1
// Never used // Never used
private function dec(n : int) : int = n - 1 private function dec(n : int) : int = n - 1
contract Remote =
entrypoint id(_) = 0
contract C =
payable stateful entrypoint
call_missing_con() : int = (ct_1111111111111111111111111111112JF6Dz72 : Remote).id(value = 1, 0)