Keywords

1 Introduction

Non-fungible Tokens (NFTs) are digital representations of assets providing ownership records stored on a blockchain. They are cryptographic assets on a blockchain with unique identification codes and pointers to associated metadata, possibly stored off-chain. They can be seen as digital passports or a conventional proof-of-purchase of a digital asset, functioning in the same manner than paper invoices. Blockchains allow two mutually distrustful parties to exchange token ownership for cryptocurrency without a trusted intermediary. The exchange is usually atomic in the sense that it happens in the same transaction or is controlled by a smart contract. NFTs have received huge interest due to their transparency in transaction details, public verifiability and trustless transfer [32]. Unlike conventional systems, public verifiability and transfer of ownership can be tracked continuously [3, 27, 31, 33]. Despite the fact that the complete capabilities of NFTs have not yet been fully realized, they are already being utilized in various business models, including decentralized gaming [18] or e-commerce [7].

NFTs cannot be traded or exchanged in the same way as fungible tokens. Their size can be dynamically large and they cannot be replicated due to its non-fungibility. In Ethereum, the ERC-721 standard [16] defines a minimal interface to exchange NFTs. It specifies ownership details, security, and metadata. The ERC-1155 standard [29] builds on top improving several aspects, such as reducing transaction and storage costs by up to 90%, and batching multiple types of NFTs into a single contract. On a separate note, platforms that incorporate off-chain infrastructure enable the listing of tokens, the creation of new tokens (minting), the connection of sellers with buyers, and on-chain settlement of the exchange. NFT marketplaces (NFTM) like OpenSea, Rarible, SuperRare, Foundation, or Nifty, fill this gap and sit between the end users and the blockchain.

NFT Security. Token authenticity is the main concern with NFTs. After all, digital assets can easily be copied in fraudulent tokens. In all existing solutions, the burden of verifying the authenticity of the purchased token lies on the buyer. However, as blockchain technology evolves, it becomes harder for regular users (without specialized hardware) to access the network and check by themselves the on-chain state. NFTMs facilitate the trades, but they can impose his view of the blockchain, unilaterally remove tokens from their listings, and tend to rely on off-chain centralized databases that can serve arbitrary content [23]. This questions the purported decentralization and transparency of such platforms. In a recent study [15] a large number of potential vulnerabilities related to NFTMs were identified. We highlight some of the identified issues.

  • Buggy token contracts. Code of custom contracts deployed by users are not properly audited. They may not pay the seller after the trade, or do not transfer the ownership at all (non-atomicity).

  • Lack of transparency in trading. For example, Nifty uses escrow accounts and off-chain trades to reduce the transaction fees.

  • Control delegation. The NFTM takes control of the token and funds to execute the trade without interaction between sellers and buyers. If the NFTM is given full control, it introduces a single point of failure in the security of all its users. Nifty, Foundation and SuperRare follow this approach via escrow accounts. OpenSea has a somewhat safer delegation mechanism, requiring authorization from the seller.

  • Royalty evasion. If enforcement of royalties fees is delegated to NFTMs, buyers can avoid paying the fee by trading in plattforms that do not set royalties. Also, on-chain standards like ERC-721 do not capture royalties neither. Hence, payments can be settled off-chain, and transfer ownership on-chain (assuming the parties are willing to conduct non-atomic exchanges).

  • Wash trading. Sales volume is artificially inflated to create an illusion of demand or to inflate financial metrics of their interests. For example, in Rarible, the more a user spends, the more $RARI tokens it receives. It is suspected that high-value NFTs such as CryptoKitties are example of wash trading.

Related Work. The authors in [28] proposed a solution called zero-knowledge Address Abstraction (zkAA) to eliminate the need for mapping and enables the direct use of web2 identity in the blockchain. In this way, users can utilize their web2 identities on blockchain through smart contracts leveraging zero-knowledge proofs without disclosing their identity.

In [20], the authors presented an auction protocol for NFTs with supports in multi-chain platforms. The design uses hash time lock transactions and additional strategies to control users malicious behaviour. However, without supporting trustless bridges the multichain platform (i.e., the cross-chain asset exchange process) could be secured. The authors in [12] presented a multi-stage NFT transaction protocol, called LiftChain, which builds a NFT transaction protocol performing a batch of NFT transactions off-chain and then propagates them on-chain. Although it aims to optimize the cost, the existing interfaces as a whole are still very expensive and not scalable.

More related to our work, Ordinal Inscriptions [17, 26] is a numbering system that allows individual satoshis (the smallest Bitcoin denomination), referred to as sequence numbers, to be tracked and transferred in ownership. In short, Ordinals can be considered digital assets inscribed in satoshis. More concretely, satoshis are numbered in the order they are mined and transferred based on the first-in, first-out principle of transaction inputs and outputs. Proofs can be created to show that a specific satoshi is indeed present in a specific output. However, these proofs are large, consisting of the block headers and the Merkle path to the coinbase transaction that creates the satoshi, and every transaction that spends the satoshi. Note that the proof size is linear in the number of total current spends, and it increases with each spend. Unlike NFTs that can be purchased through platforms like OpenSea and Nifty Gateway, there are currently no marketplaces or wallets dedicated to Ordinals. They can be traded through Telegram and Discord channels, and the order book is currently maintained as a Google sheet.

