Skip to content

Latest commit

 

History

History
133 lines (85 loc) · 11.9 KB

security.md

File metadata and controls

133 lines (85 loc) · 11.9 KB

Marlowe Security Guide

Contracts

See the Best Practices for Marlowe on Cardano for guidelines on verifying that a Marlowe contract will execute correctly on the Cardano blockchain. Use Marlowe Playground or marlowe-cli run prepare to simulate the execution of the contract. Use the marlowe-cli run analyze tool to check for Cardano-specific problems in the contract, or run the contract itself on one of the Cardano testnets. In general, one should not participate in a smart contract whose execution paths one does not understand.

Transactions

The spending of a UTxO for a Marlowe contract or a payout is validated by a Plutus script, either the semantics validator or the payout validator. For maximum security, one should not sign a transaction unless one has reviewed and understood the contents and implications of the unsigned transaction. For Marlowe, this means verifying the Marlowe contract and its input.

Marlowe Semantics Validator

Before signing a Marlowe transaction, one should understand the following:

  1. Does the transaction operate a Marlowe contract?
  2. What is the current contract and its state?
  3. What input is being applied to the contract?
  4. What else is occurring in the transaction?

Does the transaction operate a Marlowe contract?

Because Marlowe's Plutus validator script is a universal interpreter for all Marlowe contracts of a specified version, the UTxO for a Marlowe contract resides at a well-known script hash. If one verifies that a transaction spends from an address that has the Marlowe script hash as its payment part, then one knows that the true Marlowe validator will run to validate the spending of that UTxO.

One can compute the script hash of the Marlowe validator from first principles by compiling the validator and computing its hash, assuming that one trusts the Marlowe script source code in this repository. Here is a recipe:

nix run 'github:input-output-hk/marlowe-cardano#marlowe-cli' -- contract validator --mainnet --out-file /dev/null --print-hash
addr1w94f8ywk4fg672xasahtk4t9k6w3aql943uxz5rt62d4dvq8evxaf
Validator hash: "6a9391d6aa51af28dd876ebb5565b69d1e83e5ac7861506bd29b56b0"

Here addr1w94f8ywk4fg672xasahtk4t9k6w3aql943uxz5rt62d4dvq8evxaf is the address of the unstaked Marlowe validator and 6a9391d6aa51af28dd876ebb5565b69d1e83e5ac7861506bd29b56b0 is the well-known script hash of the Marlowe V1 validator.

A staking credential may be associated with the Marlowe validator so that any Ada residing in Marlowe contracts there accrues staking rewards. Thus, the same Marlowe validator might have many different addresses. For example, here are several addresses associated with the same validator hash:

$ nix run 'github:input-output-hk/marlowe-cardano#marlowe-cli' -- contract address --mainnet
addr1w94f8ywk4fg672xasahtk4t9k6w3aql943uxz5rt62d4dvq8evxaf

$ nix run 'github:input-output-hk/marlowe-cardano#marlowe-cli' -- contract address --mainnet --stake-address stake1u8plvp2a7dythh6yxutd0qlzzkncr3gy5ftvxj02d3etafq4kz6s2
addr1z94f8ywk4fg672xasahtk4t9k6w3aql943uxz5rt62d4dvxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqe7ks37

$ nix run 'github:input-output-hk/marlowe-cardano#marlowe-cli' -- contract address --mainnet --stake-address stake1u8f6d2307veldu24l0u8gck9yp2f0mvxjqtja9ras2wzacss7utvx
addr1z94f8ywk4fg672xasahtk4t9k6w3aql943uxz5rt62d4dvxn564zluen7mc4t7lcw33v2gz5jlkcdyqh9628mq5u9m3qfuhp8s

Representing an address as base 16 bytes reveals the payment script hash, starting at the second byte:

$ cardano-cli address info --address addr1w94f8ywk4fg672xasahtk4t9k6w3aql943uxz5rt62d4dvq8evxaf | jq -r .base16
716a9391d6aa51af28dd876ebb5565b69d1e83e5ac7861506bd29b56b0

$ cardano-cli address info --address addr1z94f8ywk4fg672xasahtk4t9k6w3aql943uxz5rt62d4dvxr7cz4mu6gh005gdck67p7y9d8s8zsfgjkcdy75mrjh6jqe7ks37 | jq -r .base16
116a9391d6aa51af28dd876ebb5565b69d1e83e5ac7861506bd29b56b0c3f6055df348bbdf443716d783e215a781c504a256c349ea6c72bea4

$ cardano-cli address info --address addr1z94f8ywk4fg672xasahtk4t9k6w3aql943uxz5rt62d4dvxn564zluen7mc4t7lcw33v2gz5jlkcdyqh9628mq5u9m3qfuhp8s | jq -r .base16
116a9391d6aa51af28dd876ebb5565b69d1e83e5ac7861506bd29b56b0d3a6aa2ff333f6f155fbf87462c5205497ed8690172e947d829c2ee2

Below are the version hashes as of January 20, 2024.

