Skip to content

Commit

Permalink
make packet commitments fixed length (#7564)
Browse files Browse the repository at this point in the history
* make packet commitments fixed length

* updated docs for packet commits
  • Loading branch information
gjermundgaraba authored Nov 14, 2024
1 parent a2d377c commit 107ab75
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 5 deletions.
15 changes: 10 additions & 5 deletions modules/core/04-channel/v2/types/commitment.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
)

// CommitPacket returns the V2 packet commitment bytes. The commitment consists of:
// 0x02 + sha256_hash(destinationChannel) + sha256_hash(timeout) + sha256_hash(payload) from a given packet.
// This results in a fixed length preimage.
// ha256_hash(0x02 + sha256_hash(destinationChannel) + sha256_hash(timeout) + sha256_hash(payload)) from a given packet.
// This results in a fixed length preimage of 32 bytes.
// NOTE: A fixed length preimage is ESSENTIAL to prevent relayers from being able
// to malleate the packet fields and create a commitment hash that matches the original packet.
func CommitPacket(packet Packet) []byte {
Expand All @@ -27,8 +27,10 @@ func CommitPacket(packet Packet) []byte {
appHash := sha256.Sum256(appBytes)
buf = append(buf, appHash[:]...)

buf = append([]byte{byte(2)}, buf...)

hash := sha256.Sum256(buf)
return append([]byte{byte(2)}, hash[:]...)
return hash[:]
}

// hashPayload returns the hash of the payload.
Expand All @@ -48,14 +50,17 @@ func hashPayload(data Payload) []byte {
return hash[:]
}

// CommitAcknowledgement returns the hash of the acknowledgement data.
// CommitAcknowledgement returns the V2 acknowledgement commitment bytes. The commitment consists of:
// sha256_hash(0x02 + sha256_hash(ack1) + sha256_hash(ack2) + ...) from a given acknowledgement.
func CommitAcknowledgement(acknowledgement Acknowledgement) []byte {
var buf []byte
for _, ack := range acknowledgement.GetAppAcknowledgements() {
hash := sha256.Sum256(ack)
buf = append(buf, hash[:]...)
}

buf = append([]byte{byte(2)}, buf...)

hash := sha256.Sum256(buf)
return append([]byte{byte(2)}, hash[:]...)
return hash[:]
}
58 changes: 58 additions & 0 deletions modules/core/04-channel/v2/types/commitment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package types_test

import (
"encoding/hex"
"encoding/json"
"testing"

"github.com/stretchr/testify/require"

transfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types"
"github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types"
)

// TestCommitPacket is primarily used to document the expected commitment output
// so that other implementations (such as the IBC Solidity) can replicate the
// same commitment output. But it is also useful to catch any changes in the commitment.
func TestCommitPacket(t *testing.T) {
transferData, err := json.Marshal(transfertypes.FungibleTokenPacketData{
Denom: "uatom",
Amount: "1000000",
Sender: "sender",
Receiver: "receiver",
Memo: "memo",
})
require.NoError(t, err)
packet := types.Packet{
Sequence: 1,
SourceChannel: "channel-0",
DestinationChannel: "channel-1",
TimeoutTimestamp: 100,
Payloads: []types.Payload{
{
SourcePort: transfertypes.PortID,
DestinationPort: transfertypes.PortID,
Version: transfertypes.V1,
Encoding: "application/json",
Value: transferData,
},
},
}
commitment := types.CommitPacket(packet)
require.Equal(t, "450194f2ce25b12487f65593e106d91367a1e5c90b2efc03ed78265a54cfcebe", hex.EncodeToString(commitment))
require.Len(t, commitment, 32)
}

// TestCommitAcknowledgement is primarily used to document the expected commitment output
// so that other implementations (such as the IBC Solidity) can replicate the
// same commitment output. But it is also useful to catch any changes in the commitment.
func TestCommitAcknowledgement(t *testing.T) {
ack := types.Acknowledgement{
AppAcknowledgements: [][]byte{
[]byte("some bytes"),
},
}

commitment := types.CommitAcknowledgement(ack)
require.Equal(t, "f03b4667413e56aaf086663267913e525c442b56fa1af4fa3f3dab9f37044c5b", hex.EncodeToString(commitment))
}
34 changes: 34 additions & 0 deletions modules/core/24-host/v2/packet_key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package v2_test

import (
"encoding/hex"
"testing"

"github.com/stretchr/testify/require"

"github.com/cosmos/ibc-go/v9/modules/core/24-host/v2"
)

// TestPacketCommitmentKey is primarily used to document the expected key output
// so that other implementations (such as the IBC Solidity) can replicate the
// same key output. But it is also useful to catch any changes in the keys.
func TestPacketCommitmentKey(t *testing.T) {
actual := hex.EncodeToString(v2.PacketCommitmentKey("channel-0", 1))
require.Equal(t, "6368616e6e656c2d30010000000000000001", actual)
}

// TestPacketReceiptKey is primarily used to document the expected key output
// so that other implementations (such as the IBC Solidity) can replicate the
// same key output. But it is also useful to catch any changes in the keys.
func TestPacketReceiptKey(t *testing.T) {
actual := hex.EncodeToString(v2.PacketReceiptKey("channel-0", 1))
require.Equal(t, "6368616e6e656c2d30020000000000000001", actual)
}

// TestPacketAcknowledgementKey is primarily used to document the expected key output
// so that other implementations (such as the IBC Solidity) can replicate the
// same key output. But it is also useful to catch any changes in the keys.
func TestPacketAcknowledgementKey(t *testing.T) {
actual := hex.EncodeToString(v2.PacketAcknowledgementKey("channel-0", 1))
require.Equal(t, "6368616e6e656c2d30030000000000000001", actual)
}

0 comments on commit 107ab75

Please sign in to comment.