Our Contributions and Techniques. Researchers generally refrained from creating and sending NFTs over the BTC network due to its expensive transaction fees and purported lack of programmability. In this paper, we fill this gap by explaining how to achieve fair exchanges without control delegation on Bitcoin-like blockchains with few transaction fees. More specifically, our main contributions are as follows.

  • We design, implement, and benchmark, a proof system to prove and verify that an issuance transaction \(\textsf{tx}_0\) (with an embedded representation of the token), and the current trade transaction \(\textsf{tx}_n\) are linked through a unique transaction chain. Our proof system is a recursive SNARK [2, 5, 10, 11, 14, 22]. This means that if an additional transaction \(\textsf{tx}_{n+1}\) is added to the chain, then the proof \(\pi _{n}\) can be updated into \(\pi _{n+1}\) incrementally, without requiring all previous transactions. The proof receipt \(\pi _n\) functions as an ‘off-chain receipt’ handed by the current owner to the new owner of the token. Since we use SNARKs, the size of \(\pi _n\) is constant or just logarithmic in the number n of total current trades.

  • We present a new scheme \(\textsf{NFT}=(\textsf{mint},\textsf{list},\textsf{sell},\textsf{buy})\) to trade NFTs on Bitcoin-like blockchains in the presence of untrusted marketplaces. A trade is settled in just one transaction \(\textsf{tx}_n\) and hence it is atomic: the payment and the ownership transfer cannot be decoupled. We guarantee token authenticity leveraging the off-chain proof receipt \(\pi _{n}\) to dispense access to the blockchain or the need of trusted intermediaries. To provide fairness for sellers and buyers without delegating control of tokens or funds to intermediaries, we employ appropriate combinations of \(\texttt {sighash}\) flags when signing (unlocking) inputs of \(\textsf{tx}_n\).

In our \(\textsf{NFT}\) scheme, all trades appear on-chain, therefore it is transparent by design. As mentioned, the trade is settled by publishing a single transaction on-chain, as opposed to deploying complex smart contracts. The off-chain mechanism for token authenticity is also very flexible and can be enhanced in a number of ways. For example, the issuer can enforce royalty fees, or wash trading can be mitigated. Last, it is worth mentioning that although we describe our NFT scheme for Bitcoin, our techniques are fundamentally independent of the underlying blockchain technology. This does not come as a surprise as the main bulk of work happens off-chain, as we shall see. For example, it could be adapted to Ethereum’s smart contract logic.

Paper Organisation. Section 2 gives some background needed. Section 3 introduces transaction chains and discuss their properties. Section 4 explains how to prove existence of transaction chains in Bitcoin using SNARKs. Finally, Sect. 5 presents our non-fungible token scheme \(\textsf{NFT}\) and analyses its security.

2 Preliminaries

2.1 Bitcoin Transactions

A transaction \(\textsf{tx}\) in the Bitcoin network has a unique identifier \(\textsf{txid}\) which is defined as the double \(\textsf{SHA256}\) of the serialized transaction data. The \(\textsf{txid}\) is not part of the transaction itself. A transaction input \(\mathsf {tx.in}\) contains several fields. Including a reference to previous transaction ID \(\textsf{prevtxid}\), an output index \(\textsf{vout}\), (this pair is known as the outpoint), and the unlocking script \(\texttt {scriptSig}\). A transaction output \(\mathsf {tx.out}\) contains the index \(\textsf{vout}\) of the output, a locking script \(\texttt {scriptPubKey}\), and the amount of satoshis \(\textsf{value}\) locked.

Embedding Data in Transactions. Data can be inserted into transactions at several positions. Data payloads do not play a role in script validation as they can be embedded between \(\texttt {OP}\_\texttt {PUSH}\) and \(\texttt {OP}\_\texttt {DROP}\) codes or positioned often an \(\texttt {OP}\_\texttt {RETURN}\) opcode. For example, it is possible to have a pay-to-public-key script \(\texttt {P2PK}\) with embedded data. During the transaction validation, the unlocking script of the spending transaction \(\textsf{tx}\), and the locking script of the parent transaction \(\textsf{prevtx}\) are combined:

$$\begin{aligned} \langle \texttt {scriptSig}\rangle \ ||\ \texttt {scriptPubKey}:= \langle \sigma \ \texttt {sighash}\rangle \ ||\ [\texttt {P2PK}\ \textsf{pk}]\ \texttt {OP}\_\texttt {RETURN}\ \langle \textsf{data} \rangle \ \end{aligned}$$
(1)

The unlocking script contains the signature \(\sigma \), and the locking script is the \(\texttt {P2PK}\) script (with public key \(\textsf{pk}\)) and the embedded data. Note that we are not writing out explicitly the set of opcodes comprising \([\texttt {P2PK}\ \textsf{pk}]\). The script is evaluated in reverse polish notation in the stack of the Bitcoin engine starting by pushing the data of \(\texttt {scriptSig}\) to the stack. Once the \(\texttt {P2PK}\) script has been executed successfully, which includes the signature check, the script becomes \( \texttt {OP}\_\texttt {RETURN}\ \langle \textsf{data}\rangle \) The script execution terminates when opcode \(\texttt {OP}\_\texttt {RETURN}\) is reached. Hence the appended \(\textsf{data}\) is never pushed to the stack, but stored in the Bitcoin network as part of \(\textsf{tx}\).

Choosing Which Inputs and Outputs are Signed. The result of the \(\texttt {P2PK}\) script evaluation above is either \(\textsf{true}\) or \(\textsf{false}\). It depends on the signature check, which involves verifying the signature \(\sigma \) using public key \(\textsf{pk}\). The message that is verified against \(\sigma \) is essentially a portion of the spending transaction \(\textsf{tx}\). The parts of \(\textsf{tx}\) that are signed is controlled with the flag \(\texttt {sighash}\). For example, if set to \(\texttt {sighash}\_\texttt {all}||\texttt {anyonecanpay}\) in the unlocking script of the i-th input \(\textsf{tx}\mathsf {.in}_{i}\), the signature verification discards all other inputs but uses all outputs of \(\textsf{tx}\). This allows different parties to add inputs to partially signed Bitcoin transactions (PSBT) while fixing the outputs (destination addresses). We will make use of different \(\texttt {sighash}\) flags in our NFT scheme of Sect. 5. See Table 1 for all possible flag values.

