Skip to content

Commit

Permalink
update new version checking snapshot instead of event nonce
Browse files Browse the repository at this point in the history
  • Loading branch information
tubackkhoa committed Apr 26, 2023
2 parents 978b7ef + b03543e commit 8ec5d49
Show file tree
Hide file tree
Showing 80 changed files with 15,542 additions and 9,633 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,17 @@ jobs:
run: tests/all-up-test.sh SEND_TO_ETH_FEES
env:
NO_IMAGE_BUILD: True
cross_bridge_balances:
runs-on: ubuntu-latest
needs: happy-path-geth
steps:
- uses: actions/checkout@v2
- uses: jpribyl/[email protected]
with:
key: integration-test-cache-{hash}
restore-keys: |
integration-test-cache-
- name: Test end-to-end bridge balance monitoring
run: tests/all-up-test.sh CROSS_BRIDGE_BALANCES
env:
NO_IMAGE_BUILD: True
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
"solidity.packageDefaultDependenciesDirectory": "solidity/node_modules",
"files.associations": {
"validator-eth-keys": "cpp"
}
},
"vue.features.codeActions.enable": false
}
4 changes: 4 additions & 0 deletions docs/design/ethereum-signing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

As outlined in the [overview](/docs/design/overview.md) the [Gravity.sol](/solidity/contracts/Gravity.sol) contract acts as a weighted powers multisig for the funds sorted in the bridge. Effectively producing a situation where the validator set of the Cosmos chain owns all the funds in the bridge in a multisig that replicates their stake weighted voting power on Cosmos.

## End-to-End Balance Monitoring

As part of the Orion update, the `Ethereum Signer` will collect a list of montitored ERC20 addresses and the relevant token supply snapshots from the Cosmos side of the bridge and make assertions about the monitored ERC20 supplies before submitting any signatures. The snapshots include an Ethereum block height for which the `Ethereum Signer` process must get the historical balances of each monitored ERC20 address held by the [Gravity.sol](/solidity/contracts/Gravity.sol). If the `Gravity.sol` balance is less than the balance on the Cosmos side of the bridge, then the `Ethereum Signer` will halt the signature submission process until the imbalance is resolved or manually attended to.

## Delegate Addresses

This document outlines the Ethereum signatures, all contract calls on [Gravity.sol](/solidity/contracts/Gravity.sol) accept an array of signatures provided by a validator set stored in the contract.
Expand Down
4 changes: 2 additions & 2 deletions docs/design/oracle.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

As part of operating the Gravity bridge all validators run an `Oracle` this Ethereum oracle is bundled into the `gbt` (Gravity bridge tools) binary along with the [ethereum signer](/docs/design/ethereum-signing.md). For a detailed look at the code involved in this process see [code structure intro](/docs/developer/code-structure.md)

This process connects to an Ethereum node to monitor the Ethereum blockchain for new events involving the `Gravity Contract`.
This process connects to an Ethereum node to monitor the Ethereum blockchain for new events involving the `Gravity Contract`. While monitoring for events, the `Oracle` will also collect both a list of ERC20 token addresses to monitor, and snapshots of relevant token supply amounts from Cosmos. With this key information the Oracle will make end-to-end bridge balance assertions before continuing operation.

The `Gravity Contract` assigns every event a monotonically increasing `event_nonce` with no gaps. This nonces is the unique coordinating value for the Oracle. Every event has the `event_nonce` attached, this is used to ensure that when a validator submits a claim stating it has seen a specific event happening on Ethereum the ordering is unambiguous.
The `Gravity Contract` assigns every event a strictly increasing `event_nonce` with no gaps. This nonce is the unique coordinating value for the Oracle. Every event has the `event_nonce` attached, this is used to ensure an unambiguous ordering when when a validator submits a claim stating it has seen a specific event happening on Ethereum.

