-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sketch out what a proxy script for DRep would look like.
- Loading branch information
0 parents
commit 7667f40
Showing
8 changed files
with
787 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: Continuous Integration | ||
|
||
on: | ||
push: | ||
branches: ["main"] | ||
pull_request: | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: aiken-lang/setup-aiken@v1 | ||
with: | ||
version: v1.1.0 | ||
- run: aiken fmt --check | ||
- run: aiken check -D | ||
- run: aiken build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/ |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Proxy DReps | ||
|
||
A validator to provide hot/cold account management to DReps. The scripts provides an authentication mecanism around an administrator multisig script (m-of-n type), itself granting powers to two sub-scripts to manage stake in two contexts: | ||
|
||
- For block-production; or specifically delegation to stake pools and withdrawal of rewards. | ||
- For governance; or specifically voting on governance action and management of DReps metadata. | ||
|
||
This is achieved through the use of receipt tokens that are minted alongside the publication of certificates. The minting (resp. burning) of those tokens is tied to the registration (resp. unregistration) of their corresponding certificates. | ||
|
||
## Configuration | ||
|
||
The validator itself is bound to a particular administrator which can be configured directly in the `aiken.toml`. | ||
|
||
```toml | ||
[config.default] | ||
threshold = 1 # How many administrors signatories are required to approve actions | ||
|
||
# List of administators (verification key hashes) | ||
[[config.default.administrators]] | ||
bytes = "00000000000000000000000000000000000000000000000000000000" | ||
encoding = "base16" | ||
|
||
[[config.default.administrators]] | ||
bytes = "00000000000000000000000000000000000000000000000000000001" | ||
encoding = "base16" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# This file was generated by Aiken | ||
# You typically do not need to edit this file | ||
|
||
[[requirements]] | ||
name = "aiken-lang/stdlib" | ||
version = "v2.0.0" | ||
source = "github" | ||
|
||
[[requirements]] | ||
name = "KtorZ/aicone" | ||
version = "a9ae9ef8b6bdb183ea020ea97f6b648f9343924e" | ||
source = "github" | ||
|
||
[[requirements]] | ||
name = "aiken-lang/fuzz" | ||
version = "v2" | ||
source = "github" | ||
|
||
[[packages]] | ||
name = "aiken-lang/stdlib" | ||
version = "v2.0.0" | ||
requirements = [] | ||
source = "github" | ||
|
||
[[packages]] | ||
name = "KtorZ/aicone" | ||
version = "a9ae9ef8b6bdb183ea020ea97f6b648f9343924e" | ||
requirements = [] | ||
source = "github" | ||
|
||
[[packages]] | ||
name = "aiken-lang/fuzz" | ||
version = "v2" | ||
requirements = [] | ||
source = "github" | ||
|
||
[etags] | ||
"aiken-lang/fuzz@v2" = [{ secs_since_epoch = 1725527905, nanos_since_epoch = 856547000 }, "34ffec10cce786bf823c7505589a3b5e0663792ef8efd31f870d7bcc37e0f593"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
name = "cardanosolutions/proxy-dreps" | ||
version = "0.0.0" | ||
compiler = "v1.1.0" | ||
plutus = "v3" | ||
license = "MPL-2.0" | ||
description = "Aiken contracts for project 'cardanosolutions/proxy-dreps'" | ||
|
||
[repository] | ||
user = "cardanosolutions" | ||
project = "proxy-dreps" | ||
platform = "github" | ||
|
||
[[dependencies]] | ||
name = "aiken-lang/stdlib" | ||
version = "v2.0.0" | ||
source = "github" | ||
|
||
[[dependencies]] | ||
name = "KtorZ/aicone" | ||
version = "a9ae9ef8b6bdb183ea020ea97f6b648f9343924e" | ||
source = "github" | ||
|
||
[[dependencies]] | ||
name = "aiken-lang/fuzz" | ||
version = "v2" | ||
source = "github" | ||
|
||
[config.default] | ||
threshold = 1 # How many administrors signatories are required to approve actions | ||
|
||
# List of administators (verification key hashes) | ||
[[config.default.administrators]] | ||
bytes = "00000000000000000000000000000000000000000000000000000000" | ||
encoding = "base16" | ||
|
||
[[config.default.administrators]] | ||
bytes = "00000000000000000000000000000000000000000000000000000001" | ||
encoding = "base16" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
use aiken/collection/dict | ||
use aiken/collection/list | ||
use cardano/address.{Credential, Script} | ||
use cardano/assets.{AssetName} | ||
use cardano/transaction.{InlineDatum, Input, Output, Transaction} | ||
use sundae/multisig.{MultisigScript} | ||
|
||
pub type State { | ||
block_production_delegate: Option<MultisigScript>, | ||
governance_delegate: Option<MultisigScript>, | ||
} | ||
|
||
pub type Update { | ||
Register | ||
Unregister | ||
} | ||
|
||
pub fn for_block_production(st: State) -> Option<MultisigScript> { | ||
st.block_production_delegate | ||
} | ||
|
||
pub fn for_governance(st: State) -> Option<MultisigScript> { | ||
st.governance_delegate | ||
} | ||
|
||
pub fn must_forward_script(outputs: List<Output>, from: Input) -> Bool { | ||
expect Some(to) = | ||
list.find(outputs, fn(output) { output.address == from.output.address }) | ||
|
||
// Ensures strict following of assets. | ||
let from_assets = assets.without_lovelace(from.output.value) | ||
let to_assets = assets.without_lovelace(to.value) | ||
expect from_assets == to_assets | ||
|
||
// Ensures ADA also follows, but may increase. | ||
let from_lovelace = assets.lovelace_of(from.output.value) | ||
let to_lovelace = assets.lovelace_of(to.value) | ||
expect from_lovelace >= to_lovelace | ||
|
||
// Ensure datum is identical | ||
from.output.datum == to.datum | ||
} | ||
|
||
pub fn update_delegate( | ||
self: Transaction, | ||
script: Data, | ||
delegate: Credential, | ||
token_name: AssetName, | ||
update: Update, | ||
) -> Bool { | ||
// Credential is necessarily a script. Note that the policy_id and | ||
// the _actual_ delegate representative script hash are identical | ||
// since they come from the same script hash. | ||
expect Script(policy_id) = delegate | ||
|
||
let expected_quantity = | ||
when update is { | ||
Register -> { | ||
// When registering, we must ensure that one output targets the script. | ||
// This outputs is assumed to hold the minted token. | ||
expect Some(authorization) = | ||
list.find( | ||
self.outputs, | ||
fn(output) { output.address.payment_credential == delegate }, | ||
) | ||
|
||
// Ensures that the output holds the token. | ||
expect | ||
assets.quantity_of(authorization.value, policy_id, token_name) > 0 | ||
|
||
// Ensures that the script is structurally valid, to avoid problems later. | ||
expect _: MultisigScript = script | ||
|
||
// Ensures the output holds the multisig script. | ||
expect InlineDatum(script) == authorization.datum | ||
|
||
1 | ||
} | ||
Unregister -> -1 | ||
} | ||
|
||
let minted_quantity = | ||
self.mint | ||
|> assets.quantity_of(policy_id, token_name) | ||
|
||
// Ensure that the right amount of token is minted or burnt during the update. | ||
(minted_quantity == expected_quantity)? | ||
} | ||
|
||
pub fn must_be_approved_by_delegate( | ||
self: Transaction, | ||
delegate: Credential, | ||
choose_delegate: fn(State) -> Option<MultisigScript>, | ||
) { | ||
expect Script(policy_id) = delegate | ||
|
||
let st = | ||
list.foldr( | ||
self.inputs, | ||
fn() { fail }, | ||
fn(input, st) { | ||
let tokens = assets.tokens(input.output.value, policy_id) | ||
when dict.to_pairs(tokens) is { | ||
[Pair(_, 1)] -> | ||
fn() { | ||
expect InlineDatum(st) = input.output.datum | ||
expect st: State = st | ||
st | ||
} | ||
_ -> st | ||
} | ||
}, | ||
)() | ||
|
||
expect Some(script) = choose_delegate(st) | ||
multisig.satisfied( | ||
script, | ||
self.extra_signatories, | ||
self.validity_range, | ||
self.withdrawals, | ||
)? | ||
} | ||
|
||
pub fn must_be_approved_by_administrator( | ||
self: Transaction, | ||
administrator: MultisigScript, | ||
) { | ||
multisig.satisfied( | ||
administrator, | ||
self.extra_signatories, | ||
self.validity_range, | ||
self.withdrawals, | ||
)? | ||
} |
Oops, something went wrong.