CashScript / cashscript

⚖️ Easily write and interact with Bitcoin Cash smart contracts
https://cashscript.org
MIT License
111 stars 77 forks source link

only fetch utxos when necessary to avoid network call latency #166

Closed emergent-reasons closed 8 months ago

emergent-reasons commented 8 months ago

Today I used patch-package to patch cashscript@0.9.1 for the project I'm working on.

I found that even when I set locktime to ensure that Transaction.build() does not make a network call to get latest blockheight, that it was still taking a long time. I dug in and found setInputsAndOutputs() is always fetching utxos from the network.

The diff below is just for the build, and may have a better way, but I think something like it should work.

Here is the diff that solved my problem:

diff --git a/node_modules/cashscript/dist/Transaction.js b/node_modules/cashscript/dist/Transaction.js
index d1ab5d7..963445e 100644
--- a/node_modules/cashscript/dist/Transaction.js
+++ b/node_modules/cashscript/dist/Transaction.js
@@ -179,10 +179,16 @@ export class Transaction {
         if (this.outputs.length === 0) {
             throw Error('Attempted to build a transaction without outputs');
         }
-        const allUtxos = await this.provider.getUtxos(this.address);
+
+        let fetchedUtxos = [];
+        if(this.inputs.length === 0)
+        {
+            fetchedUtxos = await this.provider.getUtxos(this.address);
+        }
         const tokenInputs = this.inputs.length > 0
             ? this.inputs.filter((input) => input.token)
-            : selectAllTokenUtxos(allUtxos, this.outputs);
+            : selectAllTokenUtxos(fetchedUtxos, this.outputs);
         // This throws if the manually selected inputs are not enough to cover the outputs
         if (this.inputs.length > 0) {
             selectAllTokenUtxos(this.inputs, this.outputs);
@@ -300,7 +306,7 @@ export class Transaction {
         }
         else {
             // If inputs are not defined yet, we retrieve the contract's UTXOs and perform selection
-            const bchUtxos = allUtxos.filter((utxo) => !utxo.token);
+            const bchUtxos = fetchedUtxos.filter((utxo) => !utxo.token);
             // We sort the UTXOs mainly so there is consistent behaviour between network providers
             // even if they report UTXOs in a different order
             bchUtxos.sort(utxoComparator).reverse();

This issue body was partially generated by patch-package.

emergent-reasons commented 8 months ago

Regarding scale of impact, this made just one test file in the updated (using 0.9.1) anyhedge library test suite go from 120 seconds to 1.2 seconds.

emergent-reasons commented 8 months ago

Created #167 as a starting point for this.

mr-zwets commented 8 months ago

tweaked the PR & merged to fix this issue!