Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support threshold signing in bridge withdrawer #1937

Closed
SuperFluffy opened this issue Jan 28, 2025 · 1 comment · Fixed by #1948 · May be fixed by #1960
Closed

Support threshold signing in bridge withdrawer #1937

SuperFluffy opened this issue Jan 28, 2025 · 1 comment · Fixed by #1948 · May be fixed by #1960
Assignees
Labels
bridge-withdrawer code touching the bridge-withdrawer service enhancement New feature or request stale

Comments

@SuperFluffy
Copy link
Member

SuperFluffy commented Jan 28, 2025

PRD (private): https://www.notion.so/astria-org/Rough-Sketch-of-Threshold-Signing-for-Bridge-17e6bd31a90c8056a8c8fb980620ace7

┆Issue Number: ENG-1081

@SuperFluffy SuperFluffy added bridge-withdrawer code touching the bridge-withdrawer service enhancement New feature or request labels Jan 28, 2025
@SuperFluffy SuperFluffy assigned SuperFluffy and noot and unassigned SuperFluffy Jan 28, 2025
@joroshiba
Copy link
Member

This issue is stale because it has been open 45 days with no activity. Remove stale label or this issue
be closed in 7 days.

github-merge-queue bot pushed a commit that referenced this issue Mar 20, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
## Summary
support FROST ed25519 threshold signing in the bridge withdrawer. 

## Background
improves security of the withdrawer over having one private key used;
instead, we can employ an m-of-n threshold signature scheme to sign
withdrawals.

## Changes
- create `FrostParticipantService` gRPC proto definition, which is to be
implemented by a binary which contains a FROST secret key partial that
participates in the threshold signing process
- update withdrawer config/setup to support single signer (previous
behaviour) or threshold signing via the `Signer` trait
- create `FrostSigner` which has gRPC clients for the signing
participants
- `FrostSigner.sign()` performs the signing process by calling each
participant for their commitment (part 1) and signature share (part 2)
and finally aggregates the shares to create a valid signature.
- `FrostSigner.sign()` will fail if it does not receive responses from
at least the minimum number of signers required. the min number of
signers is determined during key generation, which is done completely
separately.

## Testing
blackbox tests with mock signer servers have been added.

also, this was tested with a 2/2 threshold signer node setup. withdrawal
transactions are successfully signed, submitted, and included on the
sequencer. see
https://www.notion.so/astria-org/bridge-threshold-withdrawer-testing-1936bd31a90c803ab33ccc1221f545a1?pvs=4

use the following testing keys which are for 2/2 threshold and represent
astria address `astria1w2lxx9p02u7u934ljl060wannqm40g3y089lmh`

put the following keys into their own files.

pubkey package:

```bash
{
  "header": {
    "version": 0,
    "ciphersuite": "FROST-ED25519-SHA512-v1"
  },
  "verifying_shares": {
    "0100000000000000000000000000000000000000000000000000000000000000": "bd209bd0c47806fee2db29bde0b705f6a191602f0307e8d959d74f189ae92e9e",
    "0200000000000000000000000000000000000000000000000000000000000000": "0a677e1c6ad0c1906bf6ac53810b29efcb9ca9e7ab50fe9fca3ae49e613b922f"
  },
  "verifying_key": "ecbe5e2fbaaf23f14ca43f34d71ad733c57afcadeb5782809af48a3da17b9b69"
```

secret key 1:

```bash
{
  "header": {
    "version": 0,
    "ciphersuite": "FROST-ED25519-SHA512-v1"
  },
  "identifier": "0100000000000000000000000000000000000000000000000000000000000000",
  "signing_share": "4b45de055567d7a2027bfc9a2463de4aaa6f2df995180e638dc938013e9bf70e",
  "verifying_share": "bd209bd0c47806fee2db29bde0b705f6a191602f0307e8d959d74f189ae92e9e",
  "verifying_key": "ecbe5e2fbaaf23f14ca43f34d71ad733c57afcadeb5782809af48a3da17b9b69",
  "min_signers": 2
}
```

secret key 2:

```bash
{
  "header": {
    "version": 0,
    "ciphersuite": "FROST-ED25519-SHA512-v1"
  },
  "identifier": "0200000000000000000000000000000000000000000000000000000000000000",
  "signing_share": "29a52cd248df9a7bb2346fb4ed53318f0bff320985c8e49062c68e4fd0012d0f",
  "verifying_share": "0a677e1c6ad0c1906bf6ac53810b29efcb9ca9e7ab50fe9fca3ae49e613b922f",
  "verifying_key": "ecbe5e2fbaaf23f14ca43f34d71ad733c57afcadeb5782809af48a3da17b9b69",
  "min_signers": 2
}
```

