Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement 1st pass of space-time contract #1

Merged
merged 2 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Tests

on:
push:
branches: ["main"]
pull_request:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: aiken-lang/setup-aiken@v0.1.0
with:
version: v1.0.24-alpha

- run: aiken fmt --check
- run: aiken check -D
- run: aiken build
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Aiken compilation artifacts
artifacts/
# Aiken's project working directory
build/
# Aiken's default documentation export
docs/
15 changes: 15 additions & 0 deletions aiken.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This file was generated by Aiken
# You typically do not need to edit this file

[[requirements]]
name = "aiken-lang/stdlib"
version = "1.7.0"
source = "github"

[[packages]]
name = "aiken-lang/stdlib"
version = "1.7.0"
requirements = []
source = "github"

[etags]
14 changes: 14 additions & 0 deletions aiken.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name = "txpipe/asteria"
version = "0.0.0"
license = "Apache-2.0"
description = "Aiken contracts for project 'txpipe/asteria'"

[repository]
user = "txpipe"
project = "asteria"
platform = "github"

[[dependencies]]
name = "aiken-lang/stdlib"
version = "1.7.0"
source = "github"
108 changes: 108 additions & 0 deletions plutus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{
"preamble": {
"title": "txpipe/asteria",
"description": "Aiken contracts for project 'txpipe/asteria'",
"version": "0.0.0",
"plutusVersion": "v2",
"compiler": {
"name": "Aiken",
"version": "v1.0.24-alpha+982eff4"
},
"license": "Apache-2.0"
},
"validators": [
{
"title": "spacetime.spend",
"datum": {
"title": "datum",
"schema": {
"$ref": "#/definitions/spacetime~1Datum"
}
},
"redeemer": {
"title": "redeemer",
"schema": {
"$ref": "#/definitions/spacetime~1Redeemer"
}
},
"parameters": [
{
"title": "ship_policy_id",
"schema": {
"$ref": "#/definitions/ByteArray"
}
},
{
"title": "max_speed",
"schema": {
"$ref": "#/definitions/Int"
}
},
{
"title": "fuel_per_step",
"schema": {
"$ref": "#/definitions/Int"
}
}
],
"compiledCode": "59035e010000323232323232323232232232232222323232533300f32323232323232323232323232323232323232323253330243370e9001181180309919191919299981499b8748000c0a00044c8c8c8c8c94ccc0b8cdc3a4000605a0022646464646464646464a66606e66e1d2004303600113232323232533303c00c1533303c0091533303c0081533303c002100114a029405280a503371e6eb8c054c0e400c09d4ccc0e8cdc39bad300f303800233700048054266e1cdd69802981c00119b8002202814a0605a002607a002606a0022c6002606800e460766078607800266e24008068cdc480101699b8200102a3233700600204460020404a66606466e2000520001337029000000880099b873330043756600a605c600a605c00c0580389001181a00098160008b19803005119b873330023756600660580020540349001111191919299981919b8748008004520001375a606e6060004606000264a66606266e1d200200114c103d87a8000132323300100100222533303700114c103d87a800013232323253330383371e014004266e9520003303c375000297ae0133006006003375a60720066eb8c0dc008c0ec008c0e4004dd5981b18178011817800991980080080211299981a0008a6103d87a800013232323253330353371e010004266e95200033039374c00297ae01330060060033756606c0066eb8c0d0008c0e0008c0d80048c0c4c0c8004c0bc004c09c00458cc0040208cdd7980198138008021119198008008019129998170008a6103d87a800013232533302d300500213374a90001981880125eb804cc010010004c0c8008c0c00048c0b0004c0a8004c08801858dd61814000981400098138011bac3025001301d0033023001302300230210013019010375a603e002603e0046eb4c074004c074008dd6980d800980d8011bae3019001301100a375a602e002602e0046eb4c054004c0340145261365632533300f3370e9000000899191919299980b180c8010a4c2c6eb4c05c004c05c008dd6980a80098068028b18068021800802119299980719b87480000044c8c8c8c8c8c8c8c94ccc064c07000852616375a603400260340046eb4c060004c060008dd6980b000980b0011bae3014001300c00216300c001375a0026eb4004dd7000918029baa001230033754002ae6955ceaab9e5573eae815d0aba21",
"hash": "24dc592d83d2a81ee4e3981d3cb09f6141ef08f974e617a251745f97"
}
],
"definitions": {
"ByteArray": {
"dataType": "bytes"
},
"Int": {
"dataType": "integer"
},
"spacetime/Datum": {
"title": "Datum",
"anyOf": [
{
"title": "Datum",
"dataType": "constructor",
"index": 0,
"fields": [
{
"title": "ship_id",
"$ref": "#/definitions/ByteArray"
},
{
"title": "pos_x",
"$ref": "#/definitions/Int"
},
{
"title": "pos_y",
"$ref": "#/definitions/Int"
},
{
"title": "fuel",
"$ref": "#/definitions/Int"
}
]
}
]
},
"spacetime/Redeemer": {
"title": "Redeemer",
"anyOf": [
{
"title": "Redeemer",
"dataType": "constructor",
"index": 0,
"fields": [
{
"title": "delta_x",
"$ref": "#/definitions/Int"
},
{
"title": "delta_y",
"$ref": "#/definitions/Int"
}
]
}
]
}
}
}
86 changes: 86 additions & 0 deletions validators/spacetime.ak
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use aiken/list
use aiken/math
use aiken/transaction.{InlineDatum, ScriptContext, Spend, Transaction}
use aiken/transaction/value.{PolicyId, quantity_of}

