Skip to content

Commit

Permalink
feat: slashing unsign bridge call (#321)
Browse files Browse the repository at this point in the history
  • Loading branch information
zakir-code authored Apr 7, 2024
1 parent e166649 commit 61912c6
Show file tree
Hide file tree
Showing 19 changed files with 680 additions and 1,692 deletions.
34 changes: 17 additions & 17 deletions proto/fx/crosschain/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,17 @@ service Query {
rpc GetPendingSendToExternal(QueryPendingSendToExternalRequest) returns (QueryPendingSendToExternalResponse) {
option (google.api.http).get = "/fx/crosschain/v1/pending_send_to_external";
}
rpc RefundRecordByNonce(QueryRefundRecordByNonceRequest) returns (QueryRefundRecordByNonceResponse) {
option (google.api.http).get = "/fx/crosschain/v1/refund_record_by_nonce";
}
rpc RefundRecordByReceiver(QueryRefundRecordByReceiverRequest) returns (QueryRefundRecordByReceiverResponse) {
option (google.api.http).get = "/fx/crosschain/v1/refund_record_by_receiver";
}
rpc BridgeCallConfirmByNonce(QueryBridgeCallConfirmByNonceRequest) returns (QueryBridgeCallConfirmByNonceResponse) {
option (google.api.http).get = "/fx/crosschain/v1/bridge_call_confirm_by_nonce";
}
rpc LastPendingRefundRecordByAddr(QueryLastPendingRefundRecordByAddrRequest) returns (QueryLastPendingRefundRecordByAddrResponse) {
option (google.api.http).get = "/fx/crosschain/v1/last_pending_refund_record_by_addr";
rpc BridgeCallByNonce(QueryBridgeCallByNonceRequest) returns (QueryBridgeCallByNonceResponse) {
option (google.api.http).get = "/fx/crosschain/v1/bridge_call_by_nonce";
}
rpc BridgeCallByReceiver(QueryBridgeCallByReceiverRequest) returns (QueryBridgeCallByReceiverResponse) {
option (google.api.http).get = "/fx/crosschain/v1/bridge_call_by_receiver";
}
rpc LastPendingBridgeCallByAddr(QueryLastPendingBridgeCallByAddrRequest) returns (QueryLastPendingBridgeCallByAddrResponse) {
option (google.api.http).get = "/fx/crosschain/v1/last_pending_bridge_call_by_addr";
}

// Validators queries all oracle that match the given status.
Expand Down Expand Up @@ -314,20 +314,20 @@ message QueryBridgeChainListResponse {
repeated string chain_names = 1;
}

message QueryRefundRecordByNonceRequest {
message QueryBridgeCallByNonceRequest {
string chain_name = 1;
uint64 event_nonce = 2;
}
message QueryRefundRecordByNonceResponse {
RefundRecord record = 1;
message QueryBridgeCallByNonceResponse {
OutgoingBridgeCall bridge_call = 1;
}

message QueryRefundRecordByReceiverRequest {
message QueryBridgeCallByReceiverRequest {
string chain_name = 1;
string receiver_address = 2;
}
message QueryRefundRecordByReceiverResponse {
repeated RefundRecord records = 1;
message QueryBridgeCallByReceiverResponse {
repeated OutgoingBridgeCall bridge_calls = 1;
}

message QueryBridgeCallConfirmByNonceRequest {
Expand All @@ -340,10 +340,10 @@ message QueryBridgeCallConfirmByNonceResponse {
bool enough_power = 2;
}

message QueryLastPendingRefundRecordByAddrRequest {
message QueryLastPendingBridgeCallByAddrRequest {
string chain_name = 1;
string external_address = 2;
}
message QueryLastPendingRefundRecordByAddrResponse {
repeated RefundRecord records = 1;
message QueryLastPendingBridgeCallByAddrResponse {
repeated OutgoingBridgeCall bridge_call = 1;
}
9 changes: 0 additions & 9 deletions proto/fx/crosschain/v1/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,6 @@ message OutgoingTransferTx {
ERC20Token fee = 5 [(gogoproto.nullable) = false];
}

message RefundRecord {
uint64 event_nonce = 1;
string receiver = 2;
uint64 timeout = 3;
repeated ERC20Token tokens = 4 [(gogoproto.nullable) = false];
uint64 oracle_set_nonce = 5;
uint64 block = 6;
}

message SnapshotOracle {
uint64 oracle_set_nonce = 1;
repeated BridgeValidator members = 2 [(gogoproto.nullable) = false];
Expand Down
32 changes: 16 additions & 16 deletions x/crosschain/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ func GetQuerySubCmds(chainName string) []*cobra.Command {
// help cmd.
CmdCovertBridgeToken(chainName),

// refund token
CmdRefundRecord(chainName),
CmdRefundRecordByAddr(chainName),
// bridge call
CmdBridgeCall(chainName),
CmdBridgeCallByAddr(chainName),
CmdBridgeCallConfirm(chainName),
CmdLastPendingRefundRecord(chainName),
CmdLastPendingBridgeCall(chainName),
}

for _, command := range cmds {
Expand Down Expand Up @@ -828,10 +828,10 @@ func CmdGetBridgeCoinByDenom(chainName string) *cobra.Command {
return cmd
}

func CmdRefundRecord(chainName string) *cobra.Command {
func CmdBridgeCall(chainName string) *cobra.Command {
cmd := &cobra.Command{
Use: "refund-record [nonce]",
Short: "Query refund record by event nonce",
Use: "bridge-call [nonce]",
Short: "Query bridge call by event nonce",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
Expand All @@ -842,7 +842,7 @@ func CmdRefundRecord(chainName string) *cobra.Command {
return err
}

res, err := queryClient.RefundRecordByNonce(cmd.Context(), &types.QueryRefundRecordByNonceRequest{
res, err := queryClient.BridgeCallByNonce(cmd.Context(), &types.QueryBridgeCallByNonceRequest{
ChainName: chainName,
EventNonce: nonce,
})
Expand All @@ -855,10 +855,10 @@ func CmdRefundRecord(chainName string) *cobra.Command {
return cmd
}

func CmdRefundRecordByAddr(chainName string) *cobra.Command {
func CmdBridgeCallByAddr(chainName string) *cobra.Command {
cmd := &cobra.Command{
Use: "refund-record-by-receiver [address]",
Short: "Query refund records by receiver",
Use: "bridge-call-by-receiver [address]",
Short: "Query bridge call by receiver",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
Expand All @@ -868,7 +868,7 @@ func CmdRefundRecordByAddr(chainName string) *cobra.Command {
if err != nil {
return err
}
res, err := queryClient.RefundRecordByReceiver(cmd.Context(), &types.QueryRefundRecordByReceiverRequest{
res, err := queryClient.BridgeCallByReceiver(cmd.Context(), &types.QueryBridgeCallByReceiverRequest{
ChainName: chainName,
ReceiverAddress: receiver,
})
Expand Down Expand Up @@ -908,10 +908,10 @@ func CmdBridgeCallConfirm(chainName string) *cobra.Command {
return cmd
}

func CmdLastPendingRefundRecord(chainName string) *cobra.Command {
func CmdLastPendingBridgeCall(chainName string) *cobra.Command {
cmd := &cobra.Command{
Use: "last-pending-refund-record [external-address]",
Short: "Query last pending refund record for bridge address",
Use: "last-pending-bridge-call [external-address]",
Short: "Query last pending bridge call for bridge address",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
Expand All @@ -921,7 +921,7 @@ func CmdLastPendingRefundRecord(chainName string) *cobra.Command {
if err != nil {
return err
}
res, err := queryClient.LastPendingRefundRecordByAddr(cmd.Context(), &types.QueryLastPendingRefundRecordByAddrRequest{
res, err := queryClient.LastPendingBridgeCallByAddr(cmd.Context(), &types.QueryLastPendingBridgeCallByAddrRequest{
ChainName: chainName,
ExternalAddress: externalAddress,
})
Expand Down
63 changes: 11 additions & 52 deletions x/crosschain/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ func (k Keeper) slashing(ctx sdk.Context, signedWindow uint64) {
oracles := k.GetAllOracles(ctx, true)
oracleSetHasSlash := k.oracleSetSlashing(ctx, oracles, signedWindow)
batchHasSlash := k.batchSlashing(ctx, oracles, signedWindow)
refundHasSlash := k.refundSlashing(ctx, signedWindow)
if oracleSetHasSlash || batchHasSlash || refundHasSlash {
bridgeCallHasSlash := k.bridgeCallSlashing(ctx, signedWindow)
if oracleSetHasSlash || batchHasSlash || bridgeCallHasSlash {
k.CommonSetOracleTotalPower(ctx)
}
}
Expand Down Expand Up @@ -122,14 +122,14 @@ func (k Keeper) batchSlashing(ctx sdk.Context, oracles types.Oracles, signedWind
return hasSlash
}

func (k Keeper) refundSlashing(ctx sdk.Context, signedWindow uint64) (hasSlash bool) {
func (k Keeper) bridgeCallSlashing(ctx sdk.Context, signedWindow uint64) (hasSlash bool) {
maxHeight := uint64(ctx.BlockHeight()) - signedWindow
unSlashRefunds := k.GetUnSlashedRefundRecords(ctx, maxHeight)
unSlashOutgoingBridgeCalls := k.GetUnSlashedBridgeCalls(ctx, maxHeight)

snapshotOracleMap := make(map[uint64]*types.SnapshotOracle)
for _, record := range unSlashRefunds {
for _, record := range unSlashOutgoingBridgeCalls {
confirmOracleMap := make(map[string]bool)
k.IterBridgeCallConfirmByNonce(ctx, record.EventNonce, func(confirm *types.MsgBridgeCallConfirm) bool {
k.IterBridgeCallConfirmByNonce(ctx, record.Nonce, func(confirm *types.MsgBridgeCallConfirm) bool {
confirmOracleMap[confirm.ExternalAddress] = true
return false
})
Expand All @@ -138,7 +138,7 @@ func (k Keeper) refundSlashing(ctx sdk.Context, signedWindow uint64) (hasSlash b
if !found {
snapshotOracle, found = k.GetSnapshotOracle(ctx, record.OracleSetNonce)
if !found {
k.Logger(ctx).Error("refund slashing", "oracle set not found", record.OracleSetNonce)
k.Logger(ctx).Error("outgoing bridge call slashing", "oracle set not found", record.OracleSetNonce)
continue
}
snapshotOracleMap[record.OracleSetNonce] = snapshotOracle
Expand All @@ -148,16 +148,16 @@ func (k Keeper) refundSlashing(ctx sdk.Context, signedWindow uint64) (hasSlash b
if _, ok := confirmOracleMap[members.ExternalAddress]; !ok {
oracle, found := k.GetOracleByExternalAddress(ctx, members.ExternalAddress)
if !found {
k.Logger(ctx).Error("refund slashing", "oracle not found", members.ExternalAddress)
k.Logger(ctx).Error("outgoing bridge call slashing", "oracle not found", members.ExternalAddress)
continue
}
k.Logger(ctx).Info("slash oracle by refund", "externalAddress", members.ExternalAddress,
"oracleAddress", oracle.String(), "recordNonce", record.EventNonce, "blockHeight", ctx.BlockHeight())
k.Logger(ctx).Info("slash oracle by outgoing bridge call", "externalAddress", members.ExternalAddress,
"oracleAddress", oracle.String(), "nonce", record.Nonce, "blockHeight", ctx.BlockHeight())
k.SlashOracle(ctx, oracle.String())
hasSlash = true
}
}
k.SetLastSlashedRefundNonce(ctx, record.EventNonce)
k.SetLastSlashedBridgeCallNonce(ctx, record.Nonce)
}
return hasSlash
}
Expand Down Expand Up @@ -186,47 +186,6 @@ func (k Keeper) cleanupTimedOutBatches(ctx sdk.Context) {
})
}

func (k Keeper) cleanupTimeOutRefund(ctx sdk.Context) {
externalBlockHeight := k.GetLastObservedBlockHeight(ctx).ExternalBlockHeight
k.IterRefundRecord(ctx, func(record *types.RefundRecord) bool {
if record.Timeout > externalBlockHeight {
return true
}
receiver, coins, err := k.refundTokenToReceiver(ctx, record)
if err != nil {
k.Logger(ctx).Error("clean up refund timeout", "event nonce", record.EventNonce, "error", err.Error())
return false
}
k.DeleteRefundRecord(ctx, record)
k.DeleteBridgeCallConfirm(ctx, record.EventNonce)
k.RemoveEventSnapshotOracle(ctx, record.OracleSetNonce, record.EventNonce)

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(types.EventTypeRefundTimeout,
sdk.NewAttribute(sdk.AttributeKeySender, record.Receiver),
sdk.NewAttribute(types.AttributeKeyRefundAddress, receiver.String()),
sdk.NewAttribute(types.AttributeKeyEventNonce, fmt.Sprint(record.EventNonce)),
sdk.NewAttribute(sdk.AttributeKeyAmount, coins.String()),
),
})
return false
})
}

func (k Keeper) refundTokenToReceiver(ctx sdk.Context, record *types.RefundRecord) (sdk.AccAddress, sdk.Coins, error) {
receiverAddr := types.ExternalAddressToAccAddress(k.moduleName, record.Receiver)
cacheCtx, commit := ctx.CacheContext()
coins, err := k.bridgeCallTransferToSender(cacheCtx, receiverAddr.Bytes(), record.Tokens)
if err != nil {
return nil, nil, err
}
if err = k.bridgeCallTransferToReceiver(cacheCtx, receiverAddr, receiverAddr.Bytes(), coins); err != nil {
return nil, nil, err
}
commit()
return receiverAddr, coins, nil
}

func (k Keeper) cleanupTimeOutBridgeCall(ctx sdk.Context) {
externalBlockHeight := k.GetLastObservedBlockHeight(ctx).ExternalBlockHeight
k.IterateOutgoingBridgeCalls(ctx, func(data *types.OutgoingBridgeCall) bool {
Expand Down
Loading

0 comments on commit 61912c6

Please sign in to comment.