-
Notifications
You must be signed in to change notification settings - Fork 76
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
chore(spec): update bridge spec #1705
Merged
+201
−85
Merged
Changes from 3 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
bd1e319
update and add info to bridge spec
itamarreif 926dc49
update ics20 links
itamarreif ca80845
add high level overview
itamarreif 2ca8d6a
Update bridge.md
itamarreif 9234977
Merge branch 'main' into itamarreif/bridge/docs-update
itamarreif File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,210 @@ | ||
# Astria rollup bridging protocol | ||
# Astria Rollup Bridging Protocol | ||
|
||
The Astria sequencer implements a native bridging protocol which allows for | ||
bridging assets from the sequencer to rollups which decide to use this protocol. | ||
|
||
At a high level, the sequencer-to-rollup protocol works as follows: | ||
|
||
- a bridge account is initialized on the sequencer which has an associated | ||
rollup ID, which is the rollup ID that the rollup reads its block data from | ||
- the rollup enshrines the sequencer bridge account into its consensus, | ||
authorizing transfers (locks) into this bridge account of a specific asset | ||
to result in mints of the synthetic token on the rollup | ||
- users then send transfers to the sequencer bridge account, which result in | ||
`Deposit` events being included as part of the rollup's block data | ||
- when the rollup sees a `Deposit`, it mints the corresponding tokens to the | ||
user's account | ||
|
||
This is similar to how existing L1-to-rollup bridges work, where some lock | ||
event happening on the L1 results in a deposit transaction being derived | ||
automatically on the rollup. | ||
|
||
The rollup-to-sequencer protocol works as follows: | ||
|
||
- the bridge account has an associated private key. this could potentially be | ||
backed by the threshold signature scheme/multisig. | ||
- a bridge withdrawer is able to sign transaction which move funds out of the | ||
bridge account to other sequencer accounts. | ||
- there is a withdrawal contract deployed on the rollup which emits `Withdrawal` | ||
events when funds are locked in it (and effectively burned, as the contract | ||
should not be able to transfer its own funds). | ||
- the bridge withdrawer watches for these `Withdrawal` events. when it sees | ||
one, it sends a sequencer transaction which transfers funds from the bridge | ||
account to the account specified in the withdrawal event. | ||
The protocol is similar to how existing L1-to-rollup bridges work, where a lock | ||
event on the L1 results in a deposit transaction being derived automatically | ||
on the rollup. | ||
|
||
Since the sequencer can support multiple assets via IBC, the bridging protocol | ||
also has support for deposits and withdrawals via IBC, as well as support for | ||
various assets to be bridged to the rollup. | ||
|
||
The one-step deposit flow from another IBC chain is as follows: | ||
|
||
- a user initiates an ICS20 withdrawal from some IBC chain to Astria. | ||
- the user sets the destination chain address as the sequencer bridge address | ||
which corresponds to the rollup they wish to deposit to. | ||
- the user sets the withdrawal memo to their rollup address. | ||
- when the ICS20 transfer is executed on Astria, the funds are locked into the | ||
## High-Level Overview | ||
|
||
### Sequencer-to-Rollup | ||
|
||
1. The bridge account is initialized on the sequencer with an associated | ||
rollup ID. | ||
2. The rollup modifies its consensus to register the sequencer-side bridge account | ||
for use in its state transition logic. | ||
3. Users then send sequencer-side transfers to the bridge account (either natively | ||
or using IBC), which are included in the rollup's block data as `Deposit` events. | ||
4. Mints to the user's rollup-side account are derived from the `Deposit`s included | ||
in the rollup block data. | ||
|
||
### Rollup-to-Sequencer | ||
|
||
1. The bridge withdrawer is registered with the sequencer-side bridge account, | ||
allowing it to make withdrawals from the bridge account. | ||
2. The withdrawal contract is deployed on the rollup, emitting `SequencerWithdrawal` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a bit confusing, maybe rephrase to "the bridge account has an associated withdrawer address which is authorized to withdraw from the bridge account" |
||
and `Ics20Withdrawal` events when its `withdrawToSequencer` and `withdrawToIbcChain` | ||
functions are called, respectively. | ||
3. The bridge withdrawer watches for these events, converting them to the appropriate | ||
sequencer-side native or IBC withdrawals and batching them by rollup block. Batches | ||
are then submitted to the sequencer sequentially. | ||
|
||
## Bridge Account Initialization | ||
|
||
1. A bridge account is initialized on the sequencer with an associated rollup | ||
ID, which is the rollup ID that the rollup reads its block data from. | ||
|
||
2. The rollup modifies its consensus to register the sequencer bridge account | ||
for use in its state transition logic. `Deposit`s of the correct asset to the | ||
bridge account will be used to derive a mint of the corresponding tokens on the | ||
rollup, according to the metadata provided. | ||
|
||
- An example for "registering" the bridge account: [`astria-geth`](https://github.com/astriaorg/astria-geth/blob/09c27dc320570d9e1f58ea60325158f36d6a0309/genesis.json#L24) | ||
- An example for the mint derivation logic: [`astria-geth`](https://github.com/astriaorg/astria-geth/blob/09c27dc320570d9e1f58ea60325158f36d6a0309/grpc/execution/validation.go#L27) | ||
|
||
The bridge account is initialized with a sequencer-side [`InitBridgeAccount`](https://github.com/astriaorg/astria/blob/d03059977c3a40590d66591c520bfda3a9b9de1c/proto/protocolapis/astria/protocol/transaction/v1/action.proto#L146) | ||
action. | ||
|
||
After being initialized, the bridge account's rollup ID and asset ID cannot | ||
be changed. The account also cannot be re-initialized as a bridge account, or | ||
converted back into a non-bridge account. | ||
|
||
Only the `sudo_address` is authorized to change the bridge account's `sudo_address` | ||
and `withdrawer_address`. | ||
|
||
## Withdrawer Account | ||
|
||
The sequencer-side bridge account has an associated withdrawer account. This is a | ||
sequencer-side account, which uses `Ed25519`, and could potentially be backed | ||
by a threshold signature scheme. | ||
|
||
The withdrawer account is set with a sequencer-side [`BridgeSudoChange`](https://github.com/astriaorg/astria/blob/main/proto/protocolapis/astria/protocol/transaction/v1/action.proto#L211) | ||
action. | ||
|
||
The sequencer-side bridge withdrawer is the only account able to make actions that | ||
transfer funds out of the bridge account to other sequencer accounts, either via | ||
[`BridgeUnlock` actions](https://github.com/astriaorg/astria/blob/d03059977c3a40590d66591c520bfda3a9b9de1c/proto/protocolapis/astria/protocol/transaction/v1/action.proto#L186) | ||
or [`Ics20Withdrawal` actions](https://github.com/astriaorg/astria/blob/d03059977c3a40590d66591c520bfda3a9b9de1c/proto/protocolapis/astria/protocol/transaction/v1/action.proto#L78) | ||
|
||
## Sequencer-To-Rollup Deposits | ||
|
||
After the bridge account is initialized, the deposit flow works as follows: | ||
|
||
1. When the user makes sequencer-side transfers, such as `BridgeLock`, to the | ||
bridge account, `Deposit` events are included by the sequencer as part of the | ||
rollup's block data. | ||
|
||
2. When the rollup receives a `Deposit` in an `ExecuteBlockRequest`, it derives | ||
a mint transactions to the user's account according to the metadata provided. | ||
|
||
[`BridgeLock`](https://github.com/astriaorg/astria/blob/d03059977c3a40590d66591c520bfda3a9b9de1c/proto/protocolapis/astria/protocol/transaction/v1/action.proto#L167) | ||
actions have the following structure: | ||
|
||
```proto | ||
// `BridgeLock` represents a transaction that transfers | ||
// funds from a sequencer account to a bridge account. | ||
// | ||
// It's the same as a `Transfer` but with the added | ||
// `destination_chain_address` field. | ||
message BridgeLock { | ||
// the address of the bridge account to transfer to | ||
astria.primitive.v1.Address to = 1; | ||
// the amount to transfer | ||
astria.primitive.v1.Uint128 amount = 2; | ||
// the asset to be transferred | ||
string asset = 3; | ||
// the asset used to pay the transaction fee | ||
string fee_asset = 4; | ||
// the address on the destination chain which | ||
// will receive the bridged funds | ||
string destination_chain_address = 5; | ||
} | ||
``` | ||
|
||
- [`Ics20Transfer`](https://github.com/astriaorg/astria/blob/d03059977c3a40590d66591c520bfda3a9b9de1c/crates/astria-sequencer/src/ibc/ics20_transfer.rs#L335) | ||
packets are received when an IBC transfer to Astria from another chain occurs. | ||
If the recipient of the packet is a bridge account and the asset transferred is | ||
valid, the funds are locked in the bridge account and a `Deposit` is created. | ||
- `Deposit` events are defined in the `sequencerblockapis`: [`block.proto`](https://github.com/astriaorg/astria/blob/d03059977c3a40590d66591c520bfda3a9b9de1c/proto/sequencerblockapis/astria/sequencerblock/v1/block.proto#L76) | ||
- An example for the derived rollup side transaction: [`astria-geth`'s `DepositTx`](https://github.com/astriaorg/astria-geth/blob/09c27dc320570d9e1f58ea60325158f36d6a0309/core/types/deposit_tx.go#L14) | ||
|
||
## Rollup-To-Sequencer Withdrawals | ||
|
||
Tokens that have been deposited into the rollup can be withdrawn out by the user | ||
in the following way: | ||
|
||
1. There is a withdrawal smart contract deployed on the rollup. Calling its | ||
payable withdrawal function burns the transferred tokens and emits a | ||
`Withdrawal` event. | ||
|
||
2. The bridge withdrawer watches for withdrawal events. For each event emitted | ||
by the smart contract, the withdrawer creates a sequencer-side action which | ||
transfers the funds from the bridge account to the destination specified in | ||
the withdrawal event. These actions are batched by rollup block into one sequencer | ||
transaction, and the transaction is submitted to the sequencer. | ||
|
||
[`BridgeUnlock` actions](https://github.com/astriaorg/astria/blob/d03059977c3a40590d66591c520bfda3a9b9de1c/proto/protocolapis/astria/protocol/transaction/v1/action.proto#L186) | ||
have the following structure: | ||
|
||
```proto | ||
// `BridgeUnlock` represents a transaction that transfers | ||
// funds from a bridge account to a sequencer account. | ||
// | ||
// It's the same as a `Transfer` but without the `asset` field | ||
// and with the `memo` field. | ||
message BridgeUnlock { | ||
// the to withdraw funds to | ||
astria.primitive.v1.Address to = 1; | ||
// the amount to transfer | ||
astria.primitive.v1.Uint128 amount = 2; | ||
// the asset used to pay the transaction fee | ||
string fee_asset = 3; | ||
// The memo field can be used to provide unique identifying additional | ||
// information about the bridge unlock transaction. | ||
string memo = 4; | ||
// the address of the bridge account to transfer from | ||
astria.primitive.v1.Address bridge_address = 5; | ||
// The block number on the rollup that triggered the transaction underlying | ||
// this bridge unlock memo. | ||
uint64 rollup_block_number = 6; | ||
// An identifier of the original rollup event, such as a transaction hash which | ||
// triggered a bridge unlock and is underlying event that led to this bridge | ||
// unlock. This can be utilized for tracing from the bridge back to | ||
// distinct rollup events. | ||
// | ||
// This field is of type `string` so that it can be formatted in the preferred | ||
// format of the rollup when targeting plain text encoding. | ||
string rollup_withdrawal_event_id = 7; | ||
} | ||
``` | ||
|
||
- [`Ics20Withdrawal`](https://github.com/astriaorg/astria/blob/d03059977c3a40590d66591c520bfda3a9b9de1c/proto/protocolapis/astria/protocol/transaction/v1/action.proto#L78) | ||
represents a withdrawal from Astria to another IBC chain. | ||
|
||
- If the `bridge_address` field is set, the funds are transferred out of a | ||
bridge account. Alternatively, if `bridge_address` is unset but the signer | ||
of the action is a bridge address, and the withdrawer address is the same | ||
as the bridge address, the funds are transferred out of the bridge account. | ||
|
||
- Examples for a withdrawal smart contracts: [`astria-bridge-contracts`](https://github.com/astriaorg/astria-bridge-contracts/tree/main) | ||
- The events emitted by the smart contracts are defined in [`IAstriaWithdrawer`](https://github.com/astriaorg/astria-bridge-contracts/blob/038002e156c667419434204f9e5be43460da7995/src/IAstriaWithdrawer.sol#L22) | ||
|
||
## One-Step IBC Bridging | ||
|
||
### Deposit Into A Rollup | ||
|
||
The user initiates an ICS20 withdrawal from some IBC chain to the sequencer. | ||
The following metadata is provided: | ||
|
||
- The destination chain address is the sequencer-side bridge address correspodning | ||
to the destination rollup. | ||
- The correct asset denomination. | ||
- The rollup-side destination address is provided in the memo field. | ||
|
||
When the ICS20 transfer is executed on the sequencer, the funds are locked into the | ||
bridge address, and a `Deposit` event is created for that rollup's ID with the | ||
user's rollup address. | ||
|
||
The one-step withdrawal flow from a rollup to another IBC chain is as follows: | ||
### Withdrawal From A Rollup | ||
|
||
The User initiates a withdrawal from the rollup to an IBC destination using the | ||
`withdrawToIbcChain` function of an `IAstriaWithdrawer`-compatible smart contract. | ||
This contract calls burns the funds, emitting an `Ics20Withdrawal` event for the | ||
withdrawer to process (as described above). | ||
|
||
- the user withdraws the asset by burning it on the rollup, which emits a | ||
`Withdrawal` event that includes the asset, the amount, and a memo. | ||
- the memo contains the needed information for creating an Ics20 withdrawal on | ||
In addition to the metadata in a sequencer-native withdrawal, the `Ics20Withdrawal` | ||
event also provides the needed information for creating an Ics20 withdrawal on | ||
the sequencer, such as the recipient destination chain address. | ||
- the bridge withdrawer sees the `Withdrawal` event and submits a sequencer | ||
transaction which withdraws the funds to the destination IBC chain. | ||
- in the case that the transfer to the destination IBC chain fails, the | ||
sequencer is notified of this, and emits a `Deposit` refunding the funds back | ||
to the origin rollup address. | ||
|
||
In the case that the transfer to the destination IBC chain fails, the sequencer | ||
is notified of this via IBC, and emits a `Deposit` refunding the funds back to | ||
the origin rollup address via the mint derivation process described above. | ||
|
||
## Implementation | ||
|
||
|
@@ -66,43 +214,11 @@ module, and the IBC-bridging logic is in the | |
[`ibc`](https://github.com/astriaorg/astria/tree/main/crates/astria-sequencer/src/ibc) | ||
module. | ||
|
||
The bridge related actions are: | ||
|
||
- [`InitBridgeAccountAction`](https://github.com/astriaorg/astria/blob/6902ef35370e5980a76302fc756e1a9a56af21b5/proto/protocolapis/astria/protocol/transactions/v1alpha1/types.proto#L167): | ||
initializes the signer of the action as a bridge account. The associated rollup | ||
ID and asset ID which this account accepts are provided. Optional `sudo_address` | ||
and `withdrawer_address` fields can be provided, which are set to the action | ||
sender if unset. | ||
- the account's rollup ID and asset ID cannot be changed once initialized. | ||
- the account cannot be re-initialized as a bridge account, and it cannot be | ||
converted back into a non-bridge account. | ||
- `sudo_address` is authorized to change the rollup account's `sudo_address` | ||
and `withdrawer_address`. | ||
- to make withdrawals from the bridge account, the `withdrawer_address` must | ||
be the transaction signer. | ||
- withdrawals are allowed using either `BridgeUnlockAction` or `Ics20Withdrawal`. | ||
- [`BridgeLockAction`](https://github.com/astriaorg/astria/blob/6902ef35370e5980a76302fc756e1a9a56af21b5/proto/protocolapis/astria/protocol/transactions/v1alpha1/types.proto#L188): | ||
transfers funds to a bridge account, locking them and emitting a | ||
[`Deposit`](https://github.com/astriaorg/astria/blob/6902ef35370e5980a76302fc756e1a9a56af21b5/proto/sequencerblockapis/astria/sequencerblock/v1alpha1/block.proto#L76). | ||
The `destination_chain_address` is the rollup account funds are minted to. | ||
- [`BridgeUnlockAction`](https://github.com/astriaorg/astria/blob/main/proto/protocolapis/astria/protocol/transactions/v1alpha1/types.proto#L207): | ||
transfers funds from a bridge account to another account. The asset transferred | ||
is the one for the bridge account (ie. the asset ID specified in `InitBridgeAccountAction`). | ||
The signer of this action must be the bridge account's `withdrawer_address`. | ||
- [`BridgeSudoChangeAction`](https://github.com/astriaorg/astria/blob/6902ef35370e5980a76302fc756e1a9a56af21b5/proto/protocolapis/astria/protocol/transactions/v1alpha1/types.proto#L222) | ||
changes the bridge account's sudo and/or withdrawer addresses. The signer of | ||
this action must be the bridge account's `sudo_address`. | ||
|
||
The two IBC actions which can also perform bridging actions are an `IbcRelay` | ||
which contains an `Ics20Transfer` packet, and `Ics20Withdrawal`. | ||
|
||
- [`Ics20Transfer`](https://github.com/astriaorg/astria/blob/6902ef35370e5980a76302fc756e1a9a56af21b5/crates/astria-sequencer/src/ibc/ics20_transfer.rs#L370) | ||
packets are received when an IBC transfer to Astria from another chain occurs. | ||
If the recipient of the packet is a bridge account and the asset transferred is | ||
valid, the funds are locked in the bridge account and a `Deposit` is created. | ||
- [`Ics20Withdrawal`](https://github.com/astriaorg/astria/blob/6902ef35370e5980a76302fc756e1a9a56af21b5/proto/protocolapis/astria/protocol/transactions/v1alpha1/types.proto#L102) | ||
represents a withdrawal from Astria to another IBC chain. If the `bridge_address` | ||
field is set, the funds are transferred out of a bridge account. Alternatively, | ||
if `bridge_address` is unset but the signer of the action is a bridge address, | ||
and the withdrawer address is the same as the bridge address, the funds are | ||
transferred out of the bridge account. | ||
The rollup-side smart contracts can be found in the | ||
[`astria-bridge-contracts`](https://github.com/astriaorg/astria-bridge-contracts/tree/4580ffc0747f463e304214bb29848e21e4e93e32) | ||
repository. | ||
|
||
The bridge-withdrawer service is responsible for watching for `Withdrawal` events | ||
emitted by the rollup and submitting the corresponding sequencer transactions. The | ||
bridge-withdrawer service is implemented in the [`astria-bridge-withdrawer`](https://github.com/astriaorg/astria/tree/main/crates/astria-bridge-withdrawer) | ||
crate. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i like having the high level summary first, before delving into the code details. can you re-add?