type Datum {
pilot_token: ByteArray,
pos_x: Int,
pos_y: Int,
fuel: Int,
}

type MoveRedeemer {
delta_x: Int,
delta_y: Int,
}

type GatherRedeemer {GatherRedeemer}

type PotRedeemer {PotRedeemer}

fn required_fuel(distance: Int, fuel_per_step: Int) -> Int {
distance * fuel_per_step
}

fn distance(delta_x: Int, delta_y: Int) -> Int {
math.abs(delta_x) + math.abs(delta_y)
}

// we need to enforce:
// [x] that the speed (manhattan_distance/slot) doesn't exceed an upper bound
// [ ] that the ship has enough fuel (token) to move the desired delta
// [ ] that the new position of the ship utxo equals the last position + delta
// [ ] that the fuel required for the delta has been burned
// [ ] that the tx is signed by the owner of the ship (token holder)

validator(ship_policy_id: PolicyId, max_speed: Int, fuel_per_step: Int) {
fn spend(datum: Datum, redeemer: Redeemer, ctx: ScriptContext) -> Bool {
let Redeemer { delta_x, delta_y } = redeemer

let Datum { ship_id, pos_x, pos_y, fuel } = datum

let ScriptContext { transaction, purpose } = ctx

let Transaction { inputs, outputs, .. } = transaction

expect Spend(utxo_ref) = purpose

expect Some(own_input) =
list.find(inputs, fn(input) { input.output_reference == utxo_ref })

expect Some(own_output) =
list.find(
outputs,
fn(output) { quantity_of(output.value, ship_policy_id, ship_id) == 1 },
)

let must_hold_ship_asset =
quantity_of(own_input.output.value, ship_policy_id, ship_id) == 1

let distance = distance(delta_x, delta_y)
let required_fuel = required_fuel(distance, fuel_per_step)

// speed = distance since we consider each block the unit of time
let must_respect_max_speed = distance <= max_speed

let must_have_enough_fuel = fuel >= required_fuel

expect InlineDatum(out_data) = own_output.datum

expect out_data: Datum = out_data

let final_pos_must_respect_movement =
out_data.pos_x == pos_x + delta_x && out_data.pos_y == pos_y + delta_y

let final_ship_id_must_match = out_data.ship_id == ship_id

and {
must_hold_ship_asset,
must_respect_max_speed,
must_have_enough_fuel,
final_pos_must_respect_movement,
final_ship_id_must_match,
}
}
}
Loading