Table 1. Values of \(\texttt {sighash}\) flag in Bitcoin. Taken from [6].

2.2 Recursive SNARKs – Proof Carrying Data

Proof-carrying data (PCD) [14] allows to prove correct execution of distributed computations run in mutually distrustful nodes. It is a generalization of incrementally verifiable computation (IVC) [30]. It allows to prove that a value \(z_n\) is the result of applying a function F iteratively n times

$$\begin{aligned} z_n = F(z_{n-1}),\ldots ,z_1 = F(z_0) \end{aligned}$$
(2)

In short, \(z_n = F^n(z_0)\). In blockchains, PCDs have already found applications, most notably Mina [25] and others [9, 13, 21].

PCD Scheme and Properties. One can see (2) as the transcript \(\textsf{T}\) of a computation between n nodes where the i-th nodes applies F to its incoming message \(z_{i-1}\) to produce an outgoing message \(z_i\). If this is the case, the whole transcript is said to be compliant with F. Likewise, \(z_n\) is compliant with F, if it is the output of a transcript \(\textsf{T}\) compliant with F. A PCD scheme is a triplet of algorithms \(\textsf{PCD}= (\mathbb {G},\mathbb {P},\mathbb {V})\) with the following interface:

  • \(\mathbb {G}(1^\lambda ,F)\rightarrow (\textsf{pk},\textsf{vk})\). It takes as input a security parameter \(\lambda \), and a function F seen as an arithmetic circuit \(C_F\). It produces a pair of verification and proving keys.

  • \(\mathbb {P}(\textsf{pk},z_n,(z_{n-1},\pi _{n-1}))\rightarrow \pi _n\). It takes as public input the outgoing message \(z_n\), and as private input the incoming message \(z_{n-1}\) and a proof \(\pi _{n-1}\). It outputs a proof \(\pi _n\) for the F-compliance of \(z_n\). Namely, a proof for the existence of messages \(z_0,\ldots ,z_{n-1}\) as in (2).

  • \(\mathbb {V}(\textsf{vk},z_n,\pi _n)\rightarrow \{\textsf{accept},\textsf{reject}\}\). It takes the public input \(z_n\) and a proof \(\pi _n\). It either accepts or rejects the proof for the F-compliance of \(z_n\).

We informally state the properties of a PCD scheme, and refer to [2, 5, 14] for formal definitions. The scheme is complete if \(\mathbb {V}\) always accepts proofs \(\pi _n\) generated by the honest prover \(\mathbb {P}\). It is succinct if the size of \(\pi _n\) is poly(\(\lambda ,|C_F|\)). In particular the proof does not grow at each iteration, it only depends on the complexity of the arithmetic circuit for F. The scheme is knowledge sound if, given access to the random coins of any cheating prover \(\mathbb {P}^*\) that produces a pair \((z_n,\pi _n)\) accepted by the verifier \(\mathbb {V}\), it is possible to extract a compliant transcript \(\textsf{T}\) as in (2) with overwhelming probability in the security parameter \(\lambda \).

Constructing PCDs from SNARKs. PCDs can be constructed in two ways. It was first realized in [2] from preprocessing succinct non-interactive arguments of knowledge (SNARKs) [4] with sublinear verification time (also known as succinct verification) over a cycle of elliptic curves. Given a preprocessing \(\textsf{SNARK}= (\textbf{G},\textbf{P},\textbf{V})\), the statement \(z_n=F^n(z_0)\) is split in two parts. The first part proves existence of \(z_{n-1}\) such that \(z_n = F(z_{n-1})\); this is done by expressing F as an arithmetic circuit \(C_F\), that is satisfied on public input \(z_n\) and private input \(z_{n-1}\) only if \(z_n = F(z_{n-1})\). The second part proves existence of a valid proof \(\pi _{n-1}\) attesting to the correctness of the \(n-1\) previous iterations. This is done expressing the verifier \(\textbf{V}\) as a circuit \(C_{\textbf{V}}\), satisfied on public input \(\textsf{vk}\) and private inputs \(z_{n-1},\pi _{n-1}\), only if \(\textbf{V}(\textsf{vk},z_{n-1},\pi _{n-1}) =\textsf{accept}\), where \(\textsf{vk}\) is the preprocessed verification key generated by \(\textbf{G}\). The PCD prover proves satisfiability of both circuits \(C_F\) and \(C_{\textbf{V}}\) on public input \(z_n\) and private inputs \(z_{n-1},\pi _{n-1}\) using \(\textsf{vk}\) as part of its proving key. Another way of constructing PCDs, initiated in \(\textsf{Halo}\) [10], is using a SNARK without succinct verification, but with an accumulation scheme that allows to accumulate the proofs at each step, and postpone the verification of the proofs. The requirement is that the accumulator must be succinctly verifiable [8, 10, 11]. Recently, PCDs have been constructed from folding schemes, without using SNARKs at all, in \(\textsf{Nova}\) [22].

3 Transaction Chains

In this section, we introduce our notion of transaction chains. In the next section, we show how to prove the existence of a chain succinctly. The inputs and outputs of a Bitcoin transaction form ordered sets. We write \(\textsf{tx}\mathsf {.in}_{s}\) and \(\textsf{tx}\mathsf {.out}_{r}\) to respectively denote the s-th input and r-th output.

Definition 1