checkout `noot/frost-participant` (see
#1960)

build astria-cli, astria-bridge-withdrawer, astria-bridge-signer and
astria-sequencer.

run anvil (using this as fake rollup evm node for testing)

run astria-sequencer + cometbft as normal

transfer funds from funded address to withdrawer address

```bash
./target/debug/astria-cli sequencer transfer --amount 100000000 \
--private-key 2bd806c97f0e00af1a1fc3328fa763a9269723c8db8fac4f93af71db186d6e90 \
--sequencer-url http://localhost:26657 \
--sequencer.chain-id astria astria1w2lxx9p02u7u934ljl060wannqm40g3y089lmh
```

initialize bridge account on astria, with
`astria1w2lxx9p02u7u934ljl060wannqm40g3y089lmh` being the withdrawer
address

```bash
./target/debug/astria-cli sequencer init-bridge-account \
--private-key 2bd806c97f0e00af1a1fc3328fa763a9269723c8db8fac4f93af71db186d6e90 \
--withdrawer-address astria1w2lxx9p02u7u934ljl060wannqm40g3y089lmh \
--sequencer-url http://localhost:26657 \
--sequencer.chain-id astria \
--rollup-name test
```

result:

```bash
sending tx from address: astria1rsxyjrcm255ds9euthjx6yc3vrjt9sxrm9cfgm
InitBridgeAccount completed!
Included in block: 1252
Rollup name: test
Rollup ID: n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg=
```

deploy contracts to anvil using `astria-bridge-contracts` 

- set `.env` and `source .env`

```bash
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
RPC_URL="http://localhost:8545"
BASE_CHAIN_ASSET_PRECISION=9
BASE_CHAIN_BRIDGE_ADDRESS="astria1rsxyjrcm255ds9euthjx6yc3vrjt9sxrm9cfgm"
BASE_CHAIN_ASSET_DENOMINATION="nria"
```

- `forge script script/AstriaWithdrawer.s.sol:AstriaWithdrawerScript
--rpc-url $RPC_URL --broadcast --sig "deploy()" -vvvv`
- contract deployed at `0x5FbDB2315678afecb367f032d93F642f64180aa3` ,
update `.env` again

run two astria-bridge-signers, one with grpc port `9001` and first
secret key package, second with grpc port `9002` and second secret key
package.

start the bridge withdrawer, configured for 2/2 threshold (make sure to
update pubkey package path):

```bash
ASTRIA_BRIDGE_WITHDRAWER_FROST_THRESHOLD_SIGNING_ENABLED=true
ASTRIA_BRIDGE_WITHDRAWER_FROST_MIN_SIGNERS=2
ASTRIA_BRIDGE_WITHDRAWER_FROST_PUBLIC_KEY_PACKAGE_PATH="pub_bridge.key"
ASTRIA_BRIDGE_WITHDRAWER_FROST_PARTICIPANT_ENDPOINTS="http://127.0.0.1:9001,http://127.0.0.1:9002"
ASTRIA_BRIDGE_WITHDRAWER_SEQUENCER_BRIDGE_ADDRESS="astria1rsxyjrcm255ds9euthjx6yc3vrjt9sxrm9cfgm"
ASTRIA_BRIDGE_WITHDRAWER_ETHEREUM_CONTRACT_ADDRESS="0x5FbDB2315678afecb367f032d93F642f64180aa3"

```

finally, send a withdrawal on the rollup:

```bash
forge script script/AstriaWithdrawer.s.sol:AstriaWithdrawerScript \
   --rpc-url $RPC_URL --broadcast --sig "withdrawToSequencer()" -vvvv
```

in the withdrawer, should see:

```bash
2025-02-10T17:33:57.417370Z  INFO process_batch: astria_bridge_withdrawer::bridge_withdrawer::submitter: withdraw batch successfully executed. sequencer.block=41 sequencer.tx_hash=69E3997A2A67CD4716D1051D9962219FBCEF9F3F7557C276D9F4D414D30166F2 rollup.height=4 batch.value=1000
```

## Changelogs
Changelogs updated.

## Related Issues

closes  #1937

---------

Co-authored-by: Richard Janis Goldschmidt <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bridge-withdrawer code touching the bridge-withdrawer service enhancement New feature or request stale
Projects
None yet
3 participants