- An `Oracle` observes an event on the Ethereum chain, it packages this event into a `Claim` and submits this claim to the cosmos chain as an [Oracle message](/docs/design/messages.md##Oracle-messages)
- Within the Gravity Cosmos module this `Claim` either creates or is added to an existing `Attestation` that matches the details of the `Claim` once more than 66% of the active `Validator` set has made a `Claim` that matches the given `Attestation` the `Attestation` is executed. This may mint tokens, burn tokens, or whatever is appropriate for this particular event.
Expand Down
2 changes: 2 additions & 0 deletions docs/design/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ things are listed below.

[relaying semantics](/docs/design/relaying-semantics.md)

[Security Features](/docs/design/security-features.md)

### Specs

[slashing-spec](/spec/slashing-spec.md)
Expand Down
36 changes: 36 additions & 0 deletions docs/design/security-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Security Features

The Gravity Bridge has a number of features built in to double check its own operation at runtime to ensure the security of user funds. These features notably do not put users in a vulnerable spot when significant arbirage opportunities, black swan events, or large market shifts occur on either side of the bridge.

## Cross Bridge Balance Monitoring

As part of the Orion update, end-to-end bridge balance monitoring was added. This monitoring takes a two-sided approach to add security to the bridge through changes to the Ethereum side (within the `Orchestrator`, and the `Oracle`), and the Cosmos side (within the `gravity module`).

The checks described below will effectively halt the bridge on any misbehavior until it can be remedied. They will also force any attacker to execute the entirety of the attack in one go

### Cosmos-Side Balance Monitoring

Once any Ethereum `Event` has been voted on and accepted by the `validators`, an out-of-band [Sanity Check](https://en.wikipedia.org/wiki/Sanity_check) is performed to ensure that the state transitions caused by the `Event` match up to what are acceptable. This additional check and those in *Invariants* was inspired by observing types of attacks other bridges have suffered. Often in these attacks other data becomes corrupted or unusual behavior occurs alongside the critical loss of funds, so the bridge will halt in the event of any discovered irregular behavior.

### Ethereum-Side Balance Monitoring

Within the `Orchestrator` and the `Ethereum Signer` a function call has been added to assert the historical balances of the bridge are in order before any further bridge operations are performed. Specifically the balance monitoring involves:
* Collecting a governance-controlled list of monitored ERC20 token addresses from the Cosmos-side of the bridge
* Collecting a historical snapshot of both the minted Cosmos vouchers of Ethereum-originated assets and the locked Cosmos-originated assets
* Collecting the historical balances of each monitored ERC20 token held by [Gravity.sol](/solidity/contracts/Gravity.sol) at each height where a `Gravity.sol` `event` occured.
* Comparing the balances obtained from the Cosmos-side snapshots to the `Gravity.sol` balances, if any `Gravity.sol` balance is less than the Cosmos-side balance, the `Orchestrator` and the `Ethereum Signer` will not submit anything further to the Cosmos chain.


## Invariants

Cosmos SDK based blockchains have the option to enable the [Crisis module](https://docs.cosmos.network/main/modules/crisis) and gain the benefits of running [Invariants](https://en.wikipedia.org/wiki/Invariant_(mathematics)#Invariants_in_computer_science). The gravity module has two custom invariants which give the bridge additional security.

Validators are encouraged to run invariants frequently, at least every 200 blocks. Without specifying a custom invariant check rate, validators will be assigned a rate equal to a random prime number between 15 and 200.

### Module Balance Invariant

This invariant accounts for the balance held by the gravity module by looking at each unconfirmed Batch, pooled Transaction, and pending IBC Auto Forward. If an imbalance is detected, the chain will halt promptly.

### Store Validity Invariant

Inspired by attacks which other bridges have succumbed to, this check asserts that the values stored by the gravity module are not corrupt or invalid by reading every single value from the store and calling its ValidateBasic function where applicable. If any corrupt or invalid values are detected, the bridge will halt promptly.
9 changes: 4 additions & 5 deletions module/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,15 @@ all: install
install: go.sum
export GOFLAGS='-buildmode=pie'
export CGO_CPPFLAGS="-D_FORTIFY_SOURCE=2"
export CGO_LDFLAGS="-Wl,-z,relro,-z,now -fstack-protector"
export CGO_CFLAGS="-Wno-deprecated-declarations"
go install $(BUILD_FLAGS) ./cmd/gravity
export CGO_LDFLAGS="-Wl,-z,relro,-z,now -fstack-protector"
CGO_CFLAGS="-Wno-deprecated-declarations" go install $(BUILD_FLAGS) ./cmd/gravity

go.sum: go.mod
@echo "--> Ensure dependencies have not been modified"
GO111MODULE=on go mod verify

test:
@go test -mod=readonly $(PACKAGES)
test:
CGO_CFLAGS="-Wno-deprecated-declarations" go test -mod=readonly $(PACKAGES)

# look into .golangci.yml for enabling / disabling linters
lint:
Expand Down
6 changes: 3 additions & 3 deletions module/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

On first run:

```
```bash
sudo dnf install make automake gcc gcc-c++ kernel-devel

make
Expand All @@ -16,14 +16,14 @@ sudo make proto-tools

Following builds and test:

```
```bash
make
make test
```

To update protos after editing .proto files

```
```bash
make proto-gen
```

Expand Down
11 changes: 11 additions & 0 deletions module/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,17 @@ func (app *Gravity) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab
// Note: This should ONLY be called once, it should be called at the top of BeginBlocker guarded by firstBlock
func (app *Gravity) firstBeginBlocker(ctx sdk.Context) {
app.assertBech32PrefixMatches(ctx)

// The following call should panic if any invalid ERC20 addresses exist in types/const.go
monitoredErc20s := app.gravityKeeper.MonitoredERC20Tokens(ctx)
if len(monitoredErc20s) > 0 {
ctx.Logger().Info(
"Loaded Monitored ERC20 Tokens, your orchestrator is required to monitor the Gravity.sol balance of the following tokens: %v",
monitoredErc20s,
)
} else {
ctx.Logger().Info("Monitored ERC20 Tokens not yet set, your orchestrator is currently not required to monitor any Gravity.sol balances")
}
}

// EndBlocker application updates every end block
Expand Down
8 changes: 8 additions & 0 deletions module/app/upgrades/orion/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Orion UPGRADE
The *Orion* upgrade contains the following changes.

## Summary of Changes

* Updating Cosmos SDK version to v0.45.13, which is what the Cosmos Hub is currently running.
* Fee Collection Correction: Fees collected when sending tokens to Ethereum are being moved later in the transaction processing stage, meaning that the 2 basis point fee will only be collected if your message is successful.
* Cross-Bridge Balance Monitoring: This novel end-to-end balance monitoring will dramatically improve bridge security **without daily limits**. Imposing limits hurts the community by limiting valid response to dramatic shifts in the crypto market, which happen regularly. The Cosmos side of the bridge is getting enhanced monitoring every time an Ethereum event is processed. Additionally, Gravity Bridge will require all Orchestrators to check important balances of the Ethereum side of the bridge and compare them to the balances recorded on the Cosmos side of the bridge.
3 changes: 3 additions & 0 deletions module/app/upgrades/orion/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package orion

var PleiadesPart2ToOrionPlanName = "orion"
32 changes: 32 additions & 0 deletions module/app/upgrades/orion/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package orion

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
)

func GetOrionUpgradeHandler(
mm *module.Manager, configurator *module.Configurator, crisisKeeper *crisiskeeper.Keeper,
) func(
ctx sdk.Context, plan upgradetypes.Plan, vmap module.VersionMap,
) (module.VersionMap, error) {
if mm == nil {
panic("Nil argument to GetOrionUpgradeHandler")
}
return func(ctx sdk.Context, plan upgradetypes.Plan, vmap module.VersionMap) (module.VersionMap, error) {
ctx.Logger().Info("Orion upgrade: Starting upgrade")

ctx.Logger().Info("Orion Upgrade: Running any configured module migrations")
out, outErr := mm.RunMigrations(ctx, *configurator, vmap)
if outErr != nil {
return out, outErr
}
ctx.Logger().Info("Asserting invariants after upgrade")
crisisKeeper.AssertInvariants(ctx)

ctx.Logger().Info("Orion Upgrade Successful")
return out, nil
}
}
6 changes: 6 additions & 0 deletions module/app/upgrades/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
ibctransferkeeper "github.com/cosmos/ibc-go/v3/modules/apps/transfer/keeper"

"github.com/Gravity-Bridge/Gravity-Bridge/module/app/upgrades/orion"
"github.com/Gravity-Bridge/Gravity-Bridge/module/app/upgrades/singlestep"
)

Expand Down Expand Up @@ -71,4 +72,9 @@ func RegisterUpgradeHandlers(
singlestep.PlanName,
singlestep.GetUpgradeHandler(mm, configurator, crisisKeeper),
)

upgradeKeeper.SetUpgradeHandler(
orion.PleiadesPart2ToOrionPlanName,
orion.GetOrionUpgradeHandler(mm, configurator, crisisKeeper),
)
}
40 changes: 39 additions & 1 deletion module/proto/gravity/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,23 @@ service Query {

rpc GetListEvmChains(QueryListEvmChains)
returns (QueryListEvmChainsResponse) {
option (google.api.http).get = "/gravity/v1beta/query_list_evm_chains";
}
rpc GetMonitoredERC20Addresses(QueryMonitoredERC20Addresses)
returns (QueryMonitoredERC20AddressesResponse) {
option (google.api.http).get =
"/gravity/v1beta/query_monitored_token_addresses";
}
rpc GetBridgeBalanceSnapshots(QueryBridgeBalanceSnapshots)
returns (QueryBridgeBalanceSnapshotsResponse) {
option (google.api.http).get =
"/gravity/v1beta/query_list_evm_chains";
"/gravity/v1beta/query_bridge_balance_snapshots";
}
rpc GetBridgeBalanceSnapshotByEventNonce(
QueryBridgeBalanceSnapshotByEventNonce)
returns (QueryBridgeBalanceSnapshotByEventNonceResponse) {
option (google.api.http).get =
"/gravity/v1beta/query_bridge_balance_snapshot_by_event_nonce";
}
}