(Transaction Chain). Let \(\textsf{T}\) be a set of transactions. The sequence \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}:=(\textsf{tx}_0,\textsf{tx}_1,\ldots ,\textsf{tx}_{n-1},\textsf{tx}_n)\) with \(\textsf{tx}_i\in \textsf{T}\), is a transaction chain of length n if for each \(1\le i\le n\) some of the inputs of \(\textsf{tx}_i\) references an output of \(\textsf{tx}_{i-1}\).

As mentioned in Sect. 2.1, in Bitcoin, a transaction \(\textsf{tx}_i\) references a parent transaction \(\textsf{tx}_{i-1}\) in its inputs using the identifier \(\textsf{txid}_{i-1}\). We can rely on the collision resistance of the hash function to ensure distinct identifiers for all Bitcoin transactions. This ensures that any chain \(\mathbf {\textsf{c}}_{\textsf{tx}_1\rightarrow \textsf{tx}_n}\) has no repeated transactions. Also, note that transaction chain is a transitive relation, therefore we can concatenate two chains \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\), \(\mathbf {\textsf{c}}_{\textsf{tx}_n\rightarrow \textsf{tx}_m}\) to obtain a longer transaction chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_m}\) (i.e., by removing the first transaction of the second chain \(\mathbf {\textsf{c}}_{\textsf{tx}_n\rightarrow \textsf{tx}_m}\)).

We note that there could be more than one chain linking two transactions. For example, consider the set \(\textsf{T}= \{\textsf{tx}_0,\textsf{tx}_1,\textsf{tx}_2,\textsf{tx}_3\}\), where \(\textsf{tx}_0\) has two outputs, the first output is spent by \(\textsf{tx}_1\), and the second output by \(\textsf{tx}_2\). If \(\textsf{tx}_3\) spends both \(\textsf{tx}_1\) and \(\textsf{tx}_2\), then we have two chains \(\mathbf {\textsf{c}}_1 =(\textsf{tx}_0,\textsf{tx}_1,\textsf{tx}_3)\), and \(\mathbf {\textsf{c}}_2 = (\textsf{tx}_0,\textsf{tx}_2,\textsf{tx}_3)\) linking \(\textsf{tx}_0\) with \(\textsf{tx}_3\).

We are also interested in chains that are unique. That is, given two transactions there exists only one possible way to link them. We address this issue fixing the inputs and outputs through which the link is established.

Definition 2

((rs)-Primary Chain). Let a set of transactions \(\textsf{T}\) and a sequence \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}=(\textsf{tx}_0,\ldots ,\textsf{tx}_n)\) with \(\textsf{tx}_i\in \textsf{T}\). We say \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\) is a (r, s)-primary chain if it is a transaction chain and the input r-th input of \(\textsf{tx}_i\) references the s-th output of \(\textsf{tx}_{i-1}\).

Fig. 1.
figure 1

A (1, 2)-primary chain. The first input of \(\textsf{tx}_i\) spends the second output of \(\textsf{tx}_{i-1}\).

In the lemma below we characterize the set of all possible (rs)-primary chains starting at \(\textsf{tx}_0\). Namely, there can only be chains that are subsequences of the largest chain in the set \(\textsf{C}_{\textsf{tx}_0\rightarrow }^{(\textsf{T}_{\mathcal {B}})}\), where:

(3)

Lemma 1

(Non-Diverging Primary Chains). Let \(\textsf{T}_{\mathcal {B}}\) be the set of all transactions in the Bitcoin network. Let any transaction \(\textsf{tx}_0\) in \(\textsf{T}_{\mathcal {B}}\), and let \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}^{\ max}\) be an (rs)-primary chain of maximal length. Then, the set \(\textsf{C}_{\textsf{tx}_0\rightarrow }^{(\textsf{T}_{\mathcal {B}})}\) of all (rs)-primary transactions starting at \(\textsf{tx}_0\) are subsequences of \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}^{\ max}\). That is:

$$\begin{aligned} \textsf{C}_{\textsf{tx}_0\rightarrow }^{(\textsf{T}_{\mathcal {B}})}=\{(\textsf{tx}_0,\ldots ,\textsf{tx}_i)\ |\ \textsf{tx}_i\in \mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}^{\ max}\} \end{aligned}$$

Proof

This is a direct consequence of the double-spending resistance property of a blockchain. First observe that \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}^{\ max}\) is of maximal length, so it cannot be a subsequence of any other primary chain. Now, if there exists an (rs)-primary chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_m}\) that is not a proper subsequence of \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}^{\ max}\), then, since both chains share the same origin \(\textsf{tx}_0\), at some point they must diverge. Say they are equal up to the i-th transaction \(\textsf{tx}_i\). This means that the s-th output \(\textsf{tx}_i\) has been spent twice, which is not possible.    \(\square \)

The lemma above also proves that there is only one primary chain of maximal length. Not surprisingly, the largest (rs)-primary chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\) in Bitcoin is that whose end transaction \(\textsf{tx}_n\) has the s-th output unspent.

Lemma 2

(Largest Primary Chain). Let \(\textsf{T}_{\mathcal {B}}\) be the set of all transactions in the Bitcoin network. Let any \(\textsf{tx}_0\) in \(\textsf{T}_{\mathcal {B}}\), and let \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\) be an (rs)-primary chain such that the s-th output of \(\textsf{tx}_n\) is unspent. Then, \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\) is the largest (rs)-primary chain starting at \(\textsf{tx}_0\).

Proof

Lemma 1 shows that all (rs)-primary chains must be subsequences of the largest (rs)-primary chain. Now, \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\) cannot be a subsequence of any other primary chain because the s-th output of \(\textsf{tx}_n\) is unspent. We conclude that \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\) is the largest chain starting at \(\textsf{tx}_0\).   \(\square \)

4 Succinct Proofs for Transaction Chains

