Skip to content

mlabs-haskell/ytxp-lib

Repository files navigation

Yielding Transaction Pattern Library (ytxp-lib)

The Yielding Transaction Pattern is pretty simple.

  • A Yielding Script only succeeds if it can find evidence that an AuthorisedScript also succeeded.
  • The authorization is determined by examination of the script context.
  • The authorization is checked by:
    • Indexing the reference inputs to find evidence that a AuthorisedScript containing a token minted with the authorisedScriptsSTCS is being referenced
    • Searching for evidence that this script was triggered In practice this will involve either:
      • Looking at the txInfoWithdrawls field for a staking validator being triggered with the correct StakingCredential
      • Looking at the txInfoInputs field for a UTxO being spent at the correct address
      • Looking at the txInfoMints field for a mint with the correct currency symbol

About this documentation

The YTxP is something that can be implemented using a variety of onchain and offchain frameworks in a variety of programming languages. This documentation details technical aspects of the types of activities that practitioners of the YTxP architecture will need to do; it is a specification of what a YTxP library should include. It will describe the library primarily in terms of Haskell, but other languages should be able to easily adapt it.

The YTxP architecture is a principled approach to modeling and describing Cardano protocols via transaction families. A goal of the architecture is to establish a common formula for such descriptions that is:

  • flexible enough to apply to the business logic of every protocol, even if the implementation would need reformulation
  • restricted enough to give strong security guarantees
  • compositional enough that there is a clear, principled, and sound way to decompose large protocols into distinct parts that can be easily examined both in isolation and as a complete system

This documentation includes some templates in the ./templates/ directory. These templates are an attempt to establish the above formula. Designers are encouraged to use these templates as a starting point for describing new functionalities in a protocol.

The YTxP itself is described using these templates.

Documentation Structure

The documentation structure of a YTxP Protocol (as well as this library) can be made to reflect a reasonable module structure for the implementation of the protocol. We give a directory for each Transaction Flow (see below) and a single file for each Transaction Family (see below) that is part of that flow.

Note that transaction families need not be part of only one flow, and transaction flows can be composed or combined monadically; the directory structure given is a canonical association of a family to a flow, but it is not necessarily reflective of the full picture.

Vocabulary and Nomenclature

Component UTxO

A “component UTxO” is a useful model for protocol design. It is a UTxO that is “typed” by the token name of its State Thread Token (see below). The “type” of a component UTxO gives semantics to its associated address, value, datum, and reference scripts.

The YTxP does not require using the “component UTxO” model, but it is a natural fit.

State Thread Token (STT)

A token that authenticates the semantic validity of a UTxO. STTs are often referred to prefixed by the “type” of a Component UTxO, such as a “Vault State Thread Token”.

Semantically, state thread tokens constitute a proof that one of the three conditions hold for a given transaction:

  • When a STT is minted in a transaction, it is a necessary (but perhaps insufficient) condition that the “introduction rules”, “initial conditions”, or “base case” governing the creation of a Component UTxO are satisfied
  • When a STT is continued through a transaction, it is a necessary (but perhaps insufficient) condition that the transaction was a “valid state transition” or “valid recursive case” in terms of protocol semantics
  • When an STT is burned, it is a necessary (but perhaps insufficient) condition that the “elimination rules” or “terminating case” governing a component UTxO were satisfied

STCS

An abbreviation for “State Thread Currency Symbol”

STMP

An abbreviation for “State Thread Minting Policy”

Component Token

A distinguished type of STT minted by the Yielding Minting Policy that indicates the “type” of a Component UTxO via its token name.

Transaction Flows

A “transaction flow” is a combination of one-or-more “transaction families” that have intertwined semantics. These often form a sub-state-machine of the entire protocol; i.e., a loop within the overall state transition graph.

Transaction flows can be composed of other transaction flows as well.

Transaction Family

“Transaction Families” define both semantics and constraints on single, atomic transactions. A transaction is considered to be a “section of”, “member of”, or “element of” a transaction family if it obeys the constraints of the transaction. For instance, wallet-to-wallet transactions form a transaction family – any transaction that consumes only UTxOs at a single pubkey address and produces UTxOs at a single pubkey address would be a section of the transaction family.

Using the YTxP involves modeling a protocol as a series of disjoint transaction families; each transaction enabled by the protocol belongs to only one transaction family.

Transaction families are referred to by gerunds – “-ing words”. I.e., a transaction family that buys a stablecoin is referred to by the term “StableCoin Buying Transaction Family”, rather than “Buying StableCoin Transaction Family” or “Buy StableCoin Transaction”. The model views transaction families as “state machine transitions” or “methods”.

Transaction Family Hash

Transaction families are implemented as AuthorisedScripts. These can be:

  • staking validators, which are preferred because a “withdraw 0” transaction is more functionally “pure” (side-effect free) than other options
  • minting policies, which are known as “transaction tokens”, and may be useful for legacy reasons or integration with existing protocols. However, these require minting a token, which may be a superfluous side-effect.
  • validator hashes, which may be useful for legacy reasons or integration with existing protocols. However, these require spending a UTxO, which may be a superfluous side effect.

See this for more details on the idea and execution of the “withdraw 0”

Tooling

Continuous Integration (CI)

The CI for this project runs using Hercules CI. All the pre-commit checks will run in CI.

Developer Experience (DevEx)

All the commands used for development purposes are exposed through the Makefile. To see the available commands, you can simply run:

make

Formatting

The format of most of the source files is checked. You can use individual commands through the Makefile or you can simply run:

make format_lint

to apply all the linters and formatters. This might be useful.

Note: Some linters cannot automatically fix your code. For example, markdownlint may signal that a code block (delimited by ```) does not have the language specified but cannot automatically infer the language of the code. This means that in general, make format_lint does not resolve all the problems that pre-commit checks can raise.

Haddock Documentation

Below are instructions for generating Haddock documentation using different methods:

Build

Using Make Target

To build documentation directly, utilize the following make target:

make build_docs

After the execution, this command will specify the location of the generated documentation.

Using Nix

If you are using nix, the documentation for ytxp-plutarch library , generating documentation can be achieved by running:

nix build .#ytxp-plutarch-lib.doc

Serve documentation locally

To serve the documentation locally, utilize the following make target:

make serve_docs

The resulting documentation will be accessible within the result-doc directory.

Tests

Tests will run in CI thanks to some specific checks in the Nix flake.

You can run tests:

  • Using Nix: nix flake check: this will run all the checks, not only the tests;
  • Using Cabal directly (assuming it is present in the $PATH). See the Makefile targets to check the available test suites.