cardano-client-lib icon indicating copy to clipboard operation
cardano-client-lib copied to clipboard

QuickTX collateral selection results in InsufficientCollateral

Open stikkos opened this issue 1 year ago • 3 comments

I'm trying to send a scriptTx using QuickTx but getting: "InsufficientCollateral (Coin (-12084272)) (Coin 307193)"

Collateral summary: IN 5f7e7cae5ac68122fd07ae76977034802977c160e5d015cbeeb80db2e4b618d2 - index 0 - 9793445 lovelace 3e2bdf7f96ff13d552bd7a4979b04f710665fca59b98af8e1461a0fe31475c97 - index 1 - 2598020 lovelace

OUT collateralReturn: 12084272 Total collateral: 307193

Error: InsufficientCollateral (Coin (-12084272)) (Coin 307193)

The first issue is that, even though an exact UTXO for the DEFAULT_COLLATERAL_AMT is present, the UTXO selection strategy doesn't always select this one. Additionally, the calculated total collateral seems to be insufficient...

  • maybe good to use a dedicated "fixed value" UTXO selection strategy first with the aim of selecting an UTXO containing exact 5 ADA before using default UTXO selection strategy
  • it would be helpful to add functionality to QuickTx allowing users to specify collateral UTXO (hash + index) explicitly. When set, this would have priority over UTXO selection (and can be used as-is, i.e without changes based on CollateralPercentage)

Full Transaction (pre-prod):

{
  "body" : {
    "inputs" : [ {
      "transactionId" : "f02f73f6732020a2251d47360809a1475e4401f359ce8d7faed42479711b49a4",
      "index" : 0
    } ],
    "outputs" : [ {
      "address" : "addr_test1qrqhq0xp6ach453pm5cfjmhg3jg68tcvlgn80nv8zsfth956mxp5gzhjqj8xj9zdlrg6v6nr9jqwpzrvf0vmmrhuztdstmsl7l",
      "value" : {
        "coin" : 9795205,
        "multiAssets" : [ ]
      },
      "datumHash" : null,
      "inlineDatum" : null,
      "scriptRef" : null
    } ],
    "fee" : 204795,
    "ttl" : 37064850,
    "certs" : [ ],
    "withdrawals" : [ ],
    "update" : null,
    "auxiliaryDataHash" : "FrS36GUFCrqmie6wVQvEh9Grvzo82xluIuOeHzhOzmE=",
    "validityStartInterval" : 0,
    "mint" : [ ],
    "scriptDataHash" : "qYfkutoyIPZ678LGuPvvkjZFVSkqawGa0S08BnXOI8k=",
    "collateral" : [ {
      "transactionId" : "5f7e7cae5ac68122fd07ae76977034802977c160e5d015cbeeb80db2e4b618d2",
      "index" : 0
    }, {
      "transactionId" : "3e2bdf7f96ff13d552bd7a4979b04f710665fca59b98af8e1461a0fe31475c97",
      "index" : 1
    } ],
    "requiredSigners" : [ "wXA8wddxetIh3TCZbuiMkaOvDPomd82HFBK7lg==" ],
    "networkId" : null,
    "collateralReturn" : {
      "address" : "addr_test1qrqhq0xp6ach453pm5cfjmhg3jg68tcvlgn80nv8zsfth956mxp5gzhjqj8xj9zdlrg6v6nr9jqwpzrvf0vmmrhuztdstmsl7l",
      "value" : {
        "coin" : 12084272,
        "multiAssets" : [ ]
      },
      "datumHash" : null,
      "inlineDatum" : null,
      "scriptRef" : null
    },
    "totalCollateral" : 307193,
    "referenceInputs" : [ ]
  },
  "witnessSet" : {
    "vkeyWitnesses" : [ {
      "vkey" : "JUZu4RKSKZJIkr/BsL/JJtf6nvaHAtn1dwZSKWwuQEc=",
      "signature" : "zQKYkbJl1NFEA279yVow4hKXOZDYUe5zimgWFPQ5fuDy/ZtUy+HUSz0iz5wAzftuk89HqLGzHuQYK0ETrQeoDA=="
    } ],
    "nativeScripts" : null,
    "bootstrapWitnesses" : null,
    "plutusV1Scripts" : [ {
      "type" : "PlutusScriptV1",
      "description" : null,
      "cborHex" : "59014f59014c01000032323232323232322223232325333009300e30070021323233533300b3370e9000180480109118011bae30100031225001232533300d3300e22533301300114a02a66601e66ebcc04800400c5288980118070009bac3010300c300c300c300c300c300c300c007149858dd48008b18060009baa300c300b3754601860166ea80184ccccc0288894ccc04000440084c8c94ccc038cd4ccc038c04cc030008488c008dd718098018912800919b8f0014891ce1317b152faac13426e6a83e06ff88a4d62cce3c1634ab0a5ec133090014a0266008444a00226600a446004602600a601a00626600a008601a006601e0026ea8c03cc038dd5180798071baa300f300b300e3754601e00244a0026eb0c03000c92616300a001375400660106ea8c024c020dd5000aab9d5744ae688c8c0088cc0080080048c0088cc00800800555cf2ba15573e6e1d200201"
    } ],
    "plutusDataList" : [ {
      "constructor" : 0,
      "fields" : [ {
        "constructor" : 0,
        "fields" : [ {
          "constructor" : 0,
          "fields" : [ {
            "bytes" : "c1703cc1d7717ad221dd30996ee88c91a3af0cfa2677cd871412bb96"
          } ]
        }, {
          "constructor" : 0,
          "fields" : [ {
            "constructor" : 0,
            "fields" : [ {
              "constructor" : 0,
              "fields" : [ {
                "bytes" : "9ad983440af2048e69144df8d1a66a632c80e0886c4bd9bd8efc12db"
              } ]
            } ]
          } ]
        } ]
      }, {
        "constructor" : 0,
        "fields" : [ {
          "constructor" : 0,
          "fields" : [ {
            "bytes" : "c1703cc1d7717ad221dd30996ee88c91a3af0cfa2677cd871412bb96"
          } ]
        }, {
          "constructor" : 0,
          "fields" : [ {
            "constructor" : 0,
            "fields" : [ {
              "constructor" : 0,
              "fields" : [ {
                "bytes" : "9ad983440af2048e69144df8d1a66a632c80e0886c4bd9bd8efc12db"
              } ]
            } ]
          } ]
        } ]
      }, {
        "constructor" : 1,
        "fields" : [ ]
      }, {
        "constructor" : 0,
        "fields" : [ {
          "constructor" : 0,
          "fields" : [ {
            "bytes" : "e16c2dc8ae937e8d3790c7fd7168d7b994621ba14ca11415f39fed72"
          }, {
            "bytes" : "4d494e"
          } ]
        }, {
          "int" : 11604
        } ]
      }, {
        "int" : 2000000
      }, {
        "int" : 2000000
      } ]
    } ],
    "redeemers" : [ {
      "tag" : "Spend",
      "index" : 0,
      "data" : {
        "constructor" : 1,
        "fields" : [ ]
      },
      "exUnits" : {
        "mem" : 20499,
        "steps" : 8023468
      }
    } ],
    "plutusV2Scripts" : null
  },
  "auxiliaryData" : {
    "metadata" : {
      "json_metadata" : {
        "674" : {
          "msg" : [ "Jadex: cancel order" ]
        }
      },
      "cbor_metadata" : "a11902a2a1636d736781734a616465783a2063616e63656c206f72646572"
    },
    "nativeScripts" : [ ],
    "plutusV1Scripts" : [ ],
    "plutusV2Scripts" : [ ]
  },
  "valid" : true
}

Result{successful=false, response='{"error":"Bad Request","message":""transaction submit error ShelleyTxValidationError ShelleyBasedEraBabbage (ApplyTxError [UtxowFailure (UtxoFailure (FromAlonzoUtxoFail (BadInputsUTxO (fromList [TxIn (TxId {_unTxId = SafeHash \"3e2bdf7f96ff13d552bd7a4979b04f710665fca59b98af8e1461a0fe31475c97\"}) (TxIx 1),TxIn (TxId {_unTxId = SafeHash \"5f7e7cae5ac68122fd07ae76977034802977c160e5d015cbeeb80db2e4b618d2\"}) (TxIx 0)])))),UtxowFailure (UtxoFailure (FromAlonzoUtxoFail NoCollateralInputs)),UtxowFailure (UtxoFailure (IncorrectTotalCollateralField (Coin (-12084272)) (Coin 307193))),UtxowFailure (UtxoFailure (FromAlonzoUtxoFail (InsufficientCollateral (Coin (-12084272)) (Coin 307193))))])"","status_code":400}', code=400, value=null}

stikkos avatar Aug 23 '23 09:08 stikkos

@stikkos I have faced similar issue while testing a smart contract transaction with Blockfrost backend. I am not sure if those are related.

Here is my scenario.

In same method,

  1. First lock some fund at a script address
  2. Unlock fund

#2 fails with "IncorrectTotalCollateral" and "BadInputsUTxO". In my situation, it seems that the collateral inputs selected by the UtxoSelectionStrategy in step #2 have already been spent, and step #2 is retrieving outdated utxos from Blockfrost.

I'm not sure whether this is an issue with the BFUtxoService because we don't cache anything.

To validate my assumption, I modified my code to have different senders for steps 1 and 2. In this setup, sender1 locks the transaction, and sender2 unlocks it, all within the same method. This approach worked.

I'm curious if you've encountered a similar scenario.

It would be helpful to add functionality to QuickTx allowing users to specify collateral UTXO (hash + index) explicitly. When set, this would have priority over UTXO selection (and can be used as-is, i.e without changes based on CollateralPercentage)

This is a good idea. Let's add a new method collateralUtxos() to ScriptTx.

satran004 avatar Aug 23 '23 13:08 satran004

Hi Satya, that makes sense and yes I did notice some occasional failures due to IncorrectTotalCollateral or BadInputsUTxO.

I think it's more likely a race condition then a caching issue.... My assumption is that the collateral UTXO output is indeed spend by a different tx (submitted slightly earlier) but maybe this tx is not yet included in a block when the UTXO selection happens (only in mempool) but is included when the 2nd transaction is submitted? It's only an assumption though, I'm not very familiar with low-level tx validations...

Let's add a new method collateralUtxos() to ScriptTx.

Thanks, allowing to set explicit collateral in ScriptTx would be nice.

stikkos avatar Aug 23 '23 18:08 stikkos

Thanks @stikkos. I will verify again the flow to see if it's present in the library's code base. I've never encountered this issue while testing with a Yaci DevKit instance (with a 1-sec block time).

By the way, I think we can also add another method to QuickTxBuilder, something like withExclusion(Set<Utxo>). This would exclude the specified utxos from UtxoSelection. It could be useful in scenarios other than collateral.

satran004 avatar Aug 24 '23 03:08 satran004