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

How to spend multiple script outputs with inline-datum - MissingRedeemers Error

Open will-break-it opened this issue 2 years ago • 10 comments

Hi, I am using the latest CSL 11.1.0 version on the preview network and I am trying to spend 2 script outputs that hold an inline datum like so:

for (let i = 0; i < sortedScriptTxInputs.length; i++) {
          const o = sortedScriptTxInputs[i];
          const txIn = TransactionInput.new(TransactionHash.from_bytes(Buffer.from(o.txId, 'hex')), o.idx);
          const redeemer = wallet.withdrawRedeemer(i);
          const plutusWitness = PlutusWitness.new_with_ref(PlutusScriptSource.new(spendingContract), DatumSource.new_ref_input(txIn), redeemer);
          const amt = Value.new(BigNum.from_str(`${o.value.coins}`));
          txBuilder.add_plutus_script_input(plutusWitness, txIn, amt);
}
console.log(`Number of script inputs: ${sortedScriptTxInputs.length}`); // prints 2
console.log(txBuilder.get_plutus_input_scripts()?.len());                           // prints 1

I've tried both PlutusWitness constructors: new and new_with_ref. The new constructor attaches a datum to the Tx which causes a NonOutputSupplimentaryDatums error. Using the new_with_ref constructor seems to add a reference_input and no datum witnesses, but it also only attaches 1 redeemer to the transaction even though I am adding 2.

will-break-it avatar Oct 11 '22 14:10 will-break-it

Hi @will991 ! Which version of plutus script do you use ?

lisicky avatar Oct 12 '22 10:10 lisicky

Plutus V2

will-break-it avatar Oct 12 '22 10:10 will-break-it

@will991 Could you try to spend 1 script input instead all ? It might help to localize the error. Are the datums the same for all inputs ?

lisicky avatar Oct 12 '22 10:10 lisicky

Ok, I am getting a PPViewHashesDontMatch error. That is the only error in the log. Here is what I am doing:

  1. Add script input:
for (let i = 0; i < sortedScriptTxInputs.length; i++) {
        const o = sortedScriptTxInputs[i];
        const txIn = TransactionInput.new(TransactionHash.from_bytes(Buffer.from(o.txId, 'hex')), o.idx);
        const redeemer = wallet.withdrawRedeemer(i);
        const plutusWitness = PlutusWitness.new_with_ref(PlutusScriptSource.new(spendingContract), DatumSource.new_ref_input(txIn), redeemer);
        const amt = Value.new(BigNum.from_str(`${o.value.coins}`));
        scriptInputs.add_plutus_script_input(plutusWitness, txIn, amt);
}
txBuilder.set_inputs(scriptInputs);
  1. Setting collateral
  2. Adding required vkey signature
  3. Adding v2 costmodel & calculating script data hash:
const costModel = TxBuilderConstants.plutus_vasil_cost_models().get(Language.new_plutus_v2());
if (!costModel)
        throw new Error('Missing vasil plutus v2 cost model');
const costModels = Costmdls.new();
costModels.insert(Language.new_plutus_v2(), costModel);
txBuilder.calc_script_data_hash(costModels);
  1. Add change output, Build Tx:
txBuilder.add_change_if_needed(changeAddress);
const tx = txBuilder.build_tx();
  1. Sign, extract vKey witness and add it to Tx witness set.

Here is shortened json of the signed Tx:

{
  "body": {
    "inputs": [
      {
        "transaction_id": "39246caa36df6944b4fb01d1d73d6c9a3a7b59e112e60517861b83253ccdabd1",
        "index": 0
      }
    ],
    "outputs": [
      {
        "address": "addr_test1qrqcwuw9ju33z2l0zayt38wsthsldyrgyt82p2p3trccucffejwnp8afwa8v58aw7dpj7hpf9dh8txr0qlksqtcsxheqhekxra",
        "amount": {
          "coin": "3967503",
          "multiasset": null
        },
        "plutus_data": null,
        "script_ref": null
      }
    ],
    "fee": "1032497",
    "ttl": null,
    "certs": null,
    "withdrawals": null,
    "update": null,
    "auxiliary_data_hash": null,
    "validity_start_interval": null,
    "mint": null,
    "script_data_hash": "59eb6669a57d8d273b627c0f92cc55b5ebadc2a1e163973ddea981a0c402d5e3",
    "collateral": [
      {
        "transaction_id": "8ae1f95340f665cc3eb84855c6654b95f3f8a956ed63b787b48686ebe08328ed",
        "index": 0
      }
    ],
    "required_signers": [
      "c18771c59723112bef1748b89dd05de1f6906822cea0a83158f18e61"
    ],
    "network_id": null,
    "collateral_return": null,
    "total_collateral": "5000000",
    "reference_inputs": [
      {
        "transaction_id": "39246caa36df6944b4fb01d1d73d6c9a3a7b59e112e60517861b83253ccdabd1",
        "index": 0
      }
    ]
  },
  "witness_set": {
    "vkeys": [
      {
        "vkey": "ed25519_pk15g8dhxed0u4c4y8a4nwv5wvcpksx6mya2drzqjfuj2a0z3q2vlxsey056m",
        "signature": "5182c8ca3086f2f9a6d4e0d2e8ab5ead02ef99afb0c16675f3f90ee850525abc1080c232e94c83cdffc700d32703948143725383527b4ad49e31dbc8a92ed708"
      }
    ],
    "native_scripts": null,
    "bootstraps": null,
    "plutus_scripts": [
      "59153c01000033... some long script"
    ],
    "plutus_data": {
      "elems": [],
      "definite_encoding": null
    },
    "redeemers": [
      {
        "tag": "Spend",
        "index": "0",
        "data": "{\"constructor\":0,\"fields\":[]}",
        "ex_units": {
          "mem": "7000000",
          "steps": "3000000000"
        }
      }
    ]
  },
  "is_valid": true,
  "auxiliary_data": null
}

