Simplifying Lit
Programmable Key Pairs (PKPs)
Anything you do on the blockchain needs you to sign a transaction with your private key. This happens in two steps,
A transaction object is created and signed using your private key
It's then broadcasted to the blockchain network for verification
With Lit, you can generate Programmable Key Pairs (PKPs), which are wallets whose private key is securely managed over the Lit Network. Since no one holds a private key to this wallet, you can program this wallet to behave in a specified way.
This wallet will now contain auth methods with which the PKP should be able to generate signatures. Suppose you generate a PKP over a Lit Network and allow a Google account as an auth method. Then you'll be able to generate signatures with this wallet through your Google account.
Lit Protocol
Lit Protocol consists of,
Lit Network
Chronicles blockchain
Lit Network is a multi-party computation (MPC) network of nodes which manages the private keys. Wallets are generated using a Distributed Key Generation (DKG) algorithm where every node of the network holds a shard.
When a signature through a specific PKP is requested from the Lit Network, a virtual machine collects 2/3rd of the shards to generate the private key and create a sign. This key is short-lived on the VM. Lit Network is also hardware secured using SEV-SNP mechanisms where the operations running inside the node cannot be intercepted or seen from outside as well the data integrity between multiple operations is maintained on inside.
Lit Network supports several EVM, Solana and Cosmos chains.
Chronicles blockchain is Lit's custom EVM rollup. The main purpose of this custom chain is to create PKPs, manage their permissions, and incentivize the node operators. Once a PKP is generated, it acts like a wallet and can support chains compatible with Lit.
Each node of the Lit Network also runs a Chronicles state to faster read the activities on the chain and respond to them on the Network.
How is a PKP created?
Two major smart contracts on Chronicles are responsible for generating PKPs:
PKP NFT contract
PKP Permissions contract
To create a PKP on the Lit Network, a mint
call is made to the PKP NFT smart contract, which mints a PKP NFT to the caller. This NFT includes the public key and Ether address of the wallet generated on the Lit Network.
Note: Usually, when you create an account in your wallet, a new private key is generated, from which the public key and Ether address are derived.
Lit uses Homogeneous Derivatives (HDs) with smart contracts to generate public keys ahead of time. Minting a PKP also triggers a DKG on the Lit Network, creating a new wallet on the Lit Network.
Auth Methods or permissions over this wallet can now be managed with the PKP Permissions Contract. Each time an action is requested from a PKP from the Lit Network, it queries the permissions contract to check if the action is allowed or not.
One of the interesting auth methods over a PKP is a Lit Action, a Lit action is a programmable code written in Javascript on which you can program conditions for a PKP to create signs.
Lit Action
Lit Actions are programmable code written in Javascript which can run on the LIT Network. We can program a Lit Action so that if certain permissions are met for a PKP, it must sign specific transactions that can be sent to the blockchain. We need to grant a Lit Action as a permitted action to the PKP to allow the Lit Action to generate signatures with it.
They work like regular JS scripts. We can make API requests from inside of a Lit Action or use some external packages in it as well.
We upload the Lit Actions to IPFS to make the code immutable and then use their CID to add them as permitted actions to specific PKPs through smart contracts. Now, during the execution of this Lit Action, the network checks the smart contracts to see if it is allowed to generate signatures with that specific PKP.
A simple Lit Action to sign a "Hello World" message would look something like,
`const go = async () => {
let toSign = new TextEncoder().encode("Hello World");
toSign = ethers.utils.arrayify(ethers.utils.keccak256(toSign));
const signature = await Lit.Actions.signEcdsa({
toSign,
publicKey,
sigName: "signature",
});
Lit.Actions.setResponse({ response: JSON.stringify(signature) });
};
go();`
Lit Actions come with certain types that help them perform various operations on the network. One of these is a signEcdsa which takes in the object to sign, the PKP to sign with and the name for the signature.
You can get a live playground for writing Lit Actions at Lit Explorer
Lit SDKs
In most scenarios, we'll be using the following two SDKs to work with Lit:
Lit Node Client SDK
Lit Contracts SDK
The Node SDK helps the client communicate with the Lit Network. It is useful for:
Generating session signatures
Generating auth signatures
Executing Lit Actions
The Contracts SDK helps the client communicate with the PKP smart contracts. It provides us with the methods for minting the PKP and adding its permitted auth methods or scopes.
Session Signatures
Session Signatures are used to authenticate with the Lit nodes and create a secure connection to the Lit network. This essentially informs the network about the user attempting to use the Lit Network. In a Session Signature, we also include the resources we request from the Lit Network. These could be of the following types:
Executing the Lit action
Signing with the PKP
We might need a different type of session signature for each specific kind of operation we are doing on the Lit Network.
Encryption/Decryption
Apart from creating PKPs and executing Lit Actions, the Lit Network can also be used to create and store encryption keys. These keys can be used to encrypt data, which then needs to be stored on a storage provider like IPFS or Arweave. We can set access conditions on the encryption key stored on the Lit Network. These conditions can include:
On-chain conditions like wallet balance
Off-chain conditions like API calls
Lit Actions like the results of executing an action
Potential Use cases
As Lit Actions unlocks a new way of seeing wallets as PKPs, we can now innovate more. A few use cases could be,
Encryption/Decryption
Social logins
Backup for wallets
Off-chain conditions as Access Condition
Another approach is using the Mint/Grant/Burn pattern. This involves minting a PKP, granting a permitted action, and then burning the PKP so no more authentication methods can be modified. This allows the PKP to generate signatures only when requested by the Lit Action adhering to its specified conditions. It makes a wallet behave like a smart contract (Lit Action conditions) and provides a medium for cross-chain messaging. This helps us perform the following:
Anonymous cross-chain swaps
Cross-chain messaging
Bridging wrapped assets
Automatic swaps for limit orders
You can reference this demo-features repo, covering creating a PKP, changing its auth method, and signing transactions with it on the Lit Network.
Lit Event Listeners
The Lit Listener SDK lets us create event-based triggers to execute Lit Actions. For example, if you have a Lit Action to swap ETH with USDT but only want to execute it when the price of ETH reaches a certain threshold, you can create a listener on the Lit Network. This listener will monitor ETH prices and execute your Lit Action at the right time.
The flow for the Listener SDK is as follows:
Set Conditions for the listener
Create and upload a Lit Action to IPFS (making code immutable)
Mint/Grant/Burn on the Lit Action so now our JS code gets a wallet
Run the listener
Read more about LitListenerSDK here
Capacity Credits
Similar to the way we use gas fees for transactions on blockchains, we currently use a capacity credit NFT for operations on the Lit Network. This NFT decides your rate limit over the network. You can mint it for free on the testnet but need to buy it on the mainnet. Developers can choose among three of Lit's networks
Mainnet - requires a capacity NFT
Testnet - requires a capacity NFT but it's free to mint
Devnet - does not require a capacity NFT
We need to delegate this NFT to the PKP which we minted earlier so that the PKP can use the network. This delegation will create an auth signature for the capacity credit delegation. We now provide that to the session signatures while we are accessing the network.
We can set our rate limit on the network by minting capacity credits using the contracts SDK.
// this identifier will be used in delegation requests.
const { capacityTokenIdStr } = await contractClient.mintCapacityCreditsNFT({
requestsPerKilosecond: 80,
// requestsPerDay: 14400,
// requestsPerSecond: 10,
daysUntilUTCMidnightExpiration: 2,
});
Every time we access the Lit Network through a PKP, our delegation auth signature, generated with the node SDK, would look something like this:
const { capacityDelegationAuthSig } =
await litNodeClient.createCapacityDelegationAuthSig({
uses: '1',
signer: wallet,
capacityTokenId: capacityTokenIdStr,
delegateeAddresses: [secondWalletPKPInfo.ethAddress],
});
Subscribe to my newsletter
Read articles from Ansh Saxena directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Ansh Saxena
Ansh Saxena
For a programmer, laziness is a virtue.