BrightID node APIs: "blind sigs" vs. "soulbound"

A Vision for BrightID Node APIs

I want to share my vision for BrightID node APIs now that we have API v6 (blind signatures) available.

Based on the conversations happening around “Soulbound” NFTs, starting with Vitalik and then continuing with a post by @Triplespeeder and another by @Misterplus , it seems clear that BrightID API v5 can be used to create a very good implementation of a Soulbound NFT.

For this reason, I would like to maintain a form of API v5 available indefinitely as “BrightID-Soulbound.” The BrightID node API with blind signatures can just be called “BrightID” for simplicity. Both APIs can be available on nodes that choose to install them, and they can start to use their own versioning numbers.

We should recommend “BrightID” to most applications, especially more centralized or Web2 apps, because it enhances the privacy of users and simplifies our architecture.

“BrightID-Soulbound” is only for decentralized apps using (for now) Ethereum-based chains, where the dapp wants to issue users an NFT badge that is Soulbound–i.e. stays with that user. I’ll explain briefly how BrightID-Soulbound achieves this at the bottom of the article.

What stays, what goes, what’s new

The API V5 sponsorship model is deprecated and should be replaced by the API V6 sponsorship flow for all apps, including Soulbound dapps. Because Soulbound dapps always use smart contracts, sponsoring must be done by emitting a smart contract event.

Contexts and “contextIds” (called “appIds” in API v6) will remain for Soulbound dapps only. The Soulbound functionality relies on maintaining a history array of previously used contextIds, which API v5 has (but API v6 with blind signatures doesn’t.)

ContextIds in Soulbound dapps are UUIDs, not Ethereum addresses, but they must be included in verifications, signed in a way that can be verified by an Ethereum smart contract.

How Soulbound NFTs work, briefly

  1. A user generates a new UUID (using the dapp’s frontend.)
  2. The user calls the bind function of the NFT’s smart contract to link the UUID to an Ethereum address which they prove they own.[1]
  3. The user shares the UUID with a BrightID node with a typical “link” operation. (They scan a QR code.)
  4. The user gets back a signed verification from a BrightID node containing the history of all the UUIDs they’ve linked in the past in the context of this dapp.
  5. The user submits the signed verification to the NFT’s smart contract.
  6. The smart contract checks UUIDs in the user’s history until it finds one that was previously bound to an NFT and transfers that NFT to the address bound in step 2.

What this allows as @Misterplus discovered is that a BrightID user can always “take back” an NFT to an address they control. This allows users to leverage BrightID (including BrightID’s social recovery) to retain control of an NFT.

[1] The bind function actually accepts the hash of the UUID that will be registered with BrightID nodes. This prevents someone observing the blockchain from griefing the user by linking the UUID before they do.


very good let me follow

1 Like

An update to this is that @Misterplus discovered that a signed message can be used as contextId to remove the need for a bind transaction.

The signed message would include the name of the context and be signed by the private key of an Ethereum address. It must match a predetermined format, for example: Context: {context} . Don't sign this message outside of {app_url} .

We would need to revamp how signed verifications are formatted for /verifications for Soulbound apps. An array of bytes32 would no longer be possible.