Skip to content

Commit 30ac322

Browse files
committed
feat: finish incorporating one shot policy into stakinator
1 parent dc2fd07 commit 30ac322

File tree

3 files changed

+82
-71
lines changed

3 files changed

+82
-71
lines changed

lib/staking/utils.ak

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use aiken/builtin
2+
use aiken/cbor
3+
4+
test maps_serialize() {
5+
let thing =
6+
[(0, 1), (1, 2), (8, 88)]
7+
let diag = cbor.diagnostic(thing)
8+
9+
let other_diag = cbor.diagnostic(builtin.serialise_data(thing))
10+
11+
trace @"first diag"
12+
13+
trace diag
14+
15+
trace @"second diag"
16+
17+
trace other_diag
18+
19+
True
20+
}

validators/one_shot.ak

Lines changed: 0 additions & 23 deletions
This file was deleted.

validators/stakinator3000.ak

Lines changed: 62 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ type NFTAsset {
6969
asset: AssetName,
7070
}
7171

72-
validator(state_token: NFTAsset) {
72+
validator(init_input: OutputReference) {
7373
/// remember `rdr` still needs to be wrapped in a index 1 constr for multivalidator purposes
7474
fn conditional_spend(state: State, rdr: Data, ctx: ScriptContext) -> Bool {
7575
let ScriptContext { transaction, purpose } = ctx
@@ -102,8 +102,6 @@ validator(state_token: NFTAsset) {
102102

103103
let State { owner, redelegation_condition, .. } = state
104104

105-
let NFTAsset { policy: nft_policy, asset: nft_asset } = state_token
106-
107105
let Interval { lower_bound, upper_bound } = validity_range
108106

109107
let IntervalBound { bound_type, is_inclusive: upper_inclusive } =
@@ -117,34 +115,28 @@ validator(state_token: NFTAsset) {
117115
expect Finite(lower) = bound_type
118116

119117
// Checks current owner is valid
120-
expect True =
118+
expect
121119
when owner is {
122120
// An owner can be a public key, a spent NFT, or a burned receipt token that was minted by this script
123121
PKH(signer) -> list.has(extra_signatories, signer)
124122
// In this case the redeemer out ref refers to some other input that holds the nft
125123
// that we check is spent
126124
NFT(policy, token_name) -> {
127125
expect nft_input_owner: OutputReference = rdr
128-
129126
expect Some(nft_input) =
130127
list.find(
131128
inputs,
132129
fn(input) { input.output_reference == nft_input_owner },
133130
)
134-
135131
quantity_of(nft_input.output.value, policy, token_name) == 1
136132
}
137-
138133
Receipt(token_name) -> {
139134
let x = mint |> from_minted_value |> quantity_of(own_pkh, token_name)
140-
141135
x == -1
142136
}
143137
}
144-
145-
// Check input contains parameterized NFT
146-
expect True = quantity_of(in_value, nft_policy, nft_asset) == 1
147-
138+
// Check input contains init NFT
139+
expect quantity_of(in_value, own_pkh, "") == 1
148140
// Validates non-recursive conditions
149141
let tx_condition_runner =
150142
fn(cond: TxCondition) -> Bool {
@@ -178,7 +170,7 @@ validator(state_token: NFTAsset) {
178170
}
179171
}
180172

181-
expect True =
173+
expect
182174
when redelegation_condition is {
183175
Is(tx_cond) -> tx_condition_runner(tx_cond)
184176
Not(tx_cond) -> !tx_condition_runner(tx_cond)
@@ -187,17 +179,12 @@ validator(state_token: NFTAsset) {
187179
Or(conds) ->
188180
validate_stake_conditions(conds, False, tx_condition_runner)
189181
}
190-
191182
// find output with same address and nft state token
192183
expect Some(Output { datum: InlineDatum(out_datum), .. }) =
193184
list.find(
194185
outputs,
195186
fn(output) {
196-
output.address == in_address && quantity_of(
197-
output.value,
198-
nft_policy,
199-
nft_asset,
200-
) == 1
187+
output.address == in_address && quantity_of(output.value, own_pkh, "") == 1
201188
},
202189
)
203190

@@ -222,35 +209,67 @@ validator(state_token: NFTAsset) {
222209
..
223210
} = transaction
224211

225-
let NFTAsset { policy: nft_policy, asset: nft_asset } = state_token
226-
227212
when purpose is {
228213
Mint(own_policy) -> {
214+
let minted_under_policy =
215+
mint
216+
|> from_minted_value
217+
|> tokens(own_policy)
218+
|> dict.to_list
219+
229220
expect [first_input, ..] = inputs
230221

231-
let asset_name = first_input.output_reference |> builtin.serialise_data
232-
233-
mint
234-
|> from_minted_value
235-
|> tokens(own_policy)
236-
|> dict.to_list
237-
|> check_mint_to_output_datum(
238-
outputs,
239-
asset_name,
240-
state_token,
241-
ScriptCredential(own_policy),
242-
)
222+
let asset_name =
223+
first_input.output_reference
224+
|> builtin.serialise_data
225+
|> builtin.blake2b_256
226+
227+
when minted_under_policy is {
228+
// impossible case
229+
[] -> False
230+
[(minted_asset_name, 1), ..rest] if minted_asset_name == "" -> {
231+
expect [output, ..] = outputs
232+
233+
let Output { address, value, .. } = output
234+
235+
and {
236+
address.payment_credential == ScriptCredential(own_policy),
237+
value.quantity_of(value, own_policy, "") == 1,
238+
list.any(
239+
inputs,
240+
fn(input) { input.output_reference == init_input },
241+
),
242+
check_mint_to_output_datum(
243+
rest,
244+
outputs,
245+
asset_name,
246+
ScriptCredential(own_policy),
247+
own_policy,
248+
),
249+
}
250+
}
251+
252+
all ->
253+
check_mint_to_output_datum(
254+
all,
255+
outputs,
256+
asset_name,
257+
ScriptCredential(own_policy),
258+
own_policy,
259+
)
260+
}
243261
}
244262

245263
WithdrawFrom(cred) -> {
246264
expect Inline(cred) = cred
265+
expect ScriptCredential(own_policy) = cred
247266

248267
let find_predicate =
249268
fn(input: Input) {
250269
let output = input.output
251270

252271
output.address.payment_credential == cred && (
253-
output.value |> quantity_of(nft_policy, nft_asset)
272+
output.value |> quantity_of(own_policy, "")
254273
) == 1
255274
}
256275

@@ -308,20 +327,19 @@ validator(state_token: NFTAsset) {
308327
delegator,
309328
} -> {
310329
expect Inline(cred) = delegator
330+
expect ScriptCredential(own_policy) = cred
311331
// Checks for state token is spent
312332
list.any(
313333
inputs,
314334
fn(input) {
315335
let output = input.output
316336

317337
output.address.payment_credential == cred && (
318-
output.value |> quantity_of(nft_policy, nft_asset)
338+
output.value |> quantity_of(own_policy, "")
319339
) == 1
320340
},
321341
)
322342
}
323-
324-
CredentialRegistration(_) -> True
325343
_ -> False
326344
}
327345
_ -> False
@@ -484,25 +502,22 @@ fn check_mint_to_output_datum(
484502
minted_assets: List<(ByteArray, Int)>,
485503
outputs: List<Output>,
486504
expected_asset: ByteArray,
487-
expected_nft: NFTAsset,
488-
validator_cred: PaymentCredential,
505+
validator_cred: Credential,
506+
validator_policy: PolicyId,
489507
) -> Bool {
490508
when minted_assets is {
491509
[] -> True
492510
[(minted_asset_name, quantity), ..rest_assets] ->
493511
if quantity == 1 {
494-
expect True = expected_asset == minted_asset_name
495-
496-
expect True =
512+
expect expected_asset == minted_asset_name
513+
expect
497514
list.any(
498515
outputs,
499516
fn(output) {
500517
let Output { address, value, datum, .. } = output
501-
502518
if address.payment_credential == validator_cred {
503519
// Check for nft present
504-
let NFTAsset { policy, asset } = expected_nft
505-
if quantity_of(value, policy, asset) == 1 {
520+
if quantity_of(value, validator_policy, "") == 1 {
506521
// Check for receipt datum for minted receipt token
507522
expect InlineDatum(data) = datum
508523
expect OwnerCheck { owner: Receipt(asset), .. }: OwnerCheck =
@@ -516,21 +531,20 @@ fn check_mint_to_output_datum(
516531
}
517532
},
518533
)
519-
520534
check_mint_to_output_datum(
521535
rest_assets,
522536
outputs,
523537
expected_asset,
524-
expected_nft,
525538
validator_cred,
539+
validator_policy,
526540
)
527541
} else if quantity == -1 {
528542
check_mint_to_output_datum(
529543
rest_assets,
530544
outputs,
531545
expected_asset,
532-
expected_nft,
533546
validator_cred,
547+
validator_policy,
534548
)
535549
} else {
536550
False

0 commit comments

Comments
 (0)