From 1673bde881f699126128c3c4c1578c85f237b9ef Mon Sep 17 00:00:00 2001 From: logicalmechanism Date: Fri, 9 Feb 2024 12:11:00 -0800 Subject: [PATCH] adding find input by nft function --- CHANGELOG.md | 2 ++ lib/assist/find.ak | 26 ++++++++++++++++++++++++++ lib/assist/maths.ak | 20 ++++++++++++++++++++ lib/assist/tests/fake_tx.ak | 17 ++++++++++++++++- 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e06f4a6..6e12447 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # v0.x.y +- Added `input_by_nft` to the find submodule. + # v0.4.5 - Added the `Wallets` type and `to_vks` to the wallet submodule. diff --git a/lib/assist/find.ak b/lib/assist/find.ak index 54067c2..2bc4e2d 100644 --- a/lib/assist/find.ak +++ b/lib/assist/find.ak @@ -414,3 +414,29 @@ test cant_find_output_datum_by_nft2() fail { expect outcome: ByteArray = output_datum_by_nft(outputs, #"fade", #"fade") outcome == fake_tx.test_datum } + +/// Find the first occurance of an inline datum on an output with a value +/// that contains a specific nft. +pub fn input_by_nft(inputs: List, pid: PolicyId, tkn: AssetName) -> Input { + when inputs is { + [input, ..rest] -> + if values.prove_exact_nft(pid, tkn, input.output.value) { + input + } else { + input_by_nft(rest, pid, tkn) + } + [] -> fail @"No Input Found In Inputs" + } +} + +test cant_find_input_by_nft() fail { + let inputs: List = fake_tx.test_bad_inputs() + let input: Input = input_by_nft(inputs, #"acab", #"beef") + input == fake_tx.test_one_lovelace_input() +} + +test can_find_input_by_nft() { + let inputs: List = fake_tx.test_bad_inputs() + let input: Input = input_by_nft(inputs, #"", #"") + input == fake_tx.test_one_lovelace_input() +} diff --git a/lib/assist/maths.ak b/lib/assist/maths.ak index 254593b..209689f 100644 --- a/lib/assist/maths.ak +++ b/lib/assist/maths.ak @@ -5,6 +5,9 @@ use aiken/bytearray use aiken/list use aiken/math +pub const large_prime: Int = + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab + /// Calculate `n` to the power of `e` modulo `q` using the exponentiation by /// squaring method. At each multiplication a modulo is calculated, allowing /// very large `n` and `e` values. @@ -50,6 +53,13 @@ test powmod_54_123_1() { powmod(54, 123, 1) == 0 } +test powmod_very_large() { + let q = + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab + + powmod(2, 31565052264044690, q) == 2372285326153189929528332103442483377705667947278803297593729812983050665252776619156384486056106192189240939340047 +} + /// Convert a integer `n` into some base `q`. This method /// should scale with any integer and any logical base. /// @@ -89,6 +99,16 @@ test to_base_256() { base_q(78237623, 256) == [4, 169, 207, 183] } +test to_base_large() { + base_q(powmod(2, 15383577435643450949, large_prime), 15) == [ + 12, 9, 14, 13, 5, 2, 11, 13, 5, 13, 10, 8, 5, 11, 10, 4, 7, 5, 11, 0, 10, 8, + 8, 8, 11, 6, 13, 3, 4, 14, 11, 10, 0, 12, 10, 11, 10, 0, 11, 8, 2, 3, 8, 13, + 0, 1, 5, 13, 0, 8, 13, 3, 10, 6, 4, 12, 14, 3, 7, 1, 11, 3, 7, 3, 14, 6, 8, + 4, 14, 3, 2, 7, 10, 14, 13, 10, 6, 8, 1, 7, 6, 13, 11, 10, 9, 12, 2, 13, 4, + 5, 14, 8, 5, 13, 3, 12, 12, + ] +} + /// Convert a hexadecimal bytearray into its base 10 representation. This /// only works with even length bytearrays so arbitrary numbers in hexadecimal /// form will not in general work. diff --git a/lib/assist/tests/fake_tx.ak b/lib/assist/tests/fake_tx.ak index 88d789f..78d0f9d 100644 --- a/lib/assist/tests/fake_tx.ak +++ b/lib/assist/tests/fake_tx.ak @@ -130,6 +130,21 @@ pub fn test_bad_input() -> Input { input } +pub fn test_one_lovelace_input() -> Input { + Input { + output_reference: OutputReference { + transaction_id: TransactionId { hash: #"" }, + output_index: 1, + }, + output: Output { + address: addresses.create_address(#"face", #""), + value: value.from_lovelace(1), + datum: NoDatum, + reference_script: None, + }, + } +} + pub fn test_bad_inputs() -> List { [ Input { @@ -163,7 +178,7 @@ pub fn test_bad_inputs() -> List { }, output: Output { address: addresses.create_address(#"face", #""), - value: value.from_lovelace(5), + value: value.from_lovelace(1), datum: NoDatum, reference_script: None, },