Skip to content

Commit

Permalink
Total rewrite of Control Datum structure to help simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
MicroProofs committed Jan 18, 2025
1 parent 3ad8f19 commit 51992f2
Show file tree
Hide file tree
Showing 17 changed files with 624 additions and 468 deletions.
22 changes: 20 additions & 2 deletions IntentionDetails.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ value: [
// Require exactly 100 TokenA from PolicyA
(policyA, tokenA, 100),
// Require minimum 50 TokenB from PolicyB
// Require exactly 50 TokenB from PolicyB
(policyB, tokenB, 50),
// Check for ADA amount
Expand All @@ -244,6 +244,7 @@ c) Datum Field Access:
// Access nested datum fields using indices
datum_field: [0, 2, 1] // Goes 3 levels deep into datum structure
// Puts resulting value into temp_val
// Example datum structure:
Datum {
field0: {
Expand All @@ -254,8 +255,16 @@ Datum {
}
}
}
```

// Puts resulting value into temp_val
d) Input Reference:
```aiken
// Match exact output reference
in_ref: Some(output_reference)
// No output reference restriction
in_ref: None
```

### Input Constraint Examples:
Expand Down Expand Up @@ -365,6 +374,15 @@ datum: SomeTwo((prefix_bytes, postfix_bytes))
datum: Nada
```

d) Script ref Requirements:
```aiken
// Exact script hash match in reference_script field
ref: Some(script_hash)
// No reference_script requirements
ref: None
```

### Output Constraint Examples:

