Speedup Bitcoin stateful contract updates using pre-authorizing signatures

This post was first published on Medium.

State update claim

Bitcoin smart contracts store states in the output of a chain of transactions. State transition occurs when a transaction uses its output to contain the old state and creates an output containing the new state. At any given time, a single exit/UTXO at the head of the transaction chain has the latest state.

A problem arises when multiple transactions compete to update the shared state at the same time. To see why, let’s consider a simple ERC-20-like token smart contract with the following state[1]:

Contract updates
Figure 1: The state of a fungible token contract

The state records how many tokens each user has. Suppose Alice sends a transaction to transfer 5 tokens to Charlie, and updates the state to condition 3Awhile Bob sends another transaction to transfer 10 tokens to Dave at the same time and instead updates it to condition3B. One of the transactions will fail because they duplicate a single UTXO containing state2.

Contract updates
Figure 2: claim

Suppose Bob’s transaction fails. He needs to create a new transaction to use the new UTXO state3A, instead of state2, and try again. It’s not hard to see when there are many users trying to update around the same time, it can take many attempts for one’s update transaction to succeed, causing unpredictable delay and degrading the user experience.

Contract updates
Figure 3

To avoid the claim, a naive approach is to send all update transactions to an intermediate coordinator, called a sequencer, which orders them and broadcasts them to the blockchain.

Contract updates
Figure 4

Unfortunately, this approach does not work because the batch transactions can use a single UTXO, as Alice and Bob’s transactions in Fig. 2 do. When the sequencer rearranges them sequentially in a chain to avoid double use as in fig. 3, the signature in Bob’s original transaction, will condition3B, becomes invalid. If the sequencer has to ask a user to re-sign every time a transaction is re-ordered, there will be unpredictable delay again and we are back to square one.

Pre-approval of signatures

Signatures are used to pre-authorize state updates. We need a way to sign each transaction that won’t be invalidated even if the sequencer re-orders it by changing the input. None of the SIGHASH flags allow it.

Inspired by our previous work to emulate SIGHASH_NOINPUT, which excludes the input being used from the signature, we only sign a message that contains specific details about the action being authorized.

In our symbolic contract, we only sign the recipient and the amount. For example, Alice will sign to authorize the transfer of 5 tokens to Charlie.

ERC20 Contract with pre-authorized signature

Replay attack

Note that tokens can be transferred as long as a valid signature is provided. There is nothing in Alice’s signed message to prevent the same signature from being used repeatedly.

Bob (actually anyone) could reuse the same signature and send himself another 5 tokens from Alice. He can even repeat this many times until Alice’s balance is depleted.

To combat the replay attack, we can use a nonce at the application level. “Nonce” is short for “number used once” in cryptography. We can use a nonce for each signature and store the next nonce in the contract.

ERC20 Contract with not signed

Contract level

If two contracts use the same encoding of messages (eg there is another fungible token contract), a signature used by one contract may also be valid for the other, even with the nonce. We need some identifying information about the contract to prevent this type of replay attack.

We stipulate that no public key/address used in such a condition contract can be reused in other contracts. This is in accordance with the standard practice of generating a new address for each new bitcoin transaction.

Resistant to censorship

If a sequencer censors a user’s transaction, the user can always send it directly to the government contract on the chain.

There can also be multiple sequencers for a given static contract, a user can submit to alternative sequencers if one refuses to process their transaction. These sequencers can be coordinated in an overlay network outside the mining network. Standard scheduling techniques such as round-robin can be used to resolve contention between them when accessing the latest state.

***

[1] A state can be compressed by storing each table entry in a Merkle tree and only storing the root of the tree as the state in the smart contract.

See: The presentation of the BSV Global Blockchain Convention, Smart Contracts and Computation on BSV

width=”562″ height=”315″ frameborder=”0″ allowfullscreen=”allowfullscreen”>

New to Bitcoin? Check out CoinGeeks Bitcoin for beginners section, the ultimate resource guide for learning more about Bitcoin – as originally envisioned by Satoshi Nakamoto – and blockchain.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *