Skip to content

Commit

Permalink
Merge branch 'main' into bolten/replace-num256
Browse files Browse the repository at this point in the history
  • Loading branch information
EricBolten committed Nov 20, 2021
2 parents 6afba3a + b705d74 commit 9155c95
Show file tree
Hide file tree
Showing 25 changed files with 560 additions and 558 deletions.
46 changes: 20 additions & 26 deletions module/x/gravity/keeper/ethereum_event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,8 @@ import (
"github.com/peggyjv/gravity-bridge/module/x/gravity/types"
)

// EthereumEventProcessor processes `accepted` EthereumEvents
type EthereumEventProcessor struct {
keeper Keeper
bankKeeper types.BankKeeper
}

func (a EthereumEventProcessor) DetectMaliciousSupply(ctx sdk.Context, denom string, amount sdk.Int) (err error) {
currentSupply := a.keeper.bankKeeper.GetSupply(ctx, denom)
func (k Keeper) DetectMaliciousSupply(ctx sdk.Context, denom string, amount sdk.Int) (err error) {
currentSupply := k.bankKeeper.GetSupply(ctx, denom)
newSupply := new(big.Int).Add(currentSupply.Amount.BigInt(), amount.BigInt())
if newSupply.BitLen() > 256 {
return sdkerrors.Wrapf(types.ErrSupplyOverflow, "malicious supply of %s detected", denom)
Expand All @@ -28,68 +22,68 @@ func (a EthereumEventProcessor) DetectMaliciousSupply(ctx sdk.Context, denom str
}

// Handle is the entry point for EthereumEvent processing
func (a EthereumEventProcessor) Handle(ctx sdk.Context, eve types.EthereumEvent) (err error) {
func (k Keeper) Handle(ctx sdk.Context, eve types.EthereumEvent) (err error) {
switch event := eve.(type) {
case *types.SendToCosmosEvent:
// Check if coin is Cosmos-originated asset and get denom
isCosmosOriginated, denom := a.keeper.ERC20ToDenomLookup(ctx, event.TokenContract)
isCosmosOriginated, denom := k.ERC20ToDenomLookup(ctx, event.TokenContract)
addr, _ := sdk.AccAddressFromBech32(event.CosmosReceiver)
coins := sdk.Coins{sdk.NewCoin(denom, event.Amount)}

if !isCosmosOriginated {
if err := a.DetectMaliciousSupply(ctx, denom, event.Amount); err != nil {
if err := k.DetectMaliciousSupply(ctx, denom, event.Amount); err != nil {
return err
}

// if it is not cosmos originated, mint the coins (aka vouchers)
if err := a.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil {
if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, coins); err != nil {
return sdkerrors.Wrapf(err, "mint vouchers coins: %s", coins)
}
}

if err := a.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, coins); err != nil {
if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addr, coins); err != nil {
return err
}
a.keeper.AfterSendToCosmosEvent(ctx, *event)
k.AfterSendToCosmosEvent(ctx, *event)
return nil

case *types.BatchExecutedEvent:
a.keeper.batchTxExecuted(ctx, common.HexToAddress(event.TokenContract), event.BatchNonce)
a.keeper.AfterBatchExecutedEvent(ctx, *event)
k.batchTxExecuted(ctx, common.HexToAddress(event.TokenContract), event.BatchNonce)
k.AfterBatchExecutedEvent(ctx, *event)
return nil

case *types.ERC20DeployedEvent:
if err := a.verifyERC20DeployedEvent(ctx, event); err != nil {
if err := k.verifyERC20DeployedEvent(ctx, event); err != nil {
return err
}

// add to denom-erc20 mapping
a.keeper.setCosmosOriginatedDenomToERC20(ctx, event.CosmosDenom, event.TokenContract)
a.keeper.AfterERC20DeployedEvent(ctx, *event)
k.setCosmosOriginatedDenomToERC20(ctx, event.CosmosDenom, event.TokenContract)
k.AfterERC20DeployedEvent(ctx, *event)
return nil

case *types.ContractCallExecutedEvent:
a.keeper.AfterContractCallExecutedEvent(ctx, *event)
k.AfterContractCallExecutedEvent(ctx, *event)
return nil

case *types.SignerSetTxExecutedEvent:
// TODO here we should check the contents of the validator set against
// the store, if they differ we should take some action to indicate to the
// user that bridge highjacking has occurred
a.keeper.setLastObservedSignerSetTx(ctx, types.SignerSetTx{
k.setLastObservedSignerSetTx(ctx, types.SignerSetTx{
Nonce: event.SignerSetTxNonce,
Signers: event.Members,
})
a.keeper.AfterSignerSetExecutedEvent(ctx, *event)
k.AfterSignerSetExecutedEvent(ctx, *event)
return nil

default:
return sdkerrors.Wrapf(types.ErrInvalid, "event type: %T", event)
}
}

func (a EthereumEventProcessor) verifyERC20DeployedEvent(ctx sdk.Context, event *types.ERC20DeployedEvent) error {
if existingERC20, exists := a.keeper.getCosmosOriginatedERC20(ctx, event.CosmosDenom); exists {
func (k Keeper) verifyERC20DeployedEvent(ctx sdk.Context, event *types.ERC20DeployedEvent) error {
if existingERC20, exists := k.getCosmosOriginatedERC20(ctx, event.CosmosDenom); exists {
return sdkerrors.Wrapf(
types.ErrInvalidERC20Event,
"ERC20 token %s already exists for denom %s", existingERC20.Hex(), event.CosmosDenom,
Expand All @@ -109,11 +103,11 @@ func (a EthereumEventProcessor) verifyERC20DeployedEvent(ctx sdk.Context, event
// NOTE: This path is not encouraged and all supported assets should have
// metadata defined. If metadata cannot be defined, consider adding the token's
// metadata on the fly.
if md, ok := a.keeper.bankKeeper.GetDenomMetaData(ctx, event.CosmosDenom); ok && md.Base != "" {
if md, ok := k.bankKeeper.GetDenomMetaData(ctx, event.CosmosDenom); ok && md.Base != "" {
return verifyERC20Token(md, event)
}

if supply := a.keeper.bankKeeper.GetSupply(ctx, event.CosmosDenom); supply.IsZero() {
if supply := k.bankKeeper.GetSupply(ctx, event.CosmosDenom); supply.IsZero() {
return sdkerrors.Wrapf(
types.ErrInvalidERC20Event,
"no supply exists for token %s without metadata", event.CosmosDenom,
Expand Down
12 changes: 6 additions & 6 deletions module/x/gravity/keeper/ethereum_event_handler_test.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package keeper

import (
sdktypes "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"math/big"
"testing"

sdktypes "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
)

func TestEthereumEventProcessor_DetectMaliciousSupply(t *testing.T) {
func TestDetectMaliciousSupply(t *testing.T) {
input := CreateTestEnv(t)
eep := EthereumEventProcessor{keeper: input.GravityKeeper, bankKeeper: input.BankKeeper}

// set supply to maximum value
var testBigInt big.Int
testBigInt.SetBit(new(big.Int), 256, 1).Sub(&testBigInt, big.NewInt(1))
bigCoinAmount := sdktypes.NewIntFromBigInt(&testBigInt)

err := eep.DetectMaliciousSupply(input.Context, "stake", bigCoinAmount)
err := input.GravityKeeper.DetectMaliciousSupply(input.Context, "stake", bigCoinAmount)
require.Error(t, err, "didn't error out on too much added supply")
}
}
3 changes: 2 additions & 1 deletion module/x/gravity/keeper/ethereum_event_vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func (k Keeper) TryEventVoteRecord(ctx sdk.Context, eventVoteRecord *types.Ether
func (k Keeper) processEthereumEvent(ctx sdk.Context, event types.EthereumEvent) {
// then execute in a new Tx so that we can store state on failure
xCtx, commit := ctx.CacheContext()
if err := k.EthereumEventProcessor.Handle(xCtx, event); err != nil { // execute with a transient storage
if err := k.Handle(xCtx, event); err != nil { // execute with a transient storage
// If the attestation fails, something has gone wrong and we can't recover it. Log and move on
// The attestation will still be marked "Observed", and validators can still be slashed for not
// having voted for it.
Expand All @@ -130,6 +130,7 @@ func (k Keeper) processEthereumEvent(ctx sdk.Context, event types.EthereumEvent)
"nonce", fmt.Sprint(event.GetEventNonce()),
)
} else {
ctx.EventManager().EmitEvents(xCtx.EventManager().Events()) // copy events to original context
commit() // persist transient storage
}
}
Expand Down
2 changes: 1 addition & 1 deletion module/x/gravity/keeper/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,4 @@ func (k *Keeper) SetHooks(sh types.GravityHooks) *Keeper {
k.hooks = sh

return k
}
}
10 changes: 1 addition & 9 deletions module/x/gravity/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ import (

// Keeper maintains the link to storage and exposes getter/setter methods for the various parts of the state machine
type Keeper struct {
StakingKeeper types.StakingKeeper
EthereumEventProcessor interface {
Handle(sdk.Context, types.EthereumEvent) error
}

StakingKeeper types.StakingKeeper
storeKey sdk.StoreKey
paramSpace paramtypes.Subspace
cdc codec.Codec
Expand Down Expand Up @@ -66,10 +62,6 @@ func NewKeeper(
SlashingKeeper: slashingKeeper,
PowerReduction: powerReduction,
}
k.EthereumEventProcessor = EthereumEventProcessor{
keeper: k,
bankKeeper: bankKeeper,
}

return k
}
Expand Down
11 changes: 3 additions & 8 deletions orchestrator/cosmos_gravity/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use gravity_utils::message_signatures::{
encode_logic_call_confirm, encode_tx_batch_confirm, encode_valset_confirm,
};
use gravity_utils::types::*;
use std::collections::BTreeMap;

pub async fn signer_set_tx_confirmation_messages(
contact: &Contact,
Expand Down Expand Up @@ -129,7 +130,7 @@ pub fn ethereum_event_messages(
// could be reduced by adding two traits to sort against but really this is the easiest option.
//
// We index the events by event nonce in an unordered hashmap and then play them back in order into a vec
let mut unordered_msgs = std::collections::HashMap::new();
let mut unordered_msgs = BTreeMap::new();
for deposit in deposits {
let event = proto::SendToCosmosEvent {
event_nonce: downcast_to_u64(deposit.event_nonce.clone()).unwrap(),
Expand Down Expand Up @@ -206,14 +207,8 @@ pub fn ethereum_event_messages(
unordered_msgs.insert(valset.event_nonce, msg);
}

let mut keys = Vec::new();
for (key, _) in unordered_msgs.iter() {
keys.push(key.clone());
}
keys.sort();

let mut msgs = Vec::new();
for i in keys.iter() {
for (i, _) in unordered_msgs.clone().iter() {
msgs.push(unordered_msgs.remove_entry(&i).unwrap().1);
}

Expand Down
12 changes: 2 additions & 10 deletions orchestrator/cosmos_gravity/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ pub async fn get_valset(
signer_set_nonce: nonce,
})
.await?;
let valset = response.into_inner().signer_set;
let valset = match valset {
Some(v) => Some(v.into()),
None => None,
};
let valset = response.into_inner().signer_set.map(Into::into);
Ok(valset)
}

Expand Down Expand Up @@ -49,11 +45,7 @@ pub async fn get_latest_valset(
let response = client
.latest_signer_set_tx(LatestSignerSetTxRequest {})
.await?;
let valset = response.into_inner().signer_set;
let valset = match valset {
Some(v) => Some(v.into()),
None => None,
};
let valset = response.into_inner().signer_set.map(Into::into);
Ok(valset)
}

Expand Down
10 changes: 4 additions & 6 deletions orchestrator/cosmos_gravity/src/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,10 @@ pub async fn send_to_eth(
gas_adjustment: f64,
) -> Result<TxResponse, GravityError> {
if amount.denom != bridge_fee.denom {
return Err(GravityError::CosmosGrpcError(CosmosGrpcError::BadInput(
format!(
"The amount ({}) and bridge_fee ({}) denominations do not match.",
amount.denom, bridge_fee.denom,
),
)));
return Err(GravityError::CosmosGrpcError(CosmosGrpcError::BadInput(format!(
"The amount ({}) and bridge_fee ({}) denominations do not match.",
amount.denom, bridge_fee.denom,
))));
}

let cosmos_address = cosmos_key.to_address(&contact.get_prefix()).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion orchestrator/gorc/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl Application for GorcApp {
} else {
match std::env::var("RUST_LOG") {
Ok(val) => {
if val != "" {
if !val.is_empty() {
val.into()
} else {
trace::Config::default()
Expand Down
33 changes: 17 additions & 16 deletions orchestrator/gorc/src/commands/cosmos_to_eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl Runnable for CosmosToEthCmd {
let cosmos_key = config.load_deep_space_key(cosmos_key.to_string());

let cosmos_prefix = config.cosmos.prefix.trim();
let cosmos_address = cosmos_key.to_address(&cosmos_prefix).unwrap();
let cosmos_address = cosmos_key.to_address(cosmos_prefix).unwrap();
let cosmos_grpc = config.cosmos.prefix.trim();
println!("Sending from Cosmos address {}", cosmos_address);
abscissa_tokio::run_with_actix(&APP, async {
Expand Down Expand Up @@ -118,21 +118,22 @@ impl Runnable for CosmosToEthCmd {
let times = self.args.get(4).expect("times is required");
let times = times.parse::<usize>().expect("cannot parse times");

if found.is_none() {
panic!("You don't have any {} tokens!", gravity_denom);
} else if amount.amount.clone() * times.into() >= found.clone().unwrap().amount
&& times == 1
{
if is_cosmos_originated {
panic!("Your transfer of {} {} tokens is greater than your balance of {} tokens. Remember you need some to pay for fees!", print_atom(amount.amount), gravity_denom, print_atom(found.unwrap().amount.clone()));
} else {
panic!("Your transfer of {} {} tokens is greater than your balance of {} tokens. Remember you need some to pay for fees!", print_eth(amount.amount), gravity_denom, print_eth(found.unwrap().amount.clone()));
}
} else if amount.amount.clone() * times.into() >= found.clone().unwrap().amount {
if is_cosmos_originated {
panic!("Your transfer of {} * {} {} tokens is greater than your balance of {} tokens. Try to reduce the amount or the --times parameter", print_atom(amount.amount), times, gravity_denom, print_atom(found.unwrap().amount.clone()));
} else {
panic!("Your transfer of {} * {} {} tokens is greater than your balance of {} tokens. Try to reduce the amount or the --times parameter", print_eth(amount.amount), times, gravity_denom, print_eth(found.unwrap().amount.clone()));
match found {
None => panic!("You don't have any {} tokens!", gravity_denom),
Some(found) => {
if amount.amount.clone() * times.into() >= found.amount && times == 1 {
if is_cosmos_originated {
panic!("Your transfer of {} {} tokens is greater than your balance of {} tokens. Remember you need some to pay for fees!", print_atom(amount.amount), gravity_denom, print_atom(found.amount.clone()));
} else {
panic!("Your transfer of {} {} tokens is greater than your balance of {} tokens. Remember you need some to pay for fees!", print_eth(amount.amount), gravity_denom, print_eth(found.amount.clone()));
}
} else if amount.amount.clone() * times.into() >= found.amount {
if is_cosmos_originated {
panic!("Your transfer of {} * {} {} tokens is greater than your balance of {} tokens. Try to reduce the amount or the --times parameter", print_atom(amount.amount), times, gravity_denom, print_atom(found.amount.clone()));
} else {
panic!("Your transfer of {} * {} {} tokens is greater than your balance of {} tokens. Try to reduce the amount or the --times parameter", print_eth(amount.amount), times, gravity_denom, print_eth(found.amount.clone()));
}
}
}
}

Expand Down
32 changes: 19 additions & 13 deletions orchestrator/gorc/src/commands/deploy/erc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::convert::TryFrom;
use std::process::exit;
use std::{
sync::Arc,
time::{Duration, Instant},
time::Duration,
};
use tokio::time::sleep as delay_for;

Expand Down Expand Up @@ -90,30 +90,36 @@ impl Erc20 {

println!("We have deployed ERC20 contract {}, waiting to see if the Cosmos chain choses to adopt it", res);

let start = Instant::now();
loop {
let req = DenomToErc20Request {
denom: denom.clone(),
};
match tokio::time::timeout(Duration::from_secs(100), async {
loop {
let req = DenomToErc20Request {
denom: denom.clone(),
};

let res = grpc.denom_to_erc20(req).await;
let res = grpc.denom_to_erc20(req).await;

if let Ok(val) = res {
let val = val.into_inner();
if let Ok(val) = res {
break val;
}
delay_for(Duration::from_secs(1)).await;
}
})
.await
{
Ok(val) => {
println!(
"Asset {} has accepted new ERC20 representation {}",
denom, val.erc20
denom,
val.into_inner().erc20
);
exit(0);
}

if Instant::now() - start > Duration::from_secs(100) {
Err(_) => {
println!(
"Your ERC20 contract was not adopted, double check the metadata and try again"
);
exit(1);
}
delay_for(Duration::from_secs(1)).await;
}
}
}
Loading

0 comments on commit 9155c95

Please sign in to comment.