github.com/hyperledger-labs/bdls@v2.1.1+incompatible/protoutil/commonutils_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package protoutil
     8  
     9  import (
    10  	"bytes"
    11  	"errors"
    12  	"testing"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	cb "github.com/hyperledger/fabric-protos-go/common"
    16  	pb "github.com/hyperledger/fabric-protos-go/peer"
    17  	"github.com/hyperledger/fabric/common/crypto"
    18  	"github.com/hyperledger/fabric/protoutil/fakes"
    19  	"github.com/stretchr/testify/assert"
    20  )
    21  
    22  //go:generate counterfeiter -o fakes/signer_serializer.go --fake-name SignerSerializer . signerSerializer
    23  
    24  type signerSerializer interface {
    25  	Signer
    26  }
    27  
    28  func TestNonceRandomness(t *testing.T) {
    29  	n1, err := CreateNonce()
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  	n2, err := CreateNonce()
    34  	if err != nil {
    35  		t.Fatal(err)
    36  	}
    37  	if bytes.Equal(n1, n2) {
    38  		t.Fatalf("Expected nonces to be different, got %x and %x", n1, n2)
    39  	}
    40  }
    41  
    42  func TestNonceLength(t *testing.T) {
    43  	n, err := CreateNonce()
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  	actual := len(n)
    48  	expected := crypto.NonceSize
    49  	if actual != expected {
    50  		t.Fatalf("Expected nonce to be of size %d, got %d instead", expected, actual)
    51  	}
    52  
    53  }
    54  
    55  func TestUnmarshalPayload(t *testing.T) {
    56  	var payload *cb.Payload
    57  	good, _ := proto.Marshal(&cb.Payload{
    58  		Data: []byte("payload"),
    59  	})
    60  	payload, err := UnmarshalPayload(good)
    61  	assert.NoError(t, err, "Unexpected error unmarshaling payload")
    62  	assert.NotNil(t, payload, "Payload should not be nil")
    63  	payload = UnmarshalPayloadOrPanic(good)
    64  	assert.NotNil(t, payload, "Payload should not be nil")
    65  
    66  	bad := []byte("bad payload")
    67  	assert.Panics(t, func() {
    68  		_ = UnmarshalPayloadOrPanic(bad)
    69  	}, "Expected panic unmarshaling malformed payload")
    70  
    71  }
    72  
    73  func TestUnmarshalSignatureHeader(t *testing.T) {
    74  	t.Run("invalid header", func(t *testing.T) {
    75  		sighdrBytes := []byte("invalid signature header")
    76  		_, err := UnmarshalSignatureHeader(sighdrBytes)
    77  		assert.Error(t, err, "Expected unmarshaling error")
    78  	})
    79  
    80  	t.Run("valid empty header", func(t *testing.T) {
    81  		sighdr := &cb.SignatureHeader{}
    82  		sighdrBytes := MarshalOrPanic(sighdr)
    83  		sighdr, err := UnmarshalSignatureHeader(sighdrBytes)
    84  		assert.NoError(t, err, "Unexpected error unmarshaling signature header")
    85  		assert.Nil(t, sighdr.Creator)
    86  		assert.Nil(t, sighdr.Nonce)
    87  	})
    88  
    89  	t.Run("valid header", func(t *testing.T) {
    90  		sighdr := &cb.SignatureHeader{
    91  			Creator: []byte("creator"),
    92  			Nonce:   []byte("nonce"),
    93  		}
    94  		sighdrBytes := MarshalOrPanic(sighdr)
    95  		sighdr, err := UnmarshalSignatureHeader(sighdrBytes)
    96  		assert.NoError(t, err, "Unexpected error unmarshaling signature header")
    97  		assert.Equal(t, []byte("creator"), sighdr.Creator)
    98  		assert.Equal(t, []byte("nonce"), sighdr.Nonce)
    99  	})
   100  }
   101  
   102  func TestUnmarshalSignatureHeaderOrPanic(t *testing.T) {
   103  
   104  	t.Run("panic due to invalid header", func(t *testing.T) {
   105  		sighdrBytes := []byte("invalid signature header")
   106  		assert.Panics(t, func() {
   107  			UnmarshalSignatureHeaderOrPanic(sighdrBytes)
   108  		}, "Expected panic with invalid header")
   109  	})
   110  
   111  	t.Run("no panic as the header is valid", func(t *testing.T) {
   112  		sighdr := &cb.SignatureHeader{}
   113  		sighdrBytes := MarshalOrPanic(sighdr)
   114  		sighdr = UnmarshalSignatureHeaderOrPanic(sighdrBytes)
   115  		assert.Nil(t, sighdr.Creator)
   116  		assert.Nil(t, sighdr.Nonce)
   117  	})
   118  }
   119  
   120  func TestUnmarshalEnvelope(t *testing.T) {
   121  	var env *cb.Envelope
   122  	good, _ := proto.Marshal(&cb.Envelope{})
   123  	env, err := UnmarshalEnvelope(good)
   124  	assert.NoError(t, err, "Unexpected error unmarshaling envelope")
   125  	assert.NotNil(t, env, "Envelope should not be nil")
   126  	env = UnmarshalEnvelopeOrPanic(good)
   127  	assert.NotNil(t, env, "Envelope should not be nil")
   128  
   129  	bad := []byte("bad envelope")
   130  	assert.Panics(t, func() {
   131  		_ = UnmarshalEnvelopeOrPanic(bad)
   132  	}, "Expected panic unmarshaling malformed envelope")
   133  
   134  }
   135  
   136  func TestUnmarshalBlock(t *testing.T) {
   137  	var env *cb.Block
   138  	good, _ := proto.Marshal(&cb.Block{})
   139  	env, err := UnmarshalBlock(good)
   140  	assert.NoError(t, err, "Unexpected error unmarshaling block")
   141  	assert.NotNil(t, env, "Block should not be nil")
   142  	env = UnmarshalBlockOrPanic(good)
   143  	assert.NotNil(t, env, "Block should not be nil")
   144  
   145  	bad := []byte("bad block")
   146  	assert.Panics(t, func() {
   147  		_ = UnmarshalBlockOrPanic(bad)
   148  	}, "Expected panic unmarshaling malformed block")
   149  
   150  }
   151  
   152  func TestUnmarshalEnvelopeOfType(t *testing.T) {
   153  	env := &cb.Envelope{}
   154  
   155  	env.Payload = []byte("bad payload")
   156  	_, err := UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, nil)
   157  	assert.Error(t, err, "Expected error unmarshaling malformed envelope")
   158  
   159  	payload, _ := proto.Marshal(&cb.Payload{
   160  		Header: nil,
   161  	})
   162  	env.Payload = payload
   163  	_, err = UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, nil)
   164  	assert.Error(t, err, "Expected error with missing payload header")
   165  
   166  	payload, _ = proto.Marshal(&cb.Payload{
   167  		Header: &cb.Header{
   168  			ChannelHeader: []byte("bad header"),
   169  		},
   170  	})
   171  	env.Payload = payload
   172  	_, err = UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, nil)
   173  	assert.Error(t, err, "Expected error for malformed channel header")
   174  
   175  	chdr, _ := proto.Marshal(&cb.ChannelHeader{
   176  		Type: int32(cb.HeaderType_CHAINCODE_PACKAGE),
   177  	})
   178  	payload, _ = proto.Marshal(&cb.Payload{
   179  		Header: &cb.Header{
   180  			ChannelHeader: chdr,
   181  		},
   182  	})
   183  	env.Payload = payload
   184  	_, err = UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, nil)
   185  	assert.Error(t, err, "Expected error for wrong channel header type")
   186  
   187  	chdr, _ = proto.Marshal(&cb.ChannelHeader{
   188  		Type: int32(cb.HeaderType_CONFIG),
   189  	})
   190  	payload, _ = proto.Marshal(&cb.Payload{
   191  		Header: &cb.Header{
   192  			ChannelHeader: chdr,
   193  		},
   194  		Data: []byte("bad data"),
   195  	})
   196  	env.Payload = payload
   197  	_, err = UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, &cb.ConfigEnvelope{})
   198  	assert.Error(t, err, "Expected error for malformed payload data")
   199  
   200  	chdr, _ = proto.Marshal(&cb.ChannelHeader{
   201  		Type: int32(cb.HeaderType_CONFIG),
   202  	})
   203  	configEnv, _ := proto.Marshal(&cb.ConfigEnvelope{})
   204  	payload, _ = proto.Marshal(&cb.Payload{
   205  		Header: &cb.Header{
   206  			ChannelHeader: chdr,
   207  		},
   208  		Data: configEnv,
   209  	})
   210  	env.Payload = payload
   211  	_, err = UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, &cb.ConfigEnvelope{})
   212  	assert.NoError(t, err, "Unexpected error unmarshaling envelope")
   213  
   214  }
   215  
   216  func TestExtractEnvelopeNilData(t *testing.T) {
   217  	block := &cb.Block{}
   218  	_, err := ExtractEnvelope(block, 0)
   219  	assert.Error(t, err, "Nil data")
   220  }
   221  
   222  func TestExtractEnvelopeWrongIndex(t *testing.T) {
   223  	block := testBlock()
   224  	if _, err := ExtractEnvelope(block, len(block.GetData().Data)); err == nil {
   225  		t.Fatal("Expected envelope extraction to fail (wrong index)")
   226  	}
   227  }
   228  
   229  func TestExtractEnvelopeWrongIndexOrPanic(t *testing.T) {
   230  	defer func() {
   231  		if r := recover(); r == nil {
   232  			t.Fatal("Expected envelope extraction to panic (wrong index)")
   233  		}
   234  	}()
   235  
   236  	block := testBlock()
   237  	ExtractEnvelopeOrPanic(block, len(block.GetData().Data))
   238  }
   239  
   240  func TestExtractEnvelope(t *testing.T) {
   241  	if envelope, err := ExtractEnvelope(testBlock(), 0); err != nil {
   242  		t.Fatalf("Expected envelop extraction to succeed: %s", err)
   243  	} else if !proto.Equal(envelope, testEnvelope()) {
   244  		t.Fatal("Expected extracted envelope to match test envelope")
   245  	}
   246  }
   247  
   248  func TestExtractEnvelopeOrPanic(t *testing.T) {
   249  	defer func() {
   250  		if r := recover(); r != nil {
   251  			t.Fatal("Expected envelope extraction to succeed")
   252  		}
   253  	}()
   254  
   255  	if !proto.Equal(ExtractEnvelopeOrPanic(testBlock(), 0), testEnvelope()) {
   256  		t.Fatal("Expected extracted envelope to match test envelope")
   257  	}
   258  }
   259  
   260  func TestExtractPayload(t *testing.T) {
   261  	if payload, err := UnmarshalPayload(testEnvelope().Payload); err != nil {
   262  		t.Fatalf("Expected payload extraction to succeed: %s", err)
   263  	} else if !proto.Equal(payload, testPayload()) {
   264  		t.Fatal("Expected extracted payload to match test payload")
   265  	}
   266  }
   267  
   268  func TestExtractPayloadOrPanic(t *testing.T) {
   269  	defer func() {
   270  		if r := recover(); r != nil {
   271  			t.Fatal("Expected payload extraction to succeed")
   272  		}
   273  	}()
   274  
   275  	if !proto.Equal(UnmarshalPayloadOrPanic(testEnvelope().Payload), testPayload()) {
   276  		t.Fatal("Expected extracted payload to match test payload")
   277  	}
   278  }
   279  
   280  func TestUnmarshalChaincodeID(t *testing.T) {
   281  	ccname := "mychaincode"
   282  	ccversion := "myversion"
   283  	ccidbytes, _ := proto.Marshal(&pb.ChaincodeID{
   284  		Name:    ccname,
   285  		Version: ccversion,
   286  	})
   287  	ccid, err := UnmarshalChaincodeID(ccidbytes)
   288  	assert.NoError(t, err)
   289  	assert.Equal(t, ccname, ccid.Name, "Expected ccid names to match")
   290  	assert.Equal(t, ccversion, ccid.Version, "Expected ccid versions to match")
   291  
   292  	_, err = UnmarshalChaincodeID([]byte("bad chaincodeID"))
   293  	assert.Error(t, err, "Expected error marshaling malformed chaincode ID")
   294  }
   295  
   296  func TestNewSignatureHeaderOrPanic(t *testing.T) {
   297  	var sigHeader *cb.SignatureHeader
   298  
   299  	id := &fakes.SignerSerializer{}
   300  	id.SerializeReturnsOnCall(0, []byte("serialized"), nil)
   301  	id.SerializeReturnsOnCall(1, nil, errors.New("serialize failed"))
   302  	sigHeader = NewSignatureHeaderOrPanic(id)
   303  	assert.NotNil(t, sigHeader, "Signature header should not be nil")
   304  
   305  	assert.Panics(t, func() {
   306  		_ = NewSignatureHeaderOrPanic(nil)
   307  	}, "Expected panic with nil signer")
   308  
   309  	assert.Panics(t, func() {
   310  		_ = NewSignatureHeaderOrPanic(id)
   311  	}, "Expected panic with signature header error")
   312  }
   313  
   314  func TestSignOrPanic(t *testing.T) {
   315  	msg := []byte("sign me")
   316  	signer := &fakes.SignerSerializer{}
   317  	signer.SignReturnsOnCall(0, msg, nil)
   318  	signer.SignReturnsOnCall(1, nil, errors.New("bad signature"))
   319  	sig := SignOrPanic(signer, msg)
   320  	// mock signer returns message to be signed
   321  	assert.Equal(t, msg, sig, "Signature does not match expected value")
   322  
   323  	assert.Panics(t, func() {
   324  		_ = SignOrPanic(nil, []byte("sign me"))
   325  	}, "Expected panic with nil signer")
   326  
   327  	assert.Panics(t, func() {
   328  		_ = SignOrPanic(signer, []byte("sign me"))
   329  	}, "Expected panic with sign error")
   330  }
   331  
   332  // Helper functions
   333  
   334  func testPayload() *cb.Payload {
   335  	return &cb.Payload{
   336  		Header: MakePayloadHeader(
   337  			MakeChannelHeader(cb.HeaderType_MESSAGE, int32(1), "test", 0),
   338  			MakeSignatureHeader([]byte("creator"), []byte("nonce"))),
   339  		Data: []byte("test"),
   340  	}
   341  }
   342  
   343  func testEnvelope() *cb.Envelope {
   344  	// No need to set the signature
   345  	return &cb.Envelope{Payload: MarshalOrPanic(testPayload())}
   346  }
   347  
   348  func testBlock() *cb.Block {
   349  	// No need to set the block's Header, or Metadata
   350  	return &cb.Block{
   351  		Data: &cb.BlockData{
   352  			Data: [][]byte{MarshalOrPanic(testEnvelope())},
   353  		},
   354  	}
   355  }
   356  
   357  type mockLocalSigner struct {
   358  	returnError bool
   359  }
   360  
   361  func (m *mockLocalSigner) NewSignatureHeader() (*cb.SignatureHeader, error) {
   362  	if m.returnError {
   363  		return nil, errors.New("signature header error")
   364  	}
   365  	return &cb.SignatureHeader{}, nil
   366  }
   367  
   368  func (m *mockLocalSigner) Sign(message []byte) ([]byte, error) {
   369  	if m.returnError {
   370  		return nil, errors.New("sign error")
   371  	}
   372  	return message, nil
   373  }
   374  
   375  func TestChannelHeader(t *testing.T) {
   376  	makeEnvelope := func(payload *cb.Payload) *cb.Envelope {
   377  		return &cb.Envelope{
   378  			Payload: MarshalOrPanic(payload),
   379  		}
   380  	}
   381  
   382  	_, err := ChannelHeader(makeEnvelope(&cb.Payload{
   383  		Header: &cb.Header{
   384  			ChannelHeader: MarshalOrPanic(&cb.ChannelHeader{
   385  				ChannelId: "foo",
   386  			}),
   387  		},
   388  	}))
   389  	assert.NoError(t, err, "Channel header was present")
   390  
   391  	_, err = ChannelHeader(makeEnvelope(&cb.Payload{
   392  		Header: &cb.Header{},
   393  	}))
   394  	assert.Error(t, err, "ChannelHeader was missing")
   395  
   396  	_, err = ChannelHeader(makeEnvelope(&cb.Payload{}))
   397  	assert.Error(t, err, "Header was missing")
   398  
   399  	_, err = ChannelHeader(&cb.Envelope{})
   400  	assert.Error(t, err, "Payload was missing")
   401  }
   402  
   403  func TestIsConfigBlock(t *testing.T) {
   404  	newBlock := func(env *cb.Envelope) *cb.Block {
   405  		return &cb.Block{
   406  			Data: &cb.BlockData{
   407  				Data: [][]byte{MarshalOrPanic(env)},
   408  			},
   409  		}
   410  	}
   411  
   412  	newConfigEnv := func(envType int32) *cb.Envelope {
   413  		return &cb.Envelope{
   414  			Payload: MarshalOrPanic(&cb.Payload{
   415  				Header: &cb.Header{
   416  					ChannelHeader: MarshalOrPanic(&cb.ChannelHeader{
   417  						Type:      envType,
   418  						ChannelId: "test-chain",
   419  					}),
   420  				},
   421  				Data: []byte("test bytes"),
   422  			}), // common.Payload
   423  		} // LastUpdate
   424  	}
   425  
   426  	// scenario 1: CONFIG envelope
   427  	envType := int32(cb.HeaderType_CONFIG)
   428  	env := newConfigEnv(envType)
   429  	block := newBlock(env)
   430  
   431  	result := IsConfigBlock(block)
   432  	assert.True(t, result, "IsConfigBlock returns true for blocks with CONFIG envelope")
   433  
   434  	// scenario 2: ORDERER_TRANSACTION envelope
   435  	envType = int32(cb.HeaderType_ORDERER_TRANSACTION)
   436  	env = newConfigEnv(envType)
   437  	block = newBlock(env)
   438  
   439  	result = IsConfigBlock(block)
   440  	assert.True(t, result, "IsConfigBlock returns true for blocks with ORDERER_TRANSACTION envelope")
   441  
   442  	// scenario 3: MESSAGE envelope
   443  	envType = int32(cb.HeaderType_MESSAGE)
   444  	env = newConfigEnv(envType)
   445  	block = newBlock(env)
   446  
   447  	result = IsConfigBlock(block)
   448  	assert.False(t, result, "IsConfigBlock returns false for blocks with MESSAGE envelope")
   449  }
   450  
   451  func TestEnvelopeToConfigUpdate(t *testing.T) {
   452  	makeEnv := func(data []byte) *cb.Envelope {
   453  		return &cb.Envelope{
   454  			Payload: MarshalOrPanic(&cb.Payload{
   455  				Header: &cb.Header{
   456  					ChannelHeader: MarshalOrPanic(&cb.ChannelHeader{
   457  						Type:      int32(cb.HeaderType_CONFIG_UPDATE),
   458  						ChannelId: "test-chain",
   459  					}),
   460  				},
   461  				Data: data,
   462  			}), // common.Payload
   463  		} // LastUpdate
   464  	}
   465  
   466  	// scenario 1: for valid envelopes
   467  	configUpdateEnv := &cb.ConfigUpdateEnvelope{}
   468  	env := makeEnv(MarshalOrPanic(configUpdateEnv))
   469  	result, err := EnvelopeToConfigUpdate(env)
   470  
   471  	assert.NoError(t, err, "EnvelopeToConfigUpdate runs without error for valid CONFIG_UPDATE envelope")
   472  	assert.Equal(t, configUpdateEnv, result, "Correct configUpdateEnvelope returned")
   473  
   474  	// scenario 2: for invalid envelopes
   475  	env = makeEnv([]byte("test bytes"))
   476  	_, err = EnvelopeToConfigUpdate(env)
   477  
   478  	assert.Error(t, err, "EnvelopeToConfigUpdate fails with error for invalid CONFIG_UPDATE envelope")
   479  }
   480  
   481  func TestGetRandomNonce(t *testing.T) {
   482  	key1, err := getRandomNonce()
   483  	assert.NoErrorf(t, err, "error getting random bytes")
   484  	assert.Len(t, key1, crypto.NonceSize)
   485  }