Skip to content

Commit

Permalink
refactor: replace timeout with height (#269)
Browse files Browse the repository at this point in the history
Co-authored-by: nulnut <151493716+nulnut@users.noreply.github.com>
  • Loading branch information
zakir-code and nulnut authored Mar 18, 2024
1 parent bbad8aa commit 8db1a93
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 36 deletions.
16 changes: 8 additions & 8 deletions app/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestNewDefaultGenesisByDenom(t *testing.T) {
"amount": "10000000000000000000000"
},
"delegate_multiple": "10",
"bridge_call_refund_timeout": "604800000000000"
"bridge_call_refund_timeout": "604800000"
},
"last_observed_event_nonce": "0",
"last_observed_block_height": {
Expand Down Expand Up @@ -84,7 +84,7 @@ func TestNewDefaultGenesisByDenom(t *testing.T) {
"amount": "10000000000000000000000"
},
"delegate_multiple": "10",
"bridge_call_refund_timeout": "604800000000000"
"bridge_call_refund_timeout": "604800000"
},
"last_observed_event_nonce": "0",
"last_observed_block_height": {
Expand Down Expand Up @@ -167,7 +167,7 @@ func TestNewDefaultGenesisByDenom(t *testing.T) {
"amount": "10000000000000000000000"
},
"delegate_multiple": "10",
"bridge_call_refund_timeout": "604800000000000"
"bridge_call_refund_timeout": "604800000"
},
"last_observed_event_nonce": "0",
"last_observed_block_height": {
Expand Down Expand Up @@ -246,7 +246,7 @@ func TestNewDefaultGenesisByDenom(t *testing.T) {
"amount": "10000000000000000000000"
},
"delegate_multiple": "10",
"bridge_call_refund_timeout": "604800000000000"
"bridge_call_refund_timeout": "604800000"
},
"last_observed_event_nonce": "0",
"last_observed_block_height": {
Expand Down Expand Up @@ -396,7 +396,7 @@ func TestNewDefaultGenesisByDenom(t *testing.T) {
"amount": "10000000000000000000000"
},
"delegate_multiple": "10",
"bridge_call_refund_timeout": "604800000000000"
"bridge_call_refund_timeout": "604800000"
},
"last_observed_event_nonce": "0",
"last_observed_block_height": {
Expand Down Expand Up @@ -453,7 +453,7 @@ func TestNewDefaultGenesisByDenom(t *testing.T) {
"amount": "10000000000000000000000"
},
"delegate_multiple": "10",
"bridge_call_refund_timeout": "604800000000000"
"bridge_call_refund_timeout": "604800000"
},
"last_observed_event_nonce": "0",
"last_observed_block_height": {
Expand Down Expand Up @@ -496,7 +496,7 @@ func TestNewDefaultGenesisByDenom(t *testing.T) {
"amount": "10000000000000000000000"
},
"delegate_multiple": "10",
"bridge_call_refund_timeout": "604800000000000"
"bridge_call_refund_timeout": "604800000"
},
"last_observed_event_nonce": "0",
"last_observed_block_height": {
Expand Down Expand Up @@ -575,7 +575,7 @@ func TestNewDefaultGenesisByDenom(t *testing.T) {
"amount": "10000000000000000000000"
},
"delegate_multiple": "10",
"bridge_call_refund_timeout": "604800000000000"
"bridge_call_refund_timeout": "604800000"
},
"last_observed_event_nonce": "0",
"last_observed_block_height": {
Expand Down
4 changes: 2 additions & 2 deletions solidity/contracts/bridge/FxBridgeLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,8 @@ contract FxBridgeLogic is
);

require(
block.timestamp < _timeout,
"timeout must be greater than the current block timestamp."
block.number < _timeout,
"refund timeout must be greater than the current block height."
);

