diff --git a/modules/ecash-agora/tests/partial.slp.test.ts b/modules/ecash-agora/tests/partial.slp.test.ts new file mode 100644 --- /dev/null +++ b/modules/ecash-agora/tests/partial.slp.test.ts @@ -0,0 +1,45 @@ +// Copyright (c) 2024 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import { expect, use } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import { ChronikClient } from 'chronik-client'; +import { Ecc, initWasm, OP_RETURN, Script } from 'ecash-lib'; +import { TestRunner } from 'ecash-lib/dist/test/testRunner.js'; + +use(chaiAsPromised); + +// This test needs a lot of sats +const NUM_COINS = 500; +const COIN_VALUE = 1100000000; + +describe('AgoraPartial SLP', () => { + let runner: TestRunner; + let chronik: ChronikClient; + let ecc: Ecc; + + before(async () => { + await initWasm(); + runner = await TestRunner.setup('setup_scripts/ecash-agora_base'); + chronik = runner.chronik; + ecc = runner.ecc; + await runner.setupCoins(NUM_COINS, COIN_VALUE); + }); + + after(() => { + runner.stop(); + }); + + it('Can get a big UTXO', async () => { + // TODO: this will be filled in by actual tests later + const txid = await runner.sendToScript( + [10000, 1010000000], + Script.fromAddress( + 'ecash:prfhcnyqnl5cgrnmlfmms675w93ld7mvvqd0y8lz07', + ), + ); + const tx = await chronik.tx(txid); + expect(tx.outputs[1].value).to.equal(1010000000); + }); +}); diff --git a/modules/ecash-lib/src/test/testRunner.ts b/modules/ecash-lib/src/test/testRunner.ts --- a/modules/ecash-lib/src/test/testRunner.ts +++ b/modules/ecash-lib/src/test/testRunner.ts @@ -12,6 +12,7 @@ import { OP_1, OP_RETURN } from '../opcode.js'; import { Script } from '../script.js'; import { OutPoint, Tx } from '../tx.js'; +import { TxBuilder } from '../txBuilder.js'; const OP_TRUE_SCRIPT = Script.fromOps([OP_1]); const OP_TRUE_SCRIPT_SIG = Script.fromOps([ @@ -26,6 +27,7 @@ public runner: ChildProcess; public chronik: ChronikClient; private coinsTxid: string | undefined; + private coinValue: number | undefined; private lastUsedOutIdx: number; private constructor( @@ -129,20 +131,19 @@ coinValue: number, ): Promise<void> { const opTrueScriptHash = shaRmd160(OP_TRUE_SCRIPT.bytecode); - const utxo = ( + const utxos = ( await this.chronik.script('p2sh', toHex(opTrueScriptHash)).utxos() - ).utxos[0]; + ).utxos; const anyoneScriptHash = shaRmd160(ANYONE_SCRIPT.bytecode); const anyoneP2sh = Script.p2sh(anyoneScriptHash); const tx = new Tx({ - inputs: [ - { - prevOut: utxo.outpoint, - script: OP_TRUE_SCRIPT_SIG, - sequence: 0xffffffff, - }, - ], + inputs: utxos.map(utxo => ({ + prevOut: utxo.outpoint, + script: OP_TRUE_SCRIPT_SIG, + sequence: 0xffffffff, + })), }); + const utxosValue = utxos.reduce((a, b) => a + b.value, 0); for (let i = 0; i < numCoins; ++i) { tx.outputs.push({ value: coinValue, @@ -154,9 +155,10 @@ script: Script.fromOps([OP_RETURN]), }); tx.outputs[tx.outputs.length - 1].value = - utxo.value - numCoins * coinValue - tx.serSize(); + utxosValue - numCoins * coinValue - tx.serSize(); this.coinsTxid = (await this.chronik.broadcastTx(tx.ser())).txid; + this.coinValue = coinValue; } public getOutpoint(): OutPoint { @@ -169,17 +171,31 @@ }; } - public async sendToScript(value: number, script: Script): Promise<string> { - const setupTx = new Tx({ + public async sendToScript( + value: number | number[], + script: Script, + ): Promise<string> { + const coinValue = this.coinValue!; + const values = Array.isArray(value) ? value : [value]; + const setupTxBuilder = new TxBuilder({ inputs: [ { - prevOut: this.getOutpoint(), - script: ANYONE_SCRIPT_SIG, - sequence: 0xffffffff, + input: { + prevOut: this.getOutpoint(), + script: ANYONE_SCRIPT_SIG, + sequence: 0xffffffff, + signData: { + value: coinValue, + }, + }, }, ], - outputs: [{ value, script }], + outputs: [ + ...values.map(value => ({ value, script })), + Script.fromOps([OP_RETURN]), // burn leftover + ], }); + const setupTx = setupTxBuilder.sign(this.ecc, 1000, 546); return (await this.chronik.broadcastTx(setupTx.ser())).txid; } diff --git a/test/functional/setup_scripts/ecash-agora_base.py b/test/functional/setup_scripts/ecash-agora_base.py --- a/test/functional/setup_scripts/ecash-agora_base.py +++ b/test/functional/setup_scripts/ecash-agora_base.py @@ -26,7 +26,7 @@ def run_test(self): node = self.nodes[0] - self.generatetoaddress(node, 1, ADDRESS_ECREG_P2SH_OP_TRUE)[0] + self.generatetoaddress(node, 149, ADDRESS_ECREG_P2SH_OP_TRUE)[0] self.generatetoaddress(node, COINBASE_MATURITY, ADDRESS_ECREG_UNSPENDABLE) plugins_toml = os.path.join(node.datadir, "plugins.toml")