Skip to content

Commit

Permalink
fix: Fix blobHash collision
Browse files Browse the repository at this point in the history
  • Loading branch information
howjmay committed Sep 19, 2023
1 parent 9a8f776 commit 5d00efc
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 11 deletions.
13 changes: 6 additions & 7 deletions contracts/wasm/corecontracts/test/core_blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

// this is the expected blob hash for key0/val0 key1/val1
const expectedBlobHash = "0x5fec3bfc701d80bdf75e337cb3dcb401c2423d15fc17a74d5b644dae143118b1"
const expectedBlobHash = "0x54cb8e9c45ca6d368dba92da34cfa47ce617f04807af19f67de333fad0039e6b"

func setupBlob(t *testing.T) *wasmsolo.SoloContext {
ctx := setup(t)
Expand Down Expand Up @@ -78,15 +78,14 @@ func TestListBlobs(t *testing.T) {

fStore := coreblob.ScFuncs.StoreBlob(ctx)
fStore.Params.Blobs().GetBytes("key0").SetValue([]byte("val0"))
fStore.Params.Blobs().GetBytes("key1").SetValue([]byte("_val1"))
fStore.Params.Blobs().GetBytes("key1").SetValue([]byte("val1"))
fStore.Func.Post()
require.NoError(t, ctx.Err)
expectedHash := "0x462af4abe5977f4dd985a0a097705925b9fa6c033c9d931c1e2171f710693462"
require.Equal(t, expectedHash, fStore.Results.Hash().Value().String())
require.Equal(t, expectedBlobHash, fStore.Results.Hash().Value().String())

fList := coreblob.ScFuncs.ListBlobs(ctx)
fList.Func.Call()
size := fList.Results.BlobSizes().GetInt32(wasmtypes.HashFromString(expectedHash)).Value()
// The sum of the size of the value of `key0` and `key1` is len("val0")+len("_val1") = 9
require.Equal(t, int32(9), size)
size := fList.Results.BlobSizes().GetInt32(wasmtypes.HashFromString(expectedBlobHash)).Value()
// The sum of the size of the value of `key0` and `key1` is len("val0")+len("val1") = 8
require.Equal(t, int32(8), size)
}
13 changes: 9 additions & 4 deletions packages/vm/core/blob/internal.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package blob

import (
"encoding/binary"
"fmt"

"github.com/iotaledger/wasp/packages/hashing"
Expand All @@ -25,11 +26,15 @@ func mustGetBlobHash(fields dict.Dict) (hashing.HashValue, []kv.Key, [][]byte) {
sorted := fields.KeysSorted() // mind determinism
values := make([][]byte, 0, len(sorted))
all := make([][]byte, 0, 2*len(sorted))
for _, k := range sorted {
v := fields.Get(k)
var prefix [4]byte

// hashBlob = hash(KeyLen0|Key0|Val0 | KeyLen1|Key1|Val1 | ... | KeyLenN|KeyN|ValN)
// by prepend the key length we can avoid the possible collision
for _, key := range sorted {
v := fields.Get(key)
values = append(values, v)
all = append(all, v)
all = append(all, []byte(k))
binary.LittleEndian.PutUint32(prefix[:], uint32(len(key)))
all = append(all, prefix[:], []byte(key), v)
}
return hashing.HashData(all...), sorted, values
}
Expand Down
43 changes: 43 additions & 0 deletions packages/vm/core/blob/internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package blob

import (
"encoding/hex"
"testing"

"github.com/stretchr/testify/require"

"github.com/iotaledger/wasp/packages/kv/dict"
)

func TestMustGetBlobHash(t *testing.T) {
t.Run("normal", func(t *testing.T) {
fields := dict.Dict{
"key0": []byte("val0"),
"key1": []byte("val1"),
}

h, keys, values := mustGetBlobHash(fields)
for i, k := range keys {
require.Equal(t, fields[k], values[i])
}

resHash, err := hex.DecodeString("54cb8e9c45ca6d368dba92da34cfa47ce617f04807af19f67de333fad0039e6b")
require.NoError(t, err)
require.Equal(t, resHash, h.Bytes())
})
t.Run("potential collision", func(t *testing.T) {
fields := dict.Dict{
"123": []byte("ab"),
"123a": []byte("b"),
}

h, keys, values := mustGetBlobHash(fields)
for i, k := range keys {
require.Equal(t, fields[k], values[i])
}

resHash, err := hex.DecodeString("5a99cff5dcba5d8b0efcbdc8b534a57853fd468d03109d941937e480b37361b1")
require.NoError(t, err)
require.Equal(t, resHash, h.Bytes())
})
}

0 comments on commit 5d00efc

Please sign in to comment.