github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/rwsetutil/rwset_builder_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package rwsetutil
     8  
     9  import (
    10  	"os"
    11  	"testing"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/hechain20/hechain/common/flogging"
    15  	"github.com/hechain20/hechain/core/ledger/internal/version"
    16  	"github.com/hechain20/hechain/core/ledger/util"
    17  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    18  	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  func TestMain(m *testing.M) {
    23  	flogging.ActivateSpec("rwsetutil=debug")
    24  	os.Exit(m.Run())
    25  }
    26  
    27  func TestTxSimulationResultWithOnlyPubData(t *testing.T) {
    28  	rwSetBuilder := NewRWSetBuilder()
    29  
    30  	rwSetBuilder.AddToReadSet("ns1", "key2", version.NewHeight(1, 2))
    31  	rwSetBuilder.AddToReadSet("ns1", "key1", version.NewHeight(1, 1))
    32  	rwSetBuilder.AddToWriteSet("ns1", "key2", []byte("value2"))
    33  
    34  	rqi1 := &kvrwset.RangeQueryInfo{StartKey: "bKey", EndKey: "", ItrExhausted: false, ReadsInfo: nil}
    35  	rqi1.EndKey = "eKey"
    36  	SetRawReads(rqi1, []*kvrwset.KVRead{NewKVRead("bKey1", version.NewHeight(2, 3)), NewKVRead("bKey2", version.NewHeight(2, 4))})
    37  	rqi1.ItrExhausted = true
    38  	rwSetBuilder.AddToRangeQuerySet("ns1", rqi1)
    39  
    40  	rqi2 := &kvrwset.RangeQueryInfo{StartKey: "bKey", EndKey: "", ItrExhausted: false, ReadsInfo: nil}
    41  	rqi2.EndKey = "eKey"
    42  	SetRawReads(rqi2, []*kvrwset.KVRead{NewKVRead("bKey1", version.NewHeight(2, 3)), NewKVRead("bKey2", version.NewHeight(2, 4))})
    43  	rqi2.ItrExhausted = true
    44  	rwSetBuilder.AddToRangeQuerySet("ns1", rqi2)
    45  
    46  	rqi3 := &kvrwset.RangeQueryInfo{StartKey: "bKey", EndKey: "", ItrExhausted: true, ReadsInfo: nil}
    47  	rqi3.EndKey = "eKey1"
    48  	SetRawReads(rqi3, []*kvrwset.KVRead{NewKVRead("bKey1", version.NewHeight(2, 3)), NewKVRead("bKey2", version.NewHeight(2, 4))})
    49  	rwSetBuilder.AddToRangeQuerySet("ns1", rqi3)
    50  
    51  	rwSetBuilder.AddToReadSet("ns2", "key2", version.NewHeight(1, 2))
    52  	rwSetBuilder.AddToWriteSet("ns2", "key3", []byte("value3"))
    53  
    54  	txSimulationResults, err := rwSetBuilder.GetTxSimulationResults()
    55  	require.NoError(t, err)
    56  
    57  	ns1KVRWSet := &kvrwset.KVRWSet{
    58  		Reads:            []*kvrwset.KVRead{NewKVRead("key1", version.NewHeight(1, 1)), NewKVRead("key2", version.NewHeight(1, 2))},
    59  		RangeQueriesInfo: []*kvrwset.RangeQueryInfo{rqi1, rqi3},
    60  		Writes:           []*kvrwset.KVWrite{newKVWrite("key2", []byte("value2"))},
    61  	}
    62  
    63  	ns1RWSet := &rwset.NsReadWriteSet{
    64  		Namespace: "ns1",
    65  		Rwset:     serializeTestProtoMsg(t, ns1KVRWSet),
    66  	}
    67  
    68  	ns2KVRWSet := &kvrwset.KVRWSet{
    69  		Reads:            []*kvrwset.KVRead{NewKVRead("key2", version.NewHeight(1, 2))},
    70  		RangeQueriesInfo: nil,
    71  		Writes:           []*kvrwset.KVWrite{newKVWrite("key3", []byte("value3"))},
    72  	}
    73  
    74  	ns2RWSet := &rwset.NsReadWriteSet{
    75  		Namespace: "ns2",
    76  		Rwset:     serializeTestProtoMsg(t, ns2KVRWSet),
    77  	}
    78  
    79  	expectedTxRWSet := &rwset.TxReadWriteSet{NsRwset: []*rwset.NsReadWriteSet{ns1RWSet, ns2RWSet}}
    80  	require.Equal(t, expectedTxRWSet, txSimulationResults.PubSimulationResults)
    81  	require.Nil(t, txSimulationResults.PvtSimulationResults)
    82  	require.Nil(t, txSimulationResults.PubSimulationResults.NsRwset[0].CollectionHashedRwset)
    83  }
    84  
    85  func TestTxSimulationResultWithPvtData(t *testing.T) {
    86  	rwSetBuilder := NewRWSetBuilder()
    87  	// public rws ns1 + ns2
    88  	rwSetBuilder.AddToReadSet("ns1", "key1", version.NewHeight(1, 1))
    89  	rwSetBuilder.AddToReadSet("ns2", "key1", version.NewHeight(1, 1))
    90  	rwSetBuilder.AddToWriteSet("ns2", "key1", []byte("ns2-key1-value"))
    91  
    92  	// pvt rwset ns1
    93  	rwSetBuilder.AddToHashedReadSet("ns1", "coll1", "key1", version.NewHeight(1, 1))
    94  	rwSetBuilder.AddToHashedReadSet("ns1", "coll2", "key1", version.NewHeight(1, 1))
    95  	rwSetBuilder.AddToPvtAndHashedWriteSet("ns1", "coll2", "key1", []byte("pvt-ns1-coll2-key1-value"))
    96  
    97  	// pvt rwset ns2
    98  	rwSetBuilder.AddToHashedReadSet("ns2", "coll1", "key1", version.NewHeight(1, 1))
    99  	rwSetBuilder.AddToHashedReadSet("ns2", "coll1", "key2", version.NewHeight(1, 1))
   100  	rwSetBuilder.AddToPvtAndHashedWriteSet("ns2", "coll2", "key1", []byte("pvt-ns2-coll2-key1-value"))
   101  
   102  	actualSimRes, err := rwSetBuilder.GetTxSimulationResults()
   103  	require.NoError(t, err)
   104  
   105  	///////////////////////////////////////////////////////
   106  	// construct the expected pvt rwset and compare with the one present in the txSimulationResults
   107  	///////////////////////////////////////////////////////
   108  	pvtNs1Coll2 := &kvrwset.KVRWSet{
   109  		Writes: []*kvrwset.KVWrite{newKVWrite("key1", []byte("pvt-ns1-coll2-key1-value"))},
   110  	}
   111  
   112  	pvtNs2Coll2 := &kvrwset.KVRWSet{
   113  		Writes: []*kvrwset.KVWrite{newKVWrite("key1", []byte("pvt-ns2-coll2-key1-value"))},
   114  	}
   115  
   116  	expectedPvtRWSet := &rwset.TxPvtReadWriteSet{
   117  		DataModel: rwset.TxReadWriteSet_KV,
   118  		NsPvtRwset: []*rwset.NsPvtReadWriteSet{
   119  			{
   120  				Namespace: "ns1",
   121  				CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
   122  					{
   123  						CollectionName: "coll2",
   124  						Rwset:          serializeTestProtoMsg(t, pvtNs1Coll2),
   125  					},
   126  				},
   127  			},
   128  
   129  			{
   130  				Namespace: "ns2",
   131  				CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
   132  					{
   133  						CollectionName: "coll2",
   134  						Rwset:          serializeTestProtoMsg(t, pvtNs2Coll2),
   135  					},
   136  				},
   137  			},
   138  		},
   139  	}
   140  	require.Equal(t, expectedPvtRWSet, actualSimRes.PvtSimulationResults)
   141  
   142  	///////////////////////////////////////////////////////
   143  	// construct the public rwset (which will be part of the block) and compare with the one present in the txSimulationResults
   144  	///////////////////////////////////////////////////////
   145  	pubNs1 := &kvrwset.KVRWSet{
   146  		Reads: []*kvrwset.KVRead{NewKVRead("key1", version.NewHeight(1, 1))},
   147  	}
   148  
   149  	pubNs2 := &kvrwset.KVRWSet{
   150  		Reads:  []*kvrwset.KVRead{NewKVRead("key1", version.NewHeight(1, 1))},
   151  		Writes: []*kvrwset.KVWrite{newKVWrite("key1", []byte("ns2-key1-value"))},
   152  	}
   153  
   154  	hashedNs1Coll1 := &kvrwset.HashedRWSet{
   155  		HashedReads: []*kvrwset.KVReadHash{
   156  			constructTestPvtKVReadHash(t, "key1", version.NewHeight(1, 1)),
   157  		},
   158  	}
   159  
   160  	hashedNs1Coll2 := &kvrwset.HashedRWSet{
   161  		HashedReads: []*kvrwset.KVReadHash{
   162  			constructTestPvtKVReadHash(t, "key1", version.NewHeight(1, 1)),
   163  		},
   164  		HashedWrites: []*kvrwset.KVWriteHash{
   165  			constructTestPvtKVWriteHash(t, "key1", []byte("pvt-ns1-coll2-key1-value")),
   166  		},
   167  	}
   168  
   169  	hashedNs2Coll1 := &kvrwset.HashedRWSet{
   170  		HashedReads: []*kvrwset.KVReadHash{
   171  			constructTestPvtKVReadHash(t, "key1", version.NewHeight(1, 1)),
   172  			constructTestPvtKVReadHash(t, "key2", version.NewHeight(1, 1)),
   173  		},
   174  	}
   175  
   176  	hashedNs2Coll2 := &kvrwset.HashedRWSet{
   177  		HashedWrites: []*kvrwset.KVWriteHash{
   178  			constructTestPvtKVWriteHash(t, "key1", []byte("pvt-ns2-coll2-key1-value")),
   179  		},
   180  	}
   181  
   182  	combinedNs1 := &rwset.NsReadWriteSet{
   183  		Namespace: "ns1",
   184  		Rwset:     serializeTestProtoMsg(t, pubNs1),
   185  		CollectionHashedRwset: []*rwset.CollectionHashedReadWriteSet{
   186  			{
   187  				CollectionName: "coll1",
   188  				HashedRwset:    serializeTestProtoMsg(t, hashedNs1Coll1),
   189  			},
   190  			{
   191  				CollectionName: "coll2",
   192  				HashedRwset:    serializeTestProtoMsg(t, hashedNs1Coll2),
   193  				PvtRwsetHash:   util.ComputeHash(serializeTestProtoMsg(t, pvtNs1Coll2)),
   194  			},
   195  		},
   196  	}
   197  	require.Equal(t, combinedNs1, actualSimRes.PubSimulationResults.NsRwset[0])
   198  
   199  	combinedNs2 := &rwset.NsReadWriteSet{
   200  		Namespace: "ns2",
   201  		Rwset:     serializeTestProtoMsg(t, pubNs2),
   202  		CollectionHashedRwset: []*rwset.CollectionHashedReadWriteSet{
   203  			{
   204  				CollectionName: "coll1",
   205  				HashedRwset:    serializeTestProtoMsg(t, hashedNs2Coll1),
   206  			},
   207  			{
   208  				CollectionName: "coll2",
   209  				HashedRwset:    serializeTestProtoMsg(t, hashedNs2Coll2),
   210  				PvtRwsetHash:   util.ComputeHash(serializeTestProtoMsg(t, pvtNs2Coll2)),
   211  			},
   212  		},
   213  	}
   214  	require.Equal(t, combinedNs2, actualSimRes.PubSimulationResults.NsRwset[1])
   215  	expectedPubRWSet := &rwset.TxReadWriteSet{
   216  		DataModel: rwset.TxReadWriteSet_KV,
   217  		NsRwset:   []*rwset.NsReadWriteSet{combinedNs1, combinedNs2},
   218  	}
   219  	require.Equal(t, expectedPubRWSet, actualSimRes.PubSimulationResults)
   220  }
   221  
   222  func TestTxSimulationResultWithMetadata(t *testing.T) {
   223  	rwSetBuilder := NewRWSetBuilder()
   224  	// public rws ns1
   225  	rwSetBuilder.AddToReadSet("ns1", "key1", version.NewHeight(1, 1))
   226  	rwSetBuilder.AddToMetadataWriteSet("ns1", "key1",
   227  		map[string][]byte{"metadata2": []byte("ns1-key1-metadata2"), "metadata1": []byte("ns1-key1-metadata1")},
   228  	)
   229  	// public rws ns2
   230  	rwSetBuilder.AddToWriteSet("ns2", "key1", []byte("ns2-key1-value"))
   231  	rwSetBuilder.AddToMetadataWriteSet("ns2", "key1", map[string][]byte{}) // nil/empty-map indicates metadata delete
   232  
   233  	// pvt rwset <ns1, coll1>
   234  	rwSetBuilder.AddToPvtAndHashedWriteSet("ns1", "coll1", "key1", []byte("pvt-ns1-coll1-key1-value"))
   235  	rwSetBuilder.AddToHashedMetadataWriteSet("ns1", "coll1", "key1",
   236  		map[string][]byte{"metadata1": []byte("ns1-coll1-key1-metadata1")})
   237  
   238  	// pvt rwset <ns1, coll2>
   239  	rwSetBuilder.AddToHashedMetadataWriteSet("ns1", "coll2", "key1", nil) // pvt-data metadata delete
   240  
   241  	actualSimRes, err := rwSetBuilder.GetTxSimulationResults()
   242  	require.NoError(t, err)
   243  
   244  	// construct the expected pvt rwset and compare with the one present in the txSimulationResults
   245  	pvtNs1Coll1 := &kvrwset.KVRWSet{
   246  		Writes:         []*kvrwset.KVWrite{newKVWrite("key1", []byte("pvt-ns1-coll1-key1-value"))},
   247  		MetadataWrites: []*kvrwset.KVMetadataWrite{{Key: "key1"}},
   248  	}
   249  
   250  	pvtNs1Coll2 := &kvrwset.KVRWSet{
   251  		MetadataWrites: []*kvrwset.KVMetadataWrite{{Key: "key1"}},
   252  	}
   253  
   254  	expectedPvtRWSet := &rwset.TxPvtReadWriteSet{
   255  		DataModel: rwset.TxReadWriteSet_KV,
   256  		NsPvtRwset: []*rwset.NsPvtReadWriteSet{
   257  			{
   258  				Namespace: "ns1",
   259  				CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{
   260  					{
   261  						CollectionName: "coll1",
   262  						Rwset:          serializeTestProtoMsg(t, pvtNs1Coll1),
   263  					},
   264  					{
   265  						CollectionName: "coll2",
   266  						Rwset:          serializeTestProtoMsg(t, pvtNs1Coll2),
   267  					},
   268  				},
   269  			},
   270  		},
   271  	}
   272  	require.Equal(t, expectedPvtRWSet, actualSimRes.PvtSimulationResults)
   273  	// construct the public and hashed rwset (which will be part of the block) and compare with the one present in the txSimulationResults
   274  	pubNs1 := &kvrwset.KVRWSet{
   275  		Reads: []*kvrwset.KVRead{NewKVRead("key1", version.NewHeight(1, 1))},
   276  		MetadataWrites: []*kvrwset.KVMetadataWrite{
   277  			{
   278  				Key: "key1",
   279  				Entries: []*kvrwset.KVMetadataEntry{
   280  					{Name: "metadata1", Value: []byte("ns1-key1-metadata1")},
   281  					{Name: "metadata2", Value: []byte("ns1-key1-metadata2")},
   282  				},
   283  			},
   284  		},
   285  	}
   286  
   287  	pubNs2 := &kvrwset.KVRWSet{
   288  		Writes: []*kvrwset.KVWrite{newKVWrite("key1", []byte("ns2-key1-value"))},
   289  		MetadataWrites: []*kvrwset.KVMetadataWrite{
   290  			{
   291  				Key:     "key1",
   292  				Entries: nil,
   293  			},
   294  		},
   295  	}
   296  
   297  	hashedNs1Coll1 := &kvrwset.HashedRWSet{
   298  		HashedWrites: []*kvrwset.KVWriteHash{
   299  			constructTestPvtKVWriteHash(t, "key1", []byte("pvt-ns1-coll1-key1-value")),
   300  		},
   301  		MetadataWrites: []*kvrwset.KVMetadataWriteHash{
   302  			{
   303  				KeyHash: util.ComputeStringHash("key1"),
   304  				Entries: []*kvrwset.KVMetadataEntry{
   305  					{Name: "metadata1", Value: []byte("ns1-coll1-key1-metadata1")},
   306  				},
   307  			},
   308  		},
   309  	}
   310  
   311  	hashedNs1Coll2 := &kvrwset.HashedRWSet{
   312  		MetadataWrites: []*kvrwset.KVMetadataWriteHash{
   313  			{
   314  				KeyHash: util.ComputeStringHash("key1"),
   315  				Entries: nil,
   316  			},
   317  		},
   318  	}
   319  
   320  	pubAndHashCombinedNs1 := &rwset.NsReadWriteSet{
   321  		Namespace: "ns1",
   322  		Rwset:     serializeTestProtoMsg(t, pubNs1),
   323  		CollectionHashedRwset: []*rwset.CollectionHashedReadWriteSet{
   324  			{
   325  				CollectionName: "coll1",
   326  				HashedRwset:    serializeTestProtoMsg(t, hashedNs1Coll1),
   327  				PvtRwsetHash:   util.ComputeHash(serializeTestProtoMsg(t, pvtNs1Coll1)),
   328  			},
   329  			{
   330  				CollectionName: "coll2",
   331  				HashedRwset:    serializeTestProtoMsg(t, hashedNs1Coll2),
   332  				PvtRwsetHash:   util.ComputeHash(serializeTestProtoMsg(t, pvtNs1Coll2)),
   333  			},
   334  		},
   335  	}
   336  	require.Equal(t, pubAndHashCombinedNs1, actualSimRes.PubSimulationResults.NsRwset[0])
   337  	pubAndHashCombinedNs2 := &rwset.NsReadWriteSet{
   338  		Namespace:             "ns2",
   339  		Rwset:                 serializeTestProtoMsg(t, pubNs2),
   340  		CollectionHashedRwset: nil,
   341  	}
   342  	expectedPubRWSet := &rwset.TxReadWriteSet{
   343  		DataModel: rwset.TxReadWriteSet_KV,
   344  		NsRwset:   []*rwset.NsReadWriteSet{pubAndHashCombinedNs1, pubAndHashCombinedNs2},
   345  	}
   346  	require.Equal(t, expectedPubRWSet, actualSimRes.PubSimulationResults)
   347  }
   348  
   349  func constructTestPvtKVReadHash(t *testing.T, key string, version *version.Height) *kvrwset.KVReadHash {
   350  	kvReadHash := newPvtKVReadHash(key, version)
   351  	return kvReadHash
   352  }
   353  
   354  func constructTestPvtKVWriteHash(t *testing.T, key string, value []byte) *kvrwset.KVWriteHash {
   355  	_, kvWriteHash := newPvtKVWriteAndHash(key, value)
   356  	return kvWriteHash
   357  }
   358  
   359  func serializeTestProtoMsg(t *testing.T, protoMsg proto.Message) []byte {
   360  	msgBytes, err := proto.Marshal(protoMsg)
   361  	require.NoError(t, err)
   362  	return msgBytes
   363  }
   364  
   365  func TestNilOrZeroLengthByteArrayValueConvertedToDelete(t *testing.T) {
   366  	t.Run("public_writeset", func(t *testing.T) {
   367  		rwsetBuilder := NewRWSetBuilder()
   368  		rwsetBuilder.AddToWriteSet("ns", "key1", nil)
   369  		rwsetBuilder.AddToWriteSet("ns", "key2", []byte{})
   370  
   371  		simulationResults, err := rwsetBuilder.GetTxSimulationResults()
   372  		require.NoError(t, err)
   373  		pubRWSet := &kvrwset.KVRWSet{}
   374  		require.NoError(
   375  			t,
   376  			proto.Unmarshal(simulationResults.PubSimulationResults.NsRwset[0].Rwset, pubRWSet),
   377  		)
   378  		require.True(t, proto.Equal(
   379  			&kvrwset.KVRWSet{
   380  				Writes: []*kvrwset.KVWrite{
   381  					{Key: "key1", IsDelete: true},
   382  					{Key: "key2", IsDelete: true},
   383  				},
   384  			},
   385  			pubRWSet,
   386  		))
   387  	})
   388  
   389  	t.Run("pvtdata_and_hashes_writesets", func(t *testing.T) {
   390  		rwsetBuilder := NewRWSetBuilder()
   391  		rwsetBuilder.AddToPvtAndHashedWriteSet("ns", "coll", "key1", nil)
   392  		rwsetBuilder.AddToPvtAndHashedWriteSet("ns", "coll", "key2", []byte{})
   393  
   394  		simulationResults, err := rwsetBuilder.GetTxSimulationResults()
   395  		require.NoError(t, err)
   396  
   397  		t.Run("hashed_writeset", func(t *testing.T) {
   398  			hashedRWSet := &kvrwset.HashedRWSet{}
   399  			require.NoError(
   400  				t,
   401  				proto.Unmarshal(simulationResults.PubSimulationResults.NsRwset[0].CollectionHashedRwset[0].HashedRwset, hashedRWSet),
   402  			)
   403  			require.True(t, proto.Equal(
   404  				&kvrwset.HashedRWSet{
   405  					HashedWrites: []*kvrwset.KVWriteHash{
   406  						{KeyHash: util.ComputeStringHash("key1"), IsDelete: true},
   407  						{KeyHash: util.ComputeStringHash("key2"), IsDelete: true},
   408  					},
   409  				},
   410  				hashedRWSet,
   411  			))
   412  		})
   413  
   414  		t.Run("pvtdata_writeset", func(t *testing.T) {
   415  			pvtWSet := &kvrwset.KVRWSet{}
   416  			require.NoError(
   417  				t,
   418  				proto.Unmarshal(simulationResults.PvtSimulationResults.NsPvtRwset[0].CollectionPvtRwset[0].Rwset, pvtWSet),
   419  			)
   420  			require.True(t, proto.Equal(
   421  				&kvrwset.KVRWSet{
   422  					Writes: []*kvrwset.KVWrite{
   423  						{Key: "key1", IsDelete: true},
   424  						{Key: "key2", IsDelete: true},
   425  					},
   426  				},
   427  				pvtWSet,
   428  			))
   429  		})
   430  	})
   431  }