@@ -6,25 +6,31 @@ use std::panic::RefUnwindSafe;
6
6
7
7
use crate :: io:: utils:: check_namespace_key_validity;
8
8
use lightning:: util:: persist:: KVStore ;
9
+ use prost:: Message ;
10
+ use rand:: RngCore ;
9
11
use tokio:: runtime:: Runtime ;
10
12
use vss_client:: client:: VssClient ;
11
13
use vss_client:: error:: VssError ;
12
14
use vss_client:: types:: {
13
15
DeleteObjectRequest , GetObjectRequest , KeyValue , ListKeyVersionsRequest , PutObjectRequest ,
16
+ Storable ,
14
17
} ;
18
+ use vss_client:: util:: storable_builder:: { EntropySource , StorableBuilder } ;
15
19
16
20
/// A [`KVStore`] implementation that writes to and reads from a [VSS](https://github.com/lightningdevkit/vss-server/blob/main/README.md) backend.
17
21
pub struct VssStore {
18
22
client : VssClient ,
19
23
store_id : String ,
20
24
runtime : Runtime ,
25
+ storable_builder : StorableBuilder < RandEntropySource > ,
21
26
}
22
27
23
28
impl VssStore {
24
- pub ( crate ) fn new ( base_url : & str , store_id : String ) -> Self {
25
- let client = VssClient :: new ( base_url) ;
29
+ pub ( crate ) fn new ( base_url : String , store_id : String , data_encryption_key : [ u8 ; 32 ] ) -> Self {
30
+ let client = VssClient :: new ( base_url. as_str ( ) ) ;
26
31
let runtime = tokio:: runtime:: Builder :: new_multi_thread ( ) . enable_all ( ) . build ( ) . unwrap ( ) ;
27
- Self { client, store_id, runtime }
32
+ let storable_builder = StorableBuilder :: new ( data_encryption_key, RandEntropySource ) ;
33
+ Self { client, store_id, runtime, storable_builder }
28
34
}
29
35
30
36
fn build_key (
@@ -99,20 +105,25 @@ impl KVStore for VssStore {
99
105
_ => Error :: new ( ErrorKind :: Other , msg) ,
100
106
}
101
107
} ) ?;
102
- Ok ( resp. value . unwrap ( ) . value )
108
+ // unwrap safety: resp.value must be always present for a non-erroneous VSS response, otherwise
109
+ // it is an API-violation which is converted to [`VssError::InternalServerError`] in [`VssClient`]
110
+ let storable = Storable :: decode ( & resp. value . unwrap ( ) . value [ ..] ) ?;
111
+ Ok ( self . storable_builder . deconstruct ( storable) ?. 0 )
103
112
}
104
113
105
114
fn write (
106
115
& self , primary_namespace : & str , secondary_namespace : & str , key : & str , buf : & [ u8 ] ,
107
116
) -> io:: Result < ( ) > {
108
117
check_namespace_key_validity ( primary_namespace, secondary_namespace, Some ( key) , "write" ) ?;
118
+ let version = -1 ;
119
+ let storable = self . storable_builder . build ( buf. to_vec ( ) , version) ;
109
120
let request = PutObjectRequest {
110
121
store_id : self . store_id . clone ( ) ,
111
122
global_version : None ,
112
123
transaction_items : vec ! [ KeyValue {
113
124
key: self . build_key( primary_namespace, secondary_namespace, key) ?,
114
- version: - 1 ,
115
- value: buf . to_vec ( ) ,
125
+ version,
126
+ value: storable . encode_to_vec ( ) ,
116
127
} ] ,
117
128
delete_items : vec ! [ ] ,
118
129
} ;
@@ -171,6 +182,15 @@ impl KVStore for VssStore {
171
182
}
172
183
}
173
184
185
+ /// A source for generating entropy/randomness using [`rand`].
186
+ pub ( crate ) struct RandEntropySource ;
187
+
188
+ impl EntropySource for RandEntropySource {
189
+ fn fill_bytes ( & self , buffer : & mut [ u8 ] ) {
190
+ rand:: thread_rng ( ) . fill_bytes ( buffer) ;
191
+ }
192
+ }
193
+
174
194
#[ cfg( test) ]
175
195
impl RefUnwindSafe for VssStore { }
176
196
@@ -180,14 +200,16 @@ mod tests {
180
200
use super :: * ;
181
201
use crate :: io:: test_utils:: do_read_write_remove_list_persist;
182
202
use rand:: distributions:: Alphanumeric ;
183
- use rand:: { thread_rng, Rng } ;
203
+ use rand:: { thread_rng, Rng , RngCore } ;
184
204
185
205
#[ test]
186
206
fn read_write_remove_list_persist ( ) {
187
207
let vss_base_url = std:: env:: var ( "TEST_VSS_BASE_URL" ) . unwrap ( ) ;
188
208
let mut rng = thread_rng ( ) ;
189
209
let rand_store_id: String = ( 0 ..7 ) . map ( |_| rng. sample ( Alphanumeric ) as char ) . collect ( ) ;
190
- let vss_store = VssStore :: new ( & vss_base_url, rand_store_id) ;
210
+ let mut data_encryption_key = [ 0u8 ; 32 ] ;
211
+ rng. fill_bytes ( & mut data_encryption_key) ;
212
+ let vss_store = VssStore :: new ( vss_base_url, rand_store_id, data_encryption_key) ;
191
213
192
214
do_read_write_remove_list_persist ( & vss_store) ;
193
215
}
0 commit comments