Expand Down Expand Up @@ -374,3 +389,26 @@ message QueryListEvmChains {
message QueryListEvmChainsResponse {
repeated EvmChain evm_chains = 1 [ (gogoproto.nullable) = false ];
}

message QueryMonitoredERC20Addresses {}

message QueryMonitoredERC20AddressesResponse { repeated string addresses = 1; }

// Query params for GetBridgeBalanceSnapshots, with a limit (0 for unlimited),
// and boolean newest_first (true for descending by event nonce)
message QueryBridgeBalanceSnapshots {
uint64 limit = 1;
bool newest_first = 2;
}

message QueryBridgeBalanceSnapshotsResponse {
repeated BridgeBalanceSnapshot snapshots = 1;
}

// Query params for GetBridgeBalanceSnapshots, with a limit (0 for unlimited),
// and boolean newest_first (true for descending by event nonce)
message QueryBridgeBalanceSnapshotByEventNonce { uint64 nonce = 1; }

message QueryBridgeBalanceSnapshotByEventNonceResponse {
BridgeBalanceSnapshot snapshot = 1;
}
30 changes: 29 additions & 1 deletion module/proto/gravity/v1/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package gravity.v1;
import "cosmos/base/v1beta1/coin.proto";
import "cosmos/bank/v1beta1/bank.proto";
import "gogoproto/gogo.proto";
import "gravity/v1/attestation.proto";
option go_package = "github.com/Gravity-Bridge/Gravity-Bridge/module/x/gravity/types";

message MonitoredERC20Addresses { repeated bytes addresses = 1; }

// BridgeValidator represents a validator's ETH address and its power
message BridgeValidator {
uint64 power = 1;
Expand Down Expand Up @@ -117,6 +120,21 @@ message AddEvmChainProposal {
string bridge_ethereum_address = 7;
}

// MonitoredERC20TokensProposal defines a custom governance proposal type to set
// the list of ERC20 tokens which orchestrators must monitor the balance of. If
// the balance on Ethereum does not match the Cosmos supply of these tokens,
// then the bridge will stop functioning.
message MonitoredERC20TokensProposal {
option (gogoproto.equal) = true;
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;

string title = 1;
string description = 2;
string evm_chain_prefix = 3;
repeated string tokens = 4;
}

// RemoveEvmChainProposal
// this types allows users to remove an EVM chain through gov proposal
message RemoveEvmChainProposal {
Expand All @@ -142,4 +160,14 @@ message PendingIbcAutoForward {
3; // the IBC channel to send `Amount` over via ibc-transfer module
uint64 event_nonce = 4; // the EventNonce from the MsgSendToCosmosClaim, used
// for ordering the queue
}
}

// BridgeBalanceSnapshot records the total bank supply of the Monitored ERC20
// Tokens immediately after applying each Attestation, plus the Cosmos and Eth
// Block Heights associated with the Attestation
message BridgeBalanceSnapshot {
uint64 cosmos_block_height = 1;
uint64 ethereum_block_height = 2;
repeated ERC20Token balances = 3;
uint64 event_nonce = 4;
}
Loading

0 comments on commit 8ec5d49

Please sign in to comment.