All about Farcaster Signers
Most users know "Signers" as "this thing you have to pay for when you connect a new app". One of the first articles in Purple Sumbarine, was about Farcaster Signers, but my understanding has evolved since then, and we also have new tools and advances since then.
In order to understand signers, you have to keep in mind that all interactions with hubs take place by sending hubs a "message" that has a specific structure. So, when you cast, like, or recast, the app you are using sends a message to a hub saying "@vrypan.eth casted Hello World", or "@vrypan.eth liked this cast".
Messages look something like this under the hood:
As you can see such messages have two parts.
-
The data part: this is more or less what we usually consider the content, like the text of the cast, the date it was casted, the user who casted.
-
The metadata part which has a hash of the data, a digital signature of the hash, and the key that produced the signature: the signer.
(What you see in the signer filed is not the actual signer, but the public key of the signer.)
Why we need signers
In a centralized network such as twitter or facebook, you usually have a username and a password. You use your credentials to connect to a server, and then the server knows that you are who your credentials say you are. There is no other way to post something to the service, and the centralized server is the absolute authority of what was posted by whom.
Farcaster is an open, p2p network. Anyone with some technical knowledge can create a program that sends messages to the Farcaster network. The only way to verify the authenticity of these messages, is by their digital signature.
Each Farcaster user has their own keypair, a private and a public key. If you signed up using Warpcast, your recovery phrase can be used to generate this pair. This keypair also corresponds to an ethereum address, what is often called in Farcaster the custody wallet.
So, you could actually sign your messages using your private key. But users rarely create these messages on their computer using a program they wrote. They connect to a service or app, like buidler and after authenticating with it, it posts on their behalf. The problem is you don't want to give them your private key. This would be the equivalent of giving a gmail integration your username and password (and to some extent, not even being able to change the password).
Here is where Farcaster Signers come to play: Instead of giving an app your private key, the app creates a new random key, and asks you to approve it. You approve it using your private key and you register your approval onchain (gas cost!). From this point on, any hub that receives a message signed by this Signer, can check the blockchain to verify that you have approved the signer and accept it as authentic.
Warpcast and meta-transactions
When you make a call to a smart contract, the caller has to pay the gas for its execution. This is why adding or revoking a signer (onchain transactions) have a cost.
Normally, your Farcaster custody wallet would need to have some OP ETH to perform these transactions.
But wait. There's a workaround: KeyGateway, the smart contract used to approve Signers, allows meta-transactions. You can think of meta-transactions like this:
-
The user who wants to perform a transaction signs the transaction or an authorization to perform the transaction using his wallet. This is an offline action.
-
The signed transaction is not sent to the smart contract, but it is shared offchain with a third party, usually called the "relayer".
-
The relayer performs the transaction and pays the required gas.
Warpcast takes advantage of this feature to hide the added complexity of using a blockchain: It will ask the user to pay them $1, and then they use a meta-transaction and they pay for the gas.
This is roughly the equivalent of them saying "Just sign this paper, give me $1, and I'll take care of the rest."
The actual gas cost for adding and removing signers is usually well bellow $1. Warpcast now allows users to also pay using Warps, an in-app credit system: You can buy 500 Wraps for $5, and approving a signer will usually cost around 40-50 Warps (depending on gas cost at the time of the transaction).
(Warps are an interesting experiment that deserve a separate article.)
Revoking a signer
Obviously, a user must be able to revoke a signer, and they can do so using their private key and posting the revokation onchain to let everyone know that the signer is no longer authorized to act on their behalf. This was the whole point of not giving away our private key in the first place.
But, when a signer is revoked, hubs see messages that are no longer signed by a valid signer. Most people's first thought is OK, but these are old messages signed when the signer was valid. But you have to keep in mind that Farcaster is an open, p2p network. Hubs are added and removed all the time. You could spin up your hub right now (it's actually quite easy) and your hub would receive messages from other hubs it discovers in order to get its history (aka state) up to date. How can your newly created hub know when a message was signed?
This is why hubs have a simple way of "thinking": not a valid signer, not a valid message. And, as a result, when you revoke a Signer, all messages signed using it, are pruned by hubs!
This looks bad. The truth is there is a simple solution that no app (to my knowledge) has implemented (yet). Remember the message example we used earlier? What if you signed the same message with a different signer?
Signing the message with new signer will create a new signature, but the message data and the message hash will stay the same: Same user (fid), same content, same timestamp.
-
To any client, this new, re-signed message is the same as the original one.
-
To any hub, this is a valid message, provided that the original (same hash) is not in the hub's database.
So, an app could:
- Download all your messages (your Farcaster history)
- When you remove a signer, and some messages are pruned, re-sign these messages (from your download) with a new signer.
- Post the re-signed messages to a hub.
Using fario
You can perform the above steps using https://github.com/vrypan/fario if you are comfortable working in the command line. You will have to:
Backup your data using
fario-out --all
.Use
fario-grep
to select the records signed by the signer you want to remove.Remove the signer using
fario-signers remove
and create a new signer usingfario-signers add
Re-sign the messages using
fario-signers sign
Upload the re-signed messages using
fario-in
Final thoughts
Signers are an elegant approach to delegating permissions. It allows users to easily let an app act on their behalf, but at any point in time, they can revoke this permission.
The lack of a simple, user-friendly app that allows users to revoke a signer without deleting all activity performed using it, is definitely a pain-point looking for solutions: Right now, using a signer means that you are stuck with it, since revoking access will delete any casts, likes, recasts and follows you have performed using it. (Unless you are one of the few users who understand the technical details of Signers, and have the skills to use something like fario or put together a script by yourself.)
Looking forward to try the first apps that will give a user-friendly solution to this!