From 3d0c7540ffe2c530c6bca7814225ee68dd56e3d0 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Tue, 24 Sep 2024 15:46:10 +0200 Subject: [PATCH] reorganize version marshalling Signed-off-by: Angelo De Caro --- .../fabricdev/core/fabricdev/vault/vault.go | 1 + .../common/core/generic/vault/fver/version.go | 21 --- platform/common/core/generic/vault/helpers.go | 86 +++++---- .../common/core/generic/vault/interceptor.go | 1 + .../core/generic/vault/interceptor_test.go | 5 +- platform/common/core/generic/vault/rwset.go | 2 +- platform/common/core/generic/vault/vault.go | 55 +++--- .../common/core/generic/vault/vault_test.go | 2 + platform/common/core/generic/vault/version.go | 60 ++++++ platform/fabric/core/generic/vault/vault.go | 16 +- platform/orion/core/generic/vault/vault.go | 8 +- platform/view/services/db/dbtest/helpers.go | 171 ++++++++++-------- .../services/db/driver/badger/badger_test.go | 35 +++- 13 files changed, 279 insertions(+), 184 deletions(-) create mode 100644 platform/common/core/generic/vault/version.go diff --git a/docs/fabric/fabricdev/core/fabricdev/vault/vault.go b/docs/fabric/fabricdev/core/fabricdev/vault/vault.go index e75f77114..6e043a68d 100644 --- a/docs/fabric/fabricdev/core/fabricdev/vault/vault.go +++ b/docs/fabric/fabricdev/core/fabricdev/vault/vault.go @@ -34,6 +34,7 @@ func NewVault(store vault.VersionedPersistence, txIDStore TXIDStore, metricsProv &populator{}, metricsProvider, tracerProvider, + &vault.BlockTxIndexVersionBuilder{}, ) } diff --git a/platform/common/core/generic/vault/fver/version.go b/platform/common/core/generic/vault/fver/version.go index 4e811e789..614969938 100644 --- a/platform/common/core/generic/vault/fver/version.go +++ b/platform/common/core/generic/vault/fver/version.go @@ -8,9 +8,7 @@ package fver import ( "bytes" - "encoding/binary" - "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" ) @@ -28,22 +26,3 @@ func IsEqual(a, b driver.RawVersion) bool { } return false } - -func ToBytes(Block driver.BlockNum, TxNum driver.TxNum) []byte { - buf := make([]byte, 8) - binary.BigEndian.PutUint32(buf[:4], uint32(Block)) - binary.BigEndian.PutUint32(buf[4:], uint32(TxNum)) - return buf -} - -func FromBytes(data []byte) (driver.BlockNum, driver.TxNum, error) { - if len(data) == 0 { - return 0, 0, nil - } - if len(data) != 8 { - return 0, 0, errors.Errorf("block number must be 8 bytes, but got %d", len(data)) - } - Block := driver.BlockNum(binary.BigEndian.Uint32(data[:4])) - TxNum := driver.TxNum(binary.BigEndian.Uint32(data[4:])) - return Block, TxNum, nil -} diff --git a/platform/common/core/generic/vault/helpers.go b/platform/common/core/generic/vault/helpers.go index 61f71f2e8..d9eee0e42 100644 --- a/platform/common/core/generic/vault/helpers.go +++ b/platform/common/core/generic/vault/helpers.go @@ -8,10 +8,10 @@ package vault import ( "context" + "encoding/binary" "testing" "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/proto" - "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/fver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/collections" "github.com/hyperledger/fabric-protos-go/ledger/rwset" @@ -132,7 +132,7 @@ func TTestInterceptorConcurrency(t *testing.T, ddb VersionedPersistence, vp arti err = ddb.BeginUpdate() assert.NoError(t, err) - err = ddb.SetState(ns, k, VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}) + err = ddb.SetState(ns, k, VersionedValue{Raw: []byte("val"), Version: toBytes(35, 1)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) @@ -256,13 +256,13 @@ func TTestQueryExecutor(t *testing.T, ddb VersionedPersistence, vp artifactsProv err = ddb.BeginUpdate() assert.NoError(t, err) - err = ddb.SetState(ns, "k2", VersionedValue{Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}) + err = ddb.SetState(ns, "k2", VersionedValue{Raw: []byte("k2_value"), Version: toBytes(35, 1)}) assert.NoError(t, err) - err = ddb.SetState(ns, "k3", VersionedValue{Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}) + err = ddb.SetState(ns, "k3", VersionedValue{Raw: []byte("k3_value"), Version: toBytes(35, 2)}) assert.NoError(t, err) - err = ddb.SetState(ns, "k1", VersionedValue{Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}) + err = ddb.SetState(ns, "k1", VersionedValue{Raw: []byte("k1_value"), Version: toBytes(35, 3)}) assert.NoError(t, err) - err = ddb.SetState(ns, "k111", VersionedValue{Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}) + err = ddb.SetState(ns, "k111", VersionedValue{Raw: []byte("k111_value"), Version: toBytes(35, 4)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) @@ -289,10 +289,10 @@ func TTestQueryExecutor(t *testing.T, ddb VersionedPersistence, vp artifactsProv } assert.Len(t, res, 4) assert.ElementsMatch(t, []VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, - {Key: "k3", Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}, + {Key: "k1", Raw: []byte("k1_value"), Version: toBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: toBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: toBytes(35, 1)}, + {Key: "k3", Raw: []byte("k3_value"), Version: toBytes(35, 2)}, }, res) itr, err = ddb.GetStateRangeScanIterator(ns, "k1", "k3") @@ -306,9 +306,9 @@ func TTestQueryExecutor(t *testing.T, ddb VersionedPersistence, vp artifactsProv } assert.Len(t, res, 3) assert.Equal(t, []VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, + {Key: "k1", Raw: []byte("k1_value"), Version: toBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: toBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: toBytes(35, 1)}, }, res) itr, err = ddb.GetStateSetIterator(ns, "k1", "k2", "k111") @@ -322,9 +322,9 @@ func TTestQueryExecutor(t *testing.T, ddb VersionedPersistence, vp artifactsProv } assert.Len(t, res, 3) assert.ElementsMatch(t, []VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, + {Key: "k1", Raw: []byte("k1_value"), Version: toBytes(35, 3)}, + {Key: "k2", Raw: []byte("k2_value"), Version: toBytes(35, 1)}, + {Key: "k111", Raw: []byte("k111_value"), Version: toBytes(35, 4)}, }, res) itr, err = ddb.GetStateSetIterator(ns, "k1", "k5") @@ -337,7 +337,7 @@ func TTestQueryExecutor(t *testing.T, ddb VersionedPersistence, vp artifactsProv res = append(res, *n) } var expected = RemoveNils([]VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, + {Key: "k1", Raw: []byte("k1_value"), Version: toBytes(35, 3)}, }) assert.Equal(t, expected, res) } @@ -350,9 +350,9 @@ func TTestShardLikeCommit(t *testing.T, ddb VersionedPersistence, vp artifactsPr // Populate the DB with some data at some height err := ddb.BeginUpdate() assert.NoError(t, err) - err = ddb.SetState(ns, k1, VersionedValue{Raw: []byte("k1val"), Version: fver.ToBytes(35, 1)}) + err = ddb.SetState(ns, k1, VersionedValue{Raw: []byte("k1val"), Version: toBytes(35, 1)}) assert.NoError(t, err) - err = ddb.SetState(ns, k2, VersionedValue{Raw: []byte("k2val"), Version: fver.ToBytes(37, 3)}) + err = ddb.SetState(ns, k2, VersionedValue{Raw: []byte("k2val"), Version: toBytes(37, 3)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) @@ -375,8 +375,8 @@ func TTestShardLikeCommit(t *testing.T, ddb VersionedPersistence, vp artifactsPr MetaWrites: map[string]KeyedMetaWrites{}, }, } - rwsb.ReadSet.Add(ns, k1, fver.ToBytes(35, 1)) - rwsb.ReadSet.Add(ns, k2, fver.ToBytes(37, 2)) + rwsb.ReadSet.Add(ns, k1, toBytes(35, 1)) + rwsb.ReadSet.Add(ns, k2, toBytes(37, 2)) rwsb.WriteSet.Add(ns, k1, []byte("k1FromTxidInvalid")) rwsb.WriteSet.Add(ns, k2, []byte("k2FromTxidInvalid")) marshaller := vp.NewMarshaller() @@ -421,8 +421,8 @@ func TTestShardLikeCommit(t *testing.T, ddb VersionedPersistence, vp artifactsPr MetaWrites: map[string]KeyedMetaWrites{}, }, } - rwsb.ReadSet.Add(ns, k1, fver.ToBytes(35, 1)) - rwsb.ReadSet.Add(ns, k2, fver.ToBytes(37, 3)) + rwsb.ReadSet.Add(ns, k1, toBytes(35, 1)) + rwsb.ReadSet.Add(ns, k2, toBytes(37, 3)) rwsb.WriteSet.Add(ns, k1, []byte("k1FromTxidValid")) rwsb.WriteSet.Add(ns, k2, []byte("k2FromTxidValid")) rwsBytes, err = marshaller.Marshal(rwsb) @@ -456,11 +456,11 @@ func TTestShardLikeCommit(t *testing.T, ddb VersionedPersistence, vp artifactsPr // check the content of the kvs after that vv, err := ddb.GetState(ns, k1) assert.NoError(t, err) - assert.Equal(t, VersionedValue{Raw: []byte("k1FromTxidValid"), Version: fver.ToBytes(38, 10)}, vv) + assert.Equal(t, VersionedValue{Raw: []byte("k1FromTxidValid"), Version: toBytes(38, 10)}, vv) vv, err = ddb.GetState(ns, k2) assert.NoError(t, err) - assert.Equal(t, VersionedValue{Raw: []byte("k2FromTxidValid"), Version: fver.ToBytes(38, 10)}, vv) + assert.Equal(t, VersionedValue{Raw: []byte("k2FromTxidValid"), Version: toBytes(38, 10)}, vv) // all Interceptors should be gone assert.Len(t, aVault.Interceptors, 0) @@ -480,7 +480,7 @@ func TTestVaultErr(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) OrderedReads: map[string][]string{}, }, } - rws.ReadSet.Add("pineapple", "key", fver.ToBytes(35, 1)) + rws.ReadSet.Add("pineapple", "key", toBytes(35, 1)) m := vp.NewMarshaller() rwsBytes, err := m.Marshal(rws) assert.NoError(t, err) @@ -527,7 +527,7 @@ func TTestMerge(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { assert.NoError(t, err) err = ddb.BeginUpdate() assert.NoError(t, err) - err = ddb.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: fver.ToBytes(35, 1)}) + err = ddb.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: toBytes(35, 1)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) @@ -558,8 +558,8 @@ func TTestMerge(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { MetaWrites: map[string]KeyedMetaWrites{}, }, } - rwsb.ReadSet.Add(ns, k1, fver.ToBytes(35, 1)) - rwsb.ReadSet.Add(ns, ne2Key, fver.ToBytes(0, 0)) + rwsb.ReadSet.Add(ns, k1, toBytes(35, 1)) + rwsb.ReadSet.Add(ns, ne2Key, toBytes(0, 0)) rwsb.WriteSet.Add(ns, k1, []byte("newv1")) rwsb.MetaWriteSet.Add(ns, k1, map[string][]byte{"k1": []byte("v1")}) m := vp.NewMarshaller() @@ -580,9 +580,9 @@ func TTestMerge(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { }}, rws.RWs().Writes) assert.Equal(t, Reads{ "namespace": { - "key1": fver.ToBytes(35, 1), + "key1": toBytes(35, 1), "notexist1": nil, - "notexist2": fver.ToBytes(0, 0), + "notexist2": toBytes(0, 0), }, }, rws.RWs().Reads) @@ -592,7 +592,7 @@ func TTestMerge(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { OrderedReads: map[string][]string{}, }, } - rwsb.ReadSet.Add(ns, k1, fver.ToBytes(36, 1)) + rwsb.ReadSet.Add(ns, k1, toBytes(36, 1)) rwsBytes, err = m.Marshal(rwsb) assert.NoError(t, err) @@ -650,7 +650,7 @@ func TTestInspector(t *testing.T, ddb VersionedPersistence, vp artifactsProvider assert.NoError(t, err) err = ddb.BeginUpdate() assert.NoError(t, err) - err = ddb.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: fver.ToBytes(35, 1)}) + err = ddb.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: toBytes(35, 1)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) @@ -716,7 +716,7 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) // create and populate 2 DBs err := db1.BeginUpdate() assert.NoError(t, err) - err = db1.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: fver.ToBytes(35, 1)}) + err = db1.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: toBytes(35, 1)}) assert.NoError(t, err) err = db1.SetStateMetadata(ns, k1Meta, map[string][]byte{"metakey": []byte("metavalue")}, nil) assert.NoError(t, err) @@ -725,7 +725,7 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) err = db2.BeginUpdate() assert.NoError(t, err) - err = db2.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: fver.ToBytes(35, 1)}) + err = db2.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: toBytes(35, 1)}) assert.NoError(t, err) err = db2.SetStateMetadata(ns, k1Meta, map[string][]byte{"metakey": []byte("metavalue")}, nil) assert.NoError(t, err) @@ -1076,16 +1076,17 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) vv2, err = db2.GetState(ns, k2) assert.NoError(t, err) - assert.Equal(t, VersionedValue{Raw: []byte("v2_updated"), Version: fver.ToBytes(35, 2)}, vv1) + assert.Equal(t, VersionedValue{Raw: []byte("v2_updated"), Version: toBytes(35, 2)}, vv1) assert.Equal(t, vv1, vv2) meta1, ver1, err := db1.GetStateMetadata(ns, k1Meta) assert.NoError(t, err) - b1, t1, err := fver.FromBytes(ver1) + versionMarshaller := BlockTxIndexVersionMarshaller{} + b1, t1, err := versionMarshaller.FromBytes(ver1) assert.NoError(t, err) meta2, ver2, err := db2.GetStateMetadata(ns, k1Meta) assert.NoError(t, err) - b2, t2, err := fver.FromBytes(ver2) + b2, t2, err := versionMarshaller.FromBytes(ver2) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"newmetakey": []byte("newmetavalue")}, meta1) assert.Equal(t, uint64(35), b1) @@ -1133,7 +1134,7 @@ func queryVault(v *Vault[ValidationCode], ns driver.Namespace, key driver.PKey, if err != nil { return nil, nil, 0, 0, err } - blkNum, txNum, err := fver.FromBytes(kVersion) + blkNum, txNum, err := BlockTxIndexVersionMarshaller{}.FromBytes(kVersion) if err != nil { return nil, nil, 0, 0, err } @@ -1223,3 +1224,10 @@ func (db *duplicateErrorPersistence) GetStateRangeScanIterator(namespace driver. func (db *duplicateErrorPersistence) GetStateSetIterator(ns driver.Namespace, keys ...driver.PKey) (collections.Iterator[*VersionedRead], error) { return db.VersionedPersistence.GetStateSetIterator(ns, keys...) } + +func toBytes(Block driver.BlockNum, TxNum driver.TxNum) []byte { + buf := make([]byte, 8) + binary.BigEndian.PutUint32(buf[:4], uint32(Block)) + binary.BigEndian.PutUint32(buf[4:], uint32(TxNum)) + return buf +} diff --git a/platform/common/core/generic/vault/interceptor.go b/platform/common/core/generic/vault/interceptor.go index 275fbf6ea..697f51509 100644 --- a/platform/common/core/generic/vault/interceptor.go +++ b/platform/common/core/generic/vault/interceptor.go @@ -10,6 +10,7 @@ import ( "sync" "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/fver" + "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/hash" "github.com/pkg/errors" diff --git a/platform/common/core/generic/vault/interceptor_test.go b/platform/common/core/generic/vault/interceptor_test.go index a99748fa5..4d4888f3c 100644 --- a/platform/common/core/generic/vault/interceptor_test.go +++ b/platform/common/core/generic/vault/interceptor_test.go @@ -10,7 +10,6 @@ import ( "sync" "testing" - "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/fver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/collections" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/assert" @@ -21,7 +20,7 @@ func newMockQE() mockQE { return mockQE{ State: VersionedValue{ Raw: []byte("raw"), - Version: fver.ToBytes(1, 1), + Version: blockTxIndexToBytes(1, 1), }, Metadata: map[string][]byte{ "md": []byte("meta"), @@ -35,7 +34,7 @@ type mockQE struct { } func (qe mockQE) GetStateMetadata(driver.Namespace, driver.PKey) (driver.Metadata, driver.RawVersion, error) { - return qe.Metadata, fver.ToBytes(1, 1), nil + return qe.Metadata, blockTxIndexToBytes(1, 1), nil } func (qe mockQE) GetState(driver.Namespace, driver.PKey) (VersionedValue, error) { return qe.State, nil diff --git a/platform/common/core/generic/vault/rwset.go b/platform/common/core/generic/vault/rwset.go index 22b456181..498adee56 100644 --- a/platform/common/core/generic/vault/rwset.go +++ b/platform/common/core/generic/vault/rwset.go @@ -140,7 +140,7 @@ func (w *WriteSet) Clear(ns string) { w.OrderedWrites[ns] = []string{} } -type Version = []byte +type Version = driver.RawVersion type NamespaceReads map[string]Version diff --git a/platform/common/core/generic/vault/vault.go b/platform/common/core/generic/vault/vault.go index 3b04466c4..1a5efc2c4 100644 --- a/platform/common/core/generic/vault/vault.go +++ b/platform/common/core/generic/vault/vault.go @@ -15,7 +15,6 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/pkg/runner" "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" - "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/fver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/collections" dbdriver "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver" @@ -68,6 +67,23 @@ type ( QueryExecutor = dbdriver.QueryExecutor ) +type txCommitIndex struct { + ctx context.Context + txID driver.TxID + block driver.BlockNum + indexInBloc driver.TxNum +} + +type commitInput struct { + txCommitIndex + rws *ReadWriteSet +} + +type VersionBuilder interface { + VersionedValues(keyMap NamespaceWrites, block driver.BlockNum, indexInBloc driver.TxNum) map[driver.PKey]VersionedValue + VersionedMetaValues(keyMap KeyedMetaWrites, block driver.BlockNum, indexInBloc driver.TxNum) map[driver.PKey]driver.VersionedMetadataValue +} + var ( DeadlockDetected = dbdriver.DeadlockDetected UniqueKeyViolation = dbdriver.UniqueKeyViolation @@ -98,7 +114,8 @@ type Vault[V driver.ValidationCode] struct { populator Populator metrics *Metrics - commitBatcher runner.BatchRunner[txCommitIndex] + commitBatcher runner.BatchRunner[txCommitIndex] + versionBuilder VersionBuilder } // New returns a new instance of Vault @@ -111,6 +128,7 @@ func New[V driver.ValidationCode]( populator Populator, metricsProvider metrics.Provider, tracerProvider trace.TracerProvider, + versionBuilder VersionBuilder, ) *Vault[V] { v := &Vault[V]{ logger: logger, @@ -121,6 +139,7 @@ func New[V driver.ValidationCode]( newInterceptor: newInterceptor, populator: populator, metrics: NewMetrics(metricsProvider, tracerProvider), + versionBuilder: versionBuilder, } v.commitBatcher = runner.NewSerialRunner(v.commitTXs) return v @@ -212,18 +231,6 @@ func (db *Vault[V]) unmapInterceptors(txIDs ...driver.TxID) (map[driver.TxID]TxI return result, nil } -type txCommitIndex struct { - ctx context.Context - txID driver.TxID - block driver.BlockNum - indexInBloc driver.TxNum -} - -type commitInput struct { - txCommitIndex - rws *ReadWriteSet -} - func (db *Vault[V]) CommitTX(ctx context.Context, txID driver.TxID, block driver.BlockNum, indexInBloc driver.TxNum) error { start := time.Now() newCtx, span := db.metrics.Vault.Start(ctx, "commit") @@ -300,7 +307,7 @@ func (db *Vault[V]) commitRWs(inputs ...commitInput) error { writes := make(map[driver.Namespace]map[driver.PKey]VersionedValue) for _, input := range inputs { for ns, ws := range input.rws.Writes { - vals := versionedValues(ws, input.block, input.indexInBloc) + vals := db.versionBuilder.VersionedValues(ws, input.block, input.indexInBloc) if nsWrites, ok := writes[ns]; !ok { writes[ns] = vals } else { @@ -325,7 +332,7 @@ func (db *Vault[V]) commitRWs(inputs ...commitInput) error { metaWrites := make(map[driver.Namespace]map[driver.PKey]driver.VersionedMetadataValue) for _, input := range inputs { for ns, ws := range input.rws.MetaWrites { - vals := versionedMetaValues(ws, input.block, input.indexInBloc) + vals := db.versionBuilder.VersionedMetaValues(ws, input.block, input.indexInBloc) if nsWrites, ok := metaWrites[ns]; !ok { metaWrites[ns] = vals } else { @@ -398,22 +405,6 @@ func (db *Vault[V]) storeAllMetaWrites(metaWrites map[driver.Namespace]map[drive return errs } -func versionedValues(keyMap NamespaceWrites, block driver.BlockNum, indexInBloc driver.TxNum) map[driver.PKey]VersionedValue { - vals := make(map[driver.PKey]VersionedValue, len(keyMap)) - for pkey, val := range keyMap { - vals[pkey] = VersionedValue{Raw: val, Version: fver.ToBytes(block, indexInBloc)} - } - return vals -} - -func versionedMetaValues(keyMap KeyedMetaWrites, block driver.BlockNum, indexInBloc driver.TxNum) map[driver.PKey]driver.VersionedMetadataValue { - vals := make(map[driver.PKey]driver.VersionedMetadataValue, len(keyMap)) - for pkey, val := range keyMap { - vals[pkey] = driver.VersionedMetadataValue{Metadata: val, Version: fver.ToBytes(block, indexInBloc)} - } - return vals -} - func (db *Vault[V]) discard(ns driver.Namespace, block driver.BlockNum, indexInBloc driver.TxNum, errs map[driver.PKey]error) (bool, error) { if err1 := db.store.Discard(); err1 != nil { db.logger.Errorf("got error %v; discarding caused %s", errors2.Join(collections.Values(errs)...), err1.Error()) diff --git a/platform/common/core/generic/vault/vault_test.go b/platform/common/core/generic/vault/vault_test.go index cd028d147..4e5a9f7f8 100644 --- a/platform/common/core/generic/vault/vault_test.go +++ b/platform/common/core/generic/vault/vault_test.go @@ -44,6 +44,7 @@ func (p *testArtifactProvider) NewCachedVault(ddb VersionedPersistence) (*Vault[ &populator{}, &disabled.Provider{}, &noop.TracerProvider{}, + &BlockTxIndexVersionBuilder{}, ), nil } @@ -61,6 +62,7 @@ func (p *testArtifactProvider) NewNonCachedVault(ddb VersionedPersistence) (*Vau &populator{}, &disabled.Provider{}, &noop.TracerProvider{}, + &BlockTxIndexVersionBuilder{}, ), nil } diff --git a/platform/common/core/generic/vault/version.go b/platform/common/core/generic/vault/version.go new file mode 100644 index 000000000..b35699ff7 --- /dev/null +++ b/platform/common/core/generic/vault/version.go @@ -0,0 +1,60 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package vault + +import ( + "encoding/binary" + + "github.com/pkg/errors" + + driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" + "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver" +) + +type BlockTxIndexVersionBuilder struct{} + +func (b *BlockTxIndexVersionBuilder) VersionedValues(keyMap NamespaceWrites, block driver2.BlockNum, indexInBloc driver2.TxNum) map[driver2.PKey]driver.VersionedValue { + vals := make(map[driver2.PKey]driver.VersionedValue, len(keyMap)) + for pkey, val := range keyMap { + vals[pkey] = driver.VersionedValue{Raw: val, Version: blockTxIndexToBytes(block, indexInBloc)} + } + return vals +} + +func (b *BlockTxIndexVersionBuilder) VersionedMetaValues(keyMap KeyedMetaWrites, block driver2.BlockNum, indexInBloc driver2.TxNum) map[driver2.PKey]driver2.VersionedMetadataValue { + vals := make(map[driver2.PKey]driver2.VersionedMetadataValue, len(keyMap)) + for pkey, val := range keyMap { + vals[pkey] = driver2.VersionedMetadataValue{Metadata: val, Version: blockTxIndexToBytes(block, indexInBloc)} + } + return vals +} + +type BlockTxIndexVersionMarshaller struct{} + +func (m BlockTxIndexVersionMarshaller) FromBytes(data Version) (driver2.BlockNum, driver2.TxNum, error) { + if len(data) == 0 { + return 0, 0, nil + } + if len(data) != 8 { + return 0, 0, errors.Errorf("block number must be 8 bytes, but got %d", len(data)) + } + Block := driver2.BlockNum(binary.BigEndian.Uint32(data[:4])) + TxNum := driver2.TxNum(binary.BigEndian.Uint32(data[4:])) + return Block, TxNum, nil + +} + +func (m BlockTxIndexVersionMarshaller) ToBytes(bn driver2.BlockNum, txn driver2.TxNum) Version { + return blockTxIndexToBytes(bn, txn) +} + +func blockTxIndexToBytes(Block driver2.BlockNum, TxNum driver2.TxNum) []byte { + buf := make([]byte, 8) + binary.BigEndian.PutUint32(buf[:4], uint32(Block)) + binary.BigEndian.PutUint32(buf[4:], uint32(TxNum)) + return buf +} diff --git a/platform/fabric/core/generic/vault/vault.go b/platform/fabric/core/generic/vault/vault.go index 6b905cf97..da7487913 100644 --- a/platform/fabric/core/generic/vault/vault.go +++ b/platform/fabric/core/generic/vault/vault.go @@ -9,7 +9,6 @@ package vault import ( "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/proto" "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault" - "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/fver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/txidstore" "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/collections" @@ -49,6 +48,7 @@ func NewVault(store vault.VersionedPersistence, txIDStore TXIDStore, metricsProv &populator{}, metricsProvider, tracerProvider, + &vault.BlockTxIndexVersionBuilder{}, ) } @@ -63,7 +63,9 @@ func newInterceptor(logger vault.Logger, qe vault.VersionedQueryExecutor, txIDSt ) } -type populator struct{} +type populator struct { + versionMarshaller vault.BlockTxIndexVersionMarshaller +} func (p *populator) Populate(rws *vault.ReadWriteSet, rwsetBytes []byte, namespaces ...driver.Namespace) error { txRWSet := &rwset.TxReadWriteSet{} @@ -93,7 +95,7 @@ func (p *populator) Populate(rws *vault.ReadWriteSet, rwsetBytes []byte, namespa bn = read.Version.BlockNum txn = read.Version.TxNum } - rws.ReadSet.Add(ns, read.Key, fver.ToBytes(bn, txn)) + rws.ReadSet.Add(ns, read.Key, p.versionMarshaller.ToBytes(bn, txn)) } for _, write := range nsrws.KvRwSet.Writes { @@ -117,14 +119,16 @@ func (p *populator) Populate(rws *vault.ReadWriteSet, rwsetBytes []byte, namespa return nil } -type marshaller struct{} +type marshaller struct { + versionMarshaller vault.BlockTxIndexVersionMarshaller +} func (m *marshaller) Marshal(rws *vault.ReadWriteSet) ([]byte, error) { rwsb := rwsetutil.NewRWSetBuilder() for ns, keyMap := range rws.Reads { for key, v := range keyMap { - block, txNum, err := fver.FromBytes(v) + block, txNum, err := m.versionMarshaller.FromBytes(v) if err != nil { return nil, errors.Wrapf(err, "failed to extract block fver from bytes [%v]", v) } @@ -181,7 +185,7 @@ func (m *marshaller) Append(destination *vault.ReadWriteSet, raw []byte, nss ... txnum = read.Version.TxNum } dVersion, in := destination.ReadSet.Get(ns, read.Key) - b, t, err := fver.FromBytes(dVersion) + b, t, err := m.versionMarshaller.FromBytes(dVersion) if err != nil { return errors.Wrapf(err, "failed to extract block fver from bytes [%v]", dVersion) } diff --git a/platform/orion/core/generic/vault/vault.go b/platform/orion/core/generic/vault/vault.go index 1b2bc37d0..f6e9f4f3e 100644 --- a/platform/orion/core/generic/vault/vault.go +++ b/platform/orion/core/generic/vault/vault.go @@ -9,7 +9,6 @@ package vault import ( "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/proto" "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault" - "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/fver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/txidstore" "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" odriver "github.com/hyperledger-labs/fabric-smart-client/platform/orion/driver" @@ -42,6 +41,7 @@ func New(store vault.VersionedPersistence, txIDStore TXIDStore, metricsProvider &populator{}, metricsProvider, tracerProvider, + &vault.BlockTxIndexVersionBuilder{}, ) } @@ -83,7 +83,9 @@ func (i *Interceptor) Equals(other interface{}, nss ...string) error { return errors.Errorf("cannot compare to the passed value [%v]", other) } -type populator struct{} +type populator struct { + versionMarshaller vault.BlockTxIndexVersionMarshaller +} func (p *populator) Populate(rws *vault.ReadWriteSet, rwsetBytes []byte, namespaces ...driver.Namespace) error { txRWSet := &types.DataTx{} @@ -104,7 +106,7 @@ func (p *populator) Populate(rws *vault.ReadWriteSet, rwsetBytes []byte, namespa rws.ReadSet.Add( operation.DbName, read.Key, - fver.ToBytes( + p.versionMarshaller.ToBytes( bn, txn, ), diff --git a/platform/view/services/db/dbtest/helpers.go b/platform/view/services/db/dbtest/helpers.go index 04c4ecb58..dc70e745a 100644 --- a/platform/view/services/db/dbtest/helpers.go +++ b/platform/view/services/db/dbtest/helpers.go @@ -8,6 +8,7 @@ package dbtest import ( "database/sql" + "encoding/binary" "fmt" "strings" "sync" @@ -16,8 +17,9 @@ import ( "unicode/utf8" errors2 "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" - "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/fver" + driver3 "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" + driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/keys" "github.com/pkg/errors" @@ -108,10 +110,10 @@ func TTestRangeQueries(t *testing.T, db driver.TransactionalVersionedPersistence } assert.Len(t, res, 4) assert.Equal(t, []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, - {Key: "k3", Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: ToBytes(35, 1)}, + {Key: "k3", Raw: []byte("k3_value"), Version: ToBytes(35, 2)}, }, res) itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") @@ -126,9 +128,9 @@ func TTestRangeQueries(t *testing.T, db driver.TransactionalVersionedPersistence res = append(res, *n) } expected := []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: ToBytes(35, 1)}, } assert.Len(t, res, 3) assert.Equal(t, expected, res) @@ -145,16 +147,16 @@ func TTestRangeQueries(t *testing.T, db driver.TransactionalVersionedPersistence } itr.Close() expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, } assert.Len(t, res, 2) assert.Equal(t, expected, res) expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: ToBytes(35, 1)}, } itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") assert.NoError(t, err) @@ -169,8 +171,8 @@ func TTestRangeQueries(t *testing.T, db driver.TransactionalVersionedPersistence assert.Equal(t, expected, res) expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k3", Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k3", Raw: []byte("k3_value"), Version: ToBytes(35, 2)}, } itr, err = db.GetStateSetIterator(ns, "k1", "k3") assert.NoError(t, err) @@ -192,7 +194,7 @@ func TTestMeta(t *testing.T, db driver.TransactionalVersionedPersistence) { err := db.BeginUpdate() assert.NoError(t, err) - err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val"), Version: ToBytes(35, 1)}) assert.NoError(t, err) err = db.Commit() @@ -200,12 +202,12 @@ func TTestMeta(t *testing.T, db driver.TransactionalVersionedPersistence) { vv, err := db.GetState(ns, key) assert.NoError(t, err) - assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: ToBytes(35, 1)}, vv) m, ver, err := db.GetStateMetadata(ns, key) assert.NoError(t, err) assert.Len(t, m, 0) - bn, tn, err := fver.FromBytes(ver) + bn, tn, err := FromBytes(ver) assert.NoError(t, err) assert.Equal(t, uint64(35), bn) assert.Equal(t, uint64(1), tn) @@ -221,11 +223,11 @@ func TTestMeta(t *testing.T, db driver.TransactionalVersionedPersistence) { vv, err = db.GetState(ns, key) assert.NoError(t, err) - assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(36, 2)}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: ToBytes(36, 2)}, vv) m, ver, err = db.GetStateMetadata(ns, key) assert.NoError(t, err) - bn, tn, err = fver.FromBytes(ver) + bn, tn, err = FromBytes(ver) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"foo": []byte("bar")}, m) assert.Equal(t, uint64(36), bn) @@ -244,7 +246,7 @@ func TTestSimpleReadWrite(t *testing.T, db driver.TransactionalVersionedPersiste // empty metadata m, ver, err := db.GetStateMetadata(ns, key) assert.NoError(t, err) - bn, tn, err := fver.FromBytes(ver) + bn, tn, err := FromBytes(ver) assert.NoError(t, err) assert.Len(t, m, 0) assert.Equal(t, uint64(0), bn) @@ -253,7 +255,7 @@ func TTestSimpleReadWrite(t *testing.T, db driver.TransactionalVersionedPersiste // add data err = db.BeginUpdate() assert.NoError(t, err) - err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val"), Version: ToBytes(35, 1)}) assert.NoError(t, err) err = db.Commit() assert.NoError(t, err) @@ -261,30 +263,30 @@ func TTestSimpleReadWrite(t *testing.T, db driver.TransactionalVersionedPersiste // get data vv, err = db.GetState(ns, key) assert.NoError(t, err) - assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: ToBytes(35, 1)}, vv) // logging because this can cause a deadlock if maxOpenConnections is only 1 t.Logf("get state [%s] during set state tx", key) err = db.BeginUpdate() assert.NoError(t, err) - err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val1"), Version: fver.ToBytes(36, 2)}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val1"), Version: ToBytes(36, 2)}) assert.NoError(t, err) vv, err = db.GetState(ns, key) assert.NoError(t, err) - assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: ToBytes(35, 1)}, vv) err = db.Commit() assert.NoError(t, err) t.Logf("get state after tx [%s]", key) vv, err = db.GetState(ns, key) assert.NoError(t, err) - assert.Equal(t, driver.VersionedValue{Raw: []byte("val1"), Version: fver.ToBytes(36, 2)}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val1"), Version: ToBytes(36, 2)}, vv) // Discard an update err = db.BeginUpdate() assert.NoError(t, err) - err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val0"), Version: fver.ToBytes(37, 3)}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val0"), Version: ToBytes(37, 3)}) assert.NoError(t, err) err = db.Discard() assert.NoError(t, err) @@ -292,7 +294,7 @@ func TTestSimpleReadWrite(t *testing.T, db driver.TransactionalVersionedPersiste // Expect state to be same as before the rollback vv, err = db.GetState(ns, key) assert.NoError(t, err) - assert.Equal(t, driver.VersionedValue{Raw: []byte("val1"), Version: fver.ToBytes(36, 2)}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val1"), Version: ToBytes(36, 2)}, vv) // delete state err = db.BeginUpdate() @@ -312,10 +314,10 @@ func populateDB(t *testing.T, db driver.TransactionalVersionedPersistence, ns, k err := db.BeginUpdate() assert.NoError(t, err) - err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("bar"), Version: fver.ToBytes(1, 1)}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("bar"), Version: ToBytes(1, 1)}) assert.NoError(t, err) - err = db.SetState(ns, keyWithSuffix, driver.VersionedValue{Raw: []byte("bar1"), Version: fver.ToBytes(1, 1)}) + err = db.SetState(ns, keyWithSuffix, driver.VersionedValue{Raw: []byte("bar1"), Version: ToBytes(1, 1)}) assert.NoError(t, err) err = db.Commit() @@ -323,11 +325,11 @@ func populateDB(t *testing.T, db driver.TransactionalVersionedPersistence, ns, k vv, err := db.GetState(ns, key) assert.NoError(t, err) - assert.Equal(t, driver.VersionedValue{Raw: []byte("bar"), Version: fver.ToBytes(1, 1)}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("bar"), Version: ToBytes(1, 1)}, vv) vv, err = db.GetState(ns, keyWithSuffix) assert.NoError(t, err) - assert.Equal(t, driver.VersionedValue{Raw: []byte("bar1"), Version: fver.ToBytes(1, 1)}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("bar1"), Version: ToBytes(1, 1)}, vv) vv, err = db.GetState(ns, "barf") assert.NoError(t, err) @@ -342,13 +344,13 @@ func populateForRangeQueries(t *testing.T, db driver.TransactionalVersionedPersi err := db.BeginUpdate() assert.NoError(t, err) - err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}) + err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Version: ToBytes(35, 1)}) assert.NoError(t, err) - err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}) + err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Version: ToBytes(35, 2)}) assert.NoError(t, err) - err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}) + err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Version: ToBytes(35, 3)}) assert.NoError(t, err) - err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}) + err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Version: ToBytes(35, 4)}) assert.NoError(t, err) err = db.Commit() @@ -371,7 +373,7 @@ func TTestMetadata(t *testing.T, db driver.TransactionalVersionedPersistence) { md, ver, err := db.GetStateMetadata(ns, key) assert.NoError(t, err) assert.Nil(t, md) - bn, txn, err := fver.FromBytes(ver) + bn, txn, err := FromBytes(ver) assert.NoError(t, err) assert.Equal(t, uint64(0x0), bn) assert.Equal(t, uint64(0x0), txn) @@ -385,7 +387,7 @@ func TTestMetadata(t *testing.T, db driver.TransactionalVersionedPersistence) { md, ver, err = db.GetStateMetadata(ns, key) assert.NoError(t, err) - bn, txn, err = fver.FromBytes(ver) + bn, txn, err = FromBytes(ver) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"foo": []byte("bar")}, md) assert.Equal(t, uint64(35), bn) @@ -400,7 +402,7 @@ func TTestMetadata(t *testing.T, db driver.TransactionalVersionedPersistence) { md, ver, err = db.GetStateMetadata(ns, key) assert.NoError(t, err) - bn, txn, err = fver.FromBytes(ver) + bn, txn, err = FromBytes(ver) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"foo1": []byte("bar1")}, md) assert.Equal(t, uint64(36), bn) @@ -453,13 +455,13 @@ func TTestRangeQueries1(t *testing.T, db driver.TransactionalVersionedPersistenc err := db.BeginUpdate() assert.NoError(t, err) - err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}) + err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Version: ToBytes(35, 1)}) assert.NoError(t, err) - err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}) + err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Version: ToBytes(35, 2)}) assert.NoError(t, err) - err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}) + err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Version: ToBytes(35, 3)}) assert.NoError(t, err) - err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}) + err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Version: ToBytes(35, 4)}) assert.NoError(t, err) err = db.Commit() @@ -476,10 +478,10 @@ func TTestRangeQueries1(t *testing.T, db driver.TransactionalVersionedPersistenc } assert.Len(t, res, 4) assert.Equal(t, []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, - {Key: "k3", Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: ToBytes(35, 1)}, + {Key: "k3", Raw: []byte("k3_value"), Version: ToBytes(35, 2)}, }, res) itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") @@ -493,9 +495,9 @@ func TTestRangeQueries1(t *testing.T, db driver.TransactionalVersionedPersistenc } assert.Len(t, res, 3) assert.Equal(t, []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: ToBytes(35, 1)}, }, res) } @@ -506,13 +508,13 @@ func TTestMultiWritesAndRangeQueries(t *testing.T, db driver.TransactionalVersio t.Fatal(err) } - err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}) + err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Version: ToBytes(35, 1)}) assert.NoError(t, err) - err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}) + err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Version: ToBytes(35, 2)}) assert.NoError(t, err) - err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}) + err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Version: ToBytes(35, 3)}) assert.NoError(t, err) - err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}) + err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Version: ToBytes(35, 4)}) assert.NoError(t, err) err = db.Commit() @@ -551,10 +553,10 @@ func TTestMultiWritesAndRangeQueries(t *testing.T, db driver.TransactionalVersio } assert.Len(t, res, 4) assert.Equal(t, []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, - {Key: "k3", Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: ToBytes(35, 1)}, + {Key: "k3", Raw: []byte("k3_value"), Version: ToBytes(35, 2)}, }, res) itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") @@ -567,9 +569,9 @@ func TTestMultiWritesAndRangeQueries(t *testing.T, db driver.TransactionalVersio res = append(res, *n) } expected := []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: ToBytes(35, 1)}, } assert.Len(t, res, 3) assert.Equal(t, expected, res) @@ -585,16 +587,16 @@ func TTestMultiWritesAndRangeQueries(t *testing.T, db driver.TransactionalVersio res = append(res, *n) } expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, } assert.Len(t, res, 2) assert.Equal(t, expected, res) expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, - {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, - {Key: "k2", Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}, + {Key: "k1", Raw: []byte("k1_value"), Version: ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: ToBytes(35, 4)}, + {Key: "k2", Raw: []byte("k2_value"), Version: ToBytes(35, 1)}, } itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") assert.NoError(t, err) @@ -634,7 +636,7 @@ func TTestMultiWrites(t *testing.T, db driver.TransactionalVersionedPersistence) func write(t *testing.T, db driver.TransactionalVersionedPersistence, ns, key string, value []byte, block, txnum uint64) { tx, err := db.NewWriteTransaction() assert.NoError(t, err) - err = tx.SetState(ns, key, driver.VersionedValue{Raw: value, Version: fver.ToBytes(block, txnum)}) + err = tx.SetState(ns, key, driver.VersionedValue{Raw: value, Version: ToBytes(block, txnum)}) assert.NoError(t, err) err = tx.Commit() assert.NoError(t, err) @@ -688,7 +690,7 @@ func TTestCompositeKeys(t *testing.T, db driver.TransactionalVersionedPersistenc } { k, err := createCompositeKey(keyPrefix, comps) assert.NoError(t, err) - err = db.SetState(ns, k, driver.VersionedValue{Raw: []byte(k), Version: fver.ToBytes(35, 1)}) + err = db.SetState(ns, k, driver.VersionedValue{Raw: []byte(k), Version: ToBytes(35, 1)}) assert.NoError(t, err) } @@ -711,10 +713,10 @@ func TTestCompositeKeys(t *testing.T, db driver.TransactionalVersionedPersistenc } assert.Len(t, res, 4) assert.Equal(t, []driver.VersionedRead{ - {Key: "\x00prefix0a0b0", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30}, Version: fver.ToBytes(0x23, 1)}, - {Key: "\x00prefix0a0b010", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x31, 0x30}, Version: fver.ToBytes(0x23, 1)}, - {Key: "\x00prefix0a0b030", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x33, 0x30}, Version: fver.ToBytes(0x23, 1)}, - {Key: "\x00prefix0a0d0", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x64, 0x30}, Version: fver.ToBytes(0x23, 1)}, + {Key: "\x00prefix0a0b0", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30}, Version: ToBytes(0x23, 1)}, + {Key: "\x00prefix0a0b010", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x31, 0x30}, Version: ToBytes(0x23, 1)}, + {Key: "\x00prefix0a0b030", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x33, 0x30}, Version: ToBytes(0x23, 1)}, + {Key: "\x00prefix0a0d0", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x64, 0x30}, Version: ToBytes(0x23, 1)}, }, res) partialCompositeKey, err = createCompositeKey(keyPrefix, []string{"a", "b"}) @@ -733,9 +735,9 @@ func TTestCompositeKeys(t *testing.T, db driver.TransactionalVersionedPersistenc } assert.Len(t, res, 3) assert.Equal(t, []driver.VersionedRead{ - {Key: "\x00prefix0a0b0", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30}, Version: fver.ToBytes(0x23, 1)}, - {Key: "\x00prefix0a0b010", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x31, 0x30}, Version: fver.ToBytes(0x23, 1)}, - {Key: "\x00prefix0a0b030", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x33, 0x30}, Version: fver.ToBytes(0x23, 1)}, + {Key: "\x00prefix0a0b0", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30}, Version: ToBytes(0x23, 1)}, + {Key: "\x00prefix0a0b010", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x31, 0x30}, Version: ToBytes(0x23, 1)}, + {Key: "\x00prefix0a0b030", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x33, 0x30}, Version: ToBytes(0x23, 1)}, }, res) } @@ -1142,3 +1144,22 @@ func subscribe(db notifier) (chan notifyEvent, error) { } return ch, nil } + +func ToBytes(Block driver2.BlockNum, TxNum driver2.TxNum) []byte { + buf := make([]byte, 8) + binary.BigEndian.PutUint32(buf[:4], uint32(Block)) + binary.BigEndian.PutUint32(buf[4:], uint32(TxNum)) + return buf +} + +func FromBytes(data driver3.RawVersion) (driver2.BlockNum, driver2.TxNum, error) { + if len(data) == 0 { + return 0, 0, nil + } + if len(data) != 8 { + return 0, 0, errors.Errorf("block number must be 8 bytes, but got %d", len(data)) + } + Block := driver2.BlockNum(binary.BigEndian.Uint32(data[:4])) + TxNum := driver2.TxNum(binary.BigEndian.Uint32(data[4:])) + return Block, TxNum, nil +} diff --git a/platform/view/services/db/driver/badger/badger_test.go b/platform/view/services/db/driver/badger/badger_test.go index 95876b0a8..7552daa96 100644 --- a/platform/view/services/db/driver/badger/badger_test.go +++ b/platform/view/services/db/driver/badger/badger_test.go @@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0 package badger import ( + "encoding/binary" "fmt" "os" "path/filepath" @@ -15,10 +16,9 @@ import ( "time" "unicode/utf8" - "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/fver" - "github.com/dgraph-io/badger/v3" "github.com/golang/protobuf/proto" + driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/dbtest" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver/badger/mock" @@ -107,7 +107,8 @@ func TestMarshallingErrors(t *testing.T) { m, ver, err := db.GetStateMetadata(ns, key) assert.Contains(t, err.Error(), "could not unmarshal VersionedValue for key") assert.Len(t, m, 0) - bn, tn, err := fver.FromBytes(ver) + versionMarshaller := BlockTxIndexVersionMarshaller{} + bn, tn, err := versionMarshaller.FromBytes(ver) assert.NoError(t, err) assert.Equal(t, uint64(0), bn) assert.Equal(t, uint64(0), tn) @@ -128,7 +129,7 @@ func TestMarshallingErrors(t *testing.T) { m, ver, err = db.GetStateMetadata(ns, key) assert.EqualError(t, err, "could not get value for key ns\x00key: invalid fver, expected 1, got 34") - bn, tn, err = fver.FromBytes(ver) + bn, tn, err = versionMarshaller.FromBytes(ver) assert.NoError(t, err) assert.Len(t, m, 0) assert.Equal(t, uint64(0), bn) @@ -286,3 +287,29 @@ func BenchmarkBuilder(b *testing.B) { } result = s } + +type BlockTxIndexVersionMarshaller struct{} + +func (m BlockTxIndexVersionMarshaller) FromBytes(data driver2.RawVersion) (driver2.BlockNum, driver2.TxNum, error) { + if len(data) == 0 { + return 0, 0, nil + } + if len(data) != 8 { + return 0, 0, errors.Errorf("block number must be 8 bytes, but got %d", len(data)) + } + Block := driver2.BlockNum(binary.BigEndian.Uint32(data[:4])) + TxNum := driver2.TxNum(binary.BigEndian.Uint32(data[4:])) + return Block, TxNum, nil + +} + +func (m BlockTxIndexVersionMarshaller) ToBytes(bn driver2.BlockNum, txn driver2.TxNum) driver2.RawVersion { + return blockTxIndexToBytes(bn, txn) +} + +func blockTxIndexToBytes(Block driver2.BlockNum, TxNum driver2.TxNum) []byte { + buf := make([]byte, 8) + binary.BigEndian.PutUint32(buf[:4], uint32(Block)) + binary.BigEndian.PutUint32(buf[4:], uint32(TxNum)) + return buf +}