require(
Expand Down
19 changes: 19 additions & 0 deletions x/crosschain/keeper/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,22 @@ func (k Keeper) SetLastEventNonceByOracle(ctx sdk.Context, oracleAddr sdk.AccAdd
store := ctx.KVStore(k.storeKey)
store.Set(types.GetLastEventNonceByOracleKey(oracleAddr), sdk.Uint64ToBigEndian(eventNonce))
}

// CalExternalTimeoutHeight This gets the timeout height in External blocks.
func (k Keeper) CalExternalTimeoutHeight(ctx sdk.Context, params types.Params, timeout uint64) uint64 {
currentFxHeight := ctx.BlockHeight()
// we store the last observed Cosmos and Ethereum heights, we do not concern ourselves if these values
// are zero because no batch can be produced if the last Ethereum block height is not first populated by a deposit event.
heights := k.GetLastObservedBlockHeight(ctx)
if heights.ExternalBlockHeight == 0 {
return 0
}
// we project how long it has been in milliseconds since the last Ethereum block height was observed
projectedMillis := (uint64(currentFxHeight) - heights.BlockHeight) * params.AverageBlockTime
// we convert that projection into the current Ethereum height using the average Ethereum block time in millis
projectedCurrentEthereumHeight := (projectedMillis / params.AverageExternalBlockTime) + heights.ExternalBlockHeight
// we convert our target time for block timeouts (lets say 12 hours) into a number of blocks to
// place on top of our projection of the current Ethereum block height.
blocksToAdd := timeout / params.AverageExternalBlockTime
return projectedCurrentEthereumHeight + blocksToAdd
}
23 changes: 2 additions & 21 deletions x/crosschain/keeper/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ func (k Keeper) BuildOutgoingTxBatch(ctx sdk.Context, tokenContract, feeReceive
if types.OutgoingTransferTxs(selectedTx).TotalFee().LT(minimumFee) {
return nil, errorsmod.Wrap(types.ErrInvalid, "total fee less than minimum fee")
}
batchTimeout := k.GetBatchTimeoutHeight(ctx)
params := k.GetParams(ctx)
batchTimeout := k.CalExternalTimeoutHeight(ctx, params, params.ExternalBatchTimeout)
if batchTimeout <= 0 {
return nil, errorsmod.Wrap(types.ErrInvalid, "batch timeout height")
}
Expand Down Expand Up @@ -79,26 +80,6 @@ func (k Keeper) BuildOutgoingTxBatch(ctx sdk.Context, tokenContract, feeReceive
return batch, nil
}

// GetBatchTimeoutHeight This gets the batch timeout height in External blocks.
func (k Keeper) GetBatchTimeoutHeight(ctx sdk.Context) uint64 {
currentFxHeight := ctx.BlockHeight()
params := k.GetParams(ctx)
// we store the last observed Cosmos and Ethereum heights, we do not concern ourselves if these values
// are zero because no batch can be produced if the last Ethereum block height is not first populated by a deposit event.
heights := k.GetLastObservedBlockHeight(ctx)
if heights.ExternalBlockHeight == 0 {
return 0
}
// we project how long it has been in milliseconds since the last Ethereum block height was observed
projectedMillis := (uint64(currentFxHeight) - heights.BlockHeight) * params.AverageBlockTime
// we convert that projection into the current Ethereum height using the average Ethereum block time in millis
projectedCurrentEthereumHeight := (projectedMillis / params.AverageExternalBlockTime) + heights.ExternalBlockHeight
// we convert our target time for block timeouts (lets say 12 hours) into a number of blocks to
// place on top of our projection of the current Ethereum block height.
blocksToAdd := params.ExternalBatchTimeout / params.AverageExternalBlockTime
return projectedCurrentEthereumHeight + blocksToAdd
}

// OutgoingTxBatchExecuted is run when the Cosmos chain detects that a batch has been executed on Ethereum
// It frees all the transactions in the batch, then cancels all earlier batches
func (k Keeper) OutgoingTxBatchExecuted(ctx sdk.Context, tokenContract string, batchNonce uint64) {
Expand Down
4 changes: 3 additions & 1 deletion x/crosschain/keeper/bridge_call_refund.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ func (k Keeper) AddRefundRecord(ctx sdk.Context, receiver string, eventNonce uin
snapshotOracle.EventNonces = append(snapshotOracle.EventNonces, eventNonce)
k.SetSnapshotOracle(ctx, snapshotOracle)

params := k.GetParams(ctx)
refundTimeout := k.CalExternalTimeoutHeight(ctx, params, params.BridgeCallRefundTimeout)
k.SetRefundRecord(ctx, &types.RefundRecord{
EventNonce: eventNonce,
Receiver: receiver,
Timeout: k.GetBridgeCallRefundTimeout(ctx),
Timeout: refundTimeout,
OracleSetNonce: oracleSet.Nonce,
Tokens: tokens,
})
Expand Down
4 changes: 3 additions & 1 deletion x/crosschain/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,9 @@ func (k Keeper) Oracles(c context.Context, _ *types.QueryOraclesRequest) (*types
}

func (k Keeper) ProjectedBatchTimeoutHeight(c context.Context, _ *types.QueryProjectedBatchTimeoutHeightRequest) (*types.QueryProjectedBatchTimeoutHeightResponse, error) {
timeout := k.GetBatchTimeoutHeight(sdk.UnwrapSDKContext(c))
ctx := sdk.UnwrapSDKContext(c)
params := k.GetParams(ctx)
timeout := k.CalExternalTimeoutHeight(ctx, params, params.ExternalBatchTimeout)
return &types.QueryProjectedBatchTimeoutHeightResponse{TimeoutHeight: timeout}, nil
}

Expand Down
5 changes: 2 additions & 3 deletions x/crosschain/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package types
import (
"errors"
"fmt"
"time"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -18,7 +17,7 @@ const (
MaxResults = 100
MaxOracleSetRequestsResults = 5
MaxKeepEventSize = 100
DefaultBridgeCallRefundTimeout = uint64(7 * 24 * time.Hour)
DefaultBridgeCallRefundTimeout = 604_800_000 // 7 * 24 * 3600 * 1000
)

var (
Expand Down Expand Up @@ -98,7 +97,7 @@ func (m *Params) ValidateBasic() error {
if len(m.Oracles) > 0 {
return errors.New("deprecated oracles")
}
if m.BridgeCallRefundTimeout <= uint64(1*time.Hour) {
if m.BridgeCallRefundTimeout <= 3_600_000 {
return fmt.Errorf("invalid bridge call refund timeout")
}
return nil
Expand Down

0 comments on commit 8db1a93

Please sign in to comment.