Skip to content

Commit 7688dd2

Browse files
manish-sethicendhu
authored andcommitted
fork-det: Add function for serializing update batch
This CR adds a function to serialize an update batch The intention is to use this for computing hash of the update batch. FAB-14598 #done Change-Id: I4c73dca59aebe8588d10f6346f9055f9649f750c Signed-off-by: manish <manish.sethi@gmail.com> (cherry picked from commit 4b03bd0) (cherry picked from commit 8a7a431)
1 parent bae447d commit 7688dd2

File tree

5 files changed

+402
-0
lines changed

5 files changed

+402
-0
lines changed

core/ledger/kvledger/txmgmt/privacyenabledstate/db.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,18 @@ func (nsb nsBatch) GetCollectionNames() []string {
157157
return nsb.GetUpdatedNamespaces()
158158
}
159159

160+
func (nsb nsBatch) getCollectionUpdates(collName string) map[string]*statedb.VersionedValue {
161+
return nsb.GetUpdates(collName)
162+
}
163+
164+
func (b UpdateMap) getUpdatedNamespaces() []string {
165+
namespaces := []string{}
166+
for ns := range b {
167+
namespaces = append(namespaces, ns)
168+
}
169+
return namespaces
170+
}
171+
160172
func (b UpdateMap) getOrCreateNsBatch(ns string) nsBatch {
161173
batch, ok := b[ns]
162174
if !ok {

core/ledger/kvledger/txmgmt/privacyenabledstate/update_batch.pb.go

Lines changed: 130 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
syntax = "proto3";
7+
8+
option go_package = "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate";
9+
10+
package privacyenabledstate;
11+
12+
message KVWriteProto {
13+
string namespace = 1;
14+
string collection = 2;
15+
bytes key = 3;
16+
bool isDelete = 4;
17+
bytes value = 5;
18+
bytes version_bytes = 6;
19+
}
20+
21+
message KVWritesBatchProto {
22+
repeated KVWriteProto kvwrites = 1;
23+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package privacyenabledstate
7+
8+
import (
9+
"sort"
10+
11+
"github.com/golang/protobuf/proto"
12+
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb"
13+
"github.com/hyperledger/fabric/core/ledger/util"
14+
"github.com/pkg/errors"
15+
)
16+
17+
type updatesBytesBuilder struct {
18+
}
19+
20+
// DeterministicBytesForPubAndHashUpdates constructs the bytes for a given UpdateBatch
21+
// while constructing the bytes, it considers only public writes and hashed writes for
22+
// the collections. For achieveing the determinism, it constructs a slice of proto messages
23+
// of type 'KVWriteProto'. In the slice, all the writes for a namespace "ns1" appear before
24+
// the writes for another namespace "ns2" if "ns1" < "ns2" (lexicographically). Within a
25+
// namespace, all the public writes appear before the collection writes. Like namespaces,
26+
// the collections writes within a namespace appear in the order of lexicographical order.
27+
// If an entry has the same namespace as its preceding entry, the namespcae field is skipped.
28+
// A Similar treatment is given to the repeative entries for a collection within a namespace.
29+
// For illustration, see the corresponding unit tests
30+
func (bb *updatesBytesBuilder) DeterministicBytesForPubAndHashUpdates(u *UpdateBatch) ([]byte, error) {
31+
pubUpdates := u.PubUpdates
32+
hashUpdates := u.HashUpdates.UpdateMap
33+
namespaces := dedupAndSort(
34+
pubUpdates.GetUpdatedNamespaces(),
35+
hashUpdates.getUpdatedNamespaces(),
36+
)
37+
38+
kvWritesProto := []*KVWriteProto{}
39+
for _, ns := range namespaces {
40+
p := bb.buildForKeys(pubUpdates.GetUpdates(ns))
41+
collsForNs, ok := hashUpdates[ns]
42+
if ok {
43+
p = append(p, bb.buildForColls(collsForNs)...)
44+
}
45+
p[0].Namespace = ns
46+
kvWritesProto = append(kvWritesProto, p...)
47+
}
48+
batchProto := &KVWritesBatchProto{
49+
Kvwrites: kvWritesProto,
50+
}
51+
52+
batchBytes, err := proto.Marshal(batchProto)
53+
return batchBytes, errors.Wrap(err, "error constructing deterministic bytes from update batch")
54+
}
55+
56+
func (bb *updatesBytesBuilder) buildForColls(colls nsBatch) []*KVWriteProto {
57+
collNames := colls.GetCollectionNames()
58+
sort.Strings(collNames)
59+
collsProto := []*KVWriteProto{}
60+
for _, collName := range collNames {
61+
collUpdates := colls.getCollectionUpdates(collName)
62+
p := bb.buildForKeys(collUpdates)
63+
p[0].Collection = collName
64+
collsProto = append(collsProto, p...)
65+
}
66+
return collsProto
67+
}
68+
69+
func (bb *updatesBytesBuilder) buildForKeys(kv map[string]*statedb.VersionedValue) []*KVWriteProto {
70+
keys := util.GetSortedKeys(kv)
71+
p := []*KVWriteProto{}
72+
for _, key := range keys {
73+
val := kv[key]
74+
p = append(
75+
p,
76+
&KVWriteProto{
77+
Key: []byte(key),
78+
Value: val.Value,
79+
IsDelete: val.Value == nil,
80+
VersionBytes: val.Version.ToBytes(),
81+
},
82+
)
83+
}
84+
return p
85+
}
86+
87+
func dedupAndSort(a, b []string) []string {
88+
m := map[string]struct{}{}
89+
for _, entry := range a {
90+
m[entry] = struct{}{}
91+
}
92+
for _, entry := range b {
93+
m[entry] = struct{}{}
94+
}
95+
return util.GetSortedKeys(m)
96+
}

0 commit comments

Comments
 (0)