```aiken
Expand Down
4 changes: 2 additions & 2 deletions aiken.lock
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ requirements = []
source = "github"

[etags]
"aiken-lang/fuzz@main" = [{ secs_since_epoch = 1737003689, nanos_since_epoch = 423729000 }, "e594326795accb687e9bfacd6a0553eb1d611ba23d5bba31b49ec7fe29445e3c"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1737003688, nanos_since_epoch = 721150000 }, "9191378e1310dcd34d3f8a883f67fb6440c5535897e210e84ba90ec207b884fc"]
"aiken-lang/fuzz@main" = [{ secs_since_epoch = 1737196931, nanos_since_epoch = 830992000 }, "e594326795accb687e9bfacd6a0553eb1d611ba23d5bba31b49ec7fe29445e3c"]
"aiken-lang/stdlib@main" = [{ secs_since_epoch = 1737196930, nanos_since_epoch = 558531000 }, "9191378e1310dcd34d3f8a883f67fb6440c5535897e210e84ba90ec207b884fc"]
4 changes: 2 additions & 2 deletions aiken.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ one_shot_output_index = 0
namespace = "Bullet"

[config.preview.bullet_hash]
bytes = "2c37f1eaf3f33a14f0ec1140c74c10f78b3e5250580a926ca10f8ea6"
bytes = "04451f9d70975d2128329476fc63bd749a886a258b2cfd476a5b7892"
encoding = "hex"

[config.preview.nonce_bullet_hash]
bytes = "2d652b04dda2919010b063b0c7bd24e6abc1dff6b4bb4aa5eae25f8c"
bytes = "79ab8797c0988e4ed9bcabedf640d539ca2ab21e6a8a490cbf5fcdf8"
encoding = "hex"

[config.preview.proxy_hash]
Expand Down
102 changes: 52 additions & 50 deletions lib/intention_utils.ak
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ use intention_types.{
SignedIntention,
}
use prefix.{nonce_prefix}
use types.{
BulletCredential, Control, ParallelNonce, Vault, Verification, Vk, Withdrawal,
}
use types.{Control, ParallelNonce, Vault, Verification, Vk, Withdrawal}
use utils.{dataify, must_have_key, ref_control_datum}

/// Optimized for expecting the name values of policy and assets in one output
Expand Down Expand Up @@ -187,13 +185,13 @@ pub fn fold_intent_counts(
// We offset to outputs related to change and nonces
// The earlier outputs would be related to other dApps or intents
offset_outputs: List<Output>,
withdrawals: Pairs<Credential, Int>,
withdrawals: Pairs<Data<Credential>, Data<Int>>,
validate_signature: fn(
Int,
Data<List<Vk>>,
Pairs<VerificationKeyHash, VerificationKey>,
Pairs<Data<VerificationKeyHash>, Data<VerificationKey>>,
) ->
fn(List<Signature>, ByteArray) -> Bool,
fn(List<Data<Signature>>, ByteArray) -> Bool,
// Constraint and temp value that can be used with certain constraints
constraint_validator: fn(Data<Constraint>, Data) -> Data,
) -> Bool {
Expand Down Expand Up @@ -238,11 +236,9 @@ pub fn fold_intent_counts(
reference_inputs
|> ref_control_datum(user_address, expected_nft)

expect Control { quorum, hot_cred, hot_cred_hash, .. } = control_datum
expect Control { hot_cred, .. } = control_datum

// TODO: optimize
expect hot_cred_hash: BulletCredential = hot_cred_hash

// third part: validate user constraints for the popped off intention
expect
(constraints
Expand Down Expand Up @@ -272,47 +268,53 @@ pub fn fold_intent_counts(
<-
fn(callback) {
let sig_function =
when hot_cred_hash is {
Withdrawal(sc) -> {
// So you are probably wondering in what case do you use script withdraw
// trick over simply providing a public key?
// The answer is as Plutus versions progress and ZK folding schemes improve,
// I can see a world where most accounts depend on a validator that runs a single ZK-STARK
// or ZK-SNARK to validate each intention was signed by the owner of the respective account.
// Basically a user would produce an intention plus a ZK-proof and the sequencer
// would fold all the ZK-proofs into a single proof that checks all intentions that were
// included in the tx were properly signed. All without revealing the users signing or verifying key.
expect must_have_key(withdrawals, sc)?

fn(_a, _b, _c, _d) { True }
}
Verification(vks) -> {
let validate_signature_post =
validate_signature(builtin.un_i_data(quorum), hot_cred, vks)

let validate_signatures =
fn(
prefix: ByteArray,
intent: Data,
postfix: ByteArray,
signatures: Data,
) {
expect signatures: List<Signature> = signatures

let message =
intent
|> serialise()
|> concat(prefix, _)
|> concat(postfix)
|> blake2b_256()

validate_signature_post(signatures, message)
}

expect validate_signatures(prefix, intent, postfix, signatures)

validate_signatures
}
if builtin.unconstr_index(hot_cred) == 0 {
expect Verification { edd25519_keys, other_keys, hot_quorum, .. } =
hot_cred

let validate_signature_post =
validate_signature(
builtin.un_i_data(hot_quorum),
other_keys |> builtin.un_list_data,
edd25519_keys |> builtin.un_map_data,
)

let validate_signatures =
fn(
prefix: ByteArray,
intent: Data,
postfix: ByteArray,
signatures: Data,
) {
let message =
intent
|> serialise()
|> concat(prefix, _)
|> concat(postfix)
|> blake2b_256()

validate_signature_post(
signatures |> builtin.un_list_data,
message,
)
}

expect validate_signatures(prefix, intent, postfix, signatures)

validate_signatures
} else {
expect Withdrawal(sc) = hot_cred
// So you are probably wondering in what case do you use script withdraw
// trick over simply providing a public key?
// The answer is as Plutus versions progress and ZK folding schemes improve,
// I can see a world where most accounts depend on a validator that runs a single ZK-STARK
// or ZK-SNARK to validate each intention was signed by the owner of the respective account.
// Basically a user would produce an intention plus a ZK-proof and the sequencer
// would fold all the ZK-proofs into a single proof that checks all intentions that were
// included in the tx were properly signed. All without revealing the users signing or verifying key.
expect must_have_key(withdrawals, sc)?

fn(_a, _b, _c, _d) { True }
}

// Deal with only a single value leaving and nonce
Expand Down
41 changes: 24 additions & 17 deletions lib/types.ak
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,36 @@ pub type ProxyAction {
Delete
}

pub type BulletCredential {
Verification(Pairs<VerificationKeyHash, VerificationKey>)
Withdrawal(Credential)
pub type HotBulletCredential {
Verification {
edd25519_keys: Data<Pairs<VerificationKeyHash, VerificationKey>>,
other_keys: Data<List<Vk>>,
hot_quorum: Data<Int>,
wallet_quorum: Data<Int>,
}
Withdrawal(Data<Credential>)
}

pub type ColdBulletCredential {
ColdVerification(
Data<Pairs<VerificationKeyHash, VerificationKey>>,
Data<List<Vk>>,
)
ColdWithdrawal(Data<Credential>)
}

// Optimization:
// Possibly switch from many Vk to single one
// since Schnorr supports k of m signatures anyway
pub type AccountState {
quorum: Int,
hot_cred: List<Vk>,
hot_cred_hash: BulletCredential,
cold_cred: List<Vk>,
cold_cred_hash: BulletCredential,
hot_cred: HotBulletCredential,
cold_cred: ColdBulletCredential,
}

pub type UtxoStates {
Control {
quorum: Data<Int>,
hot_cred: Data<List<Vk>>,
hot_cred_hash: Data<BulletCredential>,
cold_cred: Data<List<Vk>>,
cold_cred_hash: Data<BulletCredential>,
hot_cred: Data<HotBulletCredential>,
cold_cred: Data<ColdBulletCredential>,
}
ParallelNonce
Vault
Expand All @@ -61,23 +68,23 @@ pub type ProxyState {
}

pub type Vk {
Secp(VerificationKey)
Schnorr(VerificationKey)
Secp(VerificationKey)
}

pub type HotAccountSpend {
user_stake: ScriptHash,
sigs: List<Signature>,
sigs: Data<List<Signature>>,
}

pub type HotAccountStake {
user_stake: Credential,
sigs: List<Signature>,
sigs: Data<List<Signature>>,
}

pub type AccountSpend {
user_stake: ScriptHash,
sigs: List<Signature>,
sigs: Data<List<Signature>>,
index: Data<Int>,
}

Expand Down
Loading

0 comments on commit 51992f2

Please sign in to comment.