Version Technical Notes Hash for Semantics Validator Hash for Role-Payout Validator Hash for Open-Role Validator
v5 Optimized using PlutusTx.asData 377325ad84a55ba0282d844dff2d5f0f18c33fd4a28a0a9d73c6f60d fcb8885eb5e4f9a5cfca3c75e8c7280e482af32dcdf2d13e47d05d27 2722e12a53dfb4fe3742b8a2c0534bd16b0b5ae492a3d76554bbe8a5
v4 Optimized using PlutusTx 1.15 6027a8010c555a4dd6b08882b899f4b3167c6e4524047132202dd984 fdade3b86107bc715037b468574dd8d3f884a0da8c9956086b9a1a51 36a5c7e49a6b11c7fb65fb61db69ed5ceaa35326af9d952fd30185c0
v3 Recompiled with Node 8.1.2 dependencies d85fa9bc2bdfd97d5ebdbc5e3fc66f7476213c40c21b73b41257f09d 10ec7e02d25f5836b3e1098e0d4d8389e71d7a97a57aa737adc1d1fa b1d61d0c8a3c0f081a7ccebf0050e3f2c9751e82a4f3953a769dddfb
v2 Changes in response to audit 2ed2631dbb277c84334453c5c437b86325d371f0835a28b910a91a6e e165610232235bbbbeff5b998b233daae42979dec92a6722d9cda989
v1 Audited 6a9391d6aa51af28dd876ebb5565b69d1e83e5ac7861506bd29b56b0 49076eab20243dc9462511fb98a9cfb719f86e9692288139b7c91df3

What is the current contract and its state?

The pre-transaction state of the contract is defined in the Plutus Datum associated with the UTxO being spent from the Marlowe script address, and this datum must be provided in the transaction. This datum contains the following:

  • the balances of the accounts internal to the contract,
  • the history of choices previously made up to this point in the contract's execution,
  • the current values of the contract's bound variables, and
  • the part of the contract that remains to be executed.

The Datum can be extracted from the unsigned transaction body and deserialized to Language.Marlowe.Core.V1.Semantics.MarloweData using the function PlutusLedgerApi.V2.fromData. Alternatively, the command-line tool marlowe log --show contract will display the on-chain history of the contract.

What input is being applied to the contract?

The input being applied to the contract in the transaction is defined in the Plutus Redeemer associated with spending the UTxO from the Marlowe script address, along with the slot validity interval for the transaction specified in the transaction body. The input is a sequence of zero or more deposits, choices, and notifications. The consequences of applying this input to the contract can be studied using a tool like Marlowe Playground or marlowe-cli run prepare.

The Redeemer can be extracted from the unsigned transaction body and deserialized to Language.Marlowe.Scripts.MarloweInput using the function PlutusLedgerApi.V2.fromData. The command-line tool marlowe-cli util slotting will compute the relationship between the slots mentioned in the validity interval to the POSIX times in the contract.

What else is occurring in the transaction?

The unsigned transaction may contain other spending and payments beyond that specified for the Marlowe contract. This can be examined with the tool cardano-cli transaction view.

Marlowe Payout Validator

In addition to the semantics validator discussed above, Marlowe has a payout validator. The same security considerations hold for it. Its script hash can be computed as follows:

nix run 'github:input-output-hk/marlowe-cardano#marlowe-cli' -- role validator --mainnet --out-file /dev/null --print-hash
addr1w9yswm4tyqjrmj2xy5glhx9fe7m3n7rwj6fz3qfekly3mucd3rynq
addr1w9yswm4tyqjrmj2xy5glhx9fe7m3n7rwj6fz3qfekly3mucd3rynq
Validator hash: "49076eab20243dc9462511fb98a9cfb719f86e9692288139b7c91df3"

Deserialization of the Datum and Redeemer should target (PlutusLedgerApi.V2.CurrencySymbol, PlutusLedgerApi.V2.TokenName) and (), respectively.

Role Tokens

The Marlowe validator does not enforce a particular monetary policy for role tokens, in order to make possible novel use cases using role tokens. However, the security of authorizations in a role-based Marlowe contract depends critically upon the role-token monetary policy. Thus, one should carefully scrutinize both the monetary policy and the on-chain disbursement of the tokens before participating in a Marlowe contract. Verifying the monetary policy of a simple script just involves retrieving the script off of the blockchain and studying it; verifying the monetary policy of a Plutus script involves obtaining and studying the Plutus source code for the script and hashing the source code to check the monetary policy ID.

One typically uses a monetary policy (like that supported in Marlowe Runtime) that enforces a single minting event and single tokens for each role: such a monetary policy ensures that the role tokens are true non-fungible tokens (NFTs) so that the holders of the role tokens are provably the only ones who can act as the parties in the contract.

Nevertheless, monetary policies that mint multiple copies of a particular role token or ones with an open minting policy support non-standard use cases. For instance, minting two copies of each role token and distributing them to the same party allows that party to place one token in cold storage as a backup if their wallet containing the "hot" role token becomes inaccessible. Some novel crowdsourcing contracts might involve assigning the role (via identical role tokens that may be minted even after the contract commences) to many participants. Finally, a Plutus contract's minting policy for role tokens can coordinate with the operation of one or more Marlowe contracts.

Marlowe Runtime

Marlowe Runtime provides off-chain services that discover Marlowe contract history and build transactions that apply input to Marlowe contracts. The Marlowe Runtime deployment does not have to be trusted if one carefully examines the Marlowe transactions it produces, as discussed in the previous section. If Marlowe Runtime is deployed as part of a web service, then one needs to be aware of the possibility of person-in-the-middle, cross-site scripting, and other attacks.

Marlowe Runtime contains a registry of known Marlowe script versions that it uses to create new Marlowe transactions. One should only use Marlowe Runtime to create contracts if one trusts the script hashes in that registry. The Marlowe test suite verifies that the script registry has not been inadvertently or maliciously altered. (Of course, this does not guarantee that the test itself has not been altered.

Marlowe CLI

Marlowe CLI provides utilities for running and managing Marlowe contracts, including simulating and analyzing them. Transactions constructed with marlowe-cli can be examined using the same techniques as for studying any other Marlowe transaction.