Consider the following scenario with a prover Alice and a verifier Bob. The first transaction \(\textsf{tx}_0\) is already in the blockchain \(\mathcal {B}\) and is known to both Alice and Bob. Alice submits a transaction \(\textsf{tx}_n\) to \(\mathcal {B}\) and also sends it to Bob. Both parties now have two transactions \((\textsf{tx}_0,\textsf{tx}_n)\). Alice wants to prove to Bob the statement:

$$\begin{aligned} ``\textsf{tx}_n \text { is linked to } \textsf{tx}_0 \text { through a primary chain } \mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}" \end{aligned}$$
(4)

Alice generates a proof \(\pi _n\) that attest to the veracity of her statement. If Bob accepts \(\pi _n\) as valid, he has the triplet \((\textsf{tx}_0,\textsf{tx}_n,\pi _n)\). Now consider a third actor Charlie. Bob creates a new transaction \(\textsf{tx}_{n+1}\) such that \((\textsf{tx}_n,\textsf{tx}_{n+1})\) is a primary chain. He amends Alice’s proof \(\pi _n\) to create a new proof \(\pi _{n+1}\) to also show that \(\textsf{tx}_{n+1}\) is linked to \(\textsf{tx}_0\) through a primary transaction chain. He sends \((\textsf{tx}_{n+1},\pi _{n+1})\) to Charlie. The information flow can be visualised in Fig. 2. The point we are trying to make is that proof generation is incremental; new parties can come in, augment an existing chain in \(\mathcal {B}\), and prove correctness of the augmentation based on older proofs.

Fig. 2.
figure 2

Incremental chain augmentation. \(\textsf{tx}_0\) is known to all parties. \(\pi _i\) proves existence of chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_i}\).

Trivial Solution: Send the Primary Transaction Chain. Alice simply sends the entire chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}=(\textsf{tx}_0,\ldots ,\textsf{tx}_n)\) as her proof \(\pi _n\). Bob can explicitly check that \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\) is a primary chain appearing in the blockchain \(\mathcal {B}\). This solution requires communication and verification cost linear in the size of the chain \(\mathcal {O}(n)\). It also incurs in repetition cost: Charlie has to check the entire chain again, even though Bob checked it already up to the n-th link.

Efficient Solution: Use SNARKs. Alice sends to Bob the last transaction \(\textsf{tx}_n\), and a short SNARK proof \(\pi _n\) attesting to the existence of \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\). Bob verifies \(\pi _{n}\) and checks that \(\textsf{tx}_n\) is in \(\mathcal {B}\). The size of the transmitted proof is now \(|\pi _{n}|=\mathcal {O}(\log (n))\), a significant improvement compared with the trivial solution above. See Table 2 for a comparison summary.

Table 2. Comparison of solutions to check primary chains \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\).

4.1 Proving Existence of Primary Chains Recursively

Recall from Sect. 3 that for a set of transactions \(\textsf{T}_{\mathcal {B}}\) in blockchain \(\mathcal {B}\), and \(\textsf{tx}_0\in \textsf{T}_\mathcal {B}\), the set \(\textsf{C}_{\textsf{tx}_0\rightarrow }^{(\textsf{T}_{\mathcal {B}})}\) denotes all the (rs)-primary chains starting at \(\textsf{tx}_0\). Thus, we can formalize the informal statement (4) in the following NP relation:

(5)

In principle the prover needs the entire chain \(\mathbf {\textsf{c}}\) linking \(\textsf{tx}_n\) to \(\textsf{tx}_0\) as private information to prove statement (4). He would somehow need to get the chain \(\mathbf {\textsf{c}}\) either from the previous prover or from \(\mathcal {B}\). This poses a problem because the chain may be large and we would like to avoid sending it between parties. The observation is that provided the chain from \(\textsf{tx}_0\) up to the parent \(\textsf{tx}_{n-1}\) is a primary chain, we just need to ensure the last link holds. We ensure the chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_{n-1}}\) is a primary chain validating a proof \(\pi _{n-1}\) for the parent transaction \(\textsf{tx}_{n-1}\) using a recursive SNARK.

Description of the Circuit. The recursive circuit \(\textsf{C}_{\textsf{ptc}}\) for primary transaction chains is described in Fig. 3. Note that the circuit has hard-coded in its description the transaction identifier \(\textsf{txid}_0\) of the first transaction \(\textsf{tx}_0\) of the chain. Also, as described, the circuit uses a \(\textsf{SNARK}\) with succinct verification.

Fig. 3.
figure 3

Circuit to prove existence of a (rs)-primary chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\).

The Recursive SNARK (PCD) for Primary Transaction Chains. Having described the circuit \(\textsf{C}_{\textsf{ptc}}\), the preprocessing PCD to prove satisfiability of \(\textsf{C}_{\textsf{ptc}}\) is the triplet of algorithms \(\mathsf {PCD_{\textsf{ptc}}}=(\mathbb {G}_{\textsf{ptc}},\mathbb {P}_\textsf{ptc},\mathbb {V}_\textsf{ptc})\) with the following interface.

  • \(\mathbb {G}_{\textsf{ptc}}(1^\lambda ,\textsf{txid}_0)\rightarrow (\textsf{pk},\textsf{vk})\). On input a security parameter \(\lambda \) and the identifier of the first transaction \(\textsf{txid}_0\) it outputs a pair of proving and verification keys \(\textsf{pk}\), \(\textsf{vk}\).

  • \(\mathbb {P}_\textsf{ptc}(\textsf{pk},(\textsf{tx}_n,b_\textsf{case});(\textsf{tx}_{n-1},\pi _{n-1}))\rightarrow \pi _n\). On input a proving key, the public input \((\textsf{tx}_n,b_\textsf{case})\), and the private input \((\textsf{tx}_{n-1},\pi _{n-1})\) it generates a proof \(\pi _n\) attesting to the existence of a chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\). Thus \((\textsf{tx}_n,\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n})\in \mathcal {R}_{\textsf{T}_{\mathcal {B}},\textsf{tx}_0}\).

  • \(\mathbb {V}_\textsf{ptc}(\textsf{vk},(\textsf{tx}_n,b_\textsf{case}),\pi _{n})\rightarrow \{\textsf{accept},\textsf{reject}\}\). On input a verification key \(\textsf{vk}\) and the public input \((\textsf{tx}_n,b_\textsf{case})\) it either accepts or rejects.

