Multisig Approval

April 6, 2025 ยท View on GitHub

Permissionless Software Foundation Specification 009 (PS009)

Specification version: 1.0.2

Date originally published: January 29, 2023

Date last updated: April 6, 2025

Authors

Chris Troutner

1. Introduction

This specification describes a workflow for generating on-chain 'approval' transactions from a multisignature wallet. The purpose of these approval transactions is to allow a group of people to securely broadcast their approval of a set of data, in way that can be independently verified, and thus impossible to counterfeit.

Doing simple transactions with a multisignature wallet is complex. Doing complex transactions with a multisignature wallet is often prohibitively complex. This specification proposes an alternative solution: Generate a complex transaction with a normal P2PKH transaction, then broadcast an 'approval transaction' from a multisignature wallet. Armed with the normal transaction and the approval transaction, an entity can independently verify the authenticity of both.

The PSF File Pinning Protocol (PSFFPP) is used as the canonical use-case to present this workflow, but it can abstracted to any workflow where a council of members (a multisignature wallet) need to securely approve on-chain data or change the consensus rules of a distributed system.

The Permissionless Software Foundation (PSF) is a decentralized organization that maintains the PSFFPP. Writing data to the PSFFPP requires payment in PSF tokens. They have created a Minting Council to set the price each quarter, targeting an equivalent price of $0.01 USD per write. They are required to approve a data update so that all PSFFPP instances on the planet can synchronize their consensus rules and charge the same price.

This specification is implemented in the psf-multisig-approval JavaScript library.

2. Overview

There are two on-chain transactions generated in this workflow:

  1. An Update Transaction is broadcast, which contains an IPFS content ID (CID) in the transaction OP_RETURN. The CID resolves into JSON data containing the new write-price and all the metadata required to validate the the Approval Transaction. This is a standard P2PKH (single signature) transaction.

  2. An Approval Transaction is generated from a P2SH multisignature wallet. It also contains an OP_RETURN that contains the word 'APPROVAL' and the Transaction ID (TXID) of the Update Transaction.

The multisignature wallet is generated from the public keys of members holding SLP NFTs. This allows a group of NFT holders to approve on-chain data.

Any entity can use the data in the Update Transaction to validate the Approval Transaction is authentic, and was generated by a multisignature wallet that was in-turn generated from the NFTs. In this way, each transactions validates the other.

3. Update Transaction

The Update Transaction must contain an OP_RETURN in its first output. The OP_RETURN data bust contain an IPFS CID in utf-8 format. This CID should resolve to a JSON file. When parsed, the JSON should contain the following properties:

  1. The token ID of the Group Token used to generate the NFTs.
  2. The token IDs of each NFT, as well as the address and public key holding each NFT at the time of the transaction.
  3. The multisig address generated from the public keys.
  4. Any additional data that needs to be approved (the write-price).

The first three pieces of information are used to validate the approval. The forth piece of data can be any arbitrary data, which is the subject of the approval.

3.1 Update Transaction Example

  • OP_RETURN { "cid": "bafybeici4rbap4pqzaoj4hy4aapd4rhl6lz6cthsxigf7zreo2akr3xkf4", "ts": 1675031723394 }

4. Approval Transaction

The Approval Transaction must contain two pieces of information in its OP_RETURN data:

  1. The word 'APPROVAL'. This makes it easy to parse and identify the transaction as an Approval Transaction.
  2. The TXID of the Update Transaction.

The Approval Transaction must include a dust output (546 satoshis) in its second output (index 1) to a Reference Address. The Reference Address can be any arbitrary BCH address, but it must be known to all parties.

4.1 Approval Transaction Example

  • OP_RETURN APPROVAL 6eaa12d2749cf15b00873551088975dd6748d9a6f867426db914735c58ad730a

5. Validation

Once the Approval Transaction is discovered by an interested entity (like a node in the PSFFPP network), the chain of data can be traversed to independently verify both transactions are valid, and thus the arbitrary data in the Update Transaction is valid.

Here is the set of steps required to validate the authenticity of the data in the Update Transaction:

  1. Request the transaction history for the Reference Address and sort the transactions in descending order by block height. This ensures the most recent transactions are evaluated first.
  2. Traverse the transaction history until one is found with the word 'APPROVAL' in the OP_RETURN data. This is the latest Approval Transaction. Note the address which generated the transaction, this is the multisignature address.
  3. Retrieve the Update Transaction from the TXID stored in the OP_RETURN of the Approval Transaction.
  4. Retrieve the CID from the OP_RETURN of the Update Transaction.
  5. Retrieve the JSON data from an IPFS gateway, using the CID.
  6. The following items in the JSON data should be validated:
  • Verify the Group token ID is listed and matches the expected value.
  • Verify that all NFTs listed are children of the given Group token.
  • Verify that each address listed is generated from the given public key.
  • Verify that each address holds the NFT listed.
    • Note: Since NFTs can move, it may instead be necessary to verify that the address held the NFT at some point in its transaction history.
  • Compute the multisignature address from the public keys and ensure it matches the address that generated the Approval Transaction (in step 2).

After computing the above validations in step 6, the validator can be assured that the data is authentic and has not been counterfeited by a malicious party.