@@ -27,8 +27,11 @@ import (
27
27
"strings"
28
28
"syscall"
29
29
30
+ "github.com/ethereum/go-ethereum/common"
30
31
"github.com/ethereum/go-ethereum/core"
31
32
"github.com/ethereum/go-ethereum/core/types"
33
+ "github.com/ethereum/go-ethereum/crypto"
34
+ "github.com/ethereum/go-ethereum/ethdb"
32
35
"github.com/ethereum/go-ethereum/internal/debug"
33
36
"github.com/ethereum/go-ethereum/log"
34
37
"github.com/ethereum/go-ethereum/node"
@@ -105,6 +108,8 @@ func ImportChain(chain *core.BlockChain, fn string) error {
105
108
}
106
109
107
110
log .Info ("Importing blockchain" , "file" , fn )
111
+
112
+ // Open the file handle and potentially unwrap the gzip stream
108
113
fh , err := os .Open (fn )
109
114
if err != nil {
110
115
return err
@@ -180,8 +185,12 @@ func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block
180
185
return nil
181
186
}
182
187
188
+ // ExportChain exports a blockchain into the specified file, truncating any data
189
+ // already present in the file.
183
190
func ExportChain (blockchain * core.BlockChain , fn string ) error {
184
191
log .Info ("Exporting blockchain" , "file" , fn )
192
+
193
+ // Open the file handle and potentially wrap with a gzip stream
185
194
fh , err := os .OpenFile (fn , os .O_CREATE | os .O_WRONLY | os .O_TRUNC , os .ModePerm )
186
195
if err != nil {
187
196
return err
@@ -193,7 +202,7 @@ func ExportChain(blockchain *core.BlockChain, fn string) error {
193
202
writer = gzip .NewWriter (writer )
194
203
defer writer .(* gzip.Writer ).Close ()
195
204
}
196
-
205
+ // Iterate over the blocks and export them
197
206
if err := blockchain .Export (writer ); err != nil {
198
207
return err
199
208
}
@@ -202,9 +211,12 @@ func ExportChain(blockchain *core.BlockChain, fn string) error {
202
211
return nil
203
212
}
204
213
214
+ // ExportAppendChain exports a blockchain into the specified file, appending to
215
+ // the file if data already exists in it.
205
216
func ExportAppendChain (blockchain * core.BlockChain , fn string , first uint64 , last uint64 ) error {
206
217
log .Info ("Exporting blockchain" , "file" , fn )
207
- // TODO verify mode perms
218
+
219
+ // Open the file handle and potentially wrap with a gzip stream
208
220
fh , err := os .OpenFile (fn , os .O_CREATE | os .O_APPEND | os .O_WRONLY , os .ModePerm )
209
221
if err != nil {
210
222
return err
@@ -216,10 +228,86 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las
216
228
writer = gzip .NewWriter (writer )
217
229
defer writer .(* gzip.Writer ).Close ()
218
230
}
219
-
231
+ // Iterate over the blocks and export them
220
232
if err := blockchain .ExportN (writer , first , last ); err != nil {
221
233
return err
222
234
}
223
235
log .Info ("Exported blockchain to" , "file" , fn )
224
236
return nil
225
237
}
238
+
239
+ // ImportPreimages imports a batch of exported hash preimages into the database.
240
+ func ImportPreimages (db * ethdb.LDBDatabase , fn string ) error {
241
+ log .Info ("Importing preimages" , "file" , fn )
242
+
243
+ // Open the file handle and potentially unwrap the gzip stream
244
+ fh , err := os .Open (fn )
245
+ if err != nil {
246
+ return err
247
+ }
248
+ defer fh .Close ()
249
+
250
+ var reader io.Reader = fh
251
+ if strings .HasSuffix (fn , ".gz" ) {
252
+ if reader , err = gzip .NewReader (reader ); err != nil {
253
+ return err
254
+ }
255
+ }
256
+ stream := rlp .NewStream (reader , 0 )
257
+
258
+ // Import the preimages in batches to prevent disk trashing
259
+ preimages := make (map [common.Hash ][]byte )
260
+
261
+ for {
262
+ // Read the next entry and ensure it's not junk
263
+ var blob []byte
264
+
265
+ if err := stream .Decode (& blob ); err != nil {
266
+ if err == io .EOF {
267
+ break
268
+ }
269
+ return err
270
+ }
271
+ // Accumulate the preimages and flush when enough ws gathered
272
+ preimages [crypto .Keccak256Hash (blob )] = common .CopyBytes (blob )
273
+ if len (preimages ) > 1024 {
274
+ if err := core .WritePreimages (db , 0 , preimages ); err != nil {
275
+ return err
276
+ }
277
+ preimages = make (map [common.Hash ][]byte )
278
+ }
279
+ }
280
+ // Flush the last batch preimage data
281
+ if len (preimages ) > 0 {
282
+ return core .WritePreimages (db , 0 , preimages )
283
+ }
284
+ return nil
285
+ }
286
+
287
+ // ExportPreimages exports all known hash preimages into the specified file,
288
+ // truncating any data already present in the file.
289
+ func ExportPreimages (db * ethdb.LDBDatabase , fn string ) error {
290
+ log .Info ("Exporting preimages" , "file" , fn )
291
+
292
+ // Open the file handle and potentially wrap with a gzip stream
293
+ fh , err := os .OpenFile (fn , os .O_CREATE | os .O_WRONLY | os .O_TRUNC , os .ModePerm )
294
+ if err != nil {
295
+ return err
296
+ }
297
+ defer fh .Close ()
298
+
299
+ var writer io.Writer = fh
300
+ if strings .HasSuffix (fn , ".gz" ) {
301
+ writer = gzip .NewWriter (writer )
302
+ defer writer .(* gzip.Writer ).Close ()
303
+ }
304
+ // Iterate over the preimages and export them
305
+ it := db .NewIteratorWithPrefix ([]byte ("secure-key-" ))
306
+ for it .Next () {
307
+ if err := rlp .Encode (writer , it .Value ()); err != nil {
308
+ return err
309
+ }
310
+ }
311
+ log .Info ("Exported preimages" , "file" , fn )
312
+ return nil
313
+ }
0 commit comments