Skip to content

Instantly share code, notes, and snippets.

@phyro
Last active June 7, 2022 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phyro/1046022377fcb1886a1b4f6500f23773 to your computer and use it in GitHub Desktop.
Save phyro/1046022377fcb1886a1b4f6500f23773 to your computer and use it in GitHub Desktop.

Contract wall

Suppose party A wants to share some data with party B. We want to do that in a way to prevent spam without giving much information about the data. The main idea is to have a centralized service which produces blind signatures for outputs in the utxo set. These signatures are used to store data on the service (e.g. partially completed contracts). This makes sure that the service can't reliably link the output with a contract while also preventing spam attacks.

Suppose we have a central service S that provides three endpoints:

  1. /claim - claims storage coupons for an output that is in the UTXO set. Returns 2 blind signatures
  2. /store - receives an unused unblinded signature and stores data with a certain ttl (e.g. 3 days)
  3. /list - lists all the public data

Claim

Claim is an operation that receives an output from the UTXO set with ComSignature and, if it has not produced blind signatures for that output commitment yet, it returns two blind signatures (similar like it's done in Chaumian ecash). The service keeps track of the commitments(utxos) it produced the blind signatures for. Let's call these blind signatures s1 and s2.

Store

Store is an operation that receives a single unblinded signature and, if that signature has not been used yet, the service stores the data and adds the signature to the list of used signatures. Stored data is expired after 3 days.

List

This operation returns a list of all current public data.

Usage

Suppose Alice has an output O1 on the chain. She calls claim for O1 to obtain two blind signatures (s1, s2) from the service. She now wants to send some coins to Bob and prepares the encrypted slate for Bob. She calls store with s1 to store the signature on the service. Since Bob needs to store the signed contract, she encrypts the remaining blind signature s2 for Bob so he's able to use it to store the signed contract. Note that after Bob calls store we have two contracts (step1 and step2) which are just two separate store calls.

The communication with the service would need to be done through some anonymous channel to avoid learning the IPs.

Noise creation

Since we're using payjoin and sometimes contributing multiple inputs in a transaction, we could be sending encrypted dummy data to the service just to produce noise in the list of contracts.

Properties

  1. The service can't provably link a contract to an output on the chain, it can only do heuristic based on timing correlations. In theory, the contract could be done by any output that redeemed the blind signatures.
  2. A spam attacker could store 2 contracts per on-chain output. This makes it free for the normal users to store, but if someone wanted to perform a spam attack with N contracts, they'd need to have claimed N/2 outputs which means they'd have to pay onchain fees for these. Even if the attacker had money to do that, this means the attacker must be paying fees on the chain for these outputs (or has done so in the past), so they're providing security to the network. We won't complain.

Open questions

When the receiver starts the contract, they may not have a blind signature available. What to do here?

Not sure yet. Perhaps the sender could share the blind signature with the receiver if the receiver didn't have any on-chain output.

The list of spent signature grows forever. Can we improve this?

To solve the ever growing nullifier set, we simply add another endpoint that communicates the current public key for service S. The service also communicates the next public key the service will use. By swapping the keys, the service can forget old blind signatures.

Should we give some more blind signatures in case they have to redo the dance?

The service could return 4 blind signatures to account for re-spend transactions.

Could we make contracts indistinguishable?

Yes. One way would be to do what is described here. Note that the dummy field doesn't need to be a part of the slatepack. We could in this case simply provide a layer that adds this dummy data and encrypt that. The data is encrypted so we can augment the structure all we want.

@VzxPLnHqr
Copy link

Got it. Thanks. I had forgotten that Grin does not expose amounts. That makes sense. In any event, this sort of a "service" seems like something which could be offered by a nostr relay which make itself available over various networks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment