From 706b4250642a6fab0d6650673297d7adbff9dbac Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Mon, 23 Sep 2024 13:10:15 +0200 Subject: [PATCH] db and vault support for generic version Signed-off-by: Angelo De Caro --- .../common/core/generic/vault/fver/version.go | 49 ++++ platform/common/core/generic/vault/helpers.go | 232 +++++++++--------- .../common/core/generic/vault/interceptor.go | 27 +- .../core/generic/vault/interceptor_test.go | 10 +- .../common/core/generic/vault/queryexec.go | 20 +- platform/common/core/generic/vault/rwset.go | 23 +- platform/common/core/generic/vault/vault.go | 6 +- .../common/core/generic/vault/vault_test.go | 9 +- platform/common/driver/vault.go | 23 +- platform/fabric/core/generic/vault/vault.go | 23 +- platform/orion/core/generic/vault/vault.go | 7 +- platform/view/services/db/dbtest/helpers.go | 167 +++++++------ .../view/services/db/driver/badger/badger.go | 32 ++- .../services/db/driver/badger/badger_test.go | 14 +- .../db/driver/badger/proto/generate.go | 2 +- .../services/db/driver/badger/proto/kvs.pb.go | 217 ++++++++++------ .../services/db/driver/badger/proto/kvs.proto | 10 +- .../view/services/db/driver/badger/range.go | 7 +- platform/view/services/db/driver/driver.go | 16 +- .../db/driver/notifier/persistence.go | 10 +- .../services/db/driver/sql/common/base.go | 9 +- .../db/driver/sql/common/versioned.go | 60 ++--- .../db/driver/sql/postgres/versioned.go | 10 +- 23 files changed, 575 insertions(+), 408 deletions(-) create mode 100644 platform/common/core/generic/vault/fver/version.go diff --git a/platform/common/core/generic/vault/fver/version.go b/platform/common/core/generic/vault/fver/version.go new file mode 100644 index 000000000..4e811e789 --- /dev/null +++ b/platform/common/core/generic/vault/fver/version.go @@ -0,0 +1,49 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +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" +) + +var zeroVersion = []byte{0, 0, 0, 0, 0, 0, 0, 0} + +func IsEqual(a, b driver.RawVersion) bool { + if bytes.Equal(a, b) { + return true + } + if len(a) == 0 && bytes.Equal(zeroVersion, b) { + return true + } + if len(b) == 0 && bytes.Equal(zeroVersion, a) { + return true + } + 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 1a4e8f45a..61f71f2e8 100644 --- a/platform/common/core/generic/vault/helpers.go +++ b/platform/common/core/generic/vault/helpers.go @@ -11,7 +11,8 @@ import ( "testing" "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/proto" - driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" + "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" "github.com/stretchr/testify/assert" @@ -131,16 +132,16 @@ 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"), Block: 35, TxNum: 1}) + err = ddb.SetState(ns, k, VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) _, _, err = rws.GetReadAt(ns, 0) - assert.EqualError(t, err, "invalid read [namespace:key1]: previous value returned at version 0:0, current value at version 35:1") + assert.EqualError(t, err, "invalid read [namespace:key1]: previous value returned at fver [[]], current value at fver [[0 0 0 35 0 0 0 1]]") _, err = rws.GetState(ns, k) - assert.EqualError(t, err, "invalid read [namespace:key1]: previous value returned at version 0:0, current value at version 35:1") + assert.EqualError(t, err, "invalid read [namespace:key1]: previous value returned at fver [[]], current value at fver [[0 0 0 35 0 0 0 1]]") mv, err := rws.GetStateMetadata(ns, mk) assert.NoError(t, err) @@ -148,13 +149,13 @@ func TTestInterceptorConcurrency(t *testing.T, ddb VersionedPersistence, vp arti err = ddb.BeginUpdate() assert.NoError(t, err) - err = ddb.SetStateMetadata(ns, mk, map[string][]byte{"k": []byte("v")}, 36, 2) + err = ddb.SetStateMetadata(ns, mk, map[string][]byte{"k": []byte("v")}, nil) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) _, err = rws.GetStateMetadata(ns, mk) - assert.EqualError(t, err, "invalid metadata read: previous value returned at version 0:0, current value at version 36:2") + assert.EqualError(t, err, "invalid metadata read: previous value returned at fver [[0 0 0 0 0 0 0 0]], current value at fver [[0 0 0 36 0 0 0 2]]") } func TTestParallelVaults(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { @@ -202,15 +203,15 @@ func TTestParallelVaults(t *testing.T, ddb VersionedPersistence, vp artifactsPro assert.NoError(t, err) assert.Equal(t, []byte("val_v1"), val) assert.Equal(t, map[string][]byte{"k1": []byte("mval1_v1")}, mval) - assert.Equal(t, uint64(1), txNum) - assert.Equal(t, uint64(2), blkNum) + assert.Equal(t, uint64(2), txNum) + assert.Equal(t, uint64(1), blkNum) val, mval, txNum, blkNum, err = queryVault(vault2, ns, k, mk) assert.NoError(t, err) assert.Equal(t, []byte("val_v1"), val) assert.Equal(t, map[string][]byte{"k1": []byte("mval1_v1")}, mval) - assert.Equal(t, uint64(1), txNum) - assert.Equal(t, uint64(2), blkNum) + assert.Equal(t, uint64(2), txNum) + assert.Equal(t, uint64(1), blkNum) } func TTestDeadlock(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { @@ -243,8 +244,8 @@ func TTestDeadlock(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) assert.Equal(t, []byte("val_v1"), val) assert.Equal(t, map[string][]byte{"k1": []byte("mval1_v1")}, mval) - assert.Equal(t, uint64(1), txNum) - assert.Equal(t, uint64(2), blkNum) + assert.Equal(t, uint64(2), txNum) + assert.Equal(t, uint64(1), blkNum) } func TTestQueryExecutor(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { @@ -255,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"), Block: 35, TxNum: 1}) + err = ddb.SetState(ns, "k2", VersionedValue{Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) - err = ddb.SetState(ns, "k3", VersionedValue{Raw: []byte("k3_value"), Block: 35, TxNum: 2}) + err = ddb.SetState(ns, "k3", VersionedValue{Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}) assert.NoError(t, err) - err = ddb.SetState(ns, "k1", VersionedValue{Raw: []byte("k1_value"), Block: 35, TxNum: 3}) + err = ddb.SetState(ns, "k1", VersionedValue{Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}) assert.NoError(t, err) - err = ddb.SetState(ns, "k111", VersionedValue{Raw: []byte("k111_value"), Block: 35, TxNum: 4}) + err = ddb.SetState(ns, "k111", VersionedValue{Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) @@ -288,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"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, - {Key: "k3", Raw: []byte("k3_value"), Block: 35, TxNum: 2}, + {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)}, }, res) itr, err = ddb.GetStateRangeScanIterator(ns, "k1", "k3") @@ -305,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"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, + {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)}, }, res) itr, err = ddb.GetStateSetIterator(ns, "k1", "k2", "k111") @@ -321,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"), Block: 35, TxNum: 3}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, + {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)}, }, res) itr, err = ddb.GetStateSetIterator(ns, "k1", "k5") @@ -336,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"), Block: 35, TxNum: 3}, + {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, }) assert.Equal(t, expected, res) } @@ -349,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"), Block: 35, TxNum: 1}) + err = ddb.SetState(ns, k1, VersionedValue{Raw: []byte("k1val"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) - err = ddb.SetState(ns, k2, VersionedValue{Raw: []byte("k2val"), Block: 37, TxNum: 3}) + err = ddb.SetState(ns, k2, VersionedValue{Raw: []byte("k2val"), Version: fver.ToBytes(37, 3)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) @@ -363,7 +364,7 @@ func TTestShardLikeCommit(t *testing.T, ddb VersionedPersistence, vp artifactsPr // create the read-write set rwsb := &ReadWriteSet{ ReadSet: ReadSet{ - Reads: map[driver2.Namespace]NamespaceReads{}, + Reads: map[driver.Namespace]NamespaceReads{}, OrderedReads: map[string][]string{}, }, WriteSet: WriteSet{ @@ -374,8 +375,8 @@ func TTestShardLikeCommit(t *testing.T, ddb VersionedPersistence, vp artifactsPr MetaWrites: map[string]KeyedMetaWrites{}, }, } - rwsb.ReadSet.Add(ns, k1, 35, 1) - rwsb.ReadSet.Add(ns, k2, 37, 2) + rwsb.ReadSet.Add(ns, k1, fver.ToBytes(35, 1)) + rwsb.ReadSet.Add(ns, k2, fver.ToBytes(37, 2)) rwsb.WriteSet.Add(ns, k1, []byte("k1FromTxidInvalid")) rwsb.WriteSet.Add(ns, k2, []byte("k2FromTxidInvalid")) marshaller := vp.NewMarshaller() @@ -386,7 +387,7 @@ func TTestShardLikeCommit(t *testing.T, ddb VersionedPersistence, vp artifactsPr rwset, err := aVault.GetRWSet("txid-invalid", rwsBytes) assert.NoError(t, err) err = rwset.IsValid() - assert.EqualError(t, err, "invalid read: vault at version namespace:key2 37:3, read-write set at version 37:2") + assert.EqualError(t, err, "invalid read: vault at fver namespace:key2 [{[107 50 118 97 108] [0 0 0 37 0 0 0 3]}], read-write set at fver [[0 0 0 37 0 0 0 2]]") // close the read-write set, even in case of error rwset.Done() @@ -409,7 +410,7 @@ func TTestShardLikeCommit(t *testing.T, ddb VersionedPersistence, vp artifactsPr // create the read-write set rwsb = &ReadWriteSet{ ReadSet: ReadSet{ - Reads: map[driver2.Namespace]NamespaceReads{}, + Reads: map[driver.Namespace]NamespaceReads{}, OrderedReads: map[string][]string{}, }, WriteSet: WriteSet{ @@ -420,8 +421,8 @@ func TTestShardLikeCommit(t *testing.T, ddb VersionedPersistence, vp artifactsPr MetaWrites: map[string]KeyedMetaWrites{}, }, } - rwsb.ReadSet.Add(ns, k1, 35, 1) - rwsb.ReadSet.Add(ns, k2, 37, 3) + rwsb.ReadSet.Add(ns, k1, fver.ToBytes(35, 1)) + rwsb.ReadSet.Add(ns, k2, fver.ToBytes(37, 3)) rwsb.WriteSet.Add(ns, k1, []byte("k1FromTxidValid")) rwsb.WriteSet.Add(ns, k2, []byte("k2FromTxidValid")) rwsBytes, err = marshaller.Marshal(rwsb) @@ -455,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"), Block: 38, TxNum: 10}, vv) + assert.Equal(t, VersionedValue{Raw: []byte("k1FromTxidValid"), Version: fver.ToBytes(38, 10)}, vv) vv, err = ddb.GetState(ns, k2) assert.NoError(t, err) - assert.Equal(t, VersionedValue{Raw: []byte("k2FromTxidValid"), Block: 38, TxNum: 10}, vv) + assert.Equal(t, VersionedValue{Raw: []byte("k2FromTxidValid"), Version: fver.ToBytes(38, 10)}, vv) // all Interceptors should be gone assert.Len(t, aVault.Interceptors, 0) @@ -475,11 +476,11 @@ func TTestVaultErr(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) rws := &ReadWriteSet{ ReadSet: ReadSet{ - Reads: map[driver2.Namespace]NamespaceReads{}, + Reads: map[driver.Namespace]NamespaceReads{}, OrderedReads: map[string][]string{}, }, } - rws.ReadSet.Add("pineapple", "key", 35, 1) + rws.ReadSet.Add("pineapple", "key", fver.ToBytes(35, 1)) m := vp.NewMarshaller() rwsBytes, err := m.Marshal(rws) assert.NoError(t, err) @@ -526,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"), Block: 35, TxNum: 1}) + err = ddb.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) @@ -546,7 +547,7 @@ func TTestMerge(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { rwsb := &ReadWriteSet{ ReadSet: ReadSet{ - Reads: map[driver2.Namespace]NamespaceReads{}, + Reads: map[driver.Namespace]NamespaceReads{}, OrderedReads: map[string][]string{}, }, WriteSet: WriteSet{ @@ -557,8 +558,8 @@ func TTestMerge(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { MetaWrites: map[string]KeyedMetaWrites{}, }, } - rwsb.ReadSet.Add(ns, k1, 35, 1) - rwsb.ReadSet.Add(ns, ne2Key, 0, 0) + rwsb.ReadSet.Add(ns, k1, fver.ToBytes(35, 1)) + rwsb.ReadSet.Add(ns, ne2Key, fver.ToBytes(0, 0)) rwsb.WriteSet.Add(ns, k1, []byte("newv1")) rwsb.MetaWriteSet.Add(ns, k1, map[string][]byte{"k1": []byte("v1")}) m := vp.NewMarshaller() @@ -579,24 +580,24 @@ func TTestMerge(t *testing.T, ddb VersionedPersistence, vp artifactsProvider) { }}, rws.RWs().Writes) assert.Equal(t, Reads{ "namespace": { - "key1": {Block: 35, TxNum: 1}, - "notexist1": {Block: 0, TxNum: 0}, - "notexist2": {Block: 0, TxNum: 0}, + "key1": fver.ToBytes(35, 1), + "notexist1": nil, + "notexist2": fver.ToBytes(0, 0), }, }, rws.RWs().Reads) rwsb = &ReadWriteSet{ ReadSet: ReadSet{ - Reads: map[driver2.Namespace]NamespaceReads{}, + Reads: map[driver.Namespace]NamespaceReads{}, OrderedReads: map[string][]string{}, }, } - rwsb.ReadSet.Add(ns, k1, 36, 1) + rwsb.ReadSet.Add(ns, k1, fver.ToBytes(36, 1)) rwsBytes, err = m.Marshal(rwsb) assert.NoError(t, err) err = rws.AppendRWSet(rwsBytes) - assert.EqualError(t, err, "invalid read [namespace:key1]: previous value returned at version 35:1, current value at version 35:1") + assert.EqualError(t, err, "invalid read [namespace:key1]: previous value returned at fver [[0 0 0 36 0 0 0 1]], current value at fver [[0 0 0 35 0 0 0 1]]") rwsb = &ReadWriteSet{ WriteSet: WriteSet{ @@ -649,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"), Block: 35, TxNum: 1}) + err = ddb.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) err = ddb.Commit() assert.NoError(t, err) @@ -715,18 +716,18 @@ 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"), Block: 35, TxNum: 1}) + err = db1.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) - err = db1.SetStateMetadata(ns, k1Meta, map[string][]byte{"metakey": []byte("metavalue")}, 35, 1) + err = db1.SetStateMetadata(ns, k1Meta, map[string][]byte{"metakey": []byte("metavalue")}, nil) assert.NoError(t, err) err = db1.Commit() assert.NoError(t, err) err = db2.BeginUpdate() assert.NoError(t, err) - err = db2.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Block: 35, TxNum: 1}) + err = db2.SetState(ns, k1, VersionedValue{Raw: []byte("v1"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) - err = db2.SetStateMetadata(ns, k1Meta, map[string][]byte{"metakey": []byte("metavalue")}, 35, 1) + err = db2.SetStateMetadata(ns, k1Meta, map[string][]byte{"metakey": []byte("metavalue")}, nil) assert.NoError(t, err) err = db2.Commit() assert.NoError(t, err) @@ -747,7 +748,7 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) rws2.Done() // GET K1 - v, err := rws.GetState(ns, k1, driver2.FromIntermediate) + v, err := rws.GetState(ns, k1, driver.FromIntermediate) assert.NoError(t, err) assert.Nil(t, v) @@ -755,12 +756,12 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) assert.Equal(t, []byte("v1"), v) - v, err = rws.GetState(ns, k1, driver2.FromBoth) + v, err = rws.GetState(ns, k1, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, []byte("v1"), v) // GET K1Meta - vMap, err := rws.GetStateMetadata(ns, k1Meta, driver2.FromIntermediate) + vMap, err := rws.GetStateMetadata(ns, k1Meta, driver.FromIntermediate) assert.NoError(t, err) assert.Nil(t, vMap) @@ -768,7 +769,7 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"metakey": []byte("metavalue")}, vMap) - vMap, err = rws.GetStateMetadata(ns, k1Meta, driver2.FromBoth) + vMap, err = rws.GetStateMetadata(ns, k1Meta, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"metakey": []byte("metavalue")}, vMap) @@ -777,15 +778,15 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) // GET K1 after setting it - v, err = rws.GetState(ns, k1, driver2.FromIntermediate) + v, err = rws.GetState(ns, k1, driver.FromIntermediate) assert.NoError(t, err) assert.Equal(t, []byte("v1_updated"), v) - v, err = rws.GetState(ns, k1, driver2.FromStorage) + v, err = rws.GetState(ns, k1, driver.FromStorage) assert.NoError(t, err) assert.Equal(t, []byte("v1"), v) - v, err = rws.GetState(ns, k1, driver2.FromBoth) + v, err = rws.GetState(ns, k1, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, []byte("v1_updated"), v) @@ -794,7 +795,7 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) // GET K1Meta after setting it - vMap, err = rws.GetStateMetadata(ns, k1Meta, driver2.FromIntermediate) + vMap, err = rws.GetStateMetadata(ns, k1Meta, driver.FromIntermediate) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"newmetakey": []byte("newmetavalue")}, vMap) @@ -802,20 +803,20 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"metakey": []byte("metavalue")}, vMap) - vMap, err = rws.GetStateMetadata(ns, k1Meta, driver2.FromBoth) + vMap, err = rws.GetStateMetadata(ns, k1Meta, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"newmetakey": []byte("newmetavalue")}, vMap) // GET K2 - v, err = rws.GetState(ns, k2, driver2.FromIntermediate) + v, err = rws.GetState(ns, k2, driver.FromIntermediate) assert.NoError(t, err) assert.Nil(t, v) - v, err = rws.GetState(ns, k2, driver2.FromStorage) + v, err = rws.GetState(ns, k2, driver.FromStorage) assert.NoError(t, err) assert.Nil(t, v) - v, err = rws.GetState(ns, k2, driver2.FromBoth) + v, err = rws.GetState(ns, k2, driver.FromBoth) assert.NoError(t, err) assert.Nil(t, v) @@ -824,15 +825,15 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) // GET K2 after setting it - v, err = rws.GetState(ns, k2, driver2.FromIntermediate) + v, err = rws.GetState(ns, k2, driver.FromIntermediate) assert.NoError(t, err) assert.Equal(t, []byte("v2_updated"), v) - v, err = rws.GetState(ns, k2, driver2.FromStorage) + v, err = rws.GetState(ns, k2, driver.FromStorage) assert.NoError(t, err) assert.Nil(t, v) - v, err = rws.GetState(ns, k2, driver2.FromBoth) + v, err = rws.GetState(ns, k2, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, []byte("v2_updated"), v) @@ -886,33 +887,33 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.EqualError(t, err, "no write at position 2 for namespace namespace") // GET K1 - v, err = rws.GetState(ns, k1, driver2.FromIntermediate) + v, err = rws.GetState(ns, k1, driver.FromIntermediate) assert.NoError(t, err) assert.Equal(t, []byte("v1_updated"), v) - v, err = rws.GetState(ns, k1, driver2.FromStorage) + v, err = rws.GetState(ns, k1, driver.FromStorage) assert.NoError(t, err) assert.Equal(t, []byte("v1"), v) - v, err = rws.GetState(ns, k1, driver2.FromBoth) + v, err = rws.GetState(ns, k1, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, []byte("v1_updated"), v) // GET K2 - v, err = rws.GetState(ns, k2, driver2.FromIntermediate) + v, err = rws.GetState(ns, k2, driver.FromIntermediate) assert.NoError(t, err) assert.Equal(t, []byte("v2_updated"), v) - v, err = rws.GetState(ns, k2, driver2.FromStorage) + v, err = rws.GetState(ns, k2, driver.FromStorage) assert.NoError(t, err) assert.Nil(t, v) - v, err = rws.GetState(ns, k2, driver2.FromBoth) + v, err = rws.GetState(ns, k2, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, []byte("v2_updated"), v) // GET K1Meta - vMap, err = rws.GetStateMetadata(ns, k1Meta, driver2.FromIntermediate) + vMap, err = rws.GetStateMetadata(ns, k1Meta, driver.FromIntermediate) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"newmetakey": []byte("newmetavalue")}, vMap) @@ -920,7 +921,7 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"metakey": []byte("metavalue")}, vMap) - vMap, err = rws.GetStateMetadata(ns, k1Meta, driver2.FromBoth) + vMap, err = rws.GetStateMetadata(ns, k1Meta, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"newmetakey": []byte("newmetavalue")}, vMap) @@ -929,15 +930,15 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) // GET K1 - v, err = rws.GetState(ns, k1, driver2.FromIntermediate) + v, err = rws.GetState(ns, k1, driver.FromIntermediate) assert.NoError(t, err) assert.Nil(t, v) - v, err = rws.GetState(ns, k1, driver2.FromStorage) + v, err = rws.GetState(ns, k1, driver.FromStorage) assert.NoError(t, err) assert.Equal(t, []byte("v1"), v) - v, err = rws.GetState(ns, k1, driver2.FromBoth) + v, err = rws.GetState(ns, k1, driver.FromBoth) assert.NoError(t, err) assert.Nil(t, v) @@ -988,33 +989,33 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.EqualError(t, err, "no write at position 2 for namespace namespace") // GET K2 - v, err = rws.GetState(ns, k2, driver2.FromIntermediate) + v, err = rws.GetState(ns, k2, driver.FromIntermediate) assert.NoError(t, err) assert.Equal(t, []byte("v2_updated"), v) - v, err = rws.GetState(ns, k2, driver2.FromStorage) + v, err = rws.GetState(ns, k2, driver.FromStorage) assert.NoError(t, err) assert.Nil(t, v) - v, err = rws.GetState(ns, k2, driver2.FromBoth) + v, err = rws.GetState(ns, k2, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, []byte("v2_updated"), v) // GET K1 - v, err = rws.GetState(ns, k1, driver2.FromIntermediate) + v, err = rws.GetState(ns, k1, driver.FromIntermediate) assert.NoError(t, err) assert.Nil(t, v) - v, err = rws.GetState(ns, k1, driver2.FromStorage) + v, err = rws.GetState(ns, k1, driver.FromStorage) assert.NoError(t, err) assert.Equal(t, []byte("v1"), v) - v, err = rws.GetState(ns, k1, driver2.FromBoth) + v, err = rws.GetState(ns, k1, driver.FromBoth) assert.NoError(t, err) assert.Nil(t, v) // GET K1Meta - vMap, err = rws.GetStateMetadata(ns, k1Meta, driver2.FromIntermediate) + vMap, err = rws.GetStateMetadata(ns, k1Meta, driver.FromIntermediate) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"newmetakey": []byte("newmetavalue")}, vMap) @@ -1022,7 +1023,7 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"metakey": []byte("metavalue")}, vMap) - vMap, err = rws.GetStateMetadata(ns, k1Meta, driver2.FromBoth) + vMap, err = rws.GetStateMetadata(ns, k1Meta, driver.FromBoth) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"newmetakey": []byte("newmetavalue")}, vMap) @@ -1068,20 +1069,23 @@ func TTestRun(t *testing.T, db1, db2 VersionedPersistence, vp artifactsProvider) vv2, err := db2.GetState(ns, k1) assert.NoError(t, err) assert.Nil(t, vv1.Raw) - assert.Zero(t, vv1.Block) - assert.Zero(t, vv1.TxNum) + assert.Zero(t, vv1.Version) assert.Equal(t, vv1, vv2) vv1, err = db1.GetState(ns, k2) assert.NoError(t, err) vv2, err = db2.GetState(ns, k2) assert.NoError(t, err) - assert.Equal(t, VersionedValue{Raw: []byte("v2_updated"), Block: 35, TxNum: 2}, vv1) + assert.Equal(t, VersionedValue{Raw: []byte("v2_updated"), Version: fver.ToBytes(35, 2)}, vv1) assert.Equal(t, vv1, vv2) - meta1, b1, t1, err := db1.GetStateMetadata(ns, k1Meta) + meta1, ver1, err := db1.GetStateMetadata(ns, k1Meta) assert.NoError(t, err) - meta2, b2, t2, err := db2.GetStateMetadata(ns, k1Meta) + b1, t1, err := fver.FromBytes(ver1) + assert.NoError(t, err) + meta2, ver2, err := db2.GetStateMetadata(ns, k1Meta) + assert.NoError(t, err) + b2, t2, err := fver.FromBytes(ver2) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"newmetakey": []byte("newmetavalue")}, meta1) assert.Equal(t, uint64(35), b1) @@ -1115,7 +1119,7 @@ func compare(t *testing.T, ns string, db1, db2 VersionedPersistence) { assert.Equal(t, res1, res2) } -func queryVault(v *Vault[ValidationCode], ns driver2.Namespace, key driver2.PKey, mkey driver2.MKey) (driver2.RawValue, driver2.Metadata, driver2.BlockNum, driver2.TxNum, error) { +func queryVault(v *Vault[ValidationCode], ns driver.Namespace, key driver.PKey, mkey driver.MKey) (driver.RawValue, driver.Metadata, driver.TxNum, driver.BlockNum, error) { qe, err := v.NewQueryExecutor() defer qe.Done() if err != nil { @@ -1125,7 +1129,11 @@ func queryVault(v *Vault[ValidationCode], ns driver2.Namespace, key driver2.PKey if err != nil { return nil, nil, 0, 0, err } - mval, txNum, blkNum, err := qe.GetStateMetadata(ns, mkey) + mval, kVersion, err := qe.GetStateMetadata(ns, mkey) + if err != nil { + return nil, nil, 0, 0, err + } + blkNum, txNum, err := fver.FromBytes(kVersion) if err != nil { return nil, nil, 0, 0, err } @@ -1138,19 +1146,19 @@ type deadlockErrorPersistence struct { key string } -func (db *deadlockErrorPersistence) GetState(namespace driver2.Namespace, key driver2.PKey) (VersionedValue, error) { +func (db *deadlockErrorPersistence) GetState(namespace driver.Namespace, key driver.PKey) (VersionedValue, error) { return db.VersionedPersistence.GetState(namespace, key) } -func (db *deadlockErrorPersistence) GetStateRangeScanIterator(namespace driver2.Namespace, startKey, endKey driver2.PKey) (collections.Iterator[*VersionedRead], error) { +func (db *deadlockErrorPersistence) GetStateRangeScanIterator(namespace driver.Namespace, startKey, endKey driver.PKey) (collections.Iterator[*VersionedRead], error) { return db.VersionedPersistence.GetStateRangeScanIterator(namespace, startKey, endKey) } -func (db *deadlockErrorPersistence) GetStateSetIterator(ns driver2.Namespace, keys ...driver2.PKey) (collections.Iterator[*VersionedRead], error) { +func (db *deadlockErrorPersistence) GetStateSetIterator(ns driver.Namespace, keys ...driver.PKey) (collections.Iterator[*VersionedRead], error) { return db.VersionedPersistence.GetStateSetIterator(ns, keys...) } -func (db *deadlockErrorPersistence) SetState(namespace driver2.Namespace, key driver2.PKey, value VersionedValue) error { +func (db *deadlockErrorPersistence) SetState(namespace driver.Namespace, key driver.PKey, value VersionedValue) error { if key == db.key && db.failures > 0 { db.failures-- return DeadlockDetected @@ -1158,8 +1166,8 @@ func (db *deadlockErrorPersistence) SetState(namespace driver2.Namespace, key dr return db.VersionedPersistence.SetState(namespace, key, value) } -func (db *deadlockErrorPersistence) SetStates(namespace driver2.Namespace, kvs map[driver2.PKey]VersionedValue) map[driver2.PKey]error { - errs := make(map[driver2.PKey]error) +func (db *deadlockErrorPersistence) SetStates(namespace driver.Namespace, kvs map[driver.PKey]VersionedValue) map[driver.PKey]error { + errs := make(map[driver.PKey]error) for k, v := range kvs { if err := db.SetState(namespace, k, v); err != nil { errs[k] = err @@ -1168,8 +1176,8 @@ func (db *deadlockErrorPersistence) SetStates(namespace driver2.Namespace, kvs m return errs } -func (db *deadlockErrorPersistence) DeleteStates(namespace driver2.Namespace, keys ...driver2.PKey) map[driver2.PKey]error { - errs := make(map[driver2.PKey]error) +func (db *deadlockErrorPersistence) DeleteStates(namespace driver.Namespace, keys ...driver.PKey) map[driver.PKey]error { + errs := make(map[driver.PKey]error) for _, key := range keys { if err := db.DeleteState(namespace, key); err != nil { errs[key] = err @@ -1182,20 +1190,20 @@ type duplicateErrorPersistence struct { VersionedPersistence } -func (db *duplicateErrorPersistence) SetState(driver2.Namespace, driver2.PKey, VersionedValue) error { +func (db *duplicateErrorPersistence) SetState(driver.Namespace, driver.PKey, VersionedValue) error { return UniqueKeyViolation } -func (db *duplicateErrorPersistence) SetStates(_ driver2.Namespace, kvs map[driver2.PKey]VersionedValue) map[driver2.PKey]error { - errs := make(map[driver2.PKey]error, len(kvs)) +func (db *duplicateErrorPersistence) SetStates(_ driver.Namespace, kvs map[driver.PKey]VersionedValue) map[driver.PKey]error { + errs := make(map[driver.PKey]error, len(kvs)) for k := range kvs { errs[k] = UniqueKeyViolation } return errs } -func (db *duplicateErrorPersistence) DeleteStates(namespace driver2.Namespace, keys ...driver2.PKey) map[driver2.PKey]error { - errs := make(map[driver2.PKey]error) +func (db *duplicateErrorPersistence) DeleteStates(namespace driver.Namespace, keys ...driver.PKey) map[driver.PKey]error { + errs := make(map[driver.PKey]error) for _, key := range keys { if err := db.DeleteState(namespace, key); err != nil { errs[key] = err @@ -1204,14 +1212,14 @@ func (db *duplicateErrorPersistence) DeleteStates(namespace driver2.Namespace, k return errs } -func (db *duplicateErrorPersistence) GetState(namespace driver2.Namespace, key driver2.PKey) (VersionedValue, error) { +func (db *duplicateErrorPersistence) GetState(namespace driver.Namespace, key driver.PKey) (VersionedValue, error) { return db.VersionedPersistence.GetState(namespace, key) } -func (db *duplicateErrorPersistence) GetStateRangeScanIterator(namespace driver2.Namespace, startKey, endKey driver2.PKey) (collections.Iterator[*VersionedRead], error) { +func (db *duplicateErrorPersistence) GetStateRangeScanIterator(namespace driver.Namespace, startKey, endKey driver.PKey) (collections.Iterator[*VersionedRead], error) { return db.VersionedPersistence.GetStateRangeScanIterator(namespace, startKey, endKey) } -func (db *duplicateErrorPersistence) GetStateSetIterator(ns driver2.Namespace, keys ...driver2.PKey) (collections.Iterator[*VersionedRead], error) { +func (db *duplicateErrorPersistence) GetStateSetIterator(ns driver.Namespace, keys ...driver.PKey) (collections.Iterator[*VersionedRead], error) { return db.VersionedPersistence.GetStateSetIterator(ns, keys...) } diff --git a/platform/common/core/generic/vault/interceptor.go b/platform/common/core/generic/vault/interceptor.go index d205435a9..275fbf6ea 100644 --- a/platform/common/core/generic/vault/interceptor.go +++ b/platform/common/core/generic/vault/interceptor.go @@ -9,13 +9,14 @@ package vault 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" ) type VersionedQueryExecutor interface { - GetStateMetadata(namespace, key string) (map[string][]byte, uint64, uint64, error) + GetStateMetadata(namespace, key string) (driver.Metadata, driver.RawVersion, error) GetState(namespace, key string) (VersionedValue, error) Done() } @@ -89,9 +90,8 @@ func (i *Interceptor[V]) IsValid() error { if err != nil { return err } - - if vv.Block != v.Block || vv.TxNum != v.TxNum { - return errors.Errorf("invalid read: vault at version %s:%s %d:%d, read-write set at version %d:%d", ns, k, vv.Block, vv.TxNum, v.Block, v.TxNum) + if !fver.IsEqual(v, vv.Version) { + return errors.Errorf("invalid read: vault at fver %s:%s [%v], read-write set at fver [%v]", ns, k, vv, v) } } } @@ -236,20 +236,20 @@ func (i *Interceptor[V]) GetStateMetadata(namespace, key string, opts ...driver. i.RUnlock() return nil, errors.New("this instance is write only") } - val, block, txnum, err := i.QE.GetStateMetadata(namespace, key) + val, vaultVersion, err := i.QE.GetStateMetadata(namespace, key) if err != nil { i.RUnlock() return nil, err } i.RUnlock() - b, t, in := i.Rws.ReadSet.Get(namespace, key) + version, in := i.Rws.ReadSet.Get(namespace, key) if in { - if b != block || t != txnum { - return nil, errors.Errorf("invalid metadata read: previous value returned at version %d:%d, current value at version %d:%d", b, t, block, txnum) + if !fver.IsEqual(version, vaultVersion) { + return nil, errors.Errorf("invalid metadata read: previous value returned at fver [%v], current value at fver [%v]", version, vaultVersion) } } else { - i.Rws.ReadSet.Add(namespace, key, block, txnum) + i.Rws.ReadSet.Add(namespace, key, vaultVersion) } return val, nil @@ -297,14 +297,15 @@ func (i *Interceptor[V]) GetState(namespace driver.Namespace, key driver.PKey, o return nil, err } i.RUnlock() + vaultVersion := vv.Version - b, t, in := i.Rws.ReadSet.Get(namespace, key) + version, in := i.Rws.ReadSet.Get(namespace, key) if in { - if b != vv.Block || t != vv.TxNum { - return nil, errors.Errorf("invalid read [%s:%s]: previous value returned at version %d:%d, current value at version %d:%d", namespace, key, b, t, vv.Block, vv.TxNum) + if !fver.IsEqual(version, vaultVersion) { + return nil, errors.Errorf("invalid read [%s:%s]: previous value returned at fver [%v], current value at fver [%v]", namespace, key, version, vaultVersion) } } else { - i.Rws.ReadSet.Add(namespace, key, vv.Block, vv.TxNum) + i.Rws.ReadSet.Add(namespace, key, vaultVersion) } return vv.Raw, nil diff --git a/platform/common/core/generic/vault/interceptor_test.go b/platform/common/core/generic/vault/interceptor_test.go index 786089578..5d0645c44 100644 --- a/platform/common/core/generic/vault/interceptor_test.go +++ b/platform/common/core/generic/vault/interceptor_test.go @@ -10,6 +10,7 @@ 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/view/services/assert" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/flogging" @@ -18,9 +19,8 @@ import ( func newMockQE() mockQE { return mockQE{ State: VersionedValue{ - Raw: []byte("raw"), - Block: 1, - TxNum: 1, + Raw: []byte("raw"), + Version: fver.ToBytes(1, 1), }, Metadata: map[string][]byte{ "md": []byte("meta"), @@ -33,8 +33,8 @@ type mockQE struct { Metadata map[string][]byte } -func (qe mockQE) GetStateMetadata(driver.Namespace, driver.PKey) (driver.Metadata, driver.BlockNum, driver.TxNum, error) { - return qe.Metadata, 1, 1, nil +func (qe mockQE) GetStateMetadata(driver.Namespace, driver.PKey) (driver.Metadata, driver.RawVersion, error) { + return qe.Metadata, fver.ToBytes(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/queryexec.go b/platform/common/core/generic/vault/queryexec.go index 961e70fcc..9931263db 100644 --- a/platform/common/core/generic/vault/queryexec.go +++ b/platform/common/core/generic/vault/queryexec.go @@ -6,7 +6,9 @@ SPDX-License-Identifier: Apache-2.0 package vault -import "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" +import ( + "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" +) // this file contains all structs that perform DB access. They // differ in terms of the results that they return. They are both @@ -28,8 +30,12 @@ func (q *directQueryExecutor[V]) GetStateRangeScanIterator(namespace driver.Name return q.vault.store.GetStateRangeScanIterator(namespace, startKey, endKey) } -func (q *directQueryExecutor[V]) GetStateMetadata(namespace driver.Namespace, key driver.PKey) (driver.Metadata, driver.BlockNum, driver.TxNum, error) { - return q.vault.store.GetStateMetadata(namespace, key) +func (q *directQueryExecutor[V]) GetStateMetadata(namespace driver.Namespace, key driver.PKey) (driver.Metadata, driver.RawVersion, error) { + m, version, err := q.vault.store.GetStateMetadata(namespace, key) + if err != nil { + return nil, nil, err + } + return m, version, nil } func (q *directQueryExecutor[V]) Done() { @@ -46,8 +52,12 @@ func (i *interceptorQueryExecutor[V]) Done() { i.storeLock.RUnlock() } -func (i *interceptorQueryExecutor[V]) GetStateMetadata(namespace driver.Namespace, key driver.PKey) (driver.Metadata, driver.BlockNum, driver.TxNum, error) { - return i.store.GetStateMetadata(namespace, key) +func (i *interceptorQueryExecutor[V]) GetStateMetadata(namespace driver.Namespace, key driver.PKey) (driver.Metadata, driver.RawVersion, error) { + m, version, err := i.store.GetStateMetadata(namespace, key) + if err != nil { + return nil, nil, err + } + return m, version, nil } func (i *interceptorQueryExecutor[V]) GetState(namespace driver.Namespace, key driver.PKey) (VersionedValue, error) { diff --git a/platform/common/core/generic/vault/rwset.go b/platform/common/core/generic/vault/rwset.go index 255ebb4a7..22b456181 100644 --- a/platform/common/core/generic/vault/rwset.go +++ b/platform/common/core/generic/vault/rwset.go @@ -140,16 +140,13 @@ func (w *WriteSet) Clear(ns string) { w.OrderedWrites[ns] = []string{} } -type TxPosition struct { - Block driver.BlockNum - TxNum driver.TxNum -} +type Version = []byte -type NamespaceReads map[string]TxPosition +type NamespaceReads map[string]Version func (r NamespaceReads) Equals(o NamespaceReads) error { - return entriesEqual(r, o, func(v, v2 TxPosition) bool { - return v.Block == v2.Block && v.TxNum == v2.TxNum + return entriesEqual(r, o, func(v, v2 Version) bool { + return bytes.Equal(v, v2) }) } @@ -164,22 +161,22 @@ type ReadSet struct { OrderedReads map[string][]string } -func (r *ReadSet) Add(ns driver.Namespace, key string, block driver.BlockNum, txnum driver.TxNum) { +func (r *ReadSet) Add(ns driver.Namespace, key string, version Version) { nsMap, in := r.Reads[ns] if !in { - nsMap = make(map[driver.Namespace]TxPosition) + nsMap = make(map[driver.Namespace]Version) r.Reads[ns] = nsMap r.OrderedReads[ns] = make([]string, 0, 8) } - nsMap[key] = TxPosition{block, txnum} + nsMap[key] = version r.OrderedReads[ns] = append(r.OrderedReads[ns], key) } -func (r *ReadSet) Get(ns driver.Namespace, key string) (driver.BlockNum, driver.TxNum, bool) { +func (r *ReadSet) Get(ns driver.Namespace, key string) (Version, bool) { entry, in := r.Reads[ns][key] - return entry.Block, entry.TxNum, in + return entry, in } func (r *ReadSet) GetAt(ns driver.Namespace, i int) (string, bool) { @@ -192,7 +189,7 @@ func (r *ReadSet) GetAt(ns driver.Namespace, i int) (string, bool) { } func (r *ReadSet) Clear(ns driver.Namespace) { - r.Reads[ns] = map[string]TxPosition{} + r.Reads[ns] = map[string]Version{} r.OrderedReads[ns] = []string{} } diff --git a/platform/common/core/generic/vault/vault.go b/platform/common/core/generic/vault/vault.go index ed4a64651..e3ae9c726 100644 --- a/platform/common/core/generic/vault/vault.go +++ b/platform/common/core/generic/vault/vault.go @@ -13,6 +13,7 @@ import ( "sync" "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" @@ -57,6 +58,7 @@ type NewInterceptorFunc[V driver.ValidationCode] func(logger Logger, qe Versione type ( VersionedPersistence = dbdriver.VersionedPersistence VersionedValue = dbdriver.VersionedValue + VersionedMetaData = dbdriver.VersionedMetaData VersionedRead = dbdriver.VersionedRead VersionedResultsIterator = dbdriver.VersionedResultsIterator QueryExecutor = dbdriver.QueryExecutor @@ -289,7 +291,7 @@ func (db *Vault[V]) storeMetaWrites(ctx context.Context, writes NamespaceKeyedMe span := trace.SpanFromContext(ctx) for ns, keyMap := range writes { span.AddEvent("set_tx_metadata_state") - if errs := db.store.SetStateMetadatas(ns, keyMap, block, indexInBloc); len(errs) > 0 { + if errs := db.store.SetStateMetadatas(ns, keyMap, nil); len(errs) > 0 { return db.discard(ns, block, indexInBloc, errs) } } @@ -310,7 +312,7 @@ func (db *Vault[V]) storeWrites(ctx context.Context, writes Writes, block driver 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, Block: block, TxNum: indexInBloc} + vals[pkey] = VersionedValue{Raw: val, Version: fver.ToBytes(block, indexInBloc)} } return vals } diff --git a/platform/common/core/generic/vault/vault_test.go b/platform/common/core/generic/vault/vault_test.go index c938564c5..e709f16f0 100644 --- a/platform/common/core/generic/vault/vault_test.go +++ b/platform/common/core/generic/vault/vault_test.go @@ -12,6 +12,7 @@ import ( "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors" "github.com/hyperledger-labs/fabric-smart-client/platform/common/core/generic/vault/db" + "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" driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/collections" @@ -109,11 +110,11 @@ func (m *marshaller) Append(destination *ReadWriteSet, raw []byte, nss ...string continue } for s, position := range reads { - b, t, in := destination.ReadSet.Get(ns, s) - if in && (b != position.Block || t != position.TxNum) { - return errors.Errorf("invalid read [%s:%s]: previous value returned at version %d:%d, current value at version %d:%d", ns, s, b, t, b, t) + v, in := destination.ReadSet.Get(ns, s) + if in && !fver.IsEqual(position, v) { + return errors.Errorf("invalid read [%s:%s]: previous value returned at fver [%v], current value at fver [%v]", ns, s, position, v) } - destination.ReadSet.Add(ns, s, position.Block, position.TxNum) + destination.ReadSet.Add(ns, s, position) } } destination.OrderedReads = source.OrderedReads diff --git a/platform/common/driver/vault.go b/platform/common/driver/vault.go index 7a1428694..e41f370a1 100644 --- a/platform/common/driver/vault.go +++ b/platform/common/driver/vault.go @@ -13,24 +13,29 @@ import ( ) type ( - PKey = string - MKey = string - RawValue = []byte - Metadata = map[MKey][]byte + PKey = string + MKey = string + RawValue = []byte + Metadata = map[MKey][]byte + RawVersion = []byte ) type VersionedRead struct { - Key PKey - Raw RawValue - Block BlockNum - TxNum TxNum + Key PKey + Raw RawValue + Version RawVersion +} + +type VersionedMetadata struct { + Metadata Metadata + Version RawVersion } type VersionedResultsIterator = collections.Iterator[*VersionedRead] type QueryExecutor interface { GetState(namespace Namespace, key PKey) (RawValue, error) - GetStateMetadata(namespace Namespace, key PKey) (Metadata, BlockNum, TxNum, error) + GetStateMetadata(namespace Namespace, key PKey) (Metadata, RawVersion, error) GetStateRangeScanIterator(namespace Namespace, startKey PKey, endKey PKey) (VersionedResultsIterator, error) Done() } diff --git a/platform/fabric/core/generic/vault/vault.go b/platform/fabric/core/generic/vault/vault.go index 8eded0178..742255e95 100644 --- a/platform/fabric/core/generic/vault/vault.go +++ b/platform/fabric/core/generic/vault/vault.go @@ -9,6 +9,7 @@ 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" @@ -90,7 +91,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, bn, txn) + rws.ReadSet.Add(ns, read.Key, fver.ToBytes(bn, txn)) } for _, write := range nsrws.KvRwSet.Writes { @@ -121,8 +122,12 @@ func (m *marshaller) Marshal(rws *vault.ReadWriteSet) ([]byte, error) { for ns, keyMap := range rws.Reads { for key, v := range keyMap { - if v.Block != 0 || v.TxNum != 0 { - rwsb.AddToReadSet(ns, key, rwsetutil.NewVersion(&kvrwset.Version{BlockNum: v.Block, TxNum: v.TxNum})) + block, txNum, err := fver.FromBytes(v) + if err != nil { + return nil, errors.Wrapf(err, "failed to extract block fver from bytes [%v]", v) + } + if block != 0 || txNum != 0 { + rwsb.AddToReadSet(ns, key, rwsetutil.NewVersion(&kvrwset.Version{BlockNum: block, TxNum: txNum})) } else { rwsb.AddToReadSet(ns, key, nil) } @@ -173,13 +178,15 @@ func (m *marshaller) Append(destination *vault.ReadWriteSet, raw []byte, nss ... bnum = read.Version.BlockNum txnum = read.Version.TxNum } - - b, t, in := destination.ReadSet.Get(ns, read.Key) + dVersion, in := destination.ReadSet.Get(ns, read.Key) + b, t, err := fver.FromBytes(dVersion) + if err != nil { + return errors.Wrapf(err, "failed to extract block fver from bytes [%v]", dVersion) + } if in && (b != bnum || t != txnum) { - return errors.Errorf("invalid read [%s:%s]: previous value returned at version %d:%d, current value at version %d:%d", ns, read.Key, b, t, b, txnum) + return errors.Errorf("invalid read [%s:%s]: previous value returned at fver %d:%d, current value at fver %d:%d", ns, read.Key, b, t, b, txnum) } - - destination.ReadSet.Add(ns, read.Key, bnum, txnum) + destination.ReadSet.Add(ns, read.Key, dVersion) } for _, write := range nsrws.KvRwSet.Writes { diff --git a/platform/orion/core/generic/vault/vault.go b/platform/orion/core/generic/vault/vault.go index d3c085a6e..49e27938c 100644 --- a/platform/orion/core/generic/vault/vault.go +++ b/platform/orion/core/generic/vault/vault.go @@ -9,6 +9,7 @@ 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" @@ -101,8 +102,10 @@ func (p *populator) Populate(rws *vault.ReadWriteSet, rwsetBytes []byte, namespa rws.ReadSet.Add( operation.DbName, read.Key, - bn, - txn, + fver.ToBytes( + bn, + txn, + ), ) } diff --git a/platform/view/services/db/dbtest/helpers.go b/platform/view/services/db/dbtest/helpers.go index 8affad0b3..04c4ecb58 100644 --- a/platform/view/services/db/dbtest/helpers.go +++ b/platform/view/services/db/dbtest/helpers.go @@ -16,6 +16,7 @@ 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" "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/driver" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/keys" @@ -107,10 +108,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"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, - {Key: "k3", Raw: []byte("k3_value"), Block: 35, TxNum: 2}, + {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)}, }, res) itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") @@ -125,9 +126,9 @@ func TTestRangeQueries(t *testing.T, db driver.TransactionalVersionedPersistence res = append(res, *n) } expected := []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, + {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)}, } assert.Len(t, res, 3) assert.Equal(t, expected, res) @@ -144,16 +145,16 @@ func TTestRangeQueries(t *testing.T, db driver.TransactionalVersionedPersistence } itr.Close() expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, + {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, } assert.Len(t, res, 2) assert.Equal(t, expected, res) expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, + {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)}, } itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") assert.NoError(t, err) @@ -168,8 +169,8 @@ func TTestRangeQueries(t *testing.T, db driver.TransactionalVersionedPersistence assert.Equal(t, expected, res) expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Block: 35, TxNum: 3}, - {Key: "k3", Raw: []byte("k3_value"), Block: 35, TxNum: 2}, + {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, + {Key: "k3", Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}, } itr, err = db.GetStateSetIterator(ns, "k1", "k3") assert.NoError(t, err) @@ -191,7 +192,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"), Block: 35, TxNum: 1}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) err = db.Commit() @@ -199,18 +200,20 @@ 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"), Block: 35, TxNum: 1}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}, vv) - m, bn, tn, err := db.GetStateMetadata(ns, key) + m, ver, err := db.GetStateMetadata(ns, key) assert.NoError(t, err) assert.Len(t, m, 0) + bn, tn, err := fver.FromBytes(ver) + assert.NoError(t, err) assert.Equal(t, uint64(35), bn) assert.Equal(t, uint64(1), tn) err = db.BeginUpdate() assert.NoError(t, err) - err = db.SetStateMetadata(ns, key, map[string][]byte{"foo": []byte("bar")}, 36, 2) + err = db.SetStateMetadata(ns, key, map[string][]byte{"foo": []byte("bar")}, nil) assert.NoError(t, err) err = db.Commit() @@ -218,9 +221,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"), Block: 36, TxNum: 2}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(36, 2)}, vv) - m, bn, tn, err = db.GetStateMetadata(ns, key) + m, ver, err = db.GetStateMetadata(ns, key) + assert.NoError(t, err) + bn, tn, err = fver.FromBytes(ver) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"foo": []byte("bar")}, m) assert.Equal(t, uint64(36), bn) @@ -237,7 +242,9 @@ func TTestSimpleReadWrite(t *testing.T, db driver.TransactionalVersionedPersiste assert.Equal(t, driver.VersionedValue{}, vv) // empty metadata - m, bn, tn, err := db.GetStateMetadata(ns, key) + m, ver, err := db.GetStateMetadata(ns, key) + assert.NoError(t, err) + bn, tn, err := fver.FromBytes(ver) assert.NoError(t, err) assert.Len(t, m, 0) assert.Equal(t, uint64(0), bn) @@ -246,7 +253,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"), Block: 35, TxNum: 1}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) err = db.Commit() assert.NoError(t, err) @@ -254,30 +261,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"), Block: 35, TxNum: 1}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: fver.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"), Block: 36, TxNum: 2}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val1"), Version: fver.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"), Block: 35, TxNum: 1}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val"), Version: fver.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"), Block: 36, TxNum: 2}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val1"), Version: fver.ToBytes(36, 2)}, vv) // Discard an update err = db.BeginUpdate() assert.NoError(t, err) - err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val0"), Block: 37, TxNum: 3}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("val0"), Version: fver.ToBytes(37, 3)}) assert.NoError(t, err) err = db.Discard() assert.NoError(t, err) @@ -285,7 +292,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"), Block: 36, TxNum: 2}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("val1"), Version: fver.ToBytes(36, 2)}, vv) // delete state err = db.BeginUpdate() @@ -305,10 +312,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"), Block: 1, TxNum: 1}) + err = db.SetState(ns, key, driver.VersionedValue{Raw: []byte("bar"), Version: fver.ToBytes(1, 1)}) assert.NoError(t, err) - err = db.SetState(ns, keyWithSuffix, driver.VersionedValue{Raw: []byte("bar1"), Block: 1, TxNum: 1}) + err = db.SetState(ns, keyWithSuffix, driver.VersionedValue{Raw: []byte("bar1"), Version: fver.ToBytes(1, 1)}) assert.NoError(t, err) err = db.Commit() @@ -316,11 +323,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"), Block: 1, TxNum: 1}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("bar"), Version: fver.ToBytes(1, 1)}, vv) vv, err = db.GetState(ns, keyWithSuffix) assert.NoError(t, err) - assert.Equal(t, driver.VersionedValue{Raw: []byte("bar1"), Block: 1, TxNum: 1}, vv) + assert.Equal(t, driver.VersionedValue{Raw: []byte("bar1"), Version: fver.ToBytes(1, 1)}, vv) vv, err = db.GetState(ns, "barf") assert.NoError(t, err) @@ -335,13 +342,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"), Block: 35, TxNum: 1}) + err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) - err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Block: 35, TxNum: 2}) + err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}) assert.NoError(t, err) - err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Block: 35, TxNum: 3}) + err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}) assert.NoError(t, err) - err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Block: 35, TxNum: 4}) + err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}) assert.NoError(t, err) err = db.Commit() @@ -361,20 +368,24 @@ func TTestMetadata(t *testing.T, db driver.TransactionalVersionedPersistence) { ns := "namespace" key := "foo" - md, bn, txn, err := db.GetStateMetadata(ns, key) + md, ver, err := db.GetStateMetadata(ns, key) assert.NoError(t, err) assert.Nil(t, md) + bn, txn, err := fver.FromBytes(ver) + assert.NoError(t, err) assert.Equal(t, uint64(0x0), bn) assert.Equal(t, uint64(0x0), txn) err = db.BeginUpdate() assert.NoError(t, err) - err = db.SetStateMetadata(ns, key, map[string][]byte{"foo": []byte("bar")}, 35, 1) + err = db.SetStateMetadata(ns, key, map[string][]byte{"foo": []byte("bar")}, nil) assert.NoError(t, err) err = db.Commit() assert.NoError(t, err) - md, bn, txn, err = db.GetStateMetadata(ns, key) + md, ver, err = db.GetStateMetadata(ns, key) + assert.NoError(t, err) + bn, txn, err = fver.FromBytes(ver) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"foo": []byte("bar")}, md) assert.Equal(t, uint64(35), bn) @@ -382,12 +393,14 @@ func TTestMetadata(t *testing.T, db driver.TransactionalVersionedPersistence) { err = db.BeginUpdate() assert.NoError(t, err) - err = db.SetStateMetadata(ns, key, map[string][]byte{"foo1": []byte("bar1")}, 36, 2) + err = db.SetStateMetadata(ns, key, map[string][]byte{"foo1": []byte("bar1")}, nil) assert.NoError(t, err) err = db.Commit() assert.NoError(t, err) - md, bn, txn, err = db.GetStateMetadata(ns, key) + md, ver, err = db.GetStateMetadata(ns, key) + assert.NoError(t, err) + bn, txn, err = fver.FromBytes(ver) assert.NoError(t, err) assert.Equal(t, map[string][]byte{"foo1": []byte("bar1")}, md) assert.Equal(t, uint64(36), bn) @@ -440,13 +453,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"), Block: 35, TxNum: 1}) + err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) - err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Block: 35, TxNum: 2}) + err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}) assert.NoError(t, err) - err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Block: 35, TxNum: 3}) + err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}) assert.NoError(t, err) - err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Block: 35, TxNum: 4}) + err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}) assert.NoError(t, err) err = db.Commit() @@ -463,10 +476,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"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, - {Key: "k3", Raw: []byte("k3_value"), Block: 35, TxNum: 2}, + {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)}, }, res) itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") @@ -480,9 +493,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"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, + {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)}, }, res) } @@ -493,13 +506,13 @@ func TTestMultiWritesAndRangeQueries(t *testing.T, db driver.TransactionalVersio t.Fatal(err) } - err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Block: 35, TxNum: 1}) + err = db.SetState(ns, "k2", driver.VersionedValue{Raw: []byte("k2_value"), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) - err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Block: 35, TxNum: 2}) + err = db.SetState(ns, "k3", driver.VersionedValue{Raw: []byte("k3_value"), Version: fver.ToBytes(35, 2)}) assert.NoError(t, err) - err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Block: 35, TxNum: 3}) + err = db.SetState(ns, "k1", driver.VersionedValue{Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}) assert.NoError(t, err) - err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Block: 35, TxNum: 4}) + err = db.SetState(ns, "k111", driver.VersionedValue{Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}) assert.NoError(t, err) err = db.Commit() @@ -538,10 +551,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"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, - {Key: "k3", Raw: []byte("k3_value"), Block: 35, TxNum: 2}, + {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)}, }, res) itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") @@ -554,9 +567,9 @@ func TTestMultiWritesAndRangeQueries(t *testing.T, db driver.TransactionalVersio res = append(res, *n) } expected := []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, + {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)}, } assert.Len(t, res, 3) assert.Equal(t, expected, res) @@ -572,16 +585,16 @@ func TTestMultiWritesAndRangeQueries(t *testing.T, db driver.TransactionalVersio res = append(res, *n) } expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, + {Key: "k1", Raw: []byte("k1_value"), Version: fver.ToBytes(35, 3)}, + {Key: "k111", Raw: []byte("k111_value"), Version: fver.ToBytes(35, 4)}, } assert.Len(t, res, 2) assert.Equal(t, expected, res) expected = []driver.VersionedRead{ - {Key: "k1", Raw: []byte("k1_value"), Block: 35, TxNum: 3}, - {Key: "k111", Raw: []byte("k111_value"), Block: 35, TxNum: 4}, - {Key: "k2", Raw: []byte("k2_value"), Block: 35, TxNum: 1}, + {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)}, } itr, err = db.GetStateRangeScanIterator(ns, "k1", "k3") assert.NoError(t, err) @@ -621,7 +634,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, Block: block, TxNum: txnum}) + err = tx.SetState(ns, key, driver.VersionedValue{Raw: value, Version: fver.ToBytes(block, txnum)}) assert.NoError(t, err) err = tx.Commit() assert.NoError(t, err) @@ -675,7 +688,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), Block: 35, TxNum: 1}) + err = db.SetState(ns, k, driver.VersionedValue{Raw: []byte(k), Version: fver.ToBytes(35, 1)}) assert.NoError(t, err) } @@ -698,10 +711,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}, Block: 0x23, TxNum: 1}, - {Key: "\x00prefix0a0b010", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x31, 0x30}, Block: 0x23, TxNum: 1}, - {Key: "\x00prefix0a0b030", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x33, 0x30}, Block: 0x23, TxNum: 1}, - {Key: "\x00prefix0a0d0", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x64, 0x30}, Block: 0x23, TxNum: 1}, + {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)}, }, res) partialCompositeKey, err = createCompositeKey(keyPrefix, []string{"a", "b"}) @@ -720,9 +733,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}, Block: 0x23, TxNum: 1}, - {Key: "\x00prefix0a0b010", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x31, 0x30}, Block: 0x23, TxNum: 1}, - {Key: "\x00prefix0a0b030", Raw: []uint8{0x0, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x30, 0x61, 0x30, 0x62, 0x30, 0x33, 0x30}, Block: 0x23, TxNum: 1}, + {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)}, }, res) } diff --git a/platform/view/services/db/driver/badger/badger.go b/platform/view/services/db/driver/badger/badger.go index 71c4bba12..6649fcb29 100644 --- a/platform/view/services/db/driver/badger/badger.go +++ b/platform/view/services/db/driver/badger/badger.go @@ -102,7 +102,7 @@ func (db *DB) Close() error { func (db *DB) SetState(namespace driver2.Namespace, key string, value driver.VersionedValue) error { if len(value.Raw) == 0 { - logger.Warnf("set key [%s:%d:%d] to nil value, will be deleted instead", key, value.Block, value.TxNum) + logger.Warnf("set key [%s:%v] to nil value, will be deleted instead", key, value.Version) return db.DeleteState(namespace, key) } @@ -118,8 +118,7 @@ func (db *DB) SetState(namespace driver2.Namespace, key string, value driver.Ver } v.Value = value.Raw - v.Block = value.Block - v.Txnum = value.TxNum + v.KeyVersion = value.Version bytes, err := proto.Marshal(v) if err != nil { @@ -144,7 +143,7 @@ func (db *DB) SetStates(namespace driver2.Namespace, kvs map[driver2.PKey]driver return errs } -func (db *DB) SetStateMetadata(namespace driver2.Namespace, key driver2.PKey, metadata driver2.Metadata, block driver2.BlockNum, txnum driver2.TxNum) error { +func (db *DB) SetStateMetadata(namespace driver2.Namespace, key driver2.PKey, metadata driver2.Metadata, version driver2.RawVersion) error { if db.Txn == nil { panic("programming error, writing without ongoing update") } @@ -157,8 +156,7 @@ func (db *DB) SetStateMetadata(namespace driver2.Namespace, key driver2.PKey, me } v.Meta = metadata - v.Block = block - v.Txnum = txnum + v.KeyVersion = version bytes, err := proto.Marshal(v) if err != nil { @@ -173,10 +171,10 @@ func (db *DB) SetStateMetadata(namespace driver2.Namespace, key driver2.PKey, me return nil } -func (db *DB) SetStateMetadatas(ns driver2.Namespace, kvs map[driver2.PKey]driver2.Metadata, block driver2.BlockNum, txnum driver2.TxNum) map[driver2.PKey]error { +func (db *DB) SetStateMetadatas(ns driver2.Namespace, kvs map[driver2.PKey]driver2.Metadata, version driver2.RawVersion) map[driver2.PKey]error { errs := make(map[driver2.PKey]error) for pkey, value := range kvs { - if err := db.SetStateMetadata(ns, pkey, value, block, txnum); err != nil { + if err := db.SetStateMetadata(ns, pkey, value, version); err != nil { errs[pkey] = err } } @@ -219,7 +217,7 @@ func (db *DB) GetState(namespace driver2.Namespace, key driver2.PKey) (driver.Ve return driver.VersionedValue{}, err } - return driver.VersionedValue{Raw: v.Value, Block: v.Block, TxNum: v.Txnum}, err + return driver.VersionedValue{Raw: v.Value, Version: v.KeyVersion}, err } func (db *DB) GetStateSetIterator(ns driver2.Namespace, keys ...driver2.PKey) (driver.VersionedResultsIterator, error) { @@ -230,16 +228,15 @@ func (db *DB) GetStateSetIterator(ns driver2.Namespace, keys ...driver2.PKey) (d return nil, err } reads[i] = &driver.VersionedRead{ - Key: key, - Raw: vv.Raw, - Block: vv.Block, - TxNum: vv.TxNum, + Key: key, + Raw: vv.Raw, + Version: vv.Version, } } return &keys2.DummyVersionedIterator{Items: reads}, nil } -func (db *DB) GetStateMetadata(namespace driver2.Namespace, key driver2.PKey) (driver2.Metadata, driver2.BlockNum, driver2.TxNum, error) { +func (db *DB) GetStateMetadata(namespace driver2.Namespace, key driver2.PKey) (driver2.Metadata, driver2.RawVersion, error) { dbKey := dbKey(namespace, key) txn := &Txn{db.db.NewTransaction(false)} @@ -247,10 +244,10 @@ func (db *DB) GetStateMetadata(namespace driver2.Namespace, key driver2.PKey) (d v, err := txVersionedValue(txn, dbKey) if err != nil { - return nil, 0, 0, err + return nil, nil, err } - return v.Meta, v.Block, v.Txnum, nil + return v.Meta, v.KeyVersion, nil } func (db *DB) NewWriteTransaction() (driver.WriteTransaction, error) { @@ -292,8 +289,7 @@ func (w *WriteTransaction) SetState(namespace driver2.Namespace, key driver2.PKe } v.Value = value.Raw - v.Block = value.Block - v.Txnum = value.TxNum + v.KeyVersion = value.Version bytes, err := proto.Marshal(v) if err != nil { diff --git a/platform/view/services/db/driver/badger/badger_test.go b/platform/view/services/db/driver/badger/badger_test.go index a5e1d03c5..95876b0a8 100644 --- a/platform/view/services/db/driver/badger/badger_test.go +++ b/platform/view/services/db/driver/badger/badger_test.go @@ -15,6 +15,8 @@ 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" "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/db/dbtest" @@ -102,9 +104,11 @@ func TestMarshallingErrors(t *testing.T) { assert.Contains(t, err.Error(), "could not unmarshal VersionedValue for key ") assert.Equal(t, driver.VersionedValue{}, vv) - m, bn, tn, err := db.GetStateMetadata(ns, key) + 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) + assert.NoError(t, err) assert.Equal(t, uint64(0), bn) assert.Equal(t, uint64(0), tn) @@ -119,11 +123,13 @@ func TestMarshallingErrors(t *testing.T) { assert.NoError(t, err) vv, err = db.GetState(ns, key) - assert.EqualError(t, err, "could not get value for key ns\x00key: invalid version, expected 1, got 34") + assert.EqualError(t, err, "could not get value for key ns\x00key: invalid fver, expected 1, got 34") assert.Equal(t, driver.VersionedValue{}, vv) - m, bn, tn, err = db.GetStateMetadata(ns, key) - assert.EqualError(t, err, "could not get value for key ns\x00key: invalid version, expected 1, got 34") + 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) + assert.NoError(t, err) assert.Len(t, m, 0) assert.Equal(t, uint64(0), bn) assert.Equal(t, uint64(0), tn) diff --git a/platform/view/services/db/driver/badger/proto/generate.go b/platform/view/services/db/driver/badger/proto/generate.go index 86f7cd879..2ce4b465f 100644 --- a/platform/view/services/db/driver/badger/proto/generate.go +++ b/platform/view/services/db/driver/badger/proto/generate.go @@ -6,4 +6,4 @@ SPDX-License-Identifier: Apache-2.0 package proto -//go:generate protoc kvs.proto --go_out=plugins=grpc:. +//go:generate protoc kvs.proto --go_out=. diff --git a/platform/view/services/db/driver/badger/proto/kvs.pb.go b/platform/view/services/db/driver/badger/proto/kvs.pb.go index c5d95bee8..2453ffa4f 100644 --- a/platform/view/services/db/driver/badger/proto/kvs.pb.go +++ b/platform/view/services/db/driver/badger/proto/kvs.pb.go @@ -1,116 +1,179 @@ // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v5.28.1 // source: kvs.proto package proto import ( - fmt "fmt" - math "math" + reflect "reflect" + sync "sync" - proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) type VersionedValue struct { - Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` - Block uint64 `protobuf:"varint,2,opt,name=block,proto3" json:"block,omitempty"` - Txnum uint64 `protobuf:"varint,3,opt,name=txnum,proto3" json:"txnum,omitempty"` - Value []byte `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"` - Meta map[string][]byte `protobuf:"bytes,5,rep,name=meta,proto3" json:"meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version uint32 `protobuf:"varint,1,opt,name=fver,proto3" json:"fver,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + KeyVersion []byte `protobuf:"bytes,3,opt,name=key_version,json=keyVersion,proto3" json:"key_version,omitempty"` + Meta map[string][]byte `protobuf:"bytes,4,rep,name=meta,proto3" json:"meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } -func (m *VersionedValue) Reset() { *m = VersionedValue{} } -func (m *VersionedValue) String() string { return proto.CompactTextString(m) } -func (*VersionedValue) ProtoMessage() {} -func (*VersionedValue) Descriptor() ([]byte, []int) { - return fileDescriptor_7630d382ef067a3e, []int{0} +func (x *VersionedValue) Reset() { + *x = VersionedValue{} + if protoimpl.UnsafeEnabled { + mi := &file_kvs_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *VersionedValue) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_VersionedValue.Unmarshal(m, b) -} -func (m *VersionedValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_VersionedValue.Marshal(b, m, deterministic) -} -func (m *VersionedValue) XXX_Merge(src proto.Message) { - xxx_messageInfo_VersionedValue.Merge(m, src) -} -func (m *VersionedValue) XXX_Size() int { - return xxx_messageInfo_VersionedValue.Size(m) -} -func (m *VersionedValue) XXX_DiscardUnknown() { - xxx_messageInfo_VersionedValue.DiscardUnknown(m) +func (x *VersionedValue) String() string { + return protoimpl.X.MessageStringOf(x) } -var xxx_messageInfo_VersionedValue proto.InternalMessageInfo +func (*VersionedValue) ProtoMessage() {} -func (m *VersionedValue) GetVersion() uint32 { - if m != nil { - return m.Version +func (x *VersionedValue) ProtoReflect() protoreflect.Message { + mi := &file_kvs_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return 0 + return mi.MessageOf(x) +} + +// Deprecated: Use VersionedValue.ProtoReflect.Descriptor instead. +func (*VersionedValue) Descriptor() ([]byte, []int) { + return file_kvs_proto_rawDescGZIP(), []int{0} } -func (m *VersionedValue) GetBlock() uint64 { - if m != nil { - return m.Block +func (x *VersionedValue) GetVersion() uint32 { + if x != nil { + return x.Version } return 0 } -func (m *VersionedValue) GetTxnum() uint64 { - if m != nil { - return m.Txnum +func (x *VersionedValue) GetValue() []byte { + if x != nil { + return x.Value } - return 0 + return nil } -func (m *VersionedValue) GetValue() []byte { - if m != nil { - return m.Value +func (x *VersionedValue) GetKeyVersion() []byte { + if x != nil { + return x.KeyVersion } return nil } -func (m *VersionedValue) GetMeta() map[string][]byte { - if m != nil { - return m.Meta +func (x *VersionedValue) GetMeta() map[string][]byte { + if x != nil { + return x.Meta } return nil } -func init() { - proto.RegisterType((*VersionedValue)(nil), "proto.VersionedValue") - proto.RegisterMapType((map[string][]byte)(nil), "proto.VersionedValue.MetaEntry") +var File_kvs_proto protoreflect.FileDescriptor + +var file_kvs_proto_rawDesc = []byte{ + 0x0a, 0x09, 0x6b, 0x76, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0xcf, 0x01, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x79, 0x5f, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6b, 0x65, 0x79, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, + 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0d, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, + 0x80, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_kvs_proto_rawDescOnce sync.Once + file_kvs_proto_rawDescData = file_kvs_proto_rawDesc +) + +func file_kvs_proto_rawDescGZIP() []byte { + file_kvs_proto_rawDescOnce.Do(func() { + file_kvs_proto_rawDescData = protoimpl.X.CompressGZIP(file_kvs_proto_rawDescData) + }) + return file_kvs_proto_rawDescData } -func init() { proto.RegisterFile("kvs.proto", fileDescriptor_7630d382ef067a3e) } - -var fileDescriptor_7630d382ef067a3e = []byte{ - // 185 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcc, 0x2e, 0x2b, 0xd6, - 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x05, 0x53, 0x4a, 0xb7, 0x18, 0xb9, 0xf8, 0xc2, 0x52, - 0x8b, 0x8a, 0x33, 0xf3, 0xf3, 0x52, 0x53, 0xc2, 0x12, 0x73, 0x4a, 0x53, 0x85, 0x24, 0xb8, 0xd8, - 0xcb, 0x20, 0x22, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xbc, 0x41, 0x30, 0xae, 0x90, 0x08, 0x17, 0x6b, - 0x52, 0x4e, 0x7e, 0x72, 0xb6, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x84, 0x03, 0x12, 0x2d, - 0xa9, 0xc8, 0x2b, 0xcd, 0x95, 0x60, 0x86, 0x88, 0x82, 0x39, 0x20, 0xd1, 0x32, 0x90, 0x71, 0x12, - 0x2c, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x10, 0x8e, 0x90, 0x31, 0x17, 0x4b, 0x6e, 0x6a, 0x49, 0xa2, - 0x04, 0xab, 0x02, 0xb3, 0x06, 0xb7, 0x91, 0x3c, 0xc4, 0x2d, 0x7a, 0xa8, 0x0e, 0xd0, 0xf3, 0x4d, - 0x2d, 0x49, 0x74, 0xcd, 0x2b, 0x29, 0xaa, 0x0c, 0x02, 0x2b, 0x96, 0x32, 0xe7, 0xe2, 0x84, 0x0b, - 0x09, 0x09, 0x70, 0x31, 0x67, 0xa7, 0x56, 0x82, 0x5d, 0xc6, 0x19, 0x04, 0x62, 0x22, 0x6c, 0x62, - 0x42, 0xb2, 0xc9, 0x8a, 0xc9, 0x82, 0x31, 0x89, 0x0d, 0x6c, 0xbc, 0x31, 0x20, 0x00, 0x00, 0xff, - 0xff, 0xf8, 0x7e, 0x02, 0xba, 0xf7, 0x00, 0x00, 0x00, +var file_kvs_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_kvs_proto_goTypes = []interface{}{ + (*VersionedValue)(nil), // 0: proto.VersionedValue + nil, // 1: proto.VersionedValue.MetaEntry +} +var file_kvs_proto_depIdxs = []int32{ + 1, // 0: proto.VersionedValue.meta:type_name -> proto.VersionedValue.MetaEntry + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_kvs_proto_init() } +func file_kvs_proto_init() { + if File_kvs_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_kvs_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VersionedValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_kvs_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_kvs_proto_goTypes, + DependencyIndexes: file_kvs_proto_depIdxs, + MessageInfos: file_kvs_proto_msgTypes, + }.Build() + File_kvs_proto = out.File + file_kvs_proto_rawDesc = nil + file_kvs_proto_goTypes = nil + file_kvs_proto_depIdxs = nil } diff --git a/platform/view/services/db/driver/badger/proto/kvs.proto b/platform/view/services/db/driver/badger/proto/kvs.proto index f5c4842cb..e01bcd50a 100644 --- a/platform/view/services/db/driver/badger/proto/kvs.proto +++ b/platform/view/services/db/driver/badger/proto/kvs.proto @@ -1,11 +1,13 @@ syntax = "proto3"; +option go_package = "./proto"; +option cc_generic_services = true; + package proto; message VersionedValue { uint32 version = 1; - uint64 block = 2; - uint64 txnum = 3; - bytes value = 4; - map meta = 5; + bytes value = 2; + bytes key_version = 3; + map meta = 4; } diff --git a/platform/view/services/db/driver/badger/range.go b/platform/view/services/db/driver/badger/range.go index 3beadb917..ce8070806 100644 --- a/platform/view/services/db/driver/badger/range.go +++ b/platform/view/services/db/driver/badger/range.go @@ -52,10 +52,9 @@ func (r *rangeScanIterator) Next() (*driver.VersionedRead, error) { r.it.Next() return &driver.VersionedRead{ - Key: dbKey, - Block: v.Block, - TxNum: v.Txnum, - Raw: v.Value, + Key: dbKey, + Version: v.KeyVersion, + Raw: v.Value, }, nil } diff --git a/platform/view/services/db/driver/driver.go b/platform/view/services/db/driver/driver.go index 21feffb78..4f6b2bd1c 100644 --- a/platform/view/services/db/driver/driver.go +++ b/platform/view/services/db/driver/driver.go @@ -22,9 +22,13 @@ var ( type SQLError = error type VersionedValue struct { - Raw driver.RawValue - Block driver.BlockNum - TxNum driver.TxNum + Raw driver.RawValue + Version driver.RawVersion +} + +type VersionedMetaData struct { + Metadata driver.Metadata + Version driver.RawVersion } type UnversionedRead struct { @@ -86,11 +90,11 @@ type UnversionedPersistence interface { type VersionedPersistence interface { BasePersistence[VersionedValue, VersionedRead] // GetStateMetadata gets the metadata and version for given namespace and key - GetStateMetadata(namespace driver.Namespace, key driver.PKey) (driver.Metadata, driver.BlockNum, driver.TxNum, error) + GetStateMetadata(namespace driver.Namespace, key driver.PKey) (driver.Metadata, driver.RawVersion, error) // SetStateMetadata sets the given metadata for the given namespace, key, and version - SetStateMetadata(namespace driver.Namespace, key driver.PKey, metadata driver.Metadata, block driver.BlockNum, txnum driver.TxNum) error + SetStateMetadata(namespace driver.Namespace, key driver.PKey, metadata driver.Metadata, version driver.RawVersion) error // SetStateMetadatas sets the given metadata for the given namespace, keys, and version - SetStateMetadatas(ns driver.Namespace, kvs map[driver.PKey]driver.Metadata, block driver.BlockNum, txnum driver.TxNum) map[driver.PKey]error + SetStateMetadatas(ns driver.Namespace, kvs map[driver.PKey]driver.Metadata, version driver.RawVersion) map[driver.PKey]error } type WriteTransaction interface { diff --git a/platform/view/services/db/driver/notifier/persistence.go b/platform/view/services/db/driver/notifier/persistence.go index b3cb5602f..c47808af2 100644 --- a/platform/view/services/db/driver/notifier/persistence.go +++ b/platform/view/services/db/driver/notifier/persistence.go @@ -191,16 +191,16 @@ func (db *VersionedPersistenceNotifier[P]) GetState(namespace driver2.Namespace, return db.Persistence.GetState(namespace, key) } -func (db *VersionedPersistenceNotifier[P]) GetStateMetadata(namespace driver2.Namespace, key driver2.PKey) (driver2.Metadata, driver2.BlockNum, driver2.TxNum, error) { +func (db *VersionedPersistenceNotifier[P]) GetStateMetadata(namespace driver2.Namespace, key driver2.PKey) (driver2.Metadata, driver2.RawVersion, error) { return db.Persistence.GetStateMetadata(namespace, key) } -func (db *VersionedPersistenceNotifier[P]) SetStateMetadata(namespace driver2.Namespace, key driver2.PKey, metadata driver2.Metadata, block driver2.BlockNum, txnum driver2.TxNum) error { - return db.Persistence.SetStateMetadata(namespace, key, metadata, block, txnum) +func (db *VersionedPersistenceNotifier[P]) SetStateMetadata(namespace driver2.Namespace, key driver2.PKey, metadata driver2.Metadata, version driver2.RawVersion) error { + return db.Persistence.SetStateMetadata(namespace, key, metadata, nil) } -func (db *VersionedPersistenceNotifier[P]) SetStateMetadatas(ns driver2.Namespace, kvs map[driver2.PKey]driver2.Metadata, block driver2.BlockNum, txnum driver2.TxNum) map[driver2.PKey]error { - return db.Persistence.SetStateMetadatas(ns, kvs, block, txnum) +func (db *VersionedPersistenceNotifier[P]) SetStateMetadatas(ns driver2.Namespace, kvs map[driver2.PKey]driver2.Metadata, version driver2.RawVersion) map[driver2.PKey]error { + return db.Persistence.SetStateMetadatas(ns, kvs, nil) } func (db *VersionedPersistenceNotifier[P]) GetStateRangeScanIterator(namespace driver2.Namespace, startKey, endKey driver2.PKey) (driver.VersionedResultsIterator, error) { diff --git a/platform/view/services/db/driver/sql/common/base.go b/platform/view/services/db/driver/sql/common/base.go index d331730d5..80f58e07b 100644 --- a/platform/view/services/db/driver/sql/common/base.go +++ b/platform/view/services/db/driver/sql/common/base.go @@ -188,19 +188,20 @@ func (db *BasePersistence[V, R]) hasKeys(ns driver2.Namespace, pkeys []driver2.P } func (db *BasePersistence[V, R]) SetStateWithTx(tx *sql.Tx, ns driver2.Namespace, pkey string, value V) error { + if tx == nil { + panic("programming error, writing without ongoing update") + } + keys := db.ValueScanner.Columns() values := db.ValueScanner.WriteValue(value) // Get rawVal valIndex := slices.Index(keys, "val") val := values[valIndex].([]byte) - if len(val) == 0 { logger.Warnf("set key [%s:%s] to nil value, will be deleted instead", ns, pkey) return db.DeleteState(ns, pkey) } - if tx == nil { - panic("programming error, writing without ongoing update") - } + logger.Debugf("set state [%s,%s]", ns, pkey) // Overwrite rawVal diff --git a/platform/view/services/db/driver/sql/common/versioned.go b/platform/view/services/db/driver/sql/common/versioned.go index 4a36fcf00..d6dfa2f01 100644 --- a/platform/view/services/db/driver/sql/common/versioned.go +++ b/platform/view/services/db/driver/sql/common/versioned.go @@ -24,26 +24,26 @@ func NewVersionedValueScanner() *versionedValueScanner { return &versionedValueS type versionedReadScanner struct{} -func (s *versionedReadScanner) Columns() []string { return []string{"pkey", "block", "txnum", "val"} } +func (s *versionedReadScanner) Columns() []string { return []string{"pkey", "kversion", "val"} } func (s *versionedReadScanner) ReadValue(txs scannable) (driver.VersionedRead, error) { var r driver.VersionedRead - err := txs.Scan(&r.Key, &r.Block, &r.TxNum, &r.Raw) + err := txs.Scan(&r.Key, &r.Version, &r.Raw) return r, err } type versionedValueScanner struct{} -func (s *versionedValueScanner) Columns() []string { return []string{"val", "block", "txnum"} } +func (s *versionedValueScanner) Columns() []string { return []string{"val", "kversion"} } func (s *versionedValueScanner) ReadValue(txs scannable) (driver.VersionedValue, error) { var r driver.VersionedValue - err := txs.Scan(&r.Raw, &r.Block, &r.TxNum) + err := txs.Scan(&r.Raw, &r.Version) return r, err } func (s *versionedValueScanner) WriteValue(value driver.VersionedValue) []any { - return []any{value.Raw, value.Block, value.TxNum} + return []any{value.Raw, value.Version} } type basePersistence[V any, R any] interface { @@ -71,8 +71,8 @@ func NewVersioned(readDB *sql.DB, writeDB *sql.DB, table string, errorWrapper dr return NewVersionedPersistence(base, base.table, base.errorWrapper, base.readDB, base.writeDB) } -func (db *VersionedPersistence) SetStateMetadata(ns driver2.Namespace, key driver2.PKey, metadata driver2.Metadata, block driver2.BlockNum, txnum driver2.TxNum) error { - if ns == "" || key == "" { +func (db *VersionedPersistence) SetStateMetadata(namespace driver2.Namespace, key driver2.PKey, metadata driver2.Metadata, version driver2.RawVersion) error { + if namespace == "" || key == "" { return errors.New("ns or key is empty") } if len(metadata) == 0 { @@ -83,23 +83,24 @@ func (db *VersionedPersistence) SetStateMetadata(ns driver2.Namespace, key drive return fmt.Errorf("error encoding metadata: %w", err) } - exists, err := db.Exists(ns, key) + exists, err := db.Exists(namespace, key) if err != nil { return err } + if exists { // Note: for consistency with badger we also update the block and txnum - query := fmt.Sprintf("UPDATE %s SET metadata = $1, block = $2, txnum = $3 WHERE ns = $4 AND pkey = $5", db.table) - logger.Debug(query, len(m), block, txnum, ns, key) - _, err = db.Exec(query, m, block, txnum, ns, key) + query := fmt.Sprintf("UPDATE %s SET metadata = $1, kversion = $2 WHERE ns = $3 AND pkey = $4", db.table) + logger.Debug(query, len(m), version, namespace, key) + _, err = db.Exec(query, m, version, namespace, key) if err != nil { return errors2.Wrapf(db.errorWrapper.WrapError(err), "could not set metadata for key [%s]", key) } } else { logger.Warnf("storing metadata without existing value at [%s]", key) - query := fmt.Sprintf("INSERT INTO %s (ns, pkey, metadata, block, txnum) VALUES ($1, $2, $3, $4, $5)", db.table) - logger.Debug(query, ns, key, len(m), block, txnum) - _, err = db.Exec(query, ns, key, m, block, txnum) + query := fmt.Sprintf("INSERT INTO %s (ns, pkey, metadata, kversion) VALUES ($1, $2, $3, $4)", db.table) + logger.Debug(query, namespace, key, len(m), version) + _, err = db.Exec(query, namespace, key, m, version) if err != nil { return errors2.Wrapf(db.errorWrapper.WrapError(err), "could not set metadata for key [%s]", key) } @@ -108,38 +109,38 @@ func (db *VersionedPersistence) SetStateMetadata(ns driver2.Namespace, key drive return nil } -func (db *VersionedPersistence) SetStateMetadatas(ns driver2.Namespace, kvs map[driver2.PKey]driver2.Metadata, block driver2.BlockNum, txnum driver2.TxNum) map[driver2.PKey]error { +func (db *VersionedPersistence) SetStateMetadatas(ns driver2.Namespace, kvs map[driver2.PKey]driver2.Metadata, version driver2.RawVersion) map[driver2.PKey]error { errs := make(map[driver2.PKey]error) for pkey, value := range kvs { - if err := db.SetStateMetadata(ns, pkey, value, block, txnum); err != nil { + if err := db.SetStateMetadata(ns, pkey, value, nil); err != nil { errs[pkey] = err } } return errs } -func (db *VersionedPersistence) GetStateMetadata(ns driver2.Namespace, key driver2.PKey) (driver2.Metadata, driver2.BlockNum, driver2.TxNum, error) { +func (db *VersionedPersistence) GetStateMetadata(namespace driver2.Namespace, key driver2.PKey) (driver2.Metadata, driver2.RawVersion, error) { var m []byte var meta map[string][]byte - var block, txnum uint64 + var kversion []byte - query := fmt.Sprintf("SELECT metadata, block, txnum FROM %s WHERE ns = $1 AND pkey = $2", db.table) - logger.Debug(query, ns, key) + query := fmt.Sprintf("SELECT metadata, kversion FROM %s WHERE ns = $1 AND pkey = $2", db.table) + logger.Debug(query, namespace, key) - row := db.readDB.QueryRow(query, ns, key) - if err := row.Scan(&m, &block, &txnum); err != nil { + row := db.readDB.QueryRow(query, namespace, key) + if err := row.Scan(&m, &kversion); err != nil { if err == sql.ErrNoRows { - logger.Debugf("not found: [%s:%s]", ns, key) - return meta, block, txnum, nil + logger.Debugf("not found: [%s:%s]", namespace, key) + return meta, nil, nil } - return meta, block, txnum, fmt.Errorf("error querying db: %w", err) + return meta, nil, fmt.Errorf("error querying db: %w", err) } meta, err := unmarshalMetadata(m) if err != nil { - return meta, block, txnum, fmt.Errorf("error decoding metadata: %w", err) + return meta, nil, fmt.Errorf("error decoding metadata: %w", err) } - return meta, block, txnum, err + return meta, kversion, err } func (db *VersionedPersistence) CreateSchema() error { @@ -147,11 +148,10 @@ func (db *VersionedPersistence) CreateSchema() error { CREATE TABLE IF NOT EXISTS %s ( ns TEXT NOT NULL, pkey BYTEA NOT NULL, - block BIGINT NOT NULL DEFAULT 0, - txnum BIGINT NOT NULL DEFAULT 0, val BYTEA NOT NULL DEFAULT '', + kversion BYTEA DEFAULT '', metadata BYTEA NOT NULL DEFAULT '', - version INT NOT NULL DEFAULT 0, + fver INT NOT NULL DEFAULT 0, PRIMARY KEY (pkey, ns) );`, db.table)) } diff --git a/platform/view/services/db/driver/sql/postgres/versioned.go b/platform/view/services/db/driver/sql/postgres/versioned.go index 92b710dcf..bd39f0e33 100644 --- a/platform/view/services/db/driver/sql/postgres/versioned.go +++ b/platform/view/services/db/driver/sql/postgres/versioned.go @@ -75,16 +75,16 @@ func (db *VersionedPersistence) Discard() error { return db.p.Discard() } -func (db *VersionedPersistence) GetStateMetadata(namespace driver2.Namespace, key driver2.PKey) (driver2.Metadata, driver2.BlockNum, driver2.TxNum, error) { +func (db *VersionedPersistence) GetStateMetadata(namespace driver2.Namespace, key driver2.PKey) (driver2.Metadata, driver2.RawVersion, error) { return db.p.GetStateMetadata(namespace, key) } -func (db *VersionedPersistence) SetStateMetadata(namespace driver2.Namespace, key driver2.PKey, metadata driver2.Metadata, block driver2.BlockNum, txnum driver2.TxNum) error { - return db.p.SetStateMetadata(namespace, key, metadata, block, txnum) +func (db *VersionedPersistence) SetStateMetadata(namespace driver2.Namespace, key driver2.PKey, metadata driver2.Metadata, version driver2.RawVersion) error { + return db.p.SetStateMetadata(namespace, key, metadata, nil) } -func (db *VersionedPersistence) SetStateMetadatas(ns driver2.Namespace, kvs map[driver2.PKey]driver2.Metadata, block driver2.BlockNum, txnum driver2.TxNum) map[driver2.PKey]error { - return db.p.SetStateMetadatas(ns, kvs, block, txnum) +func (db *VersionedPersistence) SetStateMetadatas(ns driver2.Namespace, kvs map[driver2.PKey]driver2.Metadata, version driver2.RawVersion) map[driver2.PKey]error { + return db.p.SetStateMetadatas(ns, kvs, nil) } func (db *VersionedPersistence) CreateSchema() error {