Skip to content

Commit

Permalink
allow MsgFinalizeTokenWithdrawal to be executed by anyone
Browse files Browse the repository at this point in the history
  • Loading branch information
beer-1 committed Sep 4, 2024
1 parent 5ae2b9c commit 944722e
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 182 deletions.
17 changes: 9 additions & 8 deletions proto/opinit/ophost/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -165,29 +165,30 @@ message MsgInitiateTokenDepositResponse {

// MsgFinalizeTokenWithdrawal is a message finalizing funds withdrawal from L2.
message MsgFinalizeTokenWithdrawal {
option (cosmos.msg.v1.signer) = "receiver";
option (cosmos.msg.v1.signer) = "sender";
option (amino.name) = "ophost/MsgFinalizeTokenWithdrawal";

// address of the sender of the transaction

string sender = 1 [(gogoproto.moretags) = "yaml:\"sender\"", (cosmos_proto.scalar) = "cosmos.AddressString"];
uint64 bridge_id = 2 [(gogoproto.moretags) = "yaml:\"bridge_id\""];
uint64 output_index = 3 [(gogoproto.moretags) = "yaml:\"output_index\""];
repeated bytes withdrawal_proofs = 4 [(gogoproto.nullable) = true, (amino.dont_omitempty) = false];

// withdraw tx data

string sender = 5 [(gogoproto.moretags) = "yaml:\"sender\""];
string receiver = 1 [(gogoproto.moretags) = "yaml:\"receiver\"", (cosmos_proto.scalar) = "cosmos.AddressString"];
uint64 sequence = 6 [(gogoproto.moretags) = "yaml:\"sequence\""];
cosmos.base.v1beta1.Coin amount = 7
string from = 5 [(gogoproto.moretags) = "yaml:\"from\""];
string to = 6 [(gogoproto.moretags) = "yaml:\"to\"", (cosmos_proto.scalar) = "cosmos.AddressString"];
uint64 sequence = 7 [(gogoproto.moretags) = "yaml:\"sequence\""];
cosmos.base.v1beta1.Coin amount = 8
[(gogoproto.moretags) = "yaml:\"amount\"", (gogoproto.nullable) = false, (amino.dont_omitempty) = true];

// output root proofs

// version of the output root
bytes version = 8 [(gogoproto.moretags) = "yaml:\"version\""];
bytes storage_root = 9 [(gogoproto.moretags) = "yaml:\"storage_root\""];
bytes last_block_hash = 10 [(gogoproto.moretags) = "yaml:\"last_block_hash\""];
bytes version = 9 [(gogoproto.moretags) = "yaml:\"version\""];
bytes storage_root = 10 [(gogoproto.moretags) = "yaml:\"storage_root\""];
bytes last_block_hash = 11 [(gogoproto.moretags) = "yaml:\"last_block_hash\""];
}

// MsgFinalizeTokenWithdrawalResponse returns a message handle result.
Expand Down
31 changes: 8 additions & 23 deletions x/ophost/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,8 @@ func NewFinalizeTokenWithdrawal(ac address.Codec) *cobra.Command {
"bridge_id": "1",
"output_index": "1",
"sequence": "1",
"sender" : "bech32-address",
"from" : "l2-bech32-address",
"to" : "l1-bech32-address",
"amount": {"amount": "10000000", "denom": "uinit"},
"withdrawal_proofs": [ "base64-encoded proof1", "proof2", ... ],
"version": "base64-encoded version",
Expand All @@ -358,40 +359,24 @@ func NewFinalizeTokenWithdrawal(ac address.Codec) *cobra.Command {
if err != nil {
return err
}
var withdrawalInfo types.MsgFinalizeTokenWithdrawal
err = clientCtx.Codec.UnmarshalJSON(withdrawalBytes, &withdrawalInfo)

var msg types.MsgFinalizeTokenWithdrawal
err = clientCtx.Codec.UnmarshalJSON(withdrawalBytes, &msg)
if err != nil {
return err
}

// cannot validate sender address here because it is l2 address.
sender := withdrawalInfo.Sender
if len(sender) == 0 {
return fmt.Errorf("sender address is required")
}

receiver, err := ac.BytesToString(clientCtx.GetFromAddress())
sender, err := ac.BytesToString(clientCtx.GetFromAddress())
if err != nil {
return err
}

msg := types.NewMsgFinalizeTokenWithdrawal(
withdrawalInfo.BridgeId,
withdrawalInfo.OutputIndex,
withdrawalInfo.Sequence,
withdrawalInfo.WithdrawalProofs,
sender,
receiver,
withdrawalInfo.Amount,
withdrawalInfo.Version,
withdrawalInfo.StorageRoot,
withdrawalInfo.LastBlockHash,
)
msg.Sender = sender
if err = msg.Validate(ac); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
},
}

Expand Down
3 changes: 2 additions & 1 deletion x/ophost/client/cli/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,8 @@ func (s *CLITestSuite) TestNewFinalizeTokenWithdrawal() {
"withdrawal_proofs": [
"q6T8JJm7AdbD4rgZ3BjanRHdE1x7aLZwp36pPrOOey4="
],
"sender": "init1q6jhwnarkw2j5qqgx3qlu20k8nrdglft5ksr0g",
"from": "init1q6jhwnarkw2j5qqgx3qlu20k8nrdglft5ksr0g",
"to": "init1q6jhwnarkw2j5qqgx3qlu20k8nrdglft5ksr0g",
"sequence": "5",
"amount": {"amount": "100", "denom": "uinit"},
"version": "AQ==",
Expand Down
8 changes: 4 additions & 4 deletions x/ophost/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ func (ms MsgServer) FinalizeTokenWithdrawal(ctx context.Context, req *types.MsgF
return nil, err
}

receiver, err := ms.authKeeper.AddressCodec().StringToBytes(req.Receiver)
receiver, err := ms.authKeeper.AddressCodec().StringToBytes(req.To)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -310,7 +310,7 @@ func (ms MsgServer) FinalizeTokenWithdrawal(ctx context.Context, req *types.MsgF

// verify storage root can be generated from
// withdrawal proofs and withdrawal tx data.
withdrawalHash := types.GenerateWithdrawalHash(bridgeId, l2Sequence, req.Sender, req.Receiver, denom, amount.Uint64())
withdrawalHash := types.GenerateWithdrawalHash(bridgeId, l2Sequence, req.From, req.To, denom, amount.Uint64())
if ok, err := ms.HasProvenWithdrawal(ctx, bridgeId, withdrawalHash); err != nil {
return nil, err
} else if ok {
Expand Down Expand Up @@ -339,8 +339,8 @@ func (ms MsgServer) FinalizeTokenWithdrawal(ctx context.Context, req *types.MsgF
sdk.NewAttribute(types.AttributeKeyBridgeId, strconv.FormatUint(bridgeId, 10)),
sdk.NewAttribute(types.AttributeKeyOutputIndex, strconv.FormatUint(outputIndex, 10)),
sdk.NewAttribute(types.AttributeKeyL2Sequence, strconv.FormatUint(l2Sequence, 10)),
sdk.NewAttribute(types.AttributeKeyFrom, req.Sender),
sdk.NewAttribute(types.AttributeKeyTo, req.Receiver),
sdk.NewAttribute(types.AttributeKeyFrom, req.From),
sdk.NewAttribute(types.AttributeKeyTo, req.To),
sdk.NewAttribute(types.AttributeKeyL1Denom, denom),
sdk.NewAttribute(types.AttributeKeyL2Denom, types.L2Denom(bridgeId, denom)),
sdk.NewAttribute(types.AttributeKeyAmount, amount.String()),
Expand Down
6 changes: 6 additions & 0 deletions x/ophost/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ func Test_FinalizeTokenWithdrawal(t *testing.T) {

require.NoError(t, err)
_, err = ms.FinalizeTokenWithdrawal(ctx, types.NewMsgFinalizeTokenWithdrawal(
addrsStr[3], // any address can execute this
1, 1, 1, proofs,
sender,
receiver,
Expand Down Expand Up @@ -359,6 +360,11 @@ func Test_UpdateChallengers(t *testing.T) {
_, err = ms.UpdateChallengers(ctx, msg)
require.Error(t, err)

// case 6. remove all challengers
msg = types.NewMsgUpdateChallengers(addrsStr[4], 1, []string{})
_, err = ms.UpdateChallengers(ctx, msg)
require.Error(t, err)

// invalid signer
invalidAddr, err := input.AccountKeeper.AddressCodec().BytesToString(authtypes.NewModuleAddress(types.ModuleName))
require.NoError(t, err)
Expand Down
4 changes: 0 additions & 4 deletions x/ophost/types/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ func GenerateOutputRoot(version byte, storageRoot []byte, latestBlockHash []byte
}

func GenerateWithdrawalHash(bridgeId uint64, l2Sequence uint64, sender string, receiver string, denom string, amount uint64) [32]byte {
const spliter = "|"
var withdrawalHash [32]byte
seed := []byte{}
seed = binary.BigEndian.AppendUint64(seed, bridgeId)
Expand All @@ -37,15 +36,12 @@ func GenerateWithdrawalHash(bridgeId uint64, l2Sequence uint64, sender string, r
// variable length
senderDigest := sha3.Sum256([]byte(sender))
seed = append(seed, senderDigest[:]...) // put utf8 encoded address

Check warning on line 38 in x/ophost/types/output.go

View check run for this annotation

Codecov / codecov/patch

x/ophost/types/output.go#L37-L38

Added lines #L37 - L38 were not covered by tests
seed = append(seed, []byte(spliter)...)
// variable length
receiverDigest := sha3.Sum256([]byte(receiver))
seed = append(seed, receiverDigest[:]...) // put utf8 encoded address

Check warning on line 41 in x/ophost/types/output.go

View check run for this annotation

Codecov / codecov/patch

x/ophost/types/output.go#L40-L41

Added lines #L40 - L41 were not covered by tests
seed = append(seed, []byte(spliter)...)
// variable length
denomDigest := sha3.Sum256([]byte(denom))
seed = append(seed, denomDigest[:]...)

Check warning on line 44 in x/ophost/types/output.go

View check run for this annotation

Codecov / codecov/patch

x/ophost/types/output.go#L43-L44

Added lines #L43 - L44 were not covered by tests
seed = append(seed, []byte(spliter)...)
seed = binary.BigEndian.AppendUint64(seed, amount)

// double hash the leaf node
Expand Down
22 changes: 14 additions & 8 deletions x/ophost/types/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,23 +202,25 @@ func (msg MsgInitiateTokenDeposit) Validate(ac address.Codec) error {

// NewMsgFinalizeTokenWithdrawal creates a new MsgFinalizeTokenWithdrawal
func NewMsgFinalizeTokenWithdrawal(
sender string,
bridgeId uint64,
outputIndex uint64,
sequence uint64,
withdrawalProofs [][]byte,
sender string,
receiver string,
from string,
to string,
amount sdk.Coin,
version []byte,
storageRoot []byte,
lastBlockHash []byte,
) *MsgFinalizeTokenWithdrawal {
return &MsgFinalizeTokenWithdrawal{
Sender: sender,

Check warning on line 218 in x/ophost/types/tx.go

View check run for this annotation

Codecov / codecov/patch

x/ophost/types/tx.go#L218

Added line #L218 was not covered by tests
BridgeId: bridgeId,
OutputIndex: outputIndex,
WithdrawalProofs: withdrawalProofs,
Sender: sender,
Receiver: receiver,
From: from,
To: to,

Check warning on line 223 in x/ophost/types/tx.go

View check run for this annotation

Codecov / codecov/patch

x/ophost/types/tx.go#L222-L223

Added lines #L222 - L223 were not covered by tests
Sequence: sequence,
Amount: amount,
Version: version,
Expand All @@ -229,12 +231,16 @@ func NewMsgFinalizeTokenWithdrawal(

// Validate performs basic MsgFinalizeTokenWithdrawal message validation.
func (msg MsgFinalizeTokenWithdrawal) Validate(ac address.Codec) error {
// cannot validate sender address as it can be any format of address based on the chain.
if len(msg.Sender) == 0 {
return sdkerrors.ErrInvalidAddress.Wrap("sender address cannot be empty")
if _, err := ac.StringToBytes(msg.Sender); err != nil {
return err
}

Check warning on line 236 in x/ophost/types/tx.go

View check run for this annotation

Codecov / codecov/patch

x/ophost/types/tx.go#L233-L236

Added lines #L233 - L236 were not covered by tests

// cannot validate from address as it can be any format of address based on the chain.
if len(msg.From) == 0 {
return sdkerrors.ErrInvalidAddress.Wrap("from address cannot be empty")

Check warning on line 240 in x/ophost/types/tx.go

View check run for this annotation

Codecov / codecov/patch

x/ophost/types/tx.go#L239-L240

Added lines #L239 - L240 were not covered by tests
}

if _, err := ac.StringToBytes(msg.Receiver); err != nil {
if _, err := ac.StringToBytes(msg.To); err != nil {

Check warning on line 243 in x/ophost/types/tx.go

View check run for this annotation

Codecov / codecov/patch

x/ophost/types/tx.go#L243

Added line #L243 was not covered by tests
return err
}

Expand Down
Loading

0 comments on commit 944722e

Please sign in to comment.