Skip to content

Commit

Permalink
tests: update to new test structure
Browse files Browse the repository at this point in the history
adds functions for checking that the generated sending outputs matches
exactly one of the expected.outputs candidate sets.
  • Loading branch information
josibake authored and Overtorment committed May 1, 2024
1 parent 4aa7ce8 commit 8a76bde
Showing 1 changed file with 70 additions and 46 deletions.
116 changes: 70 additions & 46 deletions tests/silent-payment.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,42 @@
import assert from "node:assert";
import { ECPairFactory } from "ecpair";
import { SilentPayment } from "../src";
import { SilentPayment, UTXOType } from "../src";
import ecc from "../src/noble_ecc";
import jsonImput from "./data/sending_test_vectors.json";
import { Vin, getUTXOType } from "../tests/utils";
import jsonInput from "./data/sending_test_vectors.json";

const ECPair = ECPairFactory(ecc);

type TestCase = {
comment: string;
given: {
outpoints: [string, number][],
input_priv_keys: [string, boolean][],
recipients: [string, number][]
},
expected: {
outputs: [string, number][],
}
function exactMatch(a: string[], b: string[]): boolean {
const sortedA = a.sort();
const sortedB = b.sort();
return sortedA.length === sortedB.length && sortedA.every((value, index) => value === sortedB[index]);
}

function matchSubset(generated: string[], expected: string[][]): boolean {
return expected.some(subArray => exactMatch(generated, subArray));
}

const tests = jsonImput as unknown as Array<TestCase>;
type Given = {
vin: Vin[];
recipients: string[];
};

type Expected = {
outputs: string[][];
};

type Sending = {
given: Given;
expected: Expected;
};

type TestCase = {
comment: string;
sending: Sending[];
};

const tests = jsonInput as unknown as Array<TestCase>;

it("smoke test", () => {
const sp = new SilentPayment();
Expand All @@ -28,33 +46,34 @@ it("smoke test", () => {
/* Sending tests from the BIP352 test vectors */
tests.forEach((testCase, index) => {
// Prepare the 'inputs' array
const inputs = testCase.given.outpoints.map((outpoint, idx) => ({
txid: outpoint[0],
vout: outpoint[1],
WIF: ECPair.fromPrivateKey(Buffer.from(testCase.given.input_priv_keys[idx][0], "hex")).toWIF(),
isTaproot: testCase.given.input_priv_keys[idx][1],
}));
testCase.sending.forEach(sending => {
const utxos = sending.given.vin.map((input) => ({
txid: input.txid,
vout: input.vout,
WIF: ECPair.fromPrivateKey(Buffer.from(input.private_key, "hex")).toWIF(),
utxoType: getUTXOType(input) as UTXOType,
}));
const noEligibleUtxos = utxos.every(utxo => utxo.utxoType === 'non-eligible');

// Prepare the 'recipients' array
const recipients = testCase.given.recipients.map((recipient) => ({
silentPaymentCode: recipient[0],
value: recipient[1],
}));
// Prepare the 'recipients' array
const recipients = sending.given.recipients.map((recipient) => ({
silentPaymentCode: recipient,
value: 1,
}));

it(`Test Case: ${testCase.comment} works`, () => {
const sp = new SilentPayment();
assert.deepStrictEqual(
sp.createTransaction(inputs, recipients),
testCase.expected.outputs.map((output) => {
const address = output[0];
const value = output[1];
return {
address: address,
value: value,
};
})
);
});
it(`Test Case: ${testCase.comment}`, () => {
const sp = new SilentPayment();
if (noEligibleUtxos) {
expect(() => {
sp.createTransaction(utxos, recipients);
}).toThrow("No eligible UTXOs with private keys found");
} else {
const generated = sp.createTransaction(utxos, recipients);
const generated_pubkeys: string[] = generated.map(obj => obj.address).filter(Boolean) as string[];
assert(matchSubset(generated_pubkeys, sending.expected.outputs));
}
});
});
});

it("2 inputs - 0 SP outputs (just a passthrough)", () => {
Expand All @@ -66,11 +85,13 @@ it("2 inputs - 0 SP outputs (just a passthrough)", () => {
txid: "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
vout: 0,
WIF: ECPair.fromPrivateKey(Buffer.from("1cd5e8f6b3f29505ed1da7a5806291ebab6491c6a172467e44debe255428a192", "hex")).toWIF(),
utxoType: "p2wpkh",
},
{
txid: "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
vout: 0,
WIF: ECPair.fromPrivateKey(Buffer.from("7416ef4d92e4dd09d680af6999d1723816e781c030f4b4ecb5bf46939ca30056", "hex")).toWIF(),
utxoType: "p2wpkh",
},
],
[
Expand Down Expand Up @@ -98,33 +119,36 @@ it("2 inputs - 0 SP outputs (just a passthrough)", () => {
});

it("SilentPayment._outpointHash() works", () => {
const A = ECPair.fromWIF("L4cJGJp4haLbS46ZKMKrjt7HqVuYTSHkChykdMrni955Fs3Sb8vq").publicKey;
assert.deepStrictEqual(
SilentPayment._outpointsHash([
{
txid: "a2365547d16b555593e3f58a2b67143fc8ab84e7e1257b1c13d2a9a2ec3a2efb",
vout: 0,
WIF: "L4cJGJp4haLbS46ZKMKrjt7HqVuYTSHkChykdMrni955Fs3Sb8vq",
WIF: "",
utxoType: "p2wpkh",
},
]).toString("hex"),
"dc28dfeffd23899e1ec394a601ef543fa4f29c59e8548ceeca8f3b40fef5d041"
],
A).toString("hex"),
"94d5923201f2f239e4d2d5a44239e0377325a343e4c068cfd078217adc663d7c"
);

// multiple outpoints

assert.deepStrictEqual(
SilentPayment._outpointsHash([
{
txid: "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
vout: 0,
WIF: "",
utxoType: "non-eligible"
},
{
txid: "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
vout: 0,
WIF: "",
utxoType: "p2wpkh",
},
]).toString("hex"),
"210fef5d624db17c965c7597e2c6c9f60ef440c831d149c43567c50158557f12"
],
A).toString("hex"),
"3ea0693eeb0c7e848ad7b875f1998e9ed02905e88a6f5c45f25fa187b7f073d2"
);
});

Expand Down

0 comments on commit 8a76bde

Please sign in to comment.