Skip to content

Commit

Permalink
Merge pull request #2 from logicalmechanism/adding-counters
Browse files Browse the repository at this point in the history
count number of address inputs and outputs
  • Loading branch information
logicalmechanism authored May 16, 2023
2 parents 3832c04 + 465d38f commit d3acbc8
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 10 deletions.
121 changes: 121 additions & 0 deletions lib/assist/count.ak
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//// This module includes code to count the number of inputs and outputs
//// associated with an address, typically a script address.
////
//// The amounts are assumed to be exact.

use aiken/transaction.{Input, Output}
use aiken/transaction/credential.{Address}
use assist/addresses
use tests/fake_tx

/// Verify that the number of inputs from a specific script is equal the amount
/// intended in the contract. The amount must be exact with the counter.
///
/// ```aiken
/// script_inputs(tx.inputs, this_script_addr, 1)
/// script_inputs(tx.inputs, that_script_addr, 2)
/// ```
pub fn script_inputs(
inputs: List<Input>,
script_addr: Address,
amount: Int,
) -> Bool {
count_script_inputs(inputs, script_addr, 0) == amount
}

fn count_script_inputs(
inputs: List<Input>,
script_addr: Address,
counter: Int,
) -> Int {
when inputs is {
[input, ..rest] ->
if input.output.address == script_addr {
count_script_inputs(rest, script_addr, counter + 1)
} else {
count_script_inputs(rest, script_addr, counter)
}
[] ->
counter
}
}

test single_script_input() {
let tx =
fake_tx.test_tx()
let addr =
addresses.create_address(#"acab", #"")
script_inputs(tx.inputs, addr, 1) == True
}

test not_enough_script_inputs() {
let tx =
fake_tx.test_tx()
let addr =
addresses.create_address(#"acab", #"")
script_inputs(tx.inputs, addr, 2) == False
}

test multiple_script_inputs() {
let tx =
fake_tx.test_tx()
let addr =
addresses.create_address(#"face", #"")
script_inputs(tx.inputs, addr, 2) == True
}

/// Verify that the number of outputs from a specific script is equal the amount
/// intended in the contract. The amount must be exact with the counter.
///
/// ```aiken
/// script_outputs(tx.outputs, this_script_addr, 1)
/// script_outputs(tx.outputs, that_script_addr, 2)
/// ```
pub fn script_outputs(
outputs: List<Output>,
script_addr: Address,
amount: Int,
) -> Bool {
count_script_outputs(outputs, script_addr, 0) == amount
}

fn count_script_outputs(
outputs: List<Output>,
script_addr: Address,
counter: Int,
) -> Int {
when outputs is {
[output, ..rest] ->
if output.address == script_addr {
count_script_outputs(rest, script_addr, counter + 1)
} else {
count_script_outputs(rest, script_addr, counter)
}
[] ->
counter
}
}

test single_script_output() {
let tx =
fake_tx.test_tx()
let addr =
addresses.create_address(#"acab", #"")
script_outputs(tx.outputs, addr, 1) == True
}

test not_enough_script_outputs() {
let tx =
fake_tx.test_tx()
let addr =
addresses.create_address(#"acab", #"")
script_outputs(tx.outputs, addr, 2) == False
}

test multiple_script_outputs() {
let tx =
fake_tx.test_tx()
let addr =
addresses.create_address(#"face", #"")
script_outputs(tx.outputs, addr, 2) == True
}
12 changes: 6 additions & 6 deletions lib/assist/signing.ak
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ pub fn verify_sig(

test no_signature() {
let tx =
fake_tx.signature_only_tx()
fake_tx.test_tx()
verify_sig(tx, #"") == False
}

test bad_signature() {
let tx =
fake_tx.signature_only_tx()
fake_tx.test_tx()
verify_sig(tx, #"cafe") == False
}

test has_signature() {
let tx =
fake_tx.signature_only_tx()
fake_tx.test_tx()
verify_sig(tx, #"acab") == True
}

Expand Down Expand Up @@ -79,18 +79,18 @@ fn run_multisig(

test no_multisig() {
let tx =
fake_tx.signature_only_tx()
fake_tx.test_tx()
verify_multisig(tx, [], 1) == False
}

test bad_multisig() {
let tx =
fake_tx.signature_only_tx()
fake_tx.test_tx()
verify_multisig(tx, [#"acab"], 2) == False
}

test has_multisig() {
let tx =
fake_tx.signature_only_tx()
fake_tx.test_tx()
verify_multisig(tx, [#"acab", #"beef"], 2) == True
}
67 changes: 63 additions & 4 deletions lib/tests/fake_tx.ak
Original file line number Diff line number Diff line change
@@ -1,14 +1,73 @@
use aiken/dict
use aiken/interval.{Interval, IntervalBound, NegativeInfinity, PositiveInfinity}
use aiken/transaction.{Transaction, TransactionId}
use aiken/transaction.{
Input, NoDatum, Output, OutputReference, Transaction, TransactionId,
}
use aiken/transaction/value
use assist/addresses

pub fn signature_only_tx() -> Transaction {
pub fn test_tx() -> Transaction {
let tx =
Transaction {
inputs: [],
inputs: [
Input {
output_reference: OutputReference {
transaction_id: TransactionId { hash: #"" },
output_index: 0,
},
output: Output {
address: addresses.create_address(#"acab", #""),
value: value.from_lovelace(100),
datum: NoDatum,
reference_script: None,
},
},
Input {
output_reference: OutputReference {
transaction_id: TransactionId { hash: #"" },
output_index: 1,
},
output: Output {
address: addresses.create_address(#"face", #""),
value: value.from_lovelace(5),
datum: NoDatum,
reference_script: None,
},
},
Input {
output_reference: OutputReference {
transaction_id: TransactionId { hash: #"" },
output_index: 1,
},
output: Output {
address: addresses.create_address(#"face", #""),
value: value.from_lovelace(5),
datum: NoDatum,
reference_script: None,
},
},
],
reference_inputs: [],
outputs: [],
outputs: [
Output {
address: addresses.create_address(#"acab", #""),
value: value.from_asset(#"acab", #"beef", 40),
datum: NoDatum,
reference_script: None,
},
Output {
address: addresses.create_address(#"face", #""),
value: value.from_lovelace(40),
datum: NoDatum,
reference_script: None,
},
Output {
address: addresses.create_address(#"face", #""),
value: value.from_lovelace(60),
datum: NoDatum,
reference_script: None,
},
],
fee: value.zero(),
mint: value.zero(),
certificates: [],
Expand Down

0 comments on commit d3acbc8

Please sign in to comment.