immudb 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/immudb/client.rb +81 -47
- data/lib/immudb/database.rb +33 -0
- data/lib/immudb/dual_proof.rb +1 -1
- data/lib/immudb/{txe.rb → entry_spec.rb} +7 -11
- data/lib/immudb/grpc/schema_pb.rb +309 -17
- data/lib/immudb/grpc/schema_services_pb.rb +38 -11
- data/lib/immudb/htree.rb +0 -21
- data/lib/immudb/kv_metadata.rb +88 -0
- data/lib/immudb/linear_proof.rb +2 -8
- data/lib/immudb/schema.rb +119 -0
- data/lib/immudb/store.rb +56 -72
- data/lib/immudb/tx.rb +60 -23
- data/lib/immudb/tx_entry.rb +34 -0
- data/lib/immudb/tx_header.rb +62 -0
- data/lib/immudb/version.rb +1 -1
- data/lib/immudb.rb +6 -2
- metadata +10 -5
data/lib/immudb/htree.rb
CHANGED
@@ -95,26 +95,5 @@ module Immudb
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
end
|
98
|
-
|
99
|
-
def self.inclusion_proof_from(iproof)
|
100
|
-
h = InclusionProof.new
|
101
|
-
h.leaf = iproof.leaf.to_i
|
102
|
-
h.width = iproof.width.to_i
|
103
|
-
h.terms = Store.digest_from(iproof.terms)
|
104
|
-
h
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.dual_proof_from(dproof)
|
108
|
-
dp = DualProof.new
|
109
|
-
dp.sourceTxMetadata = Store.tx_metadata_from(dproof.sourceTxMetadata)
|
110
|
-
dp.targetTxMetadata = Store.tx_metadata_from(dproof.targetTxMetadata)
|
111
|
-
dp.inclusionProof = Store.digest_from(dproof.inclusionProof)
|
112
|
-
# use digests_from?
|
113
|
-
dp.consistencyProof = Store.digests_from(dproof.consistencyProof)
|
114
|
-
dp.targetBlTxAlh = Store.digest_from(dproof.targetBlTxAlh)
|
115
|
-
dp.lastInclusionProof = Store.digests_from(dproof.lastInclusionProof)
|
116
|
-
dp.linearProof = Store.linear_proof_from(dproof.linearProof)
|
117
|
-
dp
|
118
|
-
end
|
119
98
|
end
|
120
99
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Copyright 2022 CodeNotary, Inc. All rights reserved.
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
module Immudb
|
14
|
+
class KVMetadata
|
15
|
+
DELETED_ATTR_CODE = 0
|
16
|
+
EXPIRES_AT_ATTR_CODE = 1
|
17
|
+
NON_INDEXABLE_ATTR_CODE = 2
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@attributes = {}
|
21
|
+
@readonly = false
|
22
|
+
end
|
23
|
+
|
24
|
+
def as_deleted(deleted)
|
25
|
+
if @readonly
|
26
|
+
raise Error, "Read-only"
|
27
|
+
elsif !deleted
|
28
|
+
@attributes.delete(DELETED_ATTR_CODE)
|
29
|
+
else
|
30
|
+
@attributes[DELETED_ATTR_CODE] = nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def deleted?
|
35
|
+
@attributes.key?(DELETED_ATTR_CODE)
|
36
|
+
end
|
37
|
+
|
38
|
+
def expires_at(expires_at)
|
39
|
+
if @readonly
|
40
|
+
raise Error, "Read-only"
|
41
|
+
end
|
42
|
+
@attributes[EXPIRES_AT_ATTR_CODE] = expires_at
|
43
|
+
end
|
44
|
+
|
45
|
+
def non_expirable
|
46
|
+
@attributes.delete(EXPIRES_AT_ATTR_CODE)
|
47
|
+
end
|
48
|
+
|
49
|
+
def expirable?
|
50
|
+
@attributes.key?(EXPIRES_AT_ATTR_CODE)
|
51
|
+
end
|
52
|
+
|
53
|
+
def expiration_time
|
54
|
+
if @attributes.key?(EXPIRES_AT_ATTR_CODE)
|
55
|
+
@attributes[EXPIRES_AT_ATTR_CODE]
|
56
|
+
else
|
57
|
+
raise Error, "Non-expirable"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def as_non_indexable(non_indexable)
|
62
|
+
if @readonly
|
63
|
+
raise Error, "Read-only"
|
64
|
+
elsif !non_indexable
|
65
|
+
@attributes.delete(NON_INDEXABLE_ATTR_CODE)
|
66
|
+
else
|
67
|
+
@attributes[NON_INDEXABLE_ATTR_CODE] = nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def non_indexable?
|
72
|
+
@attributes.key?(NON_INDEXABLE_ATTR_CODE)
|
73
|
+
end
|
74
|
+
|
75
|
+
def bytes
|
76
|
+
b = "".b
|
77
|
+
[DELETED_ATTR_CODE, EXPIRES_AT_ATTR_CODE, NON_INDEXABLE_ATTR_CODE].each do |attr_code|
|
78
|
+
if @attributes.key?(attr_code)
|
79
|
+
b += [attr_code].pack("C")
|
80
|
+
if attr_code == EXPIRES_AT_ATTR_CODE
|
81
|
+
b += [@attributes[attr_code].to_i].pack("Q>")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
b
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/immudb/linear_proof.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2022 CodeNotary, Inc. All rights reserved.
|
2
2
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,12 +12,6 @@
|
|
12
12
|
|
13
13
|
module Immudb
|
14
14
|
class LinearProof
|
15
|
-
|
16
|
-
|
17
|
-
def initialize(sourceTxID, targetTxID, terms)
|
18
|
-
@sourceTxID = sourceTxID
|
19
|
-
@targetTxID = targetTxID
|
20
|
-
@terms = terms
|
21
|
-
end
|
15
|
+
attr_accessor :sourceTxID, :targetTxID, :terms
|
22
16
|
end
|
23
17
|
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# Copyright 2022 CodeNotary, Inc. All rights reserved.
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
module Immudb
|
14
|
+
module Schema
|
15
|
+
class << self
|
16
|
+
def tx_from_proto(stx)
|
17
|
+
header = ::Immudb::TxHeader.new
|
18
|
+
header.iD = stx.header.id
|
19
|
+
header.ts = stx.header.ts
|
20
|
+
header.blTxID = stx.header.blTxId
|
21
|
+
header.blRoot = digest_from_proto(stx.header.blRoot)
|
22
|
+
header.prevAlh = digest_from_proto(stx.header.prevAlh)
|
23
|
+
|
24
|
+
header.version = stx.header.version.to_i
|
25
|
+
header.metadata = tx_metadata_from_proto(stx.header.metadata)
|
26
|
+
|
27
|
+
header.nentries = stx.header.nentries.to_i
|
28
|
+
header.eh = digest_from_proto(stx.header.eH)
|
29
|
+
|
30
|
+
entries = []
|
31
|
+
stx.entries.each do |e|
|
32
|
+
entries <<
|
33
|
+
::Immudb::TxEntry.new(
|
34
|
+
e.key,
|
35
|
+
kv_metadata_from_proto(e.metadata),
|
36
|
+
e.vLen.to_i,
|
37
|
+
digest_from_proto(e.hValue),
|
38
|
+
0
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
tx = Store.new_tx_with_entries(header, entries)
|
43
|
+
|
44
|
+
tx.build_hash_tree
|
45
|
+
|
46
|
+
tx
|
47
|
+
end
|
48
|
+
|
49
|
+
def kv_metadata_from_proto(md)
|
50
|
+
return nil if md.nil?
|
51
|
+
kvmd = ::Immudb::KVMetadata.new()
|
52
|
+
kvmd.as_deleted(md.deleted)
|
53
|
+
|
54
|
+
unless md.expiration.nil?
|
55
|
+
kvmd.expires_at(Time.at(md.expiration.expiresAt))
|
56
|
+
end
|
57
|
+
|
58
|
+
kvmd.as_non_indexable(md.nonIndexable)
|
59
|
+
|
60
|
+
kvmd
|
61
|
+
end
|
62
|
+
|
63
|
+
def inclusion_proof_from_proto(iproof)
|
64
|
+
ip = ::Immudb::InclusionProof.new
|
65
|
+
ip.leaf = iproof.leaf.to_i
|
66
|
+
ip.width = iproof.width.to_i
|
67
|
+
ip.terms = digests_from_proto(iproof.terms)
|
68
|
+
ip
|
69
|
+
end
|
70
|
+
|
71
|
+
def dual_proof_from_proto(dproof)
|
72
|
+
dp = ::Immudb::DualProof.new
|
73
|
+
dp.sourceTxHeader = tx_header_from_proto(dproof.sourceTxHeader)
|
74
|
+
dp.targetTxHeader = tx_header_from_proto(dproof.targetTxHeader)
|
75
|
+
dp.inclusionProof = digests_from_proto(dproof.inclusionProof)
|
76
|
+
dp.consistencyProof = digests_from_proto(dproof.consistencyProof)
|
77
|
+
dp.targetBlTxAlh = digest_from_proto(dproof.targetBlTxAlh)
|
78
|
+
dp.lastInclusionProof = digests_from_proto(dproof.lastInclusionProof)
|
79
|
+
dp.linearProof = linear_proof_from_proto(dproof.linearProof)
|
80
|
+
dp
|
81
|
+
end
|
82
|
+
|
83
|
+
def tx_header_from_proto(hdr)
|
84
|
+
txh = ::Immudb::TxHeader.new
|
85
|
+
txh.iD = hdr.id
|
86
|
+
txh.prevAlh = digest_from_proto(hdr.prevAlh)
|
87
|
+
txh.ts = hdr.ts
|
88
|
+
txh.version = hdr.version.to_i
|
89
|
+
txh.metadata = tx_metadata_from_proto(hdr.metadata)
|
90
|
+
txh.nentries = hdr.nentries.to_i
|
91
|
+
txh.eh = digest_from_proto(hdr.eH)
|
92
|
+
txh.blTxID = hdr.blTxId
|
93
|
+
txh.blRoot = digest_from_proto(hdr.blRoot)
|
94
|
+
txh
|
95
|
+
end
|
96
|
+
|
97
|
+
def tx_metadata_from_proto(md)
|
98
|
+
return nil if md.nil?
|
99
|
+
::Immudb::TxMetadata.new
|
100
|
+
end
|
101
|
+
|
102
|
+
def linear_proof_from_proto(lproof)
|
103
|
+
lp = ::Immudb::LinearProof.new
|
104
|
+
lp.sourceTxID = lproof.sourceTxId
|
105
|
+
lp.targetTxID = lproof.TargetTxId
|
106
|
+
lp.terms = digests_from_proto(lproof.terms)
|
107
|
+
lp
|
108
|
+
end
|
109
|
+
|
110
|
+
def digest_from_proto(sliced_digest)
|
111
|
+
sliced_digest[0, 32]
|
112
|
+
end
|
113
|
+
|
114
|
+
def digests_from_proto(sliced_terms)
|
115
|
+
sliced_terms.map(&:dup)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/immudb/store.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2022 CodeNotary, Inc. All rights reserved.
|
2
2
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -13,62 +13,14 @@
|
|
13
13
|
module Immudb
|
14
14
|
class Store
|
15
15
|
class << self
|
16
|
-
def
|
17
|
-
|
18
|
-
stx.entries.each do |e|
|
19
|
-
i = TXe.new
|
20
|
-
i.h_value = digest_from(e.hValue)
|
21
|
-
i.v_off = e.vOff
|
22
|
-
i.value_len = e.vLen.to_i
|
23
|
-
i.set_key(e.key)
|
24
|
-
entries << i
|
25
|
-
end
|
26
|
-
tx = new_tx_with_entries(entries)
|
27
|
-
tx.ID = stx.metadata.id
|
28
|
-
tx.PrevAlh = digest_from(stx.metadata.prevAlh)
|
29
|
-
tx.Ts = stx.metadata.ts
|
30
|
-
tx.BlTxID = stx.metadata.blTxId
|
31
|
-
tx.BlRoot = digest_from(stx.metadata.blRoot)
|
32
|
-
tx.build_hash_tree
|
33
|
-
tx.calc_alh
|
34
|
-
tx
|
35
|
-
end
|
36
|
-
|
37
|
-
def tx_metadata_from(txmFrom)
|
38
|
-
txm = TxMetadata.new
|
39
|
-
txm.iD = txmFrom.id
|
40
|
-
txm.prevAlh = digest_from(txmFrom.prevAlh)
|
41
|
-
txm.ts = txmFrom.ts
|
42
|
-
txm.nEntries = txmFrom.nentries.to_i
|
43
|
-
txm.eh = digest_from(txmFrom.eH)
|
44
|
-
txm.blTxID = txmFrom.blTxId
|
45
|
-
txm.blRoot = digest_from(txmFrom.blRoot)
|
46
|
-
txm
|
47
|
-
end
|
48
|
-
|
49
|
-
def encode_key(key)
|
50
|
-
SET_KEY_PREFIX + key
|
51
|
-
end
|
52
|
-
|
53
|
-
def encode_kv(key, value)
|
54
|
-
KV.new(SET_KEY_PREFIX + key, PLAIN_VALUE_PREFIX + value)
|
55
|
-
end
|
56
|
-
|
57
|
-
def encode_reference(key, referencedKey, atTx)
|
58
|
-
refVal = REFERENCE_VALUE_PREFIX + [atTx].pack("Q>") + SET_KEY_PREFIX + referencedKey
|
59
|
-
KV.new(SET_KEY_PREFIX + key, refVal)
|
60
|
-
end
|
61
|
-
|
62
|
-
def linear_proof_from(lp)
|
63
|
-
LinearProof.new(lp.sourceTxId, lp.TargetTxId, lp.terms)
|
64
|
-
end
|
16
|
+
def new_tx_with_entries(header, entries)
|
17
|
+
htree = HTree.new(entries.length)
|
65
18
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
sliced_terms.map(&:dup)
|
19
|
+
tx = Tx.new
|
20
|
+
tx.header = header
|
21
|
+
tx.entries = entries
|
22
|
+
tx.htree = htree
|
23
|
+
tx
|
72
24
|
end
|
73
25
|
|
74
26
|
def verify_inclusion(proof, digest, root)
|
@@ -92,43 +44,75 @@ module Immudb
|
|
92
44
|
end
|
93
45
|
|
94
46
|
def verify_dual_proof(proof, sourceTxID, targetTxID, sourceAlh, targetAlh)
|
95
|
-
if proof.nil? || proof.
|
47
|
+
if proof.nil? || proof.sourceTxHeader.nil? || proof.targetTxHeader.nil? || proof.sourceTxHeader.iD != sourceTxID || proof.targetTxHeader.iD != targetTxID
|
96
48
|
return false
|
97
49
|
end
|
98
|
-
if proof.
|
50
|
+
if proof.sourceTxHeader.iD == 0 || proof.sourceTxHeader.iD > proof.targetTxHeader.iD
|
99
51
|
return false
|
100
52
|
end
|
101
|
-
if sourceAlh != proof.
|
53
|
+
if sourceAlh != proof.sourceTxHeader.alh
|
102
54
|
return false
|
103
55
|
end
|
104
|
-
if targetAlh != proof.
|
56
|
+
if targetAlh != proof.targetTxHeader.alh
|
105
57
|
return false
|
106
58
|
end
|
107
|
-
if sourceTxID < proof.
|
59
|
+
if sourceTxID < proof.targetTxHeader.blTxID && !verify_inclusion_aht(proof.inclusionProof, sourceTxID, proof.targetTxHeader.blTxID, leaf_for(sourceAlh), proof.targetTxHeader.blRoot)
|
108
60
|
return false
|
109
61
|
end
|
110
|
-
if proof.
|
62
|
+
if proof.sourceTxHeader.blTxID > 0 && !verify_consistency(proof.consistencyProof, proof.sourceTxHeader.blTxID, proof.targetTxHeader.blTxID, proof.sourceTxHeader.blRoot, proof.targetTxHeader.blRoot)
|
111
63
|
return false
|
112
64
|
end
|
113
|
-
if proof.
|
65
|
+
if proof.targetTxHeader.blTxID > 0 && !verify_last_inclusion(proof.lastInclusionProof, proof.targetTxHeader.blTxID, leaf_for(proof.targetBlTxAlh), proof.targetTxHeader.blRoot)
|
114
66
|
return false
|
115
67
|
end
|
116
|
-
if sourceTxID < proof.
|
117
|
-
verify_linear_proof(proof.linearProof, proof.
|
68
|
+
if sourceTxID < proof.targetTxHeader.blTxID
|
69
|
+
verify_linear_proof(proof.linearProof, proof.targetTxHeader.blTxID, targetTxID, proof.targetBlTxAlh, targetAlh)
|
118
70
|
else
|
119
71
|
verify_linear_proof(proof.linearProof, sourceTxID, targetTxID, sourceAlh, targetAlh)
|
120
72
|
end
|
121
73
|
end
|
122
74
|
|
75
|
+
def entry_spec_digest_for(version)
|
76
|
+
if version == 0
|
77
|
+
method(:entry_spec_digest_v0)
|
78
|
+
elsif version == 1
|
79
|
+
method(:entry_spec_digest_v1)
|
80
|
+
else
|
81
|
+
# TODO raise ErrUnsupportedTxVersion
|
82
|
+
raise VerificationError
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
123
86
|
private
|
124
87
|
|
125
|
-
def
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
88
|
+
def entry_spec_digest_v0(kv)
|
89
|
+
md = Digest::SHA256.new
|
90
|
+
md.update(kv.key)
|
91
|
+
valmd = Digest::SHA256.new
|
92
|
+
valmd.update(kv.value)
|
93
|
+
md.update(valmd.digest)
|
94
|
+
md.digest
|
95
|
+
end
|
96
|
+
|
97
|
+
def entry_spec_digest_v1(kv)
|
98
|
+
mdbs = "".b
|
99
|
+
if !kv.metadata.nil?
|
100
|
+
mdbs = kv.metadata.bytes
|
101
|
+
end
|
102
|
+
mdLen = mdbs.length
|
103
|
+
kLen = kv.key.length
|
104
|
+
b = "".b
|
105
|
+
b = b + [mdLen].pack("n")
|
106
|
+
b = b + mdbs
|
107
|
+
b = b + [kLen].pack("n")
|
108
|
+
b = b + kv.key
|
109
|
+
|
110
|
+
md = Digest::SHA256.new
|
111
|
+
md.update(b)
|
112
|
+
valmd = Digest::SHA256.new
|
113
|
+
valmd.update(kv.value)
|
114
|
+
md.update(valmd.digest)
|
115
|
+
md.digest
|
132
116
|
end
|
133
117
|
|
134
118
|
def leaf_for(d)
|
data/lib/immudb/tx.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2022 CodeNotary, Inc. All rights reserved.
|
2
2
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -12,35 +12,37 @@
|
|
12
12
|
|
13
13
|
module Immudb
|
14
14
|
class Tx
|
15
|
-
attr_accessor :
|
15
|
+
attr_accessor :header, :entries, :htree
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@header = nil
|
19
|
+
@entries = nil
|
20
|
+
@htree = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def tx_entry_digest
|
24
|
+
if @header.version == 0
|
25
|
+
method(:tx_entry_digest_v1_1)
|
26
|
+
elsif @header.version == 1
|
27
|
+
method(:tx_entry_digest_v1_2)
|
28
|
+
else
|
29
|
+
raise VerificationError
|
30
|
+
end
|
31
|
+
end
|
16
32
|
|
17
33
|
def build_hash_tree
|
18
34
|
digests = []
|
35
|
+
tx_entry_digest = self.tx_entry_digest
|
19
36
|
@entries.each do |e|
|
20
|
-
digests << e
|
37
|
+
digests << tx_entry_digest.call(e)
|
21
38
|
end
|
22
39
|
@htree.build_with(digests)
|
40
|
+
root = @htree.root
|
41
|
+
@header.eh = root
|
23
42
|
end
|
24
43
|
|
25
|
-
def
|
26
|
-
calc_innerhash
|
27
|
-
bi = [@ID].pack("Q>") + @PrevAlh + @InnerHash
|
28
|
-
@Alh = Digest::SHA256.digest(bi)
|
29
|
-
end
|
30
|
-
|
31
|
-
def calc_innerhash
|
32
|
-
bj = [@Ts, @nentries].pack("Q>L>") + eh
|
33
|
-
bj += [@BlTxID].pack("Q>") + @BlRoot
|
34
|
-
@InnerHash = Digest::SHA256.digest(bj)
|
35
|
-
end
|
36
|
-
|
37
|
-
def eh
|
38
|
-
@htree.root
|
39
|
-
end
|
40
|
-
|
41
|
-
def proof(key)
|
44
|
+
def index_of(key)
|
42
45
|
kindex = nil
|
43
|
-
# find index of element holding given key
|
44
46
|
@entries.each_with_index do |v, k|
|
45
47
|
if v.key == key
|
46
48
|
kindex = k
|
@@ -48,9 +50,44 @@ module Immudb
|
|
48
50
|
end
|
49
51
|
end
|
50
52
|
if kindex.nil?
|
51
|
-
raise
|
53
|
+
raise VerificationError
|
54
|
+
end
|
55
|
+
kindex
|
56
|
+
end
|
57
|
+
|
58
|
+
def proof(key)
|
59
|
+
kindex = index_of(key)
|
60
|
+
htree.inclusion_proof(kindex)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def tx_entry_digest_v1_1(e)
|
66
|
+
unless e.md.nil?
|
67
|
+
# TODO raise ErrMetadataUnsupported
|
68
|
+
raise Error, "Metadata not supported"
|
69
|
+
end
|
70
|
+
md = Digest::SHA256.new
|
71
|
+
md.update(e.k)
|
72
|
+
md.update(e.hVal)
|
73
|
+
md.digest
|
74
|
+
end
|
75
|
+
|
76
|
+
def tx_entry_digest_v1_2(e)
|
77
|
+
mdbs = "".b
|
78
|
+
if !e.md.nil?
|
79
|
+
mdbs = e.md.bytes
|
52
80
|
end
|
53
|
-
|
81
|
+
mdLen = mdbs.length
|
82
|
+
b = "".b
|
83
|
+
b = b + [mdLen].pack("n")
|
84
|
+
b = b + mdbs
|
85
|
+
b = b + [e.kLen].pack("n")
|
86
|
+
b = b + e.k
|
87
|
+
md = Digest::SHA256.new
|
88
|
+
md.update(b)
|
89
|
+
md.update(e.hVal)
|
90
|
+
md.digest
|
54
91
|
end
|
55
92
|
end
|
56
93
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Copyright 2022 CodeNotary, Inc. All rights reserved.
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
module Immudb
|
14
|
+
class TxEntry
|
15
|
+
attr_reader :k, :kLen, :md, :vLen, :hVal, :vOff
|
16
|
+
|
17
|
+
def initialize(key, md, vLen, hVal, vOff)
|
18
|
+
@k = key
|
19
|
+
@kLen = key.length
|
20
|
+
@md = md
|
21
|
+
@vLen = vLen
|
22
|
+
@hVal = hVal
|
23
|
+
@vOff = vOff
|
24
|
+
end
|
25
|
+
|
26
|
+
def key
|
27
|
+
@k
|
28
|
+
end
|
29
|
+
|
30
|
+
def metadata
|
31
|
+
@md
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Copyright 2022 CodeNotary, Inc. All rights reserved.
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
module Immudb
|
14
|
+
class TxHeader
|
15
|
+
attr_accessor :iD, :ts, :blTxID, :blRoot, :prevAlh, :version, :metadata, :nentries, :eh
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@iD = nil
|
19
|
+
@ts = nil
|
20
|
+
@blTxID = nil
|
21
|
+
@blRoot = nil
|
22
|
+
@prevAlh = nil
|
23
|
+
|
24
|
+
@version = nil
|
25
|
+
@metadata = TxMetadata.new
|
26
|
+
|
27
|
+
@nentries = nil
|
28
|
+
@eh = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def inner_hash
|
32
|
+
md = Digest::SHA256.new
|
33
|
+
md.update([@ts].pack("Q>"))
|
34
|
+
md.update([@version].pack("n"))
|
35
|
+
if @version == 0
|
36
|
+
md.update([@nentries].pack("n"))
|
37
|
+
elsif @version == 1
|
38
|
+
mdbs = "".b
|
39
|
+
if !@metadata.nil?
|
40
|
+
mdbs = @metadata.bytes
|
41
|
+
end
|
42
|
+
md.update([mdbs.length].pack("n"))
|
43
|
+
md.update(mdbs)
|
44
|
+
md.update([@nentries].pack("N"))
|
45
|
+
else
|
46
|
+
raise VerificationError, "missing tx hash calculation method for version #{@version}"
|
47
|
+
end
|
48
|
+
md.update(@eh)
|
49
|
+
md.update([@blTxID].pack("Q>"))
|
50
|
+
md.update(@blRoot)
|
51
|
+
md.digest
|
52
|
+
end
|
53
|
+
|
54
|
+
def alh
|
55
|
+
md = Digest::SHA256.new
|
56
|
+
md.update([@iD].pack("Q>"))
|
57
|
+
md.update(@prevAlh)
|
58
|
+
md.update(inner_hash)
|
59
|
+
md.digest
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/immudb/version.rb
CHANGED
data/lib/immudb.rb
CHANGED
@@ -4,25 +4,29 @@ require "openssl"
|
|
4
4
|
require "time"
|
5
5
|
|
6
6
|
# grpc
|
7
|
-
require "immudb/grpc/schema_pb"
|
8
7
|
require "immudb/grpc/schema_services_pb"
|
9
8
|
|
10
9
|
# modules
|
11
10
|
require "immudb/client"
|
12
11
|
require "immudb/constants"
|
12
|
+
require "immudb/database"
|
13
13
|
require "immudb/dual_proof"
|
14
|
+
require "immudb/entry_spec"
|
14
15
|
require "immudb/htree"
|
15
16
|
require "immudb/inclusion_proof"
|
16
17
|
require "immudb/interceptor"
|
17
18
|
require "immudb/kv"
|
19
|
+
require "immudb/kv_metadata"
|
18
20
|
require "immudb/linear_proof"
|
19
21
|
require "immudb/root_service"
|
22
|
+
require "immudb/schema"
|
20
23
|
require "immudb/sql_result"
|
21
24
|
require "immudb/state"
|
22
25
|
require "immudb/store"
|
23
26
|
require "immudb/tx"
|
27
|
+
require "immudb/tx_entry"
|
28
|
+
require "immudb/tx_header"
|
24
29
|
require "immudb/tx_metadata"
|
25
|
-
require "immudb/txe"
|
26
30
|
require "immudb/version"
|
27
31
|
|
28
32
|
module Immudb
|