5

Most types in Plutus are simply wrappers around BuiltinByteString. For instance the bytes in PubKeyHash are not serialized/deserialized to an actual pubkey hash and checked for correctness. So basically any bytestring can be inserted here. A malicious actor could easily block spending a script utxo by adding an invalid pubkey hash. Is there a way to enforce this/let the validator check the pubkey hash for correctness?

1
  • Can you give me an example of a case that you'd care that someone created a UTxO that was unspendable? Anyone can send tokens to unowned addresses whenever they want--essentially burning them. Dec 1, 2021 at 2:59

2 Answers 2

7

Hopefully I'm following your question...

I'm not aware of any type checks performed at validation, but I'm also not aware of any situation that a validator/script would need to spend resources preventing this.

In other words, scripts generally operate under the assumption that proper off-chain code is being used in tandem with the on-chain script. The off-chain code does have type checks.

There is always the threat that a malicious actor will go around the expected off-chain code to abuse the script. The onus is on a script developer to write a script that checks for correct values--I am having a hard time thinking of a situation that someone giving the wrong type and that value being misinterpreted as the correct value.


You give the example of a "malicious actor [blocking the] spending [of] a script utxo by adding an invalid pubkey hash." I don't understand how this case is different from the malicious actor sending a random, un-owned pubkey. In both cases it would prevent the spending of the UTxO.

EDIT:

It sounds like at least in the case of PubKeyHash, which by default has no checks on bytestring length, it is possible to submit and validate against invalid pubkeys. Unfortunately, you can't just rely on type check :(.

It is the script writer's responsibility to understand this limitation and include protection for counterparties. For example:

  • Force a redeemer to use the pubkey that matches the signer of the tx in the context. That way the pubkey always a pre-verified valid pubkey OR
  • Include additional intermediary datums that can hold funds in escrow for a (potentially invalid) recipient pubkey OR
  • Check the length of the bytestring to ensure it could be a valid pubkey

Generally, while writing Plutus scripts you try to avoid over-constraining the logic. Since the PubKeyHash type problem isn't obvious, the above solutions might come across as overconstrained or overcomplicated to those outside the know. Documentation is warranted. Hopefully we can get better types for these things in the future to push devs and readers into a pit of success.

9
  • Person A makes a borrowing request/offer and locks his collateral in a script utxo. Person B comes along and accepts this offer. He gives person A the loan, destroys the old script utxo and creates a new one with the collateral and new datum, where he also specifies his receiving address (pubkey hash) for the payoff amount. But if the pubkey hash is not valid the validator will always fail and the collateral is locked forever in the utxo. Only solution I have in mind is adding a required signer and compare the pubkey hash with the signer, but wanted to know if there is a more elegant way. Dec 1, 2021 at 9:28
  • K. I gotcha. In that case Person B would need to be a deranged actor, but since the loan is overcollateralized it could be a disproportionate loss for Person A. Worth preventing actively. Dec 1, 2021 at 22:01
  • 1
    Just tried it on the testnet. The types are not checked even if you redeem a script utxo and create a new one :(. I was able to set the PubKeyHash to the ByteString "30". Dec 2, 2021 at 14:25
  • 3
    However I realized any bytestring combination, which is 28 bytes long is a valid pubkey hash. That is of course easy to verify. Dec 2, 2021 at 16:49
  • 2
    I'm also failing to understand the wrongdoings of party B. According to your scenario he could only block himself from receiving the collateral. There must be the party A counterpart to closing the contract that should not be impacted by actions of party B. Don't ask party B to provide the pkh, it is available for you from inside the script via ScriptContext{scriptContextTxInfo}
    – andycandy
    Dec 3, 2021 at 9:03
2

You should be extra careful with data that is being provided to smart contracts by the user. You might prevent user errors by using data from the Context that is already provided to you inside the Plutus script.

From the discussion around answers I'm getting a feeling that the malicious actor is only able to "break" the logic in such a way that is unfavourable for him only.

ScriptContext{scriptContextTxInfo{txInfoSignatories}} gives you access to the public key hashes, in this case Person B public key hash when he consumes initial utxo and is creating a new one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.