From the error, I suppose the calculated hash of the script_data_hash field does not match whatever is expected. But not sure how I get that resolved.

Exact Error:

""transaction submit error ShelleyTxValidationError ShelleyBasedEraBabbage (ApplyTxError [UtxowFailure (FromAlonzoUtxowFail (PPViewHashesDontMatch (SJust (SafeHash \"59eb6669a57d8d273b627c0f92cc55b5ebadc2a1e163973ddea981a0c402d5e3\")) (SJust (SafeHash \"45c67dd3aec5a66ddd3e0470d05923ad9b5cc4617ceb6aa94141e6b1abb4ee5d\"))))])""

will-break-it avatar Oct 12 '22 11:10 will-break-it

> Are the datums the same for all inputs ?

Yes the datums are the same for all script inputs in this example. They only contain the PubKeyHash. The redeemer is also the same (Unit) but indexed in the case of spending multiple script outputs.

will-break-it avatar Oct 12 '22 11:10 will-break-it

I am getting a similar error and currently working on resolving this, I will update here if I make progress

Avatar-Nick avatar Oct 13 '22 01:10 Avatar-Nick

@will991 thanks! We will investigate it soon.

@NicholasMaselli could you provide information about your case ?

lisicky avatar Oct 13 '22 07:10 lisicky

Current calc_script_data_hash function has some issues when it comes to ref datums and it also has some trouble including the right cost models. The workaround I've been using is simply to calculate and set the script_data_hash manually.

@will991 for your case, could you try

const redeemers = Redeemers.new()
redeemers.add(txBuilder.get_plutus_input_scripts().get(0).redeemer())
redeemers.add(txBuilder.get_plutus_input_scripts().get(1).redeemer())
const plutusWitnessHash = hash_script_data(redeemers, costModels, undefined)
txBuilder.set_script_data_hash(plutusWitnessHash)

twwu123 avatar Oct 13 '22 08:10 twwu123

@twwu123 thanks! This worked for me as well but only for a single script input. If I have multiple I still get:

""transaction submit error ShelleyTxValidationError ShelleyBasedEraBabbage (ApplyTxError [UtxowFailure (FromAlonzoUtxowFail (MissingRedeemers [(Spending (TxIn (TxId {_unTxId = SafeHash \"23e874d6549250c6d845031974212f87edb7f1b1d0f676afdf03cbddaf0ae9ad\"}) (TxIx 0)),ScriptHash \"d8feffeeee5fe079055719280d2a9603d93dc1289c2dff9912378d51\")])),UtxowFailure (FromAlonzoUtxowFail (PPViewHashesDontMatch (SJust (SafeHash \"ef6fdbc10a2566ba69e4ab9b8f4834c5392df30f7f7b07c216ffc059c613d569\")) (SJust (SafeHash \"8a180f238eb3cdbf8e8ef3bb7e512712fba6be0c51d25a9dc2c27a3f468c27a2\")))),UtxowFailure (UtxoFailure (FromAlonzoUtxoFail (UtxosFailure (CollectErrors [NoRedeemer (Spending (TxIn (TxId {_unTxId = SafeHash \"23e874d6549250c6d845031974212f87edb7f1b1d0f676afdf03cbddaf0ae9ad\"}) (TxIx 0)))]))))])""

It seems that the redeemers array only contains a single entry instead of 2 (for 2 script inputs)

"redeemers": [
      {
        "tag": "Spend",
        "index": "1",
        "data": "{\"constructor\":0,\"fields\":[]}",
        "ex_units": {
          "mem": "7000000",
          "steps": "3000000000"
        }
      }
    ]

I suppose this may have to do with using txBuilder#build_tx.

will-break-it avatar Oct 13 '22 08:10 will-break-it

So I think there are some issues with multiple inputs from the same script due to the current implementation. @lisicky and I will do some more investigation, thanks a lot for the details.

twwu123 avatar Oct 13 '22 08:10 twwu123

Fix will be in the next CSL release

lisicky avatar Oct 20 '22 07:10 lisicky