We emphasize that \(\textsf{txid}_0\) needs to be known in advance to use it in step (3) of \(\textsf{C}_{\textsf{ptc}}\). The later means that \(\mathsf {PCD_{\textsf{ptc}}}\) can be used only for the chain that starts at \(\textsf{tx}_0\).

Theorem 1

Let \(\textsf{T}_{\mathcal {B}}\) be the set of transactions in the Bitcoin network. If the verifier \(\mathbb {V}_\textsf{ptc}\) accepts a proof \(\pi _n\) for \(\textsf{tx}_n\in \textsf{T}_{\mathcal {B}}\), then there exists a chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\) in \(\textsf{T}_{\mathcal {B}}\) with overwhelming probability.

Proof

Using the soundness of \(\mathsf {PCD_{\textsf{ptc}}}\), it is enough to show that if the circuit \(\textsf{C}_{\textsf{ptc}}\) accepts \(\textsf{tx}_n\) then it exists a chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\) with overwhelming probability. We will use the following claim that holds true in Bitcoin.

Claim

All coinbase transactions in the Bitcoin network have one unique outpoint whose parent ID reference is the zero-byte array.

The proof of the theorem is concluded proving the following lemma.

Lemma 3

Let \(\textsf{T}_{\mathcal {B}}\) be the set of Bitcoin transactions at a given time. If \(\textsf{tx}_0\in \textsf{T}_{\mathcal {B}}\) is not an ancestor of \(\textsf{tx}_n\in \textsf{T}_{\mathcal {B}}\), then \(\textsf{C}_{\textsf{ptc}}\) rejects on public input \(\textsf{tx}_n\). Thus, \(\forall \textsf{tx}_{n-1},\pi ,b_\textsf{base}\) it holds \(\textsf{false} = \textsf{C}_{\textsf{ptc}}((\textsf{tx}_n,b_\textsf{base}),(\textsf{tx}_{n-1},\pi _{n-1}))\) with overwhelming probability.

Proof

All transactions in Bitcoin originate from a coinbase transaction. Let \(\mathbf {\textsf{c}}= (\textsf{tx}_{\textsf{cb}},\textsf{tx}_1\ldots ,\textsf{tx}_n)\) be an (rs)-primary chain connecting a coinbase transaction \(\textsf{tx}_{\textsf{cb}}\) with \(\textsf{tx}_n\). Now, assume by contradiction that \(\textsf{C}_{\textsf{ptc}}\) accepts \(\textsf{tx}_n\). By hypothesis \(\textsf{tx}_0\) is not an ancestor of \(\textsf{tx}_n\), and we assume all transactions in \(\textsf{T}_{\mathcal {B}}\) have different identifiers. Therefore the base case of \(\textsf{C}_{\textsf{ptc}}\) is not triggered, and there must be a valid proof \(\pi _{n-1}\) for the parent \(\textsf{tx}_{n-1}\). Repeating this argument backwards, there must exist a valid proof \(\pi _{\textsf{cb}-1}\) for the parent of the coinbase transaction \(\textsf{tx}_{\textsf{cb}}\). In other words, the prover used a ‘parent’ transaction \(\textsf{tx}_{\textsf{cb}-1}\) for \(\textsf{tx}_{\textsf{cb}}\) whose identifier is the zero-byte array—see the claim above. The later cannot occur in practice due to the collision resistance of \(\textsf{SHA256}\). This concludes the proof of the lemma and the theorem.    \(\square \)

4.2 Implementation Details and Benchmarks

Circuit Logic. We have implemented several circuit gadgets to construct \(\textsf{C}_{\textsf{ptc}}\) from Fig. 3. For simplicity we set \(r=s=0\).

  • \(\mathsf {first\_outpoint\_OK}(\textsf{tx},\textsf{txid})\). Evaluates to true iff \(\textsf{tx}\mathsf {.in}_{0}=\textsf{txid}||0\)

  • \(\mathsf {\textsf{txid}\_OK}(\textsf{tx},\textsf{txid})\). Evaluates to true iff \(\textsf{txid}=\textsf{SHA256d}(\textsf{tx})\)

  • \(\mathsf {proof\_OK}(\textsf{tx},\pi )\). Evaluates to true iff \(\textbf{V}(\textsf{vk},(\textsf{tx},\textsf{false}),\pi ) = \textsf{accept}\). Here recall from Sect. 2.2 that \(\textbf{V}\) is the verification logic of the underlying \(\textsf{SNARK}\) used in the construction of the PCD, and \(\textsf{vk}\) the verification key.

Using the above gadgets, we can construct the following circuits for the base case and recursive case, respectively:

$$\begin{aligned}&\mathsf {parent\_is\_txid_0}(\textsf{tx}_n):=\mathsf {first\_outpoint\_OK}(\textsf{tx}_n,\textsf{txid}_0)\\&\mathsf {primary\_chain\_OK}(\textsf{tx}_n,\textsf{tx}_{n-1},\pi _{n-1}) :=\\&\quad \quad \mathsf {\textsf{txid}\_OK}(\textsf{tx}_{n-1},\textsf{txid}_{n-1})\wedge \mathsf {first\_outpoint\_OK}(\textsf{tx}_n,\textsf{txid}_{n-1})\wedge \mathsf {proof\_OK}(\textsf{tx}_{n-1},\pi _{n-1}) \end{aligned}$$

