github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/pkg/fftypes/message_test.go (about)

     1  // Copyright © 2021 Kaleido, Inc.
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package fftypes
    18  
    19  import (
    20  	"context"
    21  	"crypto/sha256"
    22  	"encoding/json"
    23  	"testing"
    24  
    25  	"github.com/stretchr/testify/assert"
    26  )
    27  
    28  func TestSealBareMessage(t *testing.T) {
    29  	msg := Message{}
    30  	err := msg.Seal(context.Background())
    31  	assert.NoError(t, err)
    32  	assert.NotNil(t, msg.Header.ID)
    33  	assert.NotNil(t, msg.Header.DataHash)
    34  	assert.NotNil(t, msg.Hash)
    35  }
    36  
    37  func TestVerifyEmptyTopicString(t *testing.T) {
    38  	msg := Message{
    39  		Header: MessageHeader{
    40  			Topics: []string{""},
    41  		},
    42  	}
    43  	err := msg.Verify(context.Background())
    44  	assert.Regexp(t, `FF10131.*header.topics\[0\]`, err)
    45  }
    46  
    47  func TestVerifyBadTagString(t *testing.T) {
    48  	msg := Message{
    49  		Header: MessageHeader{
    50  			Tag: "!wrong",
    51  		},
    52  	}
    53  	err := msg.Verify(context.Background())
    54  	assert.Regexp(t, `FF10131.*header.tag`, err)
    55  }
    56  
    57  func TestSealNilDataID(t *testing.T) {
    58  	msg := Message{
    59  		Data: DataRefs{
    60  			{},
    61  		},
    62  	}
    63  	err := msg.Seal(context.Background())
    64  	assert.Regexp(t, "FF10144.*0", err)
    65  }
    66  
    67  func TestVerifyNilDataHash(t *testing.T) {
    68  	msg := Message{
    69  		Data: DataRefs{
    70  			{ID: NewUUID()},
    71  		},
    72  	}
    73  	err := msg.Verify(context.Background())
    74  	assert.Regexp(t, "FF10144.*0", err)
    75  }
    76  
    77  func TestSeaDupDataID(t *testing.T) {
    78  	id1 := NewUUID()
    79  	hash1 := NewRandB32()
    80  	hash2 := NewRandB32()
    81  	msg := Message{
    82  		Data: DataRefs{
    83  			{ID: id1, Hash: hash1},
    84  			{ID: id1, Hash: hash2},
    85  		},
    86  	}
    87  	err := msg.Seal(context.Background())
    88  	assert.Regexp(t, "FF10145.*1", err)
    89  }
    90  
    91  func TestVerifylDupDataHash(t *testing.T) {
    92  	id1 := NewUUID()
    93  	id2 := NewUUID()
    94  	hash1 := NewRandB32()
    95  	msg := Message{
    96  		Data: DataRefs{
    97  			{ID: id1, Hash: hash1},
    98  			{ID: id2, Hash: hash1},
    99  		},
   100  	}
   101  	err := msg.Verify(context.Background())
   102  	assert.Regexp(t, "FF10145.*1", err)
   103  }
   104  
   105  func TestVerifyNilHashes(t *testing.T) {
   106  	msg := Message{}
   107  	err := msg.Verify(context.Background())
   108  	assert.Regexp(t, "FF10147", err)
   109  }
   110  
   111  func TestVerifyNilMisMatchedHashes(t *testing.T) {
   112  	msg := Message{
   113  		Header: MessageHeader{
   114  			DataHash: NewRandB32(),
   115  		},
   116  		Hash: NewRandB32(),
   117  	}
   118  	err := msg.Verify(context.Background())
   119  	assert.Regexp(t, "FF10146", err)
   120  }
   121  
   122  func TestSealKnownMessage(t *testing.T) {
   123  	msgid := MustParseUUID("2cd37805-5f40-4e12-962e-67868cde3049")
   124  	cid := MustParseUUID("39296b6e-91b9-4a61-b279-833c85b04d94")
   125  	data1 := MustParseUUID("e3a3b714-7e49-4c73-a4ea-87a50b19961a")
   126  	data2 := MustParseUUID("cc66b23f-d340-4333-82d5-b63adc1c3c07")
   127  	data3 := MustParseUUID("189c8185-2b92-481a-847a-e57595ab3541")
   128  	var gid Bytes32
   129  	gid.UnmarshalText([]byte("3fcc7e07069e441f07c9f6b26f16fcb2dc896222d72888675082fd308440d9ae"))
   130  	var hash1, hash2, hash3 Bytes32
   131  	hash1.UnmarshalText([]byte("3fcc7e07069e441f07c9f6b26f16fcb2dc896222d72888675082fd308440d9ae"))
   132  	hash2.UnmarshalText([]byte("1d1462e02d7acee49a8448267c65067e0bec893c9a0c050b9835efa376fec046"))
   133  	hash3.UnmarshalText([]byte("284b535da66aa0734af56c708426d756331baec3bce3079e508003bcf4738ee6"))
   134  	msg := Message{
   135  		Header: MessageHeader{
   136  			ID:        msgid,
   137  			CID:       cid,
   138  			Type:      MessageTypePrivate,
   139  			TxType:    TransactionTypeBatchPin,
   140  			Author:    "0x12345",
   141  			Namespace: "ns1",
   142  			Topics:    []string{"topic1", "topic2"},
   143  			Tag:       "tag1",
   144  			Created:   UnixTime(1620104103123456789),
   145  			Group:     &gid,
   146  		},
   147  		Data: DataRefs{
   148  			{ID: data1, Hash: &hash1},
   149  			{Hash: &hash2, ID: data2}, // Demonstrating we hash in order id,hash order, even if Go definition is re-ordered
   150  			{ID: data3, Hash: &hash3},
   151  		},
   152  	}
   153  	err := msg.Seal(context.Background())
   154  	assert.NoError(t, err)
   155  
   156  	// Data IDs are hashed the the sequence of the message - that is preserved as the message moves through
   157  	dataHashData, _ := json.Marshal(&msg.Data)
   158  	var dataHash Bytes32 = sha256.Sum256([]byte(dataHashData))
   159  	assert.Equal(t, `[{"id":"e3a3b714-7e49-4c73-a4ea-87a50b19961a","hash":"3fcc7e07069e441f07c9f6b26f16fcb2dc896222d72888675082fd308440d9ae"},{"id":"cc66b23f-d340-4333-82d5-b63adc1c3c07","hash":"1d1462e02d7acee49a8448267c65067e0bec893c9a0c050b9835efa376fec046"},{"id":"189c8185-2b92-481a-847a-e57595ab3541","hash":"284b535da66aa0734af56c708426d756331baec3bce3079e508003bcf4738ee6"}]`, string(dataHashData))
   160  	assert.Equal(t, `2468d5c26cc85968acaf8b96d09476453916ea4eab41632a31d09efc7ab297d2`, dataHash.String())
   161  	assert.Equal(t, dataHash, *msg.Header.DataHash)
   162  
   163  	// Header contains the data hash, and is hashed into the message hash
   164  	actualHeader, _ := json.Marshal(&msg.Header)
   165  	expectedHeader := `{"id":"2cd37805-5f40-4e12-962e-67868cde3049","cid":"39296b6e-91b9-4a61-b279-833c85b04d94","type":"private","txtype":"batch_pin","author":"0x12345","created":"2021-05-04T04:55:03.123456789Z","namespace":"ns1","group":"3fcc7e07069e441f07c9f6b26f16fcb2dc896222d72888675082fd308440d9ae","topic":["topic1","topic2"],"tag":"tag1","datahash":"2468d5c26cc85968acaf8b96d09476453916ea4eab41632a31d09efc7ab297d2"}`
   166  	var msgHash Bytes32 = sha256.Sum256([]byte(expectedHeader))
   167  	assert.Equal(t, expectedHeader, string(actualHeader))
   168  	assert.Equal(t, `95f0a6a16ba67df7f24c5403733faebb89c304d66d55c21e149213d8ec7e2633`, msgHash.String())
   169  	assert.Equal(t, msgHash, *msg.Hash)
   170  
   171  	// Verify also returns good
   172  	err = msg.Verify(context.Background())
   173  	assert.NoError(t, err)
   174  
   175  	msg.Sequence = 12345
   176  	var ls LocallySequenced = &msg
   177  	assert.Equal(t, int64(12345), ls.LocalSequence())
   178  }