From e5d7e3fd3b4465089bd17bc371d6e7519fc490e6 Mon Sep 17 00:00:00 2001 From: microproofs Date: Sat, 13 Jan 2024 11:29:31 -0500 Subject: [PATCH] add failed fork action --- lib/hardfork.ak | 71 +++++++++++++++++++++++++++++++++++++++-- validators/hard_fork.ak | 9 +++++- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/lib/hardfork.ak b/lib/hardfork.ak index d81aa0c..fdb72b1 100644 --- a/lib/hardfork.ak +++ b/lib/hardfork.ak @@ -1,10 +1,12 @@ use aiken/builtin.{blake2b_256} -use aiken/dict +use aiken/dict.{to_list} use aiken/list use aiken/math use aiken/transaction.{InlineDatum, Input, Output, OutputReference, Transaction} use aiken/transaction/credential.{Address, ScriptCredential} -use aiken/transaction/value.{tokens} +use aiken/transaction/value.{ + from_minted_value, to_dict, tokens, without_lovelace, +} use fortuna use fortuna/parameters.{halving_number, initial_payout} use fortuna/types.{State} @@ -901,6 +903,71 @@ pub fn hard_fork( } } +pub fn failed_fork( + fortuna_v1_hash: ByteArray, + hardfork_state_input: OutputReference, + fortuna_v1_output: Int, + transaction: Transaction, + own_policy: ByteArray, +) -> Bool { + // Every action here should ensure that all mints and inputs are checked + let Transaction { inputs, outputs, mint, .. } = transaction + + let own_address = + Address { + payment_credential: ScriptCredential(own_policy), + stake_credential: None, + } + + // Needed to ensure all validator spends from this script hash are accounted for + let script_inputs = + list.filter(inputs, fn(input) { input.output.address == own_address }) + + expect [Input { output: hfs_input, .. }] = script_inputs + + expect [] = mint |> from_minted_value |> to_dict |> to_list + + expect quantity_of(hfs_input.value, own_policy, hard_fork_state_token) == 1 + + expect InlineDatum(hardfork_state_datum) = hfs_input.datum + + expect HardForkState { + status: NotForked, + fork_block_height, + fortuna_next_validator_hash, + }: ForkDatum = hardfork_state_datum + + expect [hfs_output, ..] = outputs + + expect without_lovelace(hfs_input.value) == without_lovelace(hfs_output.value) + + let output_datum = + InlineDatum( + HardForkState { + status: FailedFork, + fork_block_height, + fortuna_next_validator_hash, + }, + ) + + expect hfs_output.datum == output_datum + + // Handle getting output states + let fortuna_v1_output = list_at(outputs, fortuna_v1_output) + + let Output { value: fortuna_v1_value, datum: fortuna_v1_datum, .. } = + fortuna_v1_output + + expect InlineDatum(fortuna_v1_datum) = fortuna_v1_datum + + expect State { block_number, .. }: State = fortuna_v1_datum + + and { + fork_block_height < block_number, + quantity_of(fortuna_v1_value, fortuna_v1_hash, fortuna.master_token_name) == 1, + } +} + pub fn calculate_emission(block_height: Int) -> Int { if block_height < halving_number { block_height * initial_payout diff --git a/validators/hard_fork.ak b/validators/hard_fork.ak index 0775b36..fee03fb 100644 --- a/validators/hard_fork.ak +++ b/validators/hard_fork.ak @@ -529,7 +529,14 @@ validator(init_utxo_ref: OutputReference, fortuna_v1_hash: ByteArray) { user_locked_tuna, ) } - FailedFork { hardfork_state_input, fortuna_v1_output } -> todo + FailedFork { hardfork_state_input, fortuna_v1_output } -> + hardfork.failed_fork( + fortuna_v1_hash, + hardfork_state_input, + fortuna_v1_output, + transaction, + own_policy, + ) } }