The circuit \(\textsf{C}_{\textsf{ptc}}\) is then set to:

$$\begin{aligned}&\textsf{C}_{\textsf{ptc}}((\textsf{tx},b_\textsf{base});(\textsf{tx}_{n-1},\pi _{n-1})):=\\&\quad \quad (b_\textsf{base}=\textsf{true}\wedge \mathsf {parent\_is\_txid_0}(\textsf{tx}_n))\\&\quad \quad \vee \\&\quad \quad (b_\textsf{base}=\textsf{false}\wedge \mathsf {primary\_chain\_OK}(\textsf{tx}_n,\textsf{tx}_{n-1},\pi _{n-1})) \end{aligned}$$

PCD Scheme. We have implemented the SNARK scheme \(\mathsf {PCD_{\textsf{ptc}}}\) defined in the previous section following the approach of [2]. Namely, using cycles of elliptic curves to implement the verification logic as part of the circuit in step (4b) of \(\textsf{C}_{\textsf{ptc}}\). The underlying \(\textsf{SNARK}\) is Groth16 [19]. Our implementation is written in Rust and uses arkworks library [1]. The cycle of curves is MNT4-MNT6. These are MNT curves [24] of embedding degrees 4 and 6, respectively. For production code, the size of the fields should be large, i.e. of size \(\approx 750\) bits.

In Table 3 we report benchmarks for the time it takes to prove and verify a proof. The tests have run in a laptop, 2019 MacBook Pro 2.6 GHz 6 Cores i7, 12 Threads, 32 GB Memory, and in an embedded processor (SoC) Raspberry Pi ARM BCM2835 1.80 GHz 1 Processor, 4 Cores, 4 Threads, 3.71 GB Memory. The most expensive gadgets are \(\mathsf {\textsf{txid}\_OK}\) and \(\mathsf {proof\_OK}\). The former needs to generate constraints for two evaluations of the hash function \(\textsf{SHA256}\), which is not zero-knowledge friendly. The later contains the logic of the Groth16 verifier \(\textbf{V}\). We have fixed the transaction size to 226 bytes – the minimum size of a Bitcoin transaction. This means the compression function of \(\textsf{SHA256}\) is applied twice to generate \(\textsf{txid}\) from \(\textsf{tx}\).

Table 3. Times for proving and verifying satisfiability of circuit \(\textsf{C}_{\textsf{ptc}}\) recursing Groth16 over MNT-753 cycle.

5 An Application: NFTs with Atomic and Fully-Fair Swaps

We define a non-fungible token scheme (NFT) as a tuple of algorithms \(\textsf{NFT}=(\textsf{mint},\textsf{list},\textsf{sell},\textsf{buy})\). In our scheme, minting a token \(\textsf{tk}\) essentially embeds \(\textsf{tk}\) in a transaction \(\textsf{tx}_0\). A user with public key \(\textsf{pk}_U\) is the owner of \(\textsf{tk}\), if there exist a (rs)-primary transaction chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_n}\), with the s-th output of \(\textsf{tx}_n\) unspent and controlled by \(\textsf{pk}_U\). Owners can \(\textsf{list}\) their tokens for trading, and listed tokens can be exchanged placing \(\textsf{sell}\) or \(\textsf{buy}\) trade orders.

5.1 Description of the Scheme

Mint Tokens. The issuer embeds the digital token \(\textsf{tk}\) in an issuance transaction \(\textsf{tx}_0\). He then creates the SNARK proving key and verification key, and generates the mint transaction \(\textsf{tx}_1\) as the first link of an (rs)-primary chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_1}\) along with a proof \(\pi _1\). Both transactions \(\textsf{tx}_0\),\(\textsf{tx}_1\) are uploaded to the blockchain and the mint process is finished. See Fig. 4 for the algorithm \(\textsf{mint}\).

Note that only the issuer can unlock the s-th output of \(\textsf{tx}_0\) using his secret signing key \(\textsf{sk}_I\). Hence, the issuer owns freshly minted tokens.

Fig. 4.
figure 4

Minting tokens in Bitcoin.

List Tokens (with Off-Chain Receipts). Before a token \(\textsf{tk}\) can be traded, the keys \(\textsf{pk}\), \(\textsf{vk}\), and the first proof \(\pi _1\) generated by the issuer are publicly announced. This can be done via embedding the keys in the mint transaction \(\textsf{tx}_1\). Additionally, the data can stored off-chain such as a list maintained by a marketplace. We emphasize that the keys and the mint transaction \(\textsf{tx}_1\) can be also published by the issuer. Ultimately, the issuer is responsible for authenticating this data, not the marketplace.

To mark a token ready for trading, the marketplace receives the transaction \(\textsf{tx}_n\) from the current owner (if \(n=1\), from the issuer), checks it is linked with the previous transaction \(\textsf{tx}_{n-1}\), and if so generates the proof \(\pi _n\) (the off-chain receipt). The algorithm for listing is given in Fig. 5.

Fig. 5.
figure 5

Listing tokens in an marketplace with off-chain receipts.

Transfer Tokens. We explain how to transfer tokens via an (rs)-primary chain with \(r\ne s\). For simplicity we use a (1, 2)-primary chain as in Fig. 1. The trade is a non-interactive process that is fair for both parties, the seller and the buyer. The outcome of the process is a single transaction \(\textsf{tx}_{n+1}\) with two inputs and two outputs. The first output pays the seller, and the second output transfers token ownership to the buyer. If \(\textsf{tx}_{n+1}\) is accepted in the blockchain, the seller gets paid and the buyer is the new owner of the token (via the (1, 2)-primary chain). Otherwise, none of them gets anything.

We detail two flavours of transfers (trading orders). In \(\textsf{sell}\) orders, the seller initiates the trade and sets the offer price \(\textsf{sats}\). In \(\textsf{buy}\) orders, the buyer initiates, and sets the bid price. In either case, the initiator of the trade creates a partially-signed bitcoin transaction (PSBT) \(\textsf{tx}_{n+1}\), and sends it to the other party, who finalizes it filling the remaining inputs and outputs. The inputs of the transaction are unlocked signing with an appropriate combination of \(\texttt {sighash}\) flags for security. The exchanged information flows in one direction (one round), which means the parties do not need to be online at the same time. See Fig. 6 for the algorithms \(\textsf{sell},\textsf{buy}\).

Fig. 6.
figure 6

Selling and buying tokens without control delegation in Bitcoin.

5.2 Fairness for the Buyer and Seller

We deem an NFT scheme correct if there cannot be multiple legitimate owners of the same token \(\textsf{tk}\) at a given time. We say the exchange is fair if, provided a \(\textsf{sell}\) or \(\textsf{buy}\) trade transaction \(\textsf{tx}_{n+1}\) is accepted in the blockchain, then the buyer is the new owner of the token \(\textsf{tk}\), and the seller is rewarded in \(\textsf{sats}\).

Correctness. The correctness of our scheme \(\textsf{NFT}=(\textsf{mint},\textsf{list},\textsf{sell},\textsf{buy})\) is due to the non-diverging property of primary chains (cf. lemma 1). Primary chains originating at a given transaction \(\textsf{tx}_0\) can only be subsequences of the largest primary chain. Put differently, there cannot be ‘forked’ chains.

Fairness for the Buyer. This is achieved due to two observations. First, since the buyer successfully verifies the proof \(\pi _{n}\) of the seller, then there exists a primary chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_{n}}\); this follows from the soundness of \(\mathsf {PCD_{\textsf{ptc}}}\) and theorem 1. Therefore, there also exists a (1, 2)-primary chain \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_{n+1}}\) because the buyer explicitly adds the second output of \(\textsf{tx}_{n+1}\) (in both, \(\textsf{sell}\) and \(\textsf{buy}\) orders). Second, at the time \(\textsf{tx}_{n+1}\) is accepted in the blockchain, since its first output is unspent, it is guaranteed that \(\mathbf {\textsf{c}}_{\textsf{tx}_0\rightarrow \textsf{tx}_{n+1}}\) is the largest primary chain (cf. Lemma 2); note the second output of \(\textsf{tx}_{n+1}\) is controlled by the public key \(\textsf{pk}_B\) of the buyer, and the first input is always signed by the buyer when he funds \(\textsf{tx}_n\) (signing with either \(\texttt {sighash}\_\texttt {all}\) or \(\texttt {sighash}\_\texttt {single}\)). If the seller sends the token to someone else in between, the first input of \(\textsf{tx}_{n+1}\) is a double spend, so it will not be accepted in the blockchain. If someone else changes the second output (so the buyer would not acquire ownership), his payment will not go through neither.

Fairness for the Seller. This trivially holds because the seller always locks the payment \(\textsf{sats}\) in the first output of \(\textsf{tx}_{n+1}\), which is always signed (using either \(\texttt {sighash}\_\texttt {single}||\texttt {anyonecanpay}\) in \(\textsf{sell}\) orders, or any other flag that signs the first output in \(\textsf{buy}\) orders); if the buyer does not fund \(\textsf{tx}_{n+1}\) properly, it will never be accepted on-chain, and the seller still owns the token because the second output of \(\textsf{tx}_n\) remains unspent.

5.3 Further Remarks

Identifying Corrupted Users. The seller can prove knowledge of the signing key needed to unlock the first input of the last traded transaction \(\textsf{tx}_{n}\) to the NFTM when he engages in the \(\textsf{list}\) algorithm (e.g., by signing a challenge message). The buyer can also prove the knowledge of the signing keys that unlocks the \(\textsf{sats}\) funding the trade transaction \(\textsf{tx}_{n+1}\) when she initiates a \(\textsf{buy}\) order or finalises a \(\textsf{sell}\) order.

Trade Latency. The main overhead of our \(\textsf{NFT}\) scheme is when listing tokens. Therein, the off-chain proof receipt \(\pi _n\) for the previous transaction trade \(\textsf{tx}_n\) is generated. We report roughly three minutes runtime for the prover \(\mathbb {P}_\textsf{ptc}\) to generate \(\pi _n\) for the previous trade transaction \(\textsf{tx}_n\) (see Table 3). However, since \(\pi _{n}\) is independent of \(\textsf{tx}_{n+1}\), the algorithm \(\textsf{list}\) can be executed well ahead of time. Due to the full fairness of our \(\textsf{NFT}\) scheme, the buyer only needs to check \(\pi _n\) in a \(\textsf{sell}\) or \(\textsf{buy}\) order. This means that from users perspective, the trade is done almost instantaneous, which is the time to verify the proof \(\pi _{n}\) with \(\mathbb {V}_\textsf{ptc}\).

Royalties and Wash Trading. Each transaction in a chain can have a distinguished output with a specific amount locked by a fixed public key \(\textsf{pk}_I\) controlled by the NFT issuer. Similarly, wash trading can be mitigated by putting a cap in the number of trades for which a proof receipt can be generated. Both features can be encoded in the primary chain circuit \(\textsf{C}_{\textsf{ptc}}\) of Fig. 3. If the fee is not paid, or the trade counter reaches the upper bound, users will not be able to generate the off-chain proof receipt.