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

validators' boilerplate. #14

Merged
merged 4 commits into from
Mar 22, 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
14 changes: 7 additions & 7 deletions onchain/docs/mvp-design/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ Updates the `fuel` datum field of both the `ShipState` and `PelletState` UTxOs,
![gatherFuel diagram](img/gatherFuel.png)


### Collect Rewards:
### Mine Asteria:
Subtracts from the `AsteriaUTxO` at most `MAX_ASTERIA_MINING`% of the ada value, and pays that amount to the owner of the ship that reached Asteria, together with the min ada locked in the `ShipState` UTxO. The `ShipToken` is burnt.

![collect diagram](img/collect.png)
![mineAsteria diagram](img/mineAsteria.png)


### Quit Game:
Expand All @@ -107,19 +107,19 @@ Pays the min ada locked in the `ShipState` UTxO back to the ship owner and burns
### Asteria validator:
* Params: `AdminToken`.

#### *AddNewPlayer Redeemer*
#### *AddNewShip Redeemer*
* `AsteriaUTxO` output value equals input value plus the `SHIP_MINT_FEE`.
* `AdminToken` is in the input.
* datum doesn't change.

#### *Collect Redeemer*
#### *Mine Redeemer*
* `ShipToken` is present in some input.
* `AsteriaUTxO` output value has at most `MAX_ASTERIA_MINING`% adas less than input value.

### Pellet validator:
* Params: `AdminToken`.

#### *Gather Redeemer (includes gathering amount)*
#### *Provide Redeemer (includes gathering amount)*
* `ShipToken` is present in some input.
* the amount specified is not greater than the fuel available in the pellet.
* the amount specified is subtracted from the output `PelletState` fuel datum field, and the other fields remain unchanged.
Expand All @@ -139,15 +139,15 @@ Pays the min ada locked in the `ShipState` UTxO back to the ship owner and burns
* the output fuel datum field equals the input fuel minus the fuel required for the displacement.
* the distance advanced doesn't exceed the `MAX_SHIP_MOVEMENT_PER_TX`.

#### *Gather Redeemer (includes gathering amount)*
#### *GatherFuel Redeemer (includes gathering amount)*
* there is a single `ShipState` input.
* there is a single `ShipState` output.
* there is a `PelletState` input with the same x and y datum coordinates as the `ShipState` UTxO.
* the amount specified plus the fuel before charging does not exceed `MAX_SHIP_FUEL` capacity.
* the amount specified is added to the output `ShipState` fuel datum field, and the other fields remain unchanged.
* the `ShipState` output value is the same as the input.

#### *Collect Redeemer*
#### *MineAsteria Redeemer*
* there is a single `ShipState` input.
* `PilotToken` is present.
* `ShipState` position is (0,0).
Expand Down
Binary file modified onchain/docs/mvp-design/img/createShip.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified onchain/docs/mvp-design/img/gatherFuel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions onchain/src/lib/asteria/types.ak
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use aiken/transaction/value.{AssetName, PolicyId}

pub type ShipDatum {
fuel: Int,
pos_x: Int,
pos_y: Int,
shipyard_policy: PolicyId,
ship_token_name: AssetName,
pilot_token_name: AssetName,
}

pub type ShipRedeemer {
MoveShip { delta_x: Int, delta_y: Int }
GatherFuel { amount: Int }
MineAsteria
Quit
}

pub type PelletDatum {
fuel: Int,
pos_x: Int,
pos_y: Int,
shipyard_policy: PolicyId,
}

pub type PelletRedeemer {
Provide { amount: Int }
}

pub type AsteriaDatum {
ship_counter: Int,
shipyard_policy: PolicyId,
}

pub type AsteriaRedeemer {
AddNewShip
Mine
}

pub type ShipyardRedeemer {
Mint
Burn
}
13 changes: 13 additions & 0 deletions onchain/src/validators/asteria.ak
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use aiken/transaction.{ScriptContext}
use aiken/transaction/value.{AssetName, PolicyId}
use asteria/types.{AsteriaDatum, AsteriaRedeemer}

validator(_admin_token: (PolicyId, AssetName)) {
fn spend(
_datum: AsteriaDatum,
_redeemer: AsteriaRedeemer,
_ctx: ScriptContext,
) -> Bool {
True
}
}
13 changes: 13 additions & 0 deletions onchain/src/validators/pellet.ak
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use aiken/transaction.{ScriptContext}
use aiken/transaction/value.{AssetName, PolicyId}
use asteria/types.{PelletDatum, PelletRedeemer}

validator(_admin_token: (PolicyId, AssetName)) {
fn spend(
_datum: PelletDatum,
_redeemer: PelletRedeemer,
_ctx: ScriptContext,
) -> Bool {
True
}
}
12 changes: 12 additions & 0 deletions onchain/src/validators/shipyard.ak
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use aiken/transaction.{ScriptContext}
use aiken/transaction/credential.{Address}
use asteria/types.{ShipyardRedeemer}

validator(
_asteria_validator_address: Address,
_spacetime_validator_address: Address,
) {
fn mint(_redeemer: ShipyardRedeemer, _ctx: ScriptContext) -> Bool {
True
}
}
100 changes: 16 additions & 84 deletions onchain/src/validators/spacetime.ak
Original file line number Diff line number Diff line change
@@ -1,86 +1,18 @@
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,
}
use aiken/transaction.{ScriptContext}
use aiken/transaction/credential.{Address}
use aiken/transaction/value.{AssetName, PolicyId}
use asteria/types.{ShipDatum, ShipRedeemer}

validator(
_pellet_validator_address: Address,
_asteria_validator_address: Address,
_admin_token: (PolicyId, AssetName),
) {
fn spend(
_datum: ShipDatum,
_redeemer: ShipRedeemer,
_ctx: ScriptContext,
) -> Bool {
True
}
}
Loading