Skip to content

Commit

Permalink
Add example of a suapp storing and using a private key
Browse files Browse the repository at this point in the history
  • Loading branch information
ferranbt committed Mar 26, 2024
1 parent ede1941 commit c117500
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 0 deletions.
17 changes: 17 additions & 0 deletions examples/private-suapp-key/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Example Suapp with a stored private key

This example shows how Suapps can store private keys in the confidential storage to be used in multiple confidential requests.

## How to use

Run `Suave` in development mode:

```
$ suave --suave.dev
```

Execute the deployment script:

```
$ go run main.go
```
33 changes: 33 additions & 0 deletions examples/private-suapp-key/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"encoding/hex"
"log"

"github.com/flashbots/suapp-examples/framework"
)

func main() {
fr := framework.New()

priv := "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"

contract := fr.Suave.DeployContract("private-suapp-key.sol/PublicSuapp.json")
contract.SendConfidentialRequest("registerPrivateKey", nil, []byte(priv))

receipt := contract.SendConfidentialRequest("example", nil, nil)

// validate the signature
txnSignatureEvent, err := contract.Abi.Events["TxnSignature"].ParseLog(receipt.Logs[0])
if err != nil {
log.Fatal(err)
}
var r, s = txnSignatureEvent["r"].([32]byte), txnSignatureEvent["s"].([32]byte)

if hex.EncodeToString(r[:]) != "eebcfac0def6db5649d0ae6b52ed3b8ba1f5c6c428588df125461113ba8c6749" {
log.Fatal("wrong r signature")
}
if hex.EncodeToString(s[:]) != "5d5e1aafa0c964b43c251b6a525d49572968f2cebc5868c58bcc9281b9a07505" {
log.Fatal("wrong s signature")
}
}
53 changes: 53 additions & 0 deletions examples/private-suapp-key/private-suapp-key.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.8;

import "suave-std/suavelib/Suave.sol";
import "suave-std/Context.sol";
import "suave-std/Suapp.sol";
import "suave-std/Transactions.sol";

contract PublicSuapp is Suapp {
Suave.DataId signingKeyBid;
string public KEY_PRIVATE_KEY = "KEY";

// onchain-offchain pattern to register the new private key in the Confidential storage
function updateKeyCallback(Suave.DataId _signingKeyBid) public {
signingKeyBid = _signingKeyBid;
}

function registerPrivateKey() public returns (bytes memory) {
bytes memory keyData = Context.confidentialInputs();

address[] memory peekers = new address[](1);
peekers[0] = address(this);

Suave.DataRecord memory bid = Suave.newDataRecord(10, peekers, peekers, "private_key");
Suave.confidentialStore(bid.id, KEY_PRIVATE_KEY, keyData);

return abi.encodeWithSelector(this.updateKeyCallback.selector, bid.id);
}

// offchain-onchain pattern to sign a transaction using the private key stored in the Suapp
event TxnSignature(bytes32 r, bytes32 s);

function exampleCallback() public emitOffchainLogs {}

function example() public returns (bytes memory) {
bytes memory signingKey = Suave.confidentialRetrieve(signingKeyBid, KEY_PRIVATE_KEY);

Transactions.EIP155Request memory txnWithToAddress = Transactions.EIP155Request({
to: address(0x00000000000000000000000000000000DeaDBeef),
gas: 1000000,
gasPrice: 500,
value: 1,
nonce: 1,
data: bytes(""),
chainId: 1337
});

Transactions.EIP155 memory txn = Transactions.signTxn(txnWithToAddress, string(signingKey));
emit TxnSignature(txn.r, txn.s);

return abi.encodeWithSelector(this.exampleCallback.selector);
}
}

0 comments on commit c117500

Please sign in to comment.