aiken-lang / aiken Goto Github PK
View Code? Open in Web Editor NEWA modern smart contract platform for Cardano
Home Page: https://aiken-lang.org
License: Apache License 2.0
A modern smart contract platform for Cardano
Home Page: https://aiken-lang.org
License: Apache License 2.0
It might be more powerful for error detection and controlling importable values if instead of fn
for defining validators. This needs some thought and refinement.
In no particular order
The raw UPLC
https://github.com/input-output-hk/plutus/blob/ab3d01280109c1b5d1522f9bae475f5984fbc055/plutus-conformance/uplc/evaluation/example/fibonacci/fibonacci.uplc
doesn't parse correctly OR it doesn't get converted to DeBruijn correctly. The plan is to ignore the test for now and to add a TODO
to the code with a link to this BUG.
Repro:
We've isolated this to a one_way_fibonacci
test here:
#9
Expected Behavior:
The naming convention shouldn't affect the parser and it should look the same once converted to Program<DeBruijn>
no matter the names.
we need some initial docs for the cli and the libraries. rust doc comments are fine for now
This idea allows for the ability to specify a length for byte arrays. Doing this would allow for simplicity in cases where byte arrays need to be a certain length. A famous example is a pubkey hash of an address is 28 bytes. Adding this to the type would automatically generate the check in uplc if the type is used.
We are currently using proptest
and quickcheck
. I think quickcheck
is more ergonomic, but I'm not sure if it has the features for the same tests.
Let's try switching to quickcheck
if we can.
After formatting with lsp, comments are gone.
Comments should be preserved (and properly formatted!)
Currently aiken
's Constant
type handles only a subset of plutus-core
's DefaultUni
, in particular it's missing lists, pairs and "Data".
data DefaultUni a where
DefaultUniInteger :: DefaultUni (Esc Integer)
DefaultUniByteString :: DefaultUni (Esc BS.ByteString)
DefaultUniString :: DefaultUni (Esc Text.Text)
DefaultUniUnit :: DefaultUni (Esc ())
DefaultUniBool :: DefaultUni (Esc Bool)
DefaultUniProtoList :: DefaultUni (Esc [])
DefaultUniProtoPair :: DefaultUni (Esc (,))
DefaultUniApply :: !(DefaultUni (Esc f)) -> !(DefaultUni (Esc a)) -> DefaultUni (Esc (f a))
DefaultUniData :: DefaultUni (Esc Data)
e.g. trying to decode a script with a "Data" constant results in an Unknown constant constructor tag: 8
error, which matches the tag number used in plutus-core
for "Data":
8 -> k DefaultUniData
At the moment the test for the parser is just way too big and makes changes way too brittle. We should take each definition in the big parser test and use them for a bunch of smaller tests.
We should bring over more basic tests from the Plutus repo for uplc parsing and encoding. Also for e2e tests we should add some well known contracts because they are usually larger and provide a production like example for decoding which will be critical for the CEK machine.
When you run aiken new
the project comes with a free .gitignore
:
build
assets
aiken.lock
Most people don't need to include all their dependencies in the /build
directory in their repo. /assets
and aiken.lock
are also often superfluous.
You could add it by hand.
But I think most people are gonna want /build
and /assets
and aiken.lock
ignored from their repo.
Microsoft Windows [Version 10.0.19043.1766]
(c) Microsoft Corporation. All rights reserved.
C:\Users\besib>cargo install aiken
Updating crates.io index
Downloaded aiken v0.0.5
Downloaded 1 crate (4.7 KB) in 2.85s
Installing aiken v0.0.5
Downloaded cfg-if v1.0.0
Downloaded clap_derive v3.2.7
Downloaded hex v0.4.3
Downloaded proc-macro-error-attr v1.0.4
Downloaded thiserror-impl v1.0.31
Downloaded log v0.4.17
Downloaded atty v0.2.14
Downloaded arrayvec v0.5.2
Downloaded once_cell v1.13.0
Downloaded indexmap v1.9.1
Downloaded os_str_bytes v6.1.0
Downloaded strsim v0.10.0
Downloaded unicode-ident v1.0.1
Downloaded termcolor v1.1.3
Downloaded hashbrown v0.12.2
Downloaded typed-arena v2.0.1
Downloaded textwrap v0.15.0
Downloaded quote v1.0.20
Downloaded proc-macro2 v1.0.40
Downloaded clap v3.2.8
Downloaded autocfg v1.1.0
Downloaded anyhow v1.0.58
Downloaded bitflags v1.3.2
Downloaded syn v1.0.98
Downloaded unicode-segmentation v1.9.0
Downloaded version_check v0.9.4
Downloaded peg-runtime v0.8.0
Downloaded peg-macros v0.8.0
Downloaded winapi-util v0.1.5
Downloaded proc-macro-error v1.0.4
Downloaded peg v0.8.0
Downloaded uplc v0.0.5
Downloaded pretty v0.11.3
Downloaded flat-rs v0.0.2
Downloaded clap_lex v0.2.4
Downloaded heck v0.4.0
Downloaded winapi v0.3.9
Downloaded thiserror v1.0.31
Downloaded 38 crates (2.5 MB) in 14.70s (largest was winapi
at 1.2 MB)
Compiling proc-macro2 v1.0.40
Compiling quote v1.0.20
Compiling unicode-ident v1.0.1
Compiling syn v1.0.98
error: linker link.exe
not found
|
= note: program not found
note: the msvc targets depend on the msvc linker but link.exe
was not found
note: please ensure that VS 2013, VS 2015, VS 2017, VS 2019 or VS 2022 was installed with the Visual C++ option
error: could not compile proc-macro2
due to previous error
warning: build failed, waiting for other jobs to finish...
error: could not compile quote
due to previous error
error: could not compile syn
due to previous error
error: failed to compile aiken v0.0.5
, intermediate artifacts can be found at C:\Users\besib\AppData\Local\Temp\cargo-installMMEWY2
C:\Users\besib>
Currently we use isize or might use i64 and usize or u64 for integers.
Instead we should use a Vec to hold integers and perform large number calculations in chunks of 32 bits.
The idea is for smaller numbers we should still have fast computation speed. And super large numbers are rarer.
We can use a struct that holds the Vec plus another field for positive or negative.
Thoughts?
According to https://github.com/input-output-hk/plutus/blob/master/plutus-core/plutus-core/src/PlutusCore/Evaluation/Machine/ExMemory.hs, lines 217-221, a zero-length bytestring should have ex_mem size of 0. It also states that truncating division should be avoided because ex_mem would be 1 in that case (truncates from -1/8 to 0, then adds 1).
In aiken, crates/uplc/src/machine.rs, truncating division is however used, thus giving a wrong result for this edge case.
I suggest checking for zero-length bytestrings, and returning 0 explicitly in that edge case. (similar to the if-else expression for Constant::Integer
)
At the moment this isn't the case and would be convenient for people using the uplc crate
The Plutus Core spec says that strings are allowed to be any Unicode string. The parser currently doesn't support that. For example, my proptest quickly found this innocuous string that broke the parser:
"z2�ட@ઋ𑌷Ⱥ\"¥`\\?𐊧�M'ㄸ·ä�"
Specifically, the quotes in the middle mess it up.
Probably will never come up, but it's good to uphold contracts even if they are edge cases.
Making an issue to motivate myself to document the differences between aiken and helios.
More broadly are they competing to be the best version of the same idea? Or are they both reaching for separate use cases when writing smart contracts (i.e. python vs. rust)
Neither the aiken or helios documentation (as far as I am aware) are aware of each other. It's not clear why exactly you would use one or the other.
Let me know if I should move this to a gist or something else I was surprised to find you can't open issues on forked instance of a repo.
We should check that project name doesn't contain aiken and a few other things I will list later.
It would nice to get some basic CI set up that runs:
It depends on how we organize the libs, but a lot of this stuff could be extremely useful in web apps via Wasm. This requires the code to be no_std
compliant.
It's worth having a conversation about what things we want to make available for Wasm apps.
It looks like wasm-bindgen could solve a lot of the issues.
The last bit of recursion we have is in the discharge value and discharge value env functions. To have a truly good performance with evaluate we should remove any recursion and replace with stack machines and looping as required.
The uplc parser packaged with aiken does not support parsing ProtoList/ProtoPair/PlutusData constants. The official paper outlining UPLC does not mention these options, but they are being used i.e. when compiling pluto down to uplc as i.e. in this example pluto program:
(\s -> data [1, 2])
I am willing to work on this and will propose a PR that implements one way to specify respective constants in UPLC code. If there is some formalization of a UPLC syntax, this should be added into it.
It would be nice to get this going and deployed to https://txpipe.github.io/aiken
.
Bonus
Add an autodeploy CI job
Data
arguments in validators.#
on tuple definition. Require some care in the parser to not mix tuple definition with function calls.New syntax and baked in tooling for regular and property based testing.
The proposed syntax:
test my_test(a: Int) {
// test body
}
From there, we want to let the compiler generate arguments based on their types (which ultimately are Plutus Data) and auto-magically run the test function with multiple generated input values. Since values are fully known, the compiler should also be able to perform integrated shrinking automatically.
https://github.com/aiken-lang/stdlib
in the converter we have some todos that would should get done.
we'll need to define declareBinder
like they have in the Haskell code
Modules defined in src/scripts
are special.
Each file is a validator/entry point and nothing should ever be able to import them.
Since usize
is defined by the architecture of the machine, it's not consistent. It probably would be good to choose something that is more consistent, and hopefully the same as the Plutus Core spec.
aiken new
does generate project names with full path. (e.g. examples/aiken_std
)
The name should be only the basename aiken_std
2.34.1
Following the hello-world https://aiken-lang.org/getting-started/hello-world docs when i try to lock exactly 1000000(1 ADA) in Tx i see the it's 1034400(1.0344 ADA). is it bug or known issue?
I did tried with 10 ADA and 100 ADA which worked as expected.
const txLock = await lock(1000000, { into: validator, owner: datum });
Should exactly lock 1000000 Lovelace.
currently some edge cases require that some type alias definitions come before other type aliases that depend on them. We should be able to remove this limitations but it'll require some thought.
it seems like the flag is doing the opposite of what it's supposed to do
I did some of it but wanted to move on at the time so there are some patterns missing that we should get done ASAP.
It looks like the rule for con char
was missed while making the parser.
The following snippet has been formatted by the aiken fmt
command (or the LSP):
pub fn drop(xs: List(a), n: Int) -> List(a) {
if n <= 0 {
xs
} else {
when xs is {
[] -> []
[_x, ..rest] -> drop(rest, n - 1)
}
}
}
Visibly, the indentation of the nested when
is wrong.
pub fn drop(xs: List(a), n: Int) -> List(a) {
if n <= 0 {
xs
} else {
when xs is {
[] -> []
[_x, ..rest] -> drop(rest, n - 1)
}
}
}
The command aiken uplc eval <input>
does currently not support passing any values. This is quite cumbersome, as usually programs evaluate to lambda expressions that are meant to be executed on i.e. PlutusData.
I suggest to extend the CLI to allow the following aiken uplc eval <input> (<uplc code>)*
where the optional additional code evaluates to values that are passed to the program stored in <input>
.
Example: aiken uplc eval sc.uplc "(con data #02)"
.
An alternative is to parse data more dynamically like it is done by pluto (example pluto usage pluto eval sc.pluto 2
-> this automatically generates the above PlutusData object, a tagged integer)
It would be useful in some situations to be able to override the inferred root module name for an Aiken project.
At the moment, we use the "package" name from aiken.toml
to then search for src/{project_name}.ak
and src/{project_name}/**
.
This should still be the default behavior but only if it's not explicitly set in the config.
Projects and teams may want to use a kind of shared global namespace while having things be module and independently packaged. This would also be useful for core team built libraries.
..
|__ package1/
| |__ src/
| | |__ awesome_lib/
| |__ aiken.toml (name = package1, lib = awesome_lib)
|__ package2/
| |__ src/
| | |__ awesome_lib/
| |__ aiken.toml (name = package2, lib = awesome_lib)
using the above configuration, this projects would be able to be packaged independently but when used by another project items from both can be imported from:
use awesome_lib/
No other alternative at the moment.
This is a big issue to hold many different tasks related to improving the parser and it's error messages.
We have mostly everything we need for tuples we just need to explicitly turn on the support now
It'd be silly not to have them
nothing atm
In order to finalize the behavior of the uplc subcommand we need to pretty print uplc to a file. Blocked by #1
When someone uses aiken new my_project
we should generate a project in a folder with the given name. Some of this is in place but we also need to create a sample config and some aiken files.
We need to be able to run check
on a project through the LSP.
This will involve:
aiken.toml
Project
instancecheck
aiken.toml
changes we need to tear everything down and start a fresh Project
instancesThere are several commands now and the main file is starting to get a bit big.
We should probably create a submodule structure like this:
src/
|__ main.rs
|__ cmd/
| |__ uplc/
| | |__ eval.rs
| | |__ flat.rs
| |__ tx/
|__ lib.rs
or some other variation along these lines
build
should work offline, provided that packages are available in the build directory. Right now, if a package is specified with a branch name (e.g. name
), it'll always try to perform a HEAD request when building to check if it should re-download the package. However, when there's no network, this will fail. It should instead fallback to whatever local version of the package we have.add
/ packages add
/ packages upgrade
could check (if the network is available) that the specified package version does indeed exist.tx
and uplc
command groups are still mostly printing out some raw text. Ideally, we would want commands to have a structured (i.e. JSON) output by default on stdout, and output